This commit is contained in:
Simon Vieille 2021-03-30 21:16:52 +02:00
parent 5ff1acb093
commit e93419eafd
10 changed files with 188 additions and 55 deletions

View file

@ -11,15 +11,17 @@ use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Output\OutputInterface;
use App\Repository\Blog\PostRepositoryQuery;
class MigrateDataCommand extends Command class MigrateDataCommand extends Command
{ {
protected static $defaultName = 'app:migrate-data'; protected static $defaultName = 'app:migrate-data';
protected static $defaultDescription = ''; protected static $defaultDescription = '';
public function __construct(EntityManager $entityManager) public function __construct(EntityManager $entityManager, PostRepositoryQuery $postRepo)
{ {
$this->entityManager = $entityManager; $this->entityManager = $entityManager;
$this->postRepo = $postRepo;
parent::__construct(); parent::__construct();
} }
@ -35,6 +37,14 @@ class MigrateDataCommand extends Command
protected function execute(InputInterface $input, OutputInterface $output): int protected function execute(InputInterface $input, OutputInterface $output): int
{ {
/*
foreach ($this->postRepo->create()->find() as $post)
{
$tags = $post->getTags();
$post->setTags($tags);
$this->entityManager->update($post);
}
require 'data/category.php'; require 'data/category.php';
require 'data/comment.php'; require 'data/comment.php';
require 'data/post.php'; require 'data/post.php';
@ -103,6 +113,7 @@ class MigrateDataCommand extends Command
$this->entityManager->create($comment); $this->entityManager->create($comment);
} }
*/
return Command::SUCCESS; return Command::SUCCESS;
} }

View file

@ -95,10 +95,11 @@ class PostController extends PageController
public function search(Request $request, int $page = 1): Response public function search(Request $request, int $page = 1): Response
{ {
$query = $request->query->get('query'); $query = $request->query->get('query');
$tag = $request->query->get('tag');
if ($query) { if ($query || $tag) {
$entities = $this->createQuery() $entities = $this->createQuery()
->search($query) ->search($query, $tag)
->paginate($page, 5) ->paginate($page, 5)
; ;
} }

View file

@ -257,7 +257,21 @@ class Post implements EntityInterface
public function getTags(): ?array public function getTags(): ?array
{ {
return $this->tags; $tags = [];
foreach ($this->tags as $tag) {
if (is_string($tag)) {
$tags[] = ['label' => $tag];
} else {
$tags[] = $tag;
}
}
usort($tags, function($a, $b) {
return $a['label'] < $b['label'] ? -1 : 1;
});
return $tags;
} }
public function setTags(?array $tags): self public function setTags(?array $tags): self

View file

@ -0,0 +1,35 @@
<?php
namespace App\Form\Blog;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Validator\Constraints\NotBlank;
class PostTagType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add(
'label',
TextType::class,
[
'label' => 'Libellé',
'required' => true,
'attr' => [
],
'constraints' => [
new NotBlank(),
],
]
);
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
]);
}
}

View file

@ -20,6 +20,7 @@ use Symfony\Component\Validator\Constraints\Image;
use Symfony\Component\Validator\Constraints\NotBlank; use Symfony\Component\Validator\Constraints\NotBlank;
use Symfony\Component\Validator\Constraints\Range; use Symfony\Component\Validator\Constraints\Range;
use Symfony\Component\Validator\Constraints\Url; use Symfony\Component\Validator\Constraints\Url;
use Symfony\Component\Form\Extension\Core\Type\CollectionType;
class PostType extends AbstractType class PostType extends AbstractType
{ {
@ -156,14 +157,17 @@ class PostType extends AbstractType
] ]
); );
// $builder->add( $builder->add(
// 'tags', 'tags',
// 'text', CollectionType::class,
// [ [
// 'constraints' => [ 'entry_type' => PostTagType::class,
// ], 'by_reference' => false,
// ] 'allow_add' => true,
// ); 'allow_delete' => true,
'prototype' => true,
]
);
$builder->add( $builder->add(
'isQuick', 'isQuick',

View file

@ -63,59 +63,69 @@ class PostRepositoryQuery extends RepositoryQuery
return $this; return $this;
} }
public function search(string $keywords) public function search(?string $keywords, ?string $tag)
{ {
$conn = $this->repository->getEm()->getConnection(); if ($keywords) {
$conn = $this->repository->getEm()->getConnection();
$statement = $conn->prepare( $statement = $conn->prepare(
'SELECT 'SELECT
post.id, post.id,
post.title, post.title,
MATCH(post.title) AGAINST(:search) AS MATCH_TITLE, MATCH(post.title) AGAINST(:search) AS MATCH_TITLE,
MATCH(post.content) AGAINST(:search) AS MATCH_CONTENT MATCH(post.content) AGAINST(:search) AS MATCH_CONTENT
FROM post FROM post
WHERE WHERE
post.status = 1 AND post.status = 1 AND
post.published_at < :date post.published_at < :date
ORDER BY ORDER BY
MATCH_TITLE DESC, MATCH_TITLE DESC,
MATCH_CONTENT DESC MATCH_CONTENT DESC
'); ');
$statement->execute([ $statement->execute([
':search' => $keywords, ':search' => $keywords,
':date' => (new \DateTime())->format('Y-m-d H:i:s'), ':date' => (new \DateTime())->format('Y-m-d H:i:s'),
]); ]);
$results = $statement->fetchAll(); $results = $statement->fetchAll();
$ids = []; $ids = [];
foreach ($results as $k => $v) {
$rate = ($v['MATCH_TITLE'] * 2) + $v['MATCH_CONTENT'];
if ($rate >= 7) {
$ids[] = $v['id'];
}
}
if (0 == count($ids)) {
foreach ($results as $k => $v) { foreach ($results as $k => $v) {
$rate = ($v['MATCH_TITLE'] * 2) + $v['MATCH_CONTENT']; $rate = ($v['MATCH_TITLE'] * 2) + $v['MATCH_CONTENT'];
if ($rate >= 6) { if ($rate >= 7) {
$ids[] = $v['id']; $ids[] = $v['id'];
} }
} }
if (0 == count($ids)) {
foreach ($results as $k => $v) {
$rate = ($v['MATCH_TITLE'] * 2) + $v['MATCH_CONTENT'];
if ($rate >= 6) {
$ids[] = $v['id'];
}
}
}
if (!$ids) {
$ids = [-1];
}
$this
->orderBy('FIELD(p.id, :ids)')
->andWhere('.id IN(:ids)')
->setParameter(':ids', $ids)
;
} }
if (!$ids) { if ($tag) {
$ids = [-1]; $this
->andWhere('.tags LIKE :tag')
->setParameter(':tag', '%'.$tag.'%');
} }
return $this return $this;
->orderBy('FIELD(p.id, :ids)')
->andWhere('.id IN(:ids)')
->setParameter(':ids', $ids)
;
} }
} }

