Skip to content
This repository has been archived by the owner on Sep 16, 2021. It is now read-only.

Code time references to documents #212

Open
dantleech opened this issue Oct 30, 2014 · 24 comments
Open

Code time references to documents #212

dantleech opened this issue Oct 30, 2014 · 24 comments

Comments

@dantleech
Copy link
Member

When developing a CMS implementation the developer should not be coding to data which may or may not be in the database.

Currently it is necessary to hard code paths to documents. The problem is that these paths may change during the lifetime of the application, causing the application to fail.

Lets put our thoughts on this wiki page and discuss them here,

@benglass
Copy link
Member

@dantleech thanks for taking the time to document the various approaches being discussed. could you help me understand why neither structural nodes nor roles would work for multi-site?

For roles, at least, it would be the responsibility of the developer to ensure that there is only one document with a certain role across all sites, perhaps by prefixing them (main_privacy_policy, store_privacy_policy) if necessary.

I think its possible that for the role solution the only component that would have to support it would be the routing component. It would perhaps look for this special character like @ and do a query lookup based on role. The menu bundle I believe just sends whatever string you pass when calling knp_menu along to the router for lookup.

@dantleech
Copy link
Member Author

Well, if you have multiple sites and each site has, for example, its own "Privacy policy", we would want to assign a role to each of the sites "Privacy Policy" route / or menu item. But as I say, we could handle this at a different level.

For the MenuBundle, it is a "menu item" document we want to retrieve, not the Route. The Menu item document then references the route. So the MenuBundle also needs to be aware of the "role" solution I guess.

@joschi127
Copy link

I like the idea of using roles with an @ prefix for this. At the moment we in our implementation also have some documents which always have to exist and it breaks things if they are moved: e.g. /cms/menu/main and /cms/menu/footer and /cms/content/home and /cms/content/login.
The idea of referencing to those by using unique role names is nice and easy and I also like that it is looking similar to referencing a service by it's service name.
If a role is not found it throws an Exception. In my implementation I could then block deleting Documents via the admin interface if they have a certain mandatory role. But I could allow renaming or moving them.
At least for our use cases that would work just fine. Multi site support for sites in a sub path would be a great (future?) addition.

@joschi127
Copy link

PS: thanks!

@ElectricMaxxx
Copy link
Member

From my Point of view i see no advantage in that solution. Sorry. When a developer wants to have a secure reference he should use the uuid And we should support him in using it. Its the same way We are referencing children, reference-many, reference-one And so on. I see the paths as a kind of grouping. In a common usage we will find all content documents under /cms/content and routes under /cms/routes. If We think in blocks we would design an article in /cms/content/articles/article-one/section-one ... section-n, so We have an article called "article-one" with several sections. If one section moves to an other article it can be Part of the buisness logic or the developer should not allow it. If the application fails caused by a missing section (to stay in my example). It is the fault of the Developer. Ok, we can give some Tools to fix some documents or prevent them to be moved. This can be some constraints between parent and children. But i would suggest the uuid for referencing in the code.

@benglass
Copy link
Member

Using the uuid is a solution that works well when you have provided the user a GUI to select a page, for example in an insert link dialog that is part of a WYSIWYG editor where the user selects a page title from a dropdown.

But if the link is in a twig template such as the footer of your website containing a link to your privacy policy then using the uuid is not ideal. The template file would be committed in your git repository with a hard coded uuid that could be different on your staging server than on your production server and it would also be hard to read/understand. Granted you could put the uuid into your parameters file so you can change it from one install to another but then you are responsible for making that available in all templates and editing that parameter between installations.

@joschi127
Copy link

Good discussion :-)

@ElectricMaxxx Of course referencing by uuid would work. However for our use case it would be much better being able to reference by a "given" role name because we are using the same code base for a lot of projects and the uuid would not be the same and the role name could always be the same for some special documents. What do you think?

In addition I think the code or config referencing a document by it's role name would be easier to read and to understand as it would be when referencing a uuid. Hmm?

@dantleech
Copy link
Member Author

What are the arguments against the "Structural" node idea? i.e. simply making certain nodes immovable and/or immutable. I like that the best as it has zero impact on anything else.

@joschi127
Copy link

@dantleech Maybe you are right. For us it would do the job at the moment when referencing to some content (e.g. /cms/content/login or /cms/content/forum) because we do not use sub paths for content documents. On the other hand when referencing to a menu node or route it would not do the job because the menu node could be moved to another sub path and so the id would change. But at the moment we do not really need references to a menu node, instead we can get the menu nodes from the content document. (not sure if we will need it in the future... i guess it might be useful for menu nodes and for routes as well, or also for sub folders of the media bundle)

@dantleech
Copy link
Member Author

@joschi127 yeah good point, but I can't think of any use-cases for statically referencing nodes whose position in the content tree might change (not to say there isn't any) - I have added a use cases section to the wiki page, would be interesting to see how others need this feature to act.

@benglass
Copy link
Member

I think an issue with structural nodes is that it would make it so that clients cannot change the public URL of a page. They would not be able to change the URL of the privacy policy for example. That example is somewhat far fetched (how often do you change the url of your privacy policy) but I could easily see using the role system for linking to a contact form and the client could decide to move it from /cms/main/about/contact to /cms/main/contact or change it to contact-us

@benglass
Copy link
Member

I should be clear that the scenario I am talking about assumes that your route paths are used for your URLs which is how our CMS is set up and how SimpleCms is set up (visiting domain.com/contact will end up loading a route in /cms/main/contact or something like that so changing the URL causes the node path to change).

@ElectricMaxxx
Copy link
Member

Think that are two different things.

