webdevops / TYPO3-metaseo

TYPO3 MetaSEO Extension
https://typo3.org/extensions/repository/view/metaseo
GNU General Public License v3.0
38 stars 25 forks source link

Manipulate MetaTags in your own extension #217

Open sebastianmay opened 8 years ago

sebastianmay commented 8 years ago

Thanks to @mblaschke I learned about the possibility to use the Connector to manipulate the MetaTags in your own Extension. This is especially useful for the detail pages of the plugin. I tried it and it worked fine, but I got the idea of creating ViewHelpers to achieve the manipulation. Do you think it is better to the manipulation in the Controller instead or would it be a nice feature to have some ViewHelpers that you can place within your show template, where you ca define the meta tags? It's working fine so far, if anybody is interested, I can provide them.

thomaszbz commented 8 years ago

Would be great if you could provide some sample code. Maybe it could be helpful for other users. Plus would we see how you used the connector in ViewHelpers.

My question would be: Do you want to inject the Connector into a ViewHelper?

In terms of MVC I guess that ViewHelpers are designed to render output for the view. One could argue that meta tags are also output. But I think that a ViewHelper should only fulfil the task it is designed for and nothing else. Meaning, it should only produce some distinct peace of output. To me, letting a ViewHelper do something additional like setting meta tags looks like a tainted usage of MVC. Even if it works.

That said, in terms of using the MVC design pattern, I think the controller should get the connector injected and work with it directly or delegate to some other service.

There's some other side effects like having to check if metaseo's connector is available for the ViewHelper. I think dealing with dependencies is not a task a ViewHelper should do.

Another side effect is that using the connector in a ViewHelper would not only produce output via its return value but also aside of that via the connector. In a way, that might seem unexpected.

This issue could be looked at differently, if the task of a ViewHelper is to only produce output via the connector. Indeed, that could be useful when dealing with views. Still, I think the ViewHelper is not used as usual, because the return value of the ViewHelper needs to be empty in that case.

Plus, is the HTML meta tags section not generated by views in TYPO3 normally. One could discuss if using ViewHelpers for that is bad practise or innovative. I'm undecided on that. It also depends on the use case you are faced with.

One use case could be that we'd have to open up the creation of meta tags to users which can only manipulate the View, but cannot manipulate PHP code. This could be the case especially for a CMS.

sebastianmay commented 8 years ago

Yes, you are right. ViewHelpers should produce output. I came up with this idea, since I saw such functionality within the vhs extension. If the ViewHelpers are implemented in the metaseo extension then there would be no need for checking if the Connector is available.

My ViewHelpers are in my own extension at the moment, but thats what it could like implemented in the metaseo Extension. metaseo-viewhelper-MetaTagViewHelper.txt

namespace Metaseo\Metaseo\ViewHelpers;

/**
 * MetaTagViewHelper
 */
class MetaTagViewHelper extends \TYPO3\CMS\Fluid\Core\ViewHelper\AbstractViewHelper {

    /**
     * Meta Seo Connector
     *
     * @var \Metaseo\Metaseo\Connector
     * @inject
     */
    protected $connector;

    /**
     * Initialize arguments.
     *
     * @return void
     */
    public function initializeArguments() {
        $this->registerArgument('key', 'string', 'Key', TRUE);
        $this->registerArgument('value', 'string', 'Value (required if not disableMetaTag)', FALSE, '');
        $this->registerArgument('openGraph', 'boolean', 'Call OpenGraph Function', FALSE, FALSE);
        $this->registerArgument('customMetaTag', 'boolean', 'Calls CustomMetaTag Function', FALSE, FALSE);
        $this->registerArgument('disableMetaTag', 'boolean', 'Disables a MetaTag with the given key', FALSE, FALSE);
    }

    /**
     * Render ViewHelper
     *
     * @return void
     */
    public function render() {
        $key = (string)$this->arguments['key'];
        $value = (string)$this->arguments['value'];
        if (!empty($key)) {
            if ((bool)$this->arguments['disableMetaTag']) {
                $this->connector->disableMetaTag($key);
            }
            else if (!empty($value)) {
                if ((bool)$this->arguments['openGraph']) {
                    $this->connector->setOpenGraphTag($key, $value);
                }
                else if ((bool)$this->arguments['customMetaTag']) {
                    $this->connector->setCustomMetaTag($key, $value);
                }
                else {
                    $this->connector->setMetaTag($key, $value);
                }
            }
        }
    }
}
thomaszbz commented 8 years ago

@sebastianmay We should have a strong real world use case for this. Ideally, we'd come to the conclusion that this use case cannot or should not be done in the controller. Can you please describe the use case you have in mind? Which would be the advantages of using a ViewHelper (personally, I got the idea)?

I'd also like to hear some other opinion on this. @mblaschke Do you have comments on this?

mblaschke commented 8 years ago

I've already thought about it for frontend devs who want to set metatags. I think there is demand for such features but we need some metatag caching (plugin/view will only run once when chanced).

sebastianmay commented 8 years ago

Do mean ViewHelper or Controller? I can see both possibilities: You have your own extension, there it is possible to do this in the Controller. But if you use this extension in another typo3 where metaseo is not available you have to check if the Connector is there. The other use case is, you want to use an existing extension from TER, where you only edit the template, but want to make sure, you can use metaseo. Then you can update the metatags through the templates.

I haven't thought about the caching problem yet, but isn't the same problem occuring, when using it in the controller?

At the moment, the metatags remain in the code, even in another browser which is getting the cached site.

thomaszbz commented 8 years ago

@sebastianmay Thanks for the feedback. Indeed, there's a real world use case for the new feature.

@mblaschke

Related: #214

We'd also have to make sure that property names for key and value are according to standards in $metaTagPart->advMetaTags() (no issue opened for that yet, this is partly handled via #214 for og meta tags coming from the connector, see d006238).

Would also be nice to have some general approach to set priorities for meta tags from different sources (for override). (no issue opened for that yet). This approach should avoid if-cascades which we currently perform for fallback after fallback. Or via array-key overrides, which means that currently we have two concepts for one thing.

thomaszbz commented 8 years ago

I'm also thinking about surrounding tags which actually are rendered to the HTML body: E.g. tags for structured data. This would be a normal use case for a ViewHelper.

But doing this with ViewHelpers is very limited because we can apply the ViewHelper only for a variable and not for some segment of a paragraph from RTE. Otherwise we'd have to perform some massive string extraction and we'd also have to know what to search for. E.g. schema.org's

<span itemprop="telephone">+49-721-12340000</span>

There's also the question if that makes sense as long as this sort of tags can be hardcoded in the template. And if we can provide a set of tags which is somehow "complete".

thomaszbz commented 8 years ago

@sebastianmay It would be great if you could share your experiences with caching issues introduced by using the connector in the ViewHelpers. Maybe @mblaschke can provide some special test cases where caching issues could occur.

As you instanciate the new classes in the ViewHelper or (better) instanciate and then inject them to the ViewHelper, it should not make a difference if the class is in the namespace of your extension or in metaseo's namespace, at least in terms of caching issues (for testing).

If you run into trouble with the connector, please have a look at #214: There has recently been some work in progress with the connector.

I think we have some homework left in metaseo until we can integrate this new feature, but now that we are aware of it we can prepare things in a way that allows a later (and better) integration. Implied, we have to improve some issues with the connector now that people have figured out how to use it for expected and unexpected purposes ;-)

We'll keep track of this issue and if you can provide more code we'll always be interested in further contributions (besides code this could also be a concept or some documentation).