📜 ⬆️ ⬇️

MODX Revolution - a pair of crutches for unusual situations

MODX is certainly a cool CMF, but sometimes you get on with the little things that strain. I will not cry in this topic how bad everything is, and I'm so good. Take, for example, the Revolution branch and dissect it. And so that you don't lose interest in this article, here is a small outline of the article:
  1. Backend parsing
  2. Deeper into the settings
  3. Work with nested chunks
  4. Observe the work of the parser
  5. Powerful cache



Removing a parameter from a parameter set


Create a set of parameters. We add X parameters to it, and then we understand that we parted ways. We are trying to find the delete button ...

In general, I did not work out. I had to look for another way to remove the parameter.
Solving the problem : open an unnecessary parameter for editing and completely copy all the data of another necessary parameter (ostensibly trying to overwrite the old parameter with new data).
Corollary: We can overwrite the value of the desired parameter.

Key Values ​​in Context Settings


Let us model this situation: several contexts, each context has its own settings attached.
If there are several sites in the admin area, then as a rule in the context settings such key as site_name overrides. Now imagine, your company has always positioned its name as Steep {Peppers} .

What do you think, what result will we see in the front-end? Right, just Cool.
Solution of the problem : instead of brackets use special characters.
And what should those who have 1 template use in several contexts and want to specify a certain set of parameters for the JS code as a key? There, special characters will not help, and one chunk is indispensable.
There are already two solutions
  • The first solution : create your snippet and, depending on the context, give the desired chunk via getChunk.
  • The second solution : For each context, create your own chunk and in the template instead of the key, register [[$ name _ [[* context_key]]]]. But as if there was nothing, this record looks out of the blue ... Thank you artdevue for this solution .


Work with nested chunks


In MODX, for a long time there is such a function as
getChunk
(parseChunk, for example, depends on it).
public function getChunk($chunkName, array $properties= array ()) { $output= ''; if (array_key_exists($chunkName, $this->sourceCache['modChunk'])) { $chunk = $this->newObject('modChunk'); $chunk->fromArray($this->sourceCache['modChunk'][$chunkName]['fields'], '', true, true); $chunk->setPolicies($this->sourceCache['modChunk'][$chunkName]['policies']); } else { $chunk= $this->getObject('modChunk', array ('name' => $chunkName), true); if (!empty($chunk) || $chunk === '0') { $this->sourceCache['modChunk'][$chunkName]= array ( 'fields' => $chunk->toArray(), 'policies' => $chunk->getPolicies() ); } } if (!empty($chunk) || $chunk === '0') { $chunk->setCacheable(false); $output= $chunk->process($properties); } return $output; } 


And now let's create a simple
snippet
 <?php ini_set("display_errors",1); $data=''; $phs=isset($phs)?explode(",",$phs):array(); if(isset($tpl,$phs) && $tpl!='' && count($phs)>0){ foreach($phs as $item){ $data.=$modx->parseChunk($tpl,array('item'=>$item,'time'=>time())); } } return $data; 


install phpthumbof and create
chunk
 <p><b>[[+time]]</b>: [[+item]] - [[!phpthumbof? &input=`[[+item]]` &options=`&h=150&f=jpg`]]</p> 


Let's call this on the page like this: [[!test? &tpl=`test` &phs=`/assets/1.jpg,/assets/2.jpg`]] [[!test? &tpl=`test` &phs=`/assets/1.jpg,/assets/2.jpg`]]
But bad luck, the first time you call the [[+ item]] line in the phpthumbof snippet, and only for all subsequent rasparseny placeholder

Solution : Store such problem chunks in files. Those. tick static and select file

Another solution from bezumkin : Replace parseChunk with getChunk.
')

Observe the work of the parser


We will conduct the experiment as follows: create a new document with the blank template. Content and everything else is left blank. Let's check that it is worth checking a tick.
Now open the processElementTags function from the /core/mode/modx/modparser.class.php file
 public function processElementTags($parentTag, & $content, $processUncacheable= false, $removeUnprocessed= false, $prefix= "[[", $suffix= "]]", $tokens= array (), $depth= 0) { $this->_processingTag = true; $this->_processingUncacheable = (boolean) $processUncacheable; $this->_removingUnprocessed = (boolean) $removeUnprocessed; $depth = $depth > 0 ? $depth - 1 : 0; $processed= 0; $tags= array (); /* invoke OnParseDocument event */ $this->modx->documentOutput = $content; $this->modx->invokeEvent('OnParseDocument', array('content' => &$content)); $content = $this->modx->documentOutput; unset($this->modx->documentOutput); if ($collected= $this->collectElementTags($content, $tags, $prefix, $suffix, $tokens)) { $tagMap= array (); foreach ($tags as $tag) { $token= substr($tag[1], 0, 1); if (!$processUncacheable && $token === '!') { if ($removeUnprocessed) { $tagMap[$tag[0]]= ''; } } elseif (!empty ($tokens) && !in_array($token, $tokens)) { $collected--; continue; } if ($tag[0] === $parentTag) { $tagMap[$tag[0]]= ''; $processed++; continue; } $tagOutput= $this->processTag($tag, $processUncacheable); if (($tagOutput === null || $tagOutput === false) && $removeUnprocessed) { $tagMap[$tag[0]]= ''; $processed++; } elseif ($tagOutput !== null && $tagOutput !== false) { $tagMap[$tag[0]]= $tagOutput; if ($tag[0] !== $tagOutput) $processed++; } } $this->mergeTagOutput($tagMap, $content); if ($depth > 0) { $processed+= $this->processElementTags($parentTag, $content, $processUncacheable, $removeUnprocessed, $prefix, $suffix, $tokens, $depth); } } $this->_processingTag = false; return $processed; } 


before the line
 $this->_processingTag = true; 
add
 static $test; echo ++$test."<br />"; 

Well, open our page in the browser. o0! The number 1..2..3 What kind of mother is your question ... A blank page. What is there to parse? We look carefully the source
 $this->modx->invokeEvent('OnParseDocument', array('content' => &$content)); 

Thus, even on a blank page, we trigger the same event 3 times. I'm scared to think what will happen to those sites that have some code hanging on this event.
artdevue for the experiment checked how many times this function will be performed under different conditions. so we have the following table.
ConditionIterations
[[snippet]]2
{{$ chunk}}2
Empty page3
[[num? input = `1000`]]five
[[* pagetitle: num]]6
[[num? input = `[[* pagetitle]]`]]7
Non-existent snippet23
Nonexistent chunk23


Powerful cache


On one of the work sites I opened the cache folder and almost fell off the chair. 1 page in the cache takes from 50 to 200 KB. No, this may of course be normal, but the cache is updated with each change of documents. Updated 1 document - all cached pages were deleted. And if 100 pages? 1000? This is a few MB pulls. And if the news is added every day?

PS Renamed the topic to look less whiny and defiant

Source: https://habr.com/ru/post/153261/


All Articles