The thing with changing the url By changing the documents name should be an education problem, when document name depends on documents title. Our customers wants to have clear routes with the contents name in it (SEO) So they need to learn how to use the CMS. The time of ?site_id=xx is over! So when they want to have the contents title in the url, they need to know all consequenses.
When hardcoding a reference to that url would be the same as putting a hardcoded url into a twig template - you need to know, that this can fail. We have got the same issue when referencing routes to an menu node.

Building a structure type would be a subset of the constraints i suggested, right? Why not building a set of them?

  • parent contraint: this node is allowed to be a child of a collection of defined documents. Use case: menu nodes should be childs of menu And other menu nodes only.
  • children contraint: a document can have specific children only. Use case: for menu too and for routes. Routes can have route documents as children only.
  • path constraint: equal to the parent constraint, but from the view of the path.
  • attributes: special information like your roles or imutable names.
    (Btw there is an equal list in the config of the SonataDoctrinePHPCRBundle - class <-> valid children)

We can do that inside the document mapping. And it would be like XSD for the phpcr tree - a kind of a Schema. =

@benglass
Copy link
Member

Right now there are 2 ways to link to a document: path and uuid. The issue with each is as follows

Path

  1. The path is volatile since it can be changed by the user in the cms

UUID

  1. May be different from one install to another (dev vs. production)
  2. Its unreadable so its obscure what is being linked to
  3. Its also volatile in a way because its not really the uuid that we care about its the fact that the page in question has a certain significance to the system (its the contact page or the privacy policy page)

Making it impossible for CMS users to rename or move a document because it has significance to the system seems like an artificial constraint. CMS users should be able to change the URL of the contact page without worrying about links breaking. This can be achieved in twig templates by using the uuid but the uuid is a pain for developers for the reasons outlined above.

Overall I think the constraints system sounds like it could be useful but I think its overkill for this in terms of complexity and it also fails to solve the issue of allowing developers to link to documents in the system in a safe and clear way that works across different environments.

@dantleech
Copy link
Member Author

@ElectricMaxxx Yeah. I think roles will be useful in the context of referencing otherwise "dynamic" URLs. We should probably implement both features, but I guess this thread should be about roles now.

The constraints you mention are actually already supported by PHPCR. We just do not support mapping them in the ODM (mainly because Jackrabbit is a pain in the arse). But this is something I really want to be in PHPCR-ODM.

@dantleech
Copy link
Member Author

@benglass For URLs, yes, users should be able to change those. But nodes which have significance to the system, such as /cms, /cms/content, /cms/menu etc. should not be movable by the user. Also I think that "menu" endpoints such as /cms/menu/main, /cms/menu/footer are also strong candidates for this strategy.

As for complexity, I think it is less complex than the "role" solution, as we only have to change the ODM.

But anyway, for roles there are two issues we need to solve:

  • Where to store role data (I added something to the Wiki about that yesterday)
  • How and where roles are "resolved".

So we would want to have roles in the following situations:

  • {{ sonata_block('@sidebar') }}
  • {{ knp_menu('@main-menu') }}
  • {{ path('@home') }}

I even wonder if we should extend this concept even further:

return $this->render('@my-template-in-the-odm')

In the above example the template is stored in the content repository.

So I guess we need something like a ResourceResolver class.

EDIT: Also such a class could take care of site/portal "scope" (maybe it could even be a complete solution for multisite)

@benglass
Copy link
Member

@dantleech good point, I think you are right about the menu nodes as well since there is really no reason they should need to move those. The 'roles' concept really applies to URL-accessible documents.

@dantleech
Copy link
Member Author

I started hacking on an idea: https://github.com/dantleech/CmfContext

@dbu
Copy link
Member

dbu commented Nov 3, 2014

Interesting discussion you have going here! I lean towards the role solution. Some thoughts:

  • Multisite can be handled by a loader knowing about the site context base path in the repository. It would first search under the site specific path and only if there is nothing look in a common / base subtree. If needed, this concept of site specific and falling back to base could be more than one layer deep (but at a performance penalty)
  • The privacy policy use case i see could be the editors create a new page for the privacy policy which they want to develop inside the admin (workflows, preview) and at some point switch the two pages. (Hm, this means we would need a tool to move a role from one page to another)
  • I would provide a config option to decide whether a missing role should be an exception or not. maybe logging a critical error is better than showing an error page. (i guess i would prefer that if my privacy policy got lost for example)

@dbu
Copy link
Member

dbu commented Nov 3, 2014

oh, but for the "base paths" that we use, structural nodes would be a good thing to have. like the routing will so stop to work if you move /cms/routing to somewhere else. roles are not a fix there, as we don't want to look up routing root nodes on each request. and it just makes no sense to be able to move those paths around.

@dantleech
Copy link
Member Author

The solution I am thinking about now is to provide two things:

  1. Context document
  2. a (resource/path) resolver

The idea is the Context document provides things like base paths and role assignations. The role of the Context would typically be taken by a document representing a website in the content tree (and so the sites resources would be relative to it).

The resolver will take a path and contextualize it (here either translating a role into a resource path / UUID and/or prefixing the path with the desired base path). The resolver would be chainable / cascadable allowing you to have fallbacks. e.g. Site B > Site A > Filesystem.

This would (to an extent if not totally) solve the multi-site problem also.

Still a vague idea, I am trying to make a prototype to see how it would work.

@dantleech
Copy link
Member Author

there are some interesting developments going on in puli which may be of interest here: https://github.com/webmozart/puli/issues/2#issuecomment-61503303 could be a really nice solution

@dantleech
Copy link
Member Author

Have created a WIP ResourceBundle: symfony-cmf/resource-bundle#1

@dantleech
Copy link
Member Author

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants