Skip to content
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

[com_content] Use condition show_tags in the view instead of in the model #10519

Closed
wants to merge 11 commits into from

Conversation

csthomas
Copy link
Contributor

@csthomas csthomas commented May 16, 2016

Summary of Changes

Tags usually slow down content pages, so I changed code to not load tags when it has not been required.

Reasons:

  • When show_tags is enabled in menu/global then modules which use "model articles" load unnecessary tags but did not use it. The PR removes unnecessary sql queries.
  • Article view should not load tags if admin do not want to show tags.
  • After applied patch there is option to show tags only for article view and hide for featured/categories. This is for those who love performance.

Testing Instructions

Change options for "Show tags" in menu items related to com_content.

  1. Test menu item for featured view (test all options for "Show tags") and look at results.
  2. Do the same for menu item of category view.
  3. Check result on article views for above menu items.

@csthomas csthomas changed the title Use condition show_tags in the view instead of in the model [com_content] Use condition show_tags in the view instead of in the model May 17, 2016
@andrepereiradasilva
Copy link
Contributor

will this be B/C?

@csthomas
Copy link
Contributor Author

Currently model ContentModelArticle loads tags in view
but ContentModelArticles loads tags in model so there is some inconsistency that should be fixed.

For component content my patch is back compatibility.
I have that changes on production and it works.

For modules that use model ContentModelArticles in general yes.

In short:
In module template will be missing "item->tags" variable
when menu item will have show_tags or show_cat_tags enabled.
I suspect that nobody use that tags when it depends of menu parameters.

Joomla3 built-in modules that use the model are B/C.

When that patch won't be B/C:

If someone created custom template for ex. mod_articles_latest (default.php) and start using tags which depends on menu parameters show_tags then there will be a problem.

@andrepereiradasilva
Copy link
Contributor

If someone created custom template for ex. mod_articles_latest (default.php) and start using tags which depends on menu parameters show_tags then there will be a problem.

Gets a Fatal error right?

@csthomas
Copy link
Contributor Author

No, it should get warning or notice that variable in undefined.

@csthomas
Copy link
Contributor Author

@andrepereiradasilva
If you have some example of code I can take a look

@andrepereiradasilva
Copy link
Contributor

i don't have an example, i'm just guessing.

i don't know if this ok from a B/C point (it's not my call) but anyhow it would be better if you could prevent that php warning or notice and send a deprecated notice to the deprecated log.

@csthomas
Copy link
Contributor Author

csthomas commented May 19, 2016

Code from blog_item.php

<?php if ($params->get('show_tags') && !empty($this->item->tags->itemTags)) : ?>

describes that there is no problems with error because function empty check that.

For other unexpected codes I can add empty list of tags for B/C in model/articles.php

// Do not load tags but create empty list for B/C
if ($item->params->get('show_tags', '1') == '1')
{
    $item->tags = new JHelperTags;
    $item->tags->itemTags = [];
}

But I found other bug in my patch

show_cat_tags is not related to article tags but to category (itself) tags.

@joomla-cms-bot joomla-cms-bot added the Language Change This is for Translators label May 19, 2016
@csthomas
Copy link
Contributor Author

csthomas commented May 19, 2016

I have fixed my mentioned bug in the patch.
For do that I have to add a new option to show tags for featured and blog view:
Show only for article view

I also removed default value "1" to be more similar to code from model/articles.php.

About B/C.
Previous similar patch (not mine)
#9038
did not require any deprecated information so I do not think that now it is required. But I may think wrong.

@andrepereiradasilva
Copy link
Contributor

as said i'm not the one deciding, was just an idea.

@csthomas
Copy link
Contributor Author

csthomas commented May 19, 2016

Ok. Thanks for discussion.
If someone can add more advice I listen.

I will be thankful for testing.

@Bakual
Copy link
Contributor

Bakual commented May 19, 2016

You shouldn't need the special case for article view. You can already override the menu settings in the article settings. Which means if the article says to show tags, the tags will be shown even if the category menu item says to hide them. Article settings take precedence over menu settings which take precedence over global settings. There is an exception to that rule, but that doesn't matter in this case 😄

So please remove that added option, it only complicates code and doesn't solve anything.

