Skip to content

Add tags to Post #447

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 2 commits into from
Closed

Add tags to Post #447

wants to merge 2 commits into from

Conversation

yceruto
Copy link
Member

@yceruto yceruto commented Jan 26, 2017

This implements #44 and it's a complete variant of #192 (On hold since Ago 2016).

Blog Post Index Post Show
tags-index tags-show
Post New/Edit
tagsinput

Also this splits the only one fixture class into three classes (UserFixtures, PostFixtures and TagFixtures):

  • To prevent mess and complexity.
  • To avoid post title duplicated (slug issue).
  • To fix example and explanation of: Sharing objects between fixtures (Add tags to posts with many-to-many relation  #192 (comment)).
  • To add a new example about: Fixture ordering and DependentFixtureInterface (dependence between fixtures).

Add Translation:

  • English
  • Español

Updated blog.sqlite and blog_test.sqlite DBs.


Handling Tags (Bootstrap-tagsinput):

There is many options to do that:

TODO:

  • Create TagsInputType to handle the post tags collection (Added DataTransformer example)
  • Add typeaheadjs option to show tags hint.


private function addRandomTags(Post $post)
{
$indexes = (array) array_rand(LoadTagFixtures::$names, mt_rand(1, 3));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we use 0 as the min number of tags ? Tags are optional, so it makes sense to have untagged posts too

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed!

*/
class LoadFixtures extends AbstractFixture implements ContainerAwareInterface
class LoadPostFixtures extends AbstractFixture implements DependentFixtureInterface, ContainerAwareInterface
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMO, you can remove the Load part of the name, now that there is an entity name

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed!

@yceruto
Copy link
Member Author

yceruto commented Jan 26, 2017

Next form tags approach ( coming soon 😅 )
tagsinput

@yceruto
Copy link
Member Author

yceruto commented Jan 26, 2017

tagsinput

Ready!

Status: Need Reviews :)


$newNames = array_diff($names, $tags);
foreach ($newNames as $name) {
$tag = new Tag();
Copy link
Member Author

@yceruto yceruto Jan 27, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

❓ I'm not sure if it's the best place to do that (i.e. Inside a DataTransformer)

'Era brevis ratione est',
'Sunt torquises imitari velox mirabilis medicinaes',
'Cum mineralis persuadere omnes finises desiderium bi-color',
'Bassus fatalis classiss virtualiter transferre de flavum',
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added 15 phrases more to avoid duplicate post title and slug issue.

*
* @author Yonel Ceruto <[email protected]>
*/
class ArrayToStringTransformer implements DataTransformerInterface
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@yceruto, I would name this class like TagArrayToStringTransformer, because the current name sounds very common.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, it makes sense, thanks!

$names = explode(',', $string);
}

$tags = $this->manager->getRepository(Tag::class)->findBy([
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@yceruto, what about to define tags repository as service and inject it instead of the object manager?

Copy link
Member Author

@yceruto yceruto Jan 27, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't see the benefit :/ it could complicate things

@voronkovich
Copy link
Contributor

@yceruto, you forgot to call EntityManager::persist for post in BlogController::editAction to save the changes in tags.
https://github.com/symfony/symfony-demo/blob/master/src/AppBundle/Controller/Admin/BlogController.php#L137

@yceruto
Copy link
Member Author

yceruto commented Jan 27, 2017

@yceruto, you forgot to call EntityManager::persist for post in BlogController::editAction to save the changes in tags.

AFAIK it's not necessary, Doctrine is able to detect the changes on M2M tags property and do it. Likewise for new tags thanks to cascade={"persist"} option.

{
$builder
->addModelTransformer(new CollectionToArrayTransformer())
->addViewTransformer(new TagArrayToStringTransformer($this->manager))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this should be a model transformer, not a view transformer. The TextType expects its normalized data to be a string. Changing it to be an array of tags could lead to issues (and such issues could appear in a future version of Symfony if some changes are made, even if there is no such issue today).

Changing the type of the normalized data when extending a type is generally not a supported usage of the type.

the code should look like this:

$builder
    ->addViewTransformer(new TagArrayToStringTransformer($this->manager))
    ->addModelTransformer(new CollectionToArrayTransformer())
;

Copy link
Member Author

@yceruto yceruto Jan 27, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You are right, nice catch! fixed thanks!

web/js/main.js Outdated
// Bootstrap-tagsinput initialization
// http://bootstrap-tagsinput.github.io/bootstrap-tagsinput/examples/
var $input = $('input[data-toggle="tagsinput"]');
var source = new Bloodhound({
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this should be done only when $input.length is not 0 (i.e. at least one such input has been found on the page)

{
$builder
->addModelTransformer(new TagArrayToStringTransformer($this->manager))
->addModelTransformer(new CollectionToArrayTransformer())
Copy link
Member Author

@yceruto yceruto Jan 27, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

At sight this looks confusing for newcomers now, looks like the data transformation is (even if it doesn't really happen so):

Tag[] -> String -> Collection -> Array

(i.e. following the order of addition)

What about other alternatives to do the same:

$builder
    ->addModelTransformer(new DataTransformerChain([
        new CollectionToArrayTransformer(),
        new TagArrayToStringTransformer($this->manager),
    ]))
;

or better

$builder
    ->addModelTransformer(new CollectionToArrayTransformer(), true)
    ->addModelTransformer(new TagArrayToStringTransformer($this->manager), true)
;

Does this make sense or does it simply not matter?

@yceruto
Copy link
Member Author

yceruto commented Jan 28, 2017

@stof, @voronkovich Thanks for the review. I have addressed your comments.

@javiereguiluz
Copy link
Member

@yceruto I'm really sorry it took me so long to merge this. I finally did it and I'll propose some tweaks in a separate PR. My only regret is that the solution looks too complex. Don't get me wrong, you did a great work and the feature it's fantastically implemented ... but thinking as a potential Symfony user looking at this demo application, I don't like such a complex solution for such a common feature.

@yceruto
Copy link
Member Author

yceruto commented Feb 6, 2017

@javiereguiluz I would be happy to improve those parts where the solution is complex, please just tell me which ones and I'll try to propose a better one or comment the code for a better understanding of it.

Thanks, best regards.

@javiereguiluz
Copy link
Member

@yceruto my comment was more about the complexity imposed by the Form component, such as creating a custom data transformer, enabling two data transformers in the custom form type, calling to the always confusing ->setByReference(false) inside the form type, etc.

javiereguiluz added a commit that referenced this pull request Feb 6, 2017
This PR was squashed before being merged into the master branch (closes #448).

Discussion
----------

Tweaked the new blog post tags feature

This continues #447 and introduces some minor changes.

---

The only relevant changes for end users is the minor redesign of the tags. For example, in the blog index, before tags stand out too much and they look like buttons:

![index-before](https://cloud.githubusercontent.com/assets/73419/22641958/1681671e-ec59-11e6-8178-e60b0eff9a4f.png)

Now they are faded because, after all, they are a secondary information:

![index-after](https://cloud.githubusercontent.com/assets/73419/22641977/22e349d2-ec59-11e6-9974-85565c9a565d.png)

In the blog post show, the tags are bigger:

![show-after](https://cloud.githubusercontent.com/assets/73419/22641984/2939dc1a-ec59-11e6-952c-fe1d53dc0b04.png)

And in the admin, I haven't modified anything, so they still look like this:

![admin-after](https://cloud.githubusercontent.com/assets/73419/22642002/391c0e6e-ec59-11e6-8e8c-f23f7267bc99.png)

Commits
-------

f09c564 Tweaked the new blog post tags feature
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants