public mixed
get
(mixed $callback, mixed $args = array(), mixed $id = false, mixed $wrkarounds = false, mixed $woptions = array())
/**
* Executes a cacheable callback if not found in cache else returns cached output and result
*
* @param callable $callback Callback or string shorthand for a callback
* @param array $args Callback arguments
* @param mixed $id Cache ID
* @param boolean $wrkarounds True to use workarounds
* @param array $woptions Workaround options
*
* @return mixed Result of the callback
*
* @since 1.7.0
*/
public function get($callback, $args = array(), $id = false, $wrkarounds = false, $woptions = array())
{
if (!\is_array($args)) {
$referenceArgs = !empty($args) ? array(&$args) : array();
} else {
$referenceArgs =& $args;
}
// Just execute the callback if caching is disabled.
if (empty($this->options['caching'])) {
return \call_user_func_array($callback, $referenceArgs);
}
if (!$id) {
// Generate an ID
$id = $this->_makeId($callback, $args);
}
$data = $this->cache->get($id);
$locktest = (object) array('locked' => null, 'locklooped' => null);
if ($data === false) {
$locktest = $this->cache->lock($id);
// If locklooped is true try to get the cached data again; it could exist now.
if ($locktest->locked === true && $locktest->locklooped === true) {
$data = $this->cache->get($id);
}
}
if ($data !== false) {
if ($locktest->locked === true) {
$this->cache->unlock($id);
}
$data = unserialize(trim($data));
if ($wrkarounds) {
echo Cache::getWorkarounds($data['output'], array('mergehead' => $woptions['mergehead'] ?? 0));
} else {
echo $data['output'];
}
return $data['result'];
}
if ($locktest->locked === false && $locktest->locklooped === true) {
// We can not store data because another process is in the middle of saving
return \call_user_func_array($callback, $referenceArgs);
}
$coptions = array('modulemode' => 0);
if (isset($woptions['modulemode']) && $woptions['modulemode'] == 1) {
/** @var HtmlDocument $document */
$document = Factory::getDocument();
if (method_exists($document, 'getHeadData')) {
$coptions['headerbefore'] = $document->getHeadData();
// Reset document head before rendering module. Module will cache only assets added by itself.
$document->resetHeadData();
$document->getWebAssetManager()->reset();
$coptions['modulemode'] = 1;
}
}
$coptions['nopathway'] = $woptions['nopathway'] ?? 1;
$coptions['nohead'] = $woptions['nohead'] ?? 1;
$coptions['nomodules'] = $woptions['nomodules'] ?? 1;
ob_start();
ob_implicit_flush(false);
$result = \call_user_func_array($callback, $referenceArgs);
$output = ob_get_clean();
$data = array('result' => $result);
if ($wrkarounds) {
$data['output'] = Cache::setWorkarounds($output, $coptions);
} else {
$data['output'] = $output;
}
// Restore document head data and merge module head data.
if ($coptions['modulemode'] == 1) {
$moduleHeadData = $document->getHeadData();
$document->resetHeadData();
$document->mergeHeadData($coptions['headerbefore']);
$document->mergeHeadData($moduleHeadData);
}
// Store the cache data
$this->cache->store(serialize($data), $id);
if ($locktest->locked === true) {
$this->cache->unlock($id);
}
echo $output;
return $result;
}