@smz
Copy link
Contributor

smz commented May 19, 2016

Article settings take precedence over menu settings which take precedence over global settings. There is an exception to that rule, but that doesn't matter in this case 😄

Is this a joke, Thomas? The "exception" seems to be the rule here... #9801 (comment)

@Bakual
Copy link
Contributor

Bakual commented May 19, 2016

Is this a joke, Thomas? The "exception" seems to be the rule here

There is only one exception to that rule, and it is if the menu item is specific to the view/id being shown. That is if you have a menu item pointing to article "foo", then the settings from that article "foo" are overriden by the menu item. For the article "bar", the article settings take precedence over the menu item "foo" as usual.
Same for categories. If the menu item is pointing to the category "blubb", then the category options for category "blubb" are overriden by the menu item. But not the options for category "blabla" and not for the articles "foo" and "bar".

Once you figured that out, it's simple and actually makes sense 😄

@smz
Copy link
Contributor

smz commented May 19, 2016

Sorry, I don't want to hijack this PR and if you wish we can continue the discussion in #9801, but when you state that

if you have a menu item pointing to article "foo", then the settings from that article "foo" are overriden by the menu item.

That means that menu item options have the precedence over article options, not the other way 'round as you initially stated.

@Bakual
Copy link
Contributor

Bakual commented May 19, 2016

That means that menu item options have the precedence over article options, not the other way 'round as you initially stated.

Yes, in that specific case (menu item is specific to article "foo" and "foo" is displayed) the menu item takes precedence. It's the one exception to the rule. That's what I explained.

@smz
Copy link
Contributor

smz commented May 19, 2016

so when the "rule" ("Article settings take precedence over menu settings") does apply?

@Bakual
Copy link
Contributor

Bakual commented May 19, 2016

All other cases as explained.
Of course, if your site is built with menu items for each article, then the menu items always override the article settings as you always have that exception. But that depends on your site structure.

@smz
Copy link
Contributor

smz commented May 19, 2016

Got it: "Article settings take precedence over menu settings" apply when there is no corresponding menu item... 😜

@csthomas
Copy link
Contributor Author

csthomas commented May 19, 2016

Ok
you say about 164 line from model/article.php

                // Convert parameter fields to objects.
                $registry = new Registry;
                $registry->loadString($data->attribs);

                $data->params = clone $this->getState('params');
                $data->params->merge($registry);

But then I have to change show_tags to show for every articles (thousands).

Or I can use weird configuration like:

  1. set up menu item for featured and category view to show_tags=use_article (in article view this will be treats as true)
  2. set up component global parameters show_tags=0
  3. every article set show_tags use global - empty string (this is the default value)

Results:

  1. Then for menu item for category view, show tags will have value "use_article" which is replaced by global
    show_tags=0 (because article does not have value) => OK hide tags for category/featured view
  2. For article view joomla get value from menu item show_tags=use_article because article parameter show_tags is not set. => OK show tags for article view

Everything above seems to work so I can agree and remove added option "Show only for article view"

@csthomas
Copy link
Contributor Author

My above comment was to first comment @Bakual

@Bakual
Copy link
Contributor

Bakual commented May 19, 2016

Two things that I noticed from review:

  • You use params->get('show_tags') to fetch the value, however in most places we use params->get('show_tags', 1) (by default enabled). This seems to be an inconsistency in current code but needs to be addressed to avoid unexpected errors.
  • You use if ($item->params->get('show_tags') == '1') however that isn't the same as the current check if ($item->params->get('show_tags')), it would fail with the use_article value (which is a stupid value, but that's another topic). Is there a reason you explicitely check for 1 and not just do a boolean check like we do in the other places and did before?

@Bakual
Copy link
Contributor

Bakual commented May 19, 2016

But then I have to change show_tags to show for every articles (thousands).

Yes, as tedious as it may be. Or you could work with template overrides to achieve what you need.
Adding a specific check for a single parameter into core just to please your specific needs is sure the wrong approach.

@csthomas
Copy link
Contributor Author

Current version remove mentioned inconsistency. I had mess with that params now should be ok.

@csthomas
Copy link
Contributor Author

Is there any issue for current version?

@mbabker
Copy link
Contributor

mbabker commented May 23, 2016

Is there any issue for current version?

There's a possible B/C concern in that the article model will now not return tag data at all in com_content (inconsistent with other components which don't even check the value of this parameter) and that anyone using this model would have to manually bind tags data themselves if they are working with it. Then again, considering the terrible implementation of tags in general, at this point I'm inclined to lean toward "who cares?".

@csthomas
Copy link
Contributor Author

Then I think this pull is ready for testing.

@brianteeman
Copy link
Contributor

As soon as I see statements such as

I suspect that nobody use that tags when it depends of menu parameters.

and

If someone created custom template for ex. mod_articles_latest (default.php) and start using tags which depends on menu parameters show_tags then there will be a problem.

Then my immediate thought is that we cannot accept this


This comment was created with the J!Tracker Application at issues.joomla.org/joomla-cms/10519.

@ggppdk
Copy link
Contributor

ggppdk commented Jul 26, 2016

If we add a new method to populate then it break B/C.

why it will break B/C ?
the purpose of it would be not to break B/C while at the same time avoid tags being always populated

@csthomas
Copy link
Contributor Author

csthomas commented Jul 26, 2016

If I understand you well then you want to do something like:

$item->tags->getItemTags('com_content.article', $item->id); // populate state without loading tags
// then
print_r($item->tags->itemTags); // magic load tags

but there is place where getItemTags method return value directly.
https://github.com/joomla/joomla-cms/blob/staging/templates/beez3/html/com_weblinks/category/default_items.php#L133

@ggppdk
Copy link
Contributor

ggppdk commented Jul 26, 2016

Case 1, using:
getItemTags() load the tags explicitely, no change here

Case 2, some template code assumes, that tags have been loaded, then accessing:
$item->tags->itemTags

would call the magic method and load the tags ??

@csthomas
Copy link
Contributor Author

Something blinded me.
Now I understand, thanks.

@csthomas
Copy link
Contributor Author

Example of magic way:)

Where should we use method setItem? In model or view?

@ggppdk
Copy link
Contributor

ggppdk commented Jul 27, 2016

Where should we use method setItem? In model or view?

Since $item->tags->getItemTags() is currently called in both,

  • and since the purpose is to replace it with a call to "seItem()" when configuration says not to use tags

I think you can use it at the same places , and don't try to remove it completely from the view ?

Also since the purpose of the "setItem()" is to set an identifier:

  • typeAlias
  • itemId

for later retrieval of the tags via magic function __get()

is it a better name instead of setItem(): ?
setItemIdentifier()

@csthomas
Copy link
Contributor Author

  • I will change method name setItem to setItemIdentifier
  • tags.php $itemId is OK? or should I use contentItemId?
  • I will back to 'if ($item->params->get('show_tags', 1))' in views which will contain only setItemIdentifier
  • If you don't like any code comments or names in PR please correct me.

@ggppdk
Copy link
Contributor

ggppdk commented Jul 27, 2016

tags.php $itemId is OK? or should I use contentItemId?

since in Joomla code "item" means "record" , i think "$itemId" is good enough ?

  • and it is different from "$Itemid" that reminds of the menu item, right ?

Now about

return (array) $this->itemTags;

since in all PHP versions array typecast of null, is array(),
and since the layout code / overrides , etc that will try to use tags without considering configuration will always expect an array there ?
i think it is good to do it like that

@mbabker
Copy link
Contributor

mbabker commented Jul 27, 2016

If you're introducing a magic getter then for all intents and purposes you're treating a variable as public. So either use a proper get method or declare the variables public.

Honestly this whole pull request is starting to get a little awkward. What started as looking for a way to stop tags from always being loaded even in contexts where the data was unnecessary is turning into awkward API changes plugged into an already crappy API with tags in general.

What I suggested yesterday with the model state addresses the original concern with what was trying to be accomplished here without the awkward API changes. These are the types of things model state should be used for if not introducing explicit API methods to set behaviors from the outside. To me that was the simplest solution to this issue.

@ggppdk
Copy link
Contributor

ggppdk commented Jul 27, 2016

so you have a solution that will not break B/C and thus can be used today ? and not after 1 or 2 years ?

