diff --git a/app/Resources/translations/validators.en.xlf b/app/Resources/translations/validators.en.xlf index ce99cdb7f..d310b3d05 100644 --- a/app/Resources/translations/validators.en.xlf +++ b/app/Resources/translations/validators.en.xlf @@ -14,9 +14,9 @@ post.too_short_content Post content is too short ({{ limit }} characters minimum) - - post.too_much_tags - Too much tags ({{ limit }} maximum) + + post.too_many_tags + Too many tags (add {{ limit }} tags or less) comment.blank diff --git a/app/Resources/translations/validators.es.xlf b/app/Resources/translations/validators.es.xlf index 1e5b46531..5923fb5fd 100644 --- a/app/Resources/translations/validators.es.xlf +++ b/app/Resources/translations/validators.es.xlf @@ -14,9 +14,9 @@ post.too_short_content El contenido del artículo es demasiado corto ({{ limit }} caracteres como mínimo) - - post.too_much_tags - Demasiadas etiquetas ({{ limit }} como máximo) + + post.too_many_tags + Demasiadas etiquetas (añade {{ limit }} como máximo) comment.blank diff --git a/app/Resources/views/blog/_post_tags.html.twig b/app/Resources/views/blog/_post_tags.html.twig index 4008d2b3f..9ddb8baff 100644 --- a/app/Resources/views/blog/_post_tags.html.twig +++ b/app/Resources/views/blog/_post_tags.html.twig @@ -1,7 +1,7 @@ {% if not post.tags.empty %} {{ post.summary|md2html }} + + {{ include('blog/_post_tags.html.twig') }} {% else %}
{{ 'post.no_posts_found'|trans }}
diff --git a/app/config/services.yml b/app/config/services.yml index a4ec074ac..ec34cbaea 100644 --- a/app/config/services.yml +++ b/app/config/services.yml @@ -22,9 +22,8 @@ services: tags: - { name: twig.extension } - # This is only needed if your form type requires some dependencies to be injected - # by the container, otherwise it is unnecessary overhead and therefore not recommended - # to do this for all form type classes. + # Defining a form type as a service is only required when the form type + # needs to use some other services, such as the entity manager. # See http://symfony.com/doc/current/best_practices/forms.html app.form.type.tagsinput: class: AppBundle\Form\Type\TagsInputType diff --git a/src/AppBundle/DataFixtures/ORM/PostFixtures.php b/src/AppBundle/DataFixtures/ORM/PostFixtures.php index c54ba956c..45352ce61 100644 --- a/src/AppBundle/DataFixtures/ORM/PostFixtures.php +++ b/src/AppBundle/DataFixtures/ORM/PostFixtures.php @@ -21,10 +21,8 @@ use Symfony\Component\DependencyInjection\ContainerAwareTrait; /** - * Defines the sample data to load in the database when running the unit and - * functional tests. - * - * Execute this command to load the data: + * Defines the sample blog posts to load in the database before running the unit + * and functional tests. Execute this command to load the data. * * $ php bin/console doctrine:fixtures:load * @@ -53,8 +51,9 @@ public function load(ObjectManager $manager) $post->setSummary($this->getRandomPostSummary()); $post->setSlug($this->container->get('slugger')->slugify($post->getTitle())); $post->setContent($this->getPostContent()); - // This reference has been added in UserFixtures class and contains - // an instance of User entity. + // "References" are the way to share objects between fixtures defined + // in different files. This reference has been added in the UserFixtures + // file and it contains an instance of the User entity. $post->setAuthor($this->getReference('anna-admin')); $post->setPublishedAt(new \DateTime('now - '.$i.'days')); @@ -79,8 +78,9 @@ public function load(ObjectManager $manager) } /** - * This method must return an array of fixtures classes - * on which the implementing class depends on. + * Instead of defining the exact order in which the fixtures files must be loaded, + * this method defines which other fixtures this file depends on. Then, Doctrine + * will figure out the best order to fit all the dependencies. * * @return array */ @@ -170,14 +170,14 @@ private function getPhrases() 'Eposs sunt solems de superbus fortis', 'Vae humani generis', 'Diatrias tolerare tanquam noster caesium', - 'Teres talis orgias saepe tractare de camerarius flavum sensorem', + 'Teres talis saepe tractare de camerarius flavum sensorem', 'Silva de secundus galatae demitto quadra', 'Sunt accentores vitare salvus flavum parses', - 'Potus sensim ducunt ad ferox abnoba', + 'Potus sensim ad ferox abnoba', 'Sunt seculaes transferre talis camerarius fluctuies', 'Era brevis ratione est', 'Sunt torquises imitari velox mirabilis medicinaes', - 'Cum mineralis persuadere omnes finises desiderium bi-color', + 'Mineralis persuadere omnes finises desiderium', 'Bassus fatalis classiss virtualiter transferre de flavum', ]; } diff --git a/src/AppBundle/DataFixtures/ORM/TagFixtures.php b/src/AppBundle/DataFixtures/ORM/TagFixtures.php index de1082035..50433e9b3 100644 --- a/src/AppBundle/DataFixtures/ORM/TagFixtures.php +++ b/src/AppBundle/DataFixtures/ORM/TagFixtures.php @@ -16,10 +16,8 @@ use Doctrine\Common\Persistence\ObjectManager; /** - * Defines the sample data to load in the database when running the unit and - * functional tests. - * - * Execute this command to load the data: + * Defines the sample blog tags to load in the database before running the unit + * and functional tests. Execute this command to load the data. * * $ php bin/console doctrine:fixtures:load * @@ -30,7 +28,7 @@ class TagFixtures extends AbstractFixture { public static $names = [ - 'Lorem', + 'lorem', 'ipsum', 'consectetur', 'adipiscing', diff --git a/src/AppBundle/DataFixtures/ORM/UserFixtures.php b/src/AppBundle/DataFixtures/ORM/UserFixtures.php index 7512bb418..ab12c0abe 100644 --- a/src/AppBundle/DataFixtures/ORM/UserFixtures.php +++ b/src/AppBundle/DataFixtures/ORM/UserFixtures.php @@ -18,10 +18,8 @@ use Symfony\Component\DependencyInjection\ContainerAwareTrait; /** - * Defines the sample data to load in the database when running the unit and - * functional tests. - * - * Execute this command to load the data: + * Defines the sample users to load in the database befre running the unit and + * functional tests. Execute this command to load the data. * * $ php bin/console doctrine:fixtures:load * diff --git a/src/AppBundle/Entity/Post.php b/src/AppBundle/Entity/Post.php index 2b557b533..8f7ccaea1 100644 --- a/src/AppBundle/Entity/Post.php +++ b/src/AppBundle/Entity/Post.php @@ -105,7 +105,7 @@ class Post * * @ORM\ManyToMany(targetEntity="AppBundle\Entity\Tag", cascade={"persist"}) * @ORM\JoinTable(name="symfony_demo_post_tag") - * @Assert\Count(max="4", maxMessage="post.too_much_tags") + * @Assert\Count(max="4", maxMessage="post.too_many_tags") */ private $tags; diff --git a/tests/AppBundle/Controller/DefaultControllerTest.php b/tests/AppBundle/Controller/DefaultControllerTest.php index bc0a9ff86..c1c1126d7 100644 --- a/tests/AppBundle/Controller/DefaultControllerTest.php +++ b/tests/AppBundle/Controller/DefaultControllerTest.php @@ -11,6 +11,7 @@ namespace Tests\AppBundle\Controller; +use AppBundle\Entity\Post; use Symfony\Bundle\FrameworkBundle\Test\WebTestCase; /** @@ -43,6 +44,23 @@ public function testPublicUrls($url) ); } + /** + * A good practice for tests is to not use the service container, to make + * them more robust. However, in this example we must access to the container + * to get the entity manager and make a database query. The reason is that + * blog post fixtures are randomly generated and there's no guarantee that + * a given blog post slug will be available. + */ + public function testPublicBlogPost() + { + // the service container is always available via the client + $client = self::createClient(); + $blogPost = $client->getContainer()->get('doctrine')->getRepository(Post::class)->find(1); + $client->request('GET', sprintf('/en/blog/posts/%s', $blogPost->getSlug())); + + $this->assertTrue($client->getResponse()->isSuccessful()); + } + /** * The application contains a lot of secure URLs which shouldn't be * publicly accessible. This tests ensures that whenever a user tries to @@ -68,7 +86,6 @@ public function getPublicUrls() { yield ['/']; yield ['/en/blog/']; - yield ['/en/blog/posts/morbi-tempus-commodo-mattis']; yield ['/en/login']; } diff --git a/var/data/blog.sqlite b/var/data/blog.sqlite index 86188e51c..2d11650bf 100644 Binary files a/var/data/blog.sqlite and b/var/data/blog.sqlite differ diff --git a/var/data/blog_test.sqlite b/var/data/blog_test.sqlite index 86188e51c..2d11650bf 100644 Binary files a/var/data/blog_test.sqlite and b/var/data/blog_test.sqlite differ diff --git a/web/css/main.css b/web/css/main.css index f66edc1c2..c032416f0 100644 --- a/web/css/main.css +++ b/web/css/main.css @@ -224,12 +224,13 @@ body#login #login-users-help p .console { /* Page: 'Blog index' ------------------------------------------------------------------------- */ -body#blog_index h1 { +body#blog_index h1, +body#blog_index p { margin-bottom: 0.5em } body#blog_index article.post { - margin-bottom: 3em + margin-bottom: 3em; } body#blog_index .post-metadata { @@ -237,8 +238,12 @@ body#blog_index .post-metadata { margin-bottom: 8px; } -body#blog_index .post-tags { - margin-bottom: 15px; +body#blog_index .post-tags .label-default { + background-color: #e9ecec; + color: #6d8283; +} +body#blog_index .post-tags .label-default i { + color: #a3b2b2; } /* Page: 'Blog post show' @@ -247,6 +252,17 @@ body#blog_post_show h3 { margin-bottom: 0.75em } +body#blog_post_show .post-tags .label-default { + background-color: #e9ecec; + color: #6D8283; + font-size: 16px; + margin-right: 10px; + padding: .4em 1em .5em; +} +body#blog_post_show .post-tags .label-default i { + color: #95A6A7; +} + body#blog_post_show #post-add-comment { margin: 2em 0 } @@ -289,6 +305,20 @@ body#admin_post_index .item-actions a.btn + a.btn { margin-left: 4px } +/* Page: 'Backend post show' + ------------------------------------------------------------------------- */ +body#admin_post_show .post-tags .label-default { + background-color: #e9ecec; + color: #6D8283; + font-size: 16px; + margin-right: 10px; + padding: .4em 1em .5em; +} +body#admin_post_show .post-tags .label-default i { + color: #95A6A7; +} + + @media (min-width: 768px) and (max-width: 1200px) { .container { width: 98%;