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

[4.4] Fix multiple rendering calls on custom field #37472

Open
wants to merge 148 commits into
base: 4.4-dev
Choose a base branch
from

Conversation

korenevskiy
Copy link
Contributor

@korenevskiy korenevskiy commented Apr 3, 2022

When opening a user's page with an article and any custom field. This same field is rendered 2 times. I repeat. One field in the article is rendered 2 times. This issue has been studied. When the field is rendered 2 times, only 1 result is shown on the site, and 2 render result is meaningless. At the same time, All subscriptions of render events called by the dispatcher are also executed 2 times. Thus, it is not possible to write a user data handler without using crutches and props to avoid double processing of the field object.
For example, if you develop a new field with processing data from forms received from the user. Then such data processing needs to be subscribed to the plugin method

PlgFieldsNewForm->onCustomFieldsPrepareField($context, $item, $field)

But this method will be called 2 times.
My correction allows you to make 1 render for one field call. While maintaining backward compatibility.

This correction does not matter for static data output. But this amendment is of great importance for the output of dynamic data in user fields of articles. This can be useful when creating a complex graph field with a lot of data in one field. Or a feedback field. But in order for feedback to work in a complex field, it is required to render exactly as many times as it will be displayed on the site.

Rendering occurs when the method is called

FieldsHelper::getFields($context, $item);

When calling this method, dispatcher subscriptions are called

FieldsPlugin->onCustomFieldsBeforePrepareField($context, $item, &$field)
FieldsPlugin->onCustomFieldsPrepareField($context, $item, &$field)
FieldsPlugin->onCustomFieldsAfterPrepareField($context, $item, $field, &$value)

Accordingly, for one field, all these methods will be called twice.

However, this happens in the 2 places indicated below

PlgSystemFields->display($context, $item, $params, $displayType)
PlgSystemFields->onContentPrepare($context, $item)

This fix allows you to use the same render in both calls to these methods.

The text has been supplemented thanks to Richard's comments.
We need to create this plugin in the /plugins/fields/newmyfield folder with the class inherited from Joomla\Component\Fields\Administrator\Plugin\FieldsPlugin.
In this plugin we create methods onCustomFieldsPrepareField($context, $item, &$field)

use Joomla\Component\Fields\Administrator\Plugin;
use Joomla\CMS\Factory;
class PlgFieldsNewMyField extends FieldsPlugin {
	public function onCustomFieldsPrepareField($context, $item, &$field){
		if($field->type!='newmyfield')
			return parent::onCustomFieldsPrepareField($context, $item, $field);
		static $counter;
		if(is_null($counter))
			$counter = 0;
		Factory::getApplication()->enqueueMessage('Counter Rendering field:'.$field->type.'  counter:'.++$counter );	

		return parent::onCustomFieldsPrepareField($context, $item, $field);
	}
}

Thanks to this test, it is clear that the new amendment calls this method once. Without new corrections, this method was previously called 2 times for one field. You can also place a counter for the test in the rendering file.
/plugins/fields/newmyfield/tmpl/newmyfield.php - this is the layout file for the field.
inside this file we will place a similar counter with a message call.
Factory::getApplication()->enqueueMessage('Counter Rendering field:'.$field->type.' counter:'.++$counter );

in the message call, you need to specify $counter. Since if the messages are completely identical, then 1 message will be displayed instead of 2x. In order to accurately see the number of message calls, we must specify a different text in the message each time. The sequence number in the message will change the text. and the message will be displayed to the number of calls.

Should I blow up all the plugin methods in a row to test the number of calls? But if it is required, we can prescribe a similar example of code for methods.

FieldsPlugin->onCustomFieldsBeforePrepareField($context, $item, &$field) 
FieldsPlugin->onCustomFieldsAfterPrepareField($context, $item, $field, &$value)

But I think one method is enough for the test.

Also at the end I added a plugin event call once without multiple calls in to FOREACH.

Factory::getApplication()->triggerEvent('onCustomFieldsContentPrepare', [$context, $item, &$item->jcfields]);

This will also allow you to change the value of the fields from the beginning of the list after passing all the results.

@richard67
Copy link
Member

I don’t see any testing instructions in the description of this PR.

@korenevskiy
Copy link
Contributor Author

korenevskiy commented Apr 4, 2022

Hello Richard. I have completed the description

@korenevskiy
Copy link
Contributor Author

I have little experience in writing tests. But it will take me a long time and I will need to study the test classes. Perhaps I will consult here. But so far I have managed to find the error and issue a correction.

@richard67
Copy link
Member

I did not mean to write unit test or something like that. I meant to write testing instructions for human testers in the description of this PR. There were the headings for these tests in the description template which you get when you create a new PR, but you have removed them. Do you think we had them there for nothing?

@korenevskiy
Copy link
Contributor Author

korenevskiy commented Apr 4, 2022

Do you think we had them there for nothing?

You are right, I am aware of the seriousness of these names. I am aware of the importance of the project for many participants. I was tired, and since I don't know the language well, I'm writing a description through a translator. I was wrong, I will definitely improve in the future.
I have completed the description

@richard67 richard67 added the Updates Requested Indicates that this pull request needs an update from the author and should not be tested. label Apr 4, 2022
@Quy Quy removed the Updates Requested Indicates that this pull request needs an update from the author and should not be tested. label Apr 5, 2022
@richard67 richard67 added the PBF Pizza, Bugs and Fun label Apr 22, 2022
@korenevskiy
Copy link
Contributor Author

korenevskiy commented Apr 25, 2022

And what does the PBF hash tag mean?

@richard67
Copy link
Member

And what does the PBF hash tag mean?

Pizza, Bugs and Fun. At Joomls day USA there was such an event, and we flagged a bunch of PRs with that label so people test them. The label will be removed in a few days.

@joomla-cms-bot joomla-cms-bot removed the Language Change This is for Translators label Mar 9, 2023
@korenevskiy
Copy link
Contributor Author

@laoneo Please check.

@korenevskiy korenevskiy requested review from laoneo and removed request for chmst March 10, 2023 11:36
@Hackwar Hackwar added bug and removed PR-4.2-dev labels Apr 6, 2023
@obuisard obuisard changed the title Fix quantity times rendering for call one custom field Fix multiple rendering calls on custom field Jun 2, 2023
@korenevskiy
Copy link
Contributor Author

@HLeithner Is it possible to transfer this PR to Joomla 5 ?

@HLeithner HLeithner changed the base branch from 4.3-dev to 4.4-dev September 30, 2023 22:45
@HLeithner
Copy link
Member

This pull request has been automatically rebased to 4.4-dev.

@korenevskiy
Copy link
Contributor Author

Transfer this PR to Joomla 5

@Septdir
Copy link
Contributor

Septdir commented Jan 4, 2024

It is not correct to do this in the dislpay plugin method.
In fact, an object without jcfields can get there;
Either incorrect for a given context or parameters. For example, they were changed before the trigger was called.

@korenevskiy korenevskiy changed the title Fix multiple rendering calls on custom field [Draft] Fix multiple rendering calls on custom field Jan 5, 2024
@HLeithner HLeithner changed the title [Draft] Fix multiple rendering calls on custom field [4.4] Fix multiple rendering calls on custom field Apr 24, 2024
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.

9 participants