joomla-cms icon indicating copy to clipboard operation
joomla-cms copied to clipboard

Fix quantity times rendering for call one custom field

Open korenevskiy opened this issue 3 years ago • 12 comments

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.

korenevskiy avatar Apr 03 '22 20:04 korenevskiy

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

richard67 avatar Apr 03 '22 21:04 richard67

Hello Richard. I have completed the description

korenevskiy avatar Apr 04 '22 00:04 korenevskiy

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.

korenevskiy avatar Apr 04 '22 00:04 korenevskiy

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?

richard67 avatar Apr 04 '22 06:04 richard67

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

korenevskiy avatar Apr 04 '22 06:04 korenevskiy

And what does the PBF hash tag mean?

korenevskiy avatar Apr 25 '22 00:04 korenevskiy

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.

richard67 avatar Apr 25 '22 06:04 richard67

And how do I create another PR on the FieldsHelper.php file? But the new PR is not related to the topic of this PR. But since the current PR will change the code of this FieldsHelper.php file and make a shift in the number of lines. That new PR may conflict with the current PR, due to the fact that the amendments affect the same code.

korenevskiy avatar May 08 '22 13:05 korenevskiy

@korenevskiy Normally you create a new branch for each PR, based on the target branch of the upstream repository (= this here)

richard67 avatar May 08 '22 13:05 richard67

P.S. In case of this PR you have done it right and have created a separate branch. For the new PR just make another branch based on your 4.1-dev branch and not of the one from this PR here.

richard67 avatar May 08 '22 13:05 richard67

This pull requests has automatically rebased to 4.2-dev.

HLeithner avatar Jun 27 '22 13:06 HLeithner

This pull requests has been automatically converted to the PSR-12 coding standard.

joomla-bot avatar Jun 27 '22 21:06 joomla-bot

@laoneo Please check.

korenevskiy avatar Mar 09 '23 02:03 korenevskiy

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

korenevskiy avatar Jul 13 '23 08:07 korenevskiy

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

HLeithner avatar Sep 30 '23 22:09 HLeithner

Transfer this PR to Joomla 5

korenevskiy avatar Dec 03 '23 13:12 korenevskiy

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.

Septdir avatar Jan 04 '24 16:01 Septdir