about magic method it will serve the purpose of not running unneeded and somewhat "performance-unwise" SQL queries
that is one of the purposes of magic __get function to improve performance doing stuff if needed ... why is it bad ?

@csthomas
Copy link
Contributor Author

  • I broke B/C again to ask you if that is important for article view only.
  • If fix totally B/C then Joomla 3.7 or J3.6.x:)
  • I added @deprecated in article view because tagLayout is re-created in template again

@mbabker
Copy link
Contributor

mbabker commented Jul 27, 2016

so you have a solution that will not break B/C and thus can be used today ? and not after 1 or 2 years ?

Yes. Use the model state as I suggested at #10519 (comment) and you could have a patch merged that is B/C AND allows to opt-out of loading the tags data today.

about magic method it will serve the purpose of not running unneeded and somewhat "performance-unwise" SQL queries
that is one of the purposes of magic __get function to improve performance doing stuff if needed ... why is it bad ?

The patch as is makes two protected properties in all essence public in terms of read access. The $itemId property which has zero manipulation around it whatsoever and $itemTags which does some checks and returns different values. These should be in getItemXXX() methods, magic getters like this aren't giving any benefit over proper API endpoints and even worse can mask errors if you don't implement a proper error handling mechanism for non-existing properties.

I don't see why the new API methods are needed in JHelperTags as they quite frankly aren't adding any real value other than some magic behavior. If you're really insistent on going the new API route, I'm going to insist on properly declared API methods versus magic behaviors.

As is, this patch is NOT backward compatible. The only way to achieve backward compatibility is for the model to continue the existing behavior of default loading the tags data. An API endpoint that in the middle of a major version series stops returning data as part of a method call has introduced a B/C break. This is somewhat confirmed by the fact that this patch requires changes in view classes as a proxy layer for the existing behavior and a need for the magic getter to ensure the data actually loads. A new toggle (i.e. a model state condition) to exclude the tags data, defaulting to the data being loaded to match the existing behavior, is an acceptable backward compatible change because it creates a new API that allows a caller to opt-out of loading the data going forward.

@ggppdk
Copy link
Contributor

ggppdk commented Jul 27, 2016

... A new toggle (i.e. a model state condition) to exclude the tags data, defaulting to the data being loaded to match the existing behavior, is an acceptable backward compatible change because it creates a new API that allows a caller to opt-out of loading the data going forward.

yes , yes

but what about existing sites with template overrides that assume that tags have been loaded, and try to use them without checking configuration ?

@ggppdk
Copy link
Contributor

ggppdk commented Jul 27, 2016

I mean the "model state condition" will have to be left to ON , to retieve tags always regardless of configuration so that the thing remains B/C in all cases

@mbabker
Copy link
Contributor

mbabker commented Jul 27, 2016

In a module or another extension where you use this model you set the state
value before calling the getItem method. Other modules are already doing
this with other conditions.

So the state value defaults to true but through an explicit change you can
turn it to false without any other implications beyond that data not being
there anymore, which you know because you turned it off.

On Wednesday, July 27, 2016, Georgios Papadakis notifications@github.com
wrote:

I mean the "model state condition" will have to be left to ON , to retieve
tags always regardless of configuration so that the thing remains B/C in
all cases


You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
#10519 (comment),
or mute the thread
https://github.com/notifications/unsubscribe-auth/AAWfoQlpk0hV8sdfsk8-elc77Ec_ED2tks5qZ2EAgaJpZM4Ifr56
.

@mbabker
Copy link
Contributor

mbabker commented Jul 27, 2016

The other thing is I don't remember if JObject (which is what the model
state is represented by right now) has a def method similar to the Registry
class. If it does then the model has a simple one line check, $getTags =
$this->getState()->def('load_tags', $item->params->get('tags_condition',
true));

If it doesn't it takes a couple more lines of code (check if value is
defined in state and if not use item param value basically). Either way
it's not all that complex. Similar changes could/should be made to all
models for consistency then.

On Wednesday, July 27, 2016, Georgios Papadakis notifications@github.com
wrote:

... A new toggle (i.e. a model state condition) to exclude the tags data,
defaulting to the data being loaded to match the existing behavior, is an
acceptable backward compatible change because it creates a new API that
allows a caller to opt-out of loading the data going forward.