View file

@ -75,8 +75,8 @@
{% for tag in post.tags %} {% for tag in post.tags %}
<li> <li>
<a href="{{ safe_path('blog_menu_search', {tag: tag}) }}"> <a href="{{ safe_path('blog_menu_search', {tag: tag.label}) }}">
{{- '#' ~ tag -}} {{- '#' ~ tag.label -}}
</a> </a>
</li> </li>
{% endfor %} {% endfor %}

View file

@ -25,8 +25,8 @@
{% for tag in post.tags %} {% for tag in post.tags %}
<li> <li>
<a href="{{ safe_path('blog_menu_search', {tag: tag}) }}"> <a href="{{ safe_path('blog_menu_search', {tag: tag.value}) }}">
{{- '#' ~ tag -}} {{- '#' ~ tag.value -}}
</a> </a>
</li> </li>
{% endfor %} {% endfor %}

View file

@ -6,6 +6,37 @@
{{ form_row(form[item]) }} {{ form_row(form[item]) }}
</div> </div>
{% endfor %} {% endfor %}
<div class="col-12 accordion mb-3" data-collection="collection-tags" id="form-tags-collection">
{% for item in form.tags %}
<div class="card" data-collection-item="{{ loop.index }}">
<div class="card-header p-0">
<span class="btn btn-link btn-block text-left" data-toggle="collapse" data-target="#form-tag-{{ loop.index }}">
{{ item.vars.data.label }}
</span>
</div>
<div class="collapse" data-parent="#form-tags-collection" id="form-tag-{{ loop.index }}">
<div class="card-body">
{{ form_row(item.label) }}
<div class="text-right">
<span data-collection-delete-container class="btn btn-sm btn-danger">
<span data-collection-delete="{{ loop.index }}" class="fa fa-trash"></span>
</span>
</div>
{{ form_rest(item) }}
</div>
</div>
</div>
{% endfor %}
</div>
<div data-collection-add="collection-tags" class="collection-add">
<span class="btn btn-primary" data-collection-add="collection-tags">
<span class="fa fa-plus"></span>
{{ 'Nouveau tag'|trans }}
</span>
</div>
</div> </div>
</div> </div>
<div class="col-7 p-3"> <div class="col-7 p-3">
@ -59,3 +90,23 @@
</div> </div>
</div> </div>
<template type="text/template" id="collection-tags">
<div class="card" data-collection-item="__name__">
<div class="card-header p-0">
<span class="btn btn-link btn-block text-left" data-toggle="collapse" data-target="#form-tag-__name__">
{{ 'Nouveau tag'|trans }}
</span>
</div>
<div class="collapse show" id="form-tag-__name__" data-parent="#form-tags-collection">
<div class="card-body">
{{ form_row(form.tags.vars.prototype.label) }}
<div class="text-right">
<span data-collection-delete-container class="btn btn-sm btn-danger"></span>
</div>
{{ form_rest(form.tags.vars.prototype) }}
</div>
</div>
</div>
</template>

View file

@ -41,6 +41,13 @@
<a class="d-block" href="{{ path('admin_blog_post_show', {entity: category.id}) }}">{{ category.title }}</a> <a class="d-block" href="{{ path('admin_blog_post_show', {entity: category.id}) }}">{{ category.title }}</a>
{% endfor %} {% endfor %}
</li> </li>
<li class="list-group-item">
<span class="font-weight-bold pb-2 d-block">Tags</span>
{% for tag in entity.tags %}
<span class="d-block">{{ tag.label }}</span>
{% endfor %}
</li>
<li class="list-group-item"> <li class="list-group-item">
<span class="font-weight-bold pb-2 d-block">Slug</span> <span class="font-weight-bold pb-2 d-block">Slug</span>