yes , yes

but what about existing sites with template overrides that assume that
tags have been loaded, and try to use them without checking configuration ?


You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
#10519 (comment),
or mute the thread
https://github.com/notifications/unsubscribe-auth/AAWfoRBiWzS0rP89xxG13RfBVoQRi93qks5qZ2CGgaJpZM4Ifr56
.

{
$item->tags = new JHelperTags;
$item->tags->setItemIdentifier('com_content.article', $item->id);
}
Copy link
Contributor Author

@csthomas csthomas Jul 27, 2016

Choose a reason for hiding this comment

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

@mbabker In above If I replace only name method setItemIdentifier to getItemTags then this break B/C or not?
I do not want to create tags object in show_tags is not enabled.

Copy link
Contributor

Choose a reason for hiding this comment

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

No. Though it would not affect the com_content views, you're still making
a B/C breaking change in the model. Ultimately that is why I'm making such
a fuss; you can add all the magic behaviors you want to account for that
change elsewhere, but you're still ultimately introducing a breaking change
that has to be accounted for by any consumer of that model.

On Wednesday, July 27, 2016, Tomasz Narloch notifications@github.com
wrote:

In components/com_content/views/article/view.html.php
#10519 (comment):

@@ -152,8 +154,11 @@ public function display($tpl = null)
$item->text = $item->introtext;
}

  •   $item->tags = new JHelperTags;
    
  •   $item->tags->getItemTags('com_content.article', $this->item->id);
    
  •   if ($item->params->get('show_tags', 1))
    
  •   {
    
  •       $item->tags = new JHelperTags;
    
  •       $item->tags->setItemIdentifier('com_content.article', $item->id);
    
  •   }
    

@mbabker https://github.com/mbabker In above If I replace
setItemIdentifier to getItemTags then this break B/C or not?
I do not want to create tags object in show_tags is not enabled.


You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
https://github.com/joomla/joomla-cms/pull/10519/files/ae8a6dd5a07efd29521277ebbc0bc34277a66769#r72445013,
or mute the thread
https://github.com/notifications/unsubscribe-auth/AAWfoY8cyl6Ci-G9oyKUgCrscUMZbBSBks5qZ2XOgaJpZM4Ifr56
.

@csthomas
Copy link
Contributor Author

@mbabker about #10519 (comment)

If I go that way then can I change mod_articles_.. and add line like:
$model->setState('load_tags', false); to Joomla core modules.

Do I have to care about custom template that using tags in that modules?
I know that I can do that for my own modules, but what about core mod_articles_...? B/C?

@mbabker
Copy link
Contributor

mbabker commented Jul 27, 2016

For the core modules you'd probably need to add that as a parameter if it isn't already. I honestly don't know in what case the tags data would get used with latest or related articles but since the functionality's there now you have to assume someone's doing something crazy with it. Then again, at the same time since the modules aren't designed to display associated tags data, you could argue that it's not needed and hardcode it in too. For pure B/C you'd have to do the former; for practical purposes the latter would work. Personally I'd lean toward the latter there because modules have a lot less flexibility and re-use compared to components, but the component models do need to retain some resemblance of B/C since they have re-use potential (i.e. all the articles modules or com_contact's ability to display articles from a user).

@csthomas
Copy link
Contributor Author

Is anyone unhappy with current code?

@mbabker
Copy link
Contributor

mbabker commented Jul 27, 2016

At a glance it looks fine.

On Wednesday, July 27, 2016, Tomasz Narloch notifications@github.com
wrote:

Is anyone unhappy with current code?


You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
#10519 (comment),
or mute the thread
https://github.com/notifications/unsubscribe-auth/AAWfoW4AVgxBwjJzjfWzVOC0jF8Mh9aaks5qZ77mgaJpZM4Ifr56
.

@ghost
Copy link

ghost commented Jan 8, 2017

@csthomas is this good for testing?

@csthomas
Copy link
Contributor Author

csthomas commented Jan 8, 2017

I have to resolve conflict. Please wait.

@csthomas
Copy link
Contributor Author

I do not have more interest for that PR. I close it.

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

Successfully merging this pull request may close these issues.

9 participants