From 97f5a11fb12c07c4a69ae93903b6c4ef106c5f2e Mon Sep 17 00:00:00 2001 From: mvoevodskiy Date: Sat, 16 Mar 2019 06:47:14 +0300 Subject: [PATCH 1/5] Added direcories for static elements --- core/elements/chunks/.gitignore | 4 ++++ core/elements/snippets/.gitignore | 4 ++++ core/elements/temlplates/.gitignore | 4 ++++ 3 files changed, 12 insertions(+) create mode 100644 core/elements/chunks/.gitignore create mode 100644 core/elements/snippets/.gitignore create mode 100644 core/elements/temlplates/.gitignore diff --git a/core/elements/chunks/.gitignore b/core/elements/chunks/.gitignore new file mode 100644 index 00000000000..6c22af6ce74 --- /dev/null +++ b/core/elements/chunks/.gitignore @@ -0,0 +1,4 @@ +# ignore everything +* +# except .gitignore +!.gitignore diff --git a/core/elements/snippets/.gitignore b/core/elements/snippets/.gitignore new file mode 100644 index 00000000000..6c22af6ce74 --- /dev/null +++ b/core/elements/snippets/.gitignore @@ -0,0 +1,4 @@ +# ignore everything +* +# except .gitignore +!.gitignore diff --git a/core/elements/temlplates/.gitignore b/core/elements/temlplates/.gitignore new file mode 100644 index 00000000000..6c22af6ce74 --- /dev/null +++ b/core/elements/temlplates/.gitignore @@ -0,0 +1,4 @@ +# ignore everything +* +# except .gitignore +!.gitignore From c231c7e611ac371ff8b966accd865cb5a8a9f8ff Mon Sep 17 00:00:00 2001 From: mvoevodskiy Date: Sat, 16 Mar 2019 13:08:17 +0300 Subject: [PATCH 2/5] Added support for @INLINE, @CODE, @FILE bindings for elements Thanks @bezumkin for ideas from pdoTools::_loadElement() --- core/model/modx/modelement.class.php | 6 ++- core/model/modx/modparser.class.php | 75 +++++++++++++++++++++++++++- core/model/modx/modscript.class.php | 4 ++ 3 files changed, 82 insertions(+), 3 deletions(-) diff --git a/core/model/modx/modelement.class.php b/core/model/modx/modelement.class.php index a36a2f6d57f..3193d62ecd1 100644 --- a/core/model/modx/modelement.class.php +++ b/core/model/modx/modelement.class.php @@ -491,7 +491,11 @@ public function getSourceFile(array $options = []) } /** @var modMediaSource $source */ if ($source = $this->getSource()) { - $this->_sourceFile = !$source->getMetaData($filename) && $this->get('source') < 1 + $sourceBasePath = $source->getBasePath(); + $checkFilename = strpos($filename, $sourceBasePath) === 0 ? str_replace($sourceBasePath, '', $filename) : $filename; + $metaData = $source->getMetaData($checkFilename); + + $this->_sourceFile = empty($metaData) && $this->get('source') < 1 ? $this->getSourcePath($options) . $filename : $filename; } else { diff --git a/core/model/modx/modparser.class.php b/core/model/modx/modparser.class.php index ac6f4633867..2e6060abd51 100644 --- a/core/model/modx/modparser.class.php +++ b/core/model/modx/modparser.class.php @@ -527,7 +527,78 @@ public function processTag($tag, $processUncacheable = true) { */ public function getElement($class, $name) { $realname = $this->realname($name); - if (array_key_exists($class, $this->modx->sourceCache) && array_key_exists($realname, $this->modx->sourceCache[$class])) { + $binding = $content = $path = ''; + + if (preg_match('#^@([A-Z]+)#', $name, $matches)) { + $binding = $matches[1]; + $content = substr($name, strlen($binding) + 1); + $content = ltrim($content, ' :'); + } + + if ($class == 'modChunk' || $class == 'modTemplate') { + // Replace inline tags in chunks + $content = str_replace(array('{{', '}}'), array('[[', ']]'), $content); + } + + /** @var modElement $element */ + switch ($binding) { + case 'CODE': + case 'INLINE': + $inlineContent = $content; + break; + + case 'FILE': + $basePath = $this->modx->getOption('static_elements_basepath'); + $filename = rtrim($basePath, '/') . '/' . trim($content, '/'); + $sourceId = $this->modx->getOption('static_elements_default_mediasource'); + + /** @var modMediaSource $source */ + if ($sourceId && $source = $this->modx->getObject('sources.modMediaSource', $sourceId)) { + $source->initialize(); + $metaData = $source->getMetaData($filename); + $path = !empty($metaData) ? $filename : ''; + } else { + $source = modMediaSource::getDefaultSource($this->modx); + $source->initialize(); + $path = file_exists($filename) ? $filename : ''; + $sourceBasePath = $source->getBasePath(); + $path = strpos($path, $sourceBasePath) === 0 ? str_replace($sourceBasePath, '', $path) : $path; + + } + break; + + default: + break; + } + unset($content); + + if (!empty($inlineContent)) { + $cache_name = $binding . '__' . md5($name); + $element = $this->modx->newObject($class, array( + 'name' => $cache_name, + 'snippet' => $inlineContent, + )); + $element->setContent($inlineContent); + if ($element instanceof modScript) { + $element->_scriptName = $element->getScriptName() . $cache_name; + } + } elseif (!empty($path)) { + $cache_name = $binding . '__' . str_replace('/', '-', $path); + $element = $this->modx->newObject($class, array( + 'name' => $cache_name, + 'static' => true, + 'static_file' => $path, + 'source' => $sourceId, + )); + $element->setCacheable(false); + if (isset($source) && $source instanceof modMediaSource) { + $element->setSource($source); + } + if ($element instanceof modScript) { + $element->_scriptName = $element->getScriptName() . $cache_name; + } + + } elseif (array_key_exists($class, $this->modx->sourceCache) && array_key_exists($realname, $this->modx->sourceCache[$class])) { /** @var modElement $element */ $element = $this->modx->newObject($class); $element->fromArray($this->modx->sourceCache[$class][$realname]['fields'], '', true, true); @@ -554,7 +625,7 @@ public function getElement($class, $name) { ); } elseif(!$element) { - $evtOutput = $this->modx->invokeEvent('OnElementNotFound', array('class' => $class, 'name' => $realname)); + $evtOutput = $this->modx->invokeEvent('OnElementNotFound', array('class' => $class, 'name' => (!isset($path) ? $realname : $name))); $element = false; if ($evtOutput != false) { foreach ((array) $evtOutput as $elm) { diff --git a/core/model/modx/modscript.class.php b/core/model/modx/modscript.class.php index af0bb4c0d7f..a0e1c0268ae 100644 --- a/core/model/modx/modscript.class.php +++ b/core/model/modx/modscript.class.php @@ -145,6 +145,10 @@ public function loadScript() { $result = is_readable($includeFilename); $outdated = false; $sourceFile = $this->getSourceFile(); + if ($source = $this->getSource()) { + $sourceFile = $source->getBasePath() . ltrim($sourceFile, ' /'); + } + if ($this->isStatic() && $result && !empty($sourceFile) && is_readable($sourceFile)) { $includeMTime = filemtime($includeFilename); $sourceMTime = filemtime($sourceFile); From eb811ec900b0755421260a4d8aac9bce33a19d60 Mon Sep 17 00:00:00 2001 From: mvoevodskiy Date: Sat, 16 Mar 2019 13:14:50 +0300 Subject: [PATCH 3/5] Fix PHP notice: "Only variables should be passed by reference" --- core/model/modx/sources/modmediasource.class.php | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/core/model/modx/sources/modmediasource.class.php b/core/model/modx/sources/modmediasource.class.php index 7eac1a22a9f..9612d5115ff 100644 --- a/core/model/modx/sources/modmediasource.class.php +++ b/core/model/modx/sources/modmediasource.class.php @@ -549,9 +549,10 @@ public function getObjectContents($path) $properties = $this->getPropertyList(); $imageExtensions = array_map('trim', explode(',', $this->getOption('imageExtensions', $properties, 'jpg,jpeg,png,gif,svg'))); + $separatedPath = explode(DIRECTORY_SEPARATOR, $file->getPath()); $fa = [ 'name' => rtrim($path, DIRECTORY_SEPARATOR), - 'basename' => array_pop(explode(DIRECTORY_SEPARATOR, $file->getPath())), + 'basename' => array_pop($separatedPath), 'path' => $file->getPath(), 'size' => $file->getSize(), 'last_accessed' => $file->getTimestamp(), @@ -2266,7 +2267,8 @@ protected function isFileImage($file, $image_extensions = []) { try { $mime = $this->filesystem->getMimetype($file); - $ext = strtolower(array_pop(explode(DIRECTORY_SEPARATOR, trim($file, DIRECTORY_SEPARATOR)))); + $separatedFile = explode(DIRECTORY_SEPARATOR, trim($file, DIRECTORY_SEPARATOR)); + $ext = strtolower(array_pop($separatedFile)); return strpos($mime, 'image') === 0 || in_array($ext, array_map('strtolower', $image_extensions)); } catch (Exception $e) { From bb99beb927bb5c0e87fc5f6143b5c9180381371e Mon Sep 17 00:00:00 2001 From: mvoevodskiy Date: Sat, 16 Mar 2019 16:26:54 +0300 Subject: [PATCH 4/5] Enabled ability to use @INLINE and @CODE binding only for chunks and templates --- core/model/modx/modparser.class.php | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/core/model/modx/modparser.class.php b/core/model/modx/modparser.class.php index 2e6060abd51..a3007779860 100644 --- a/core/model/modx/modparser.class.php +++ b/core/model/modx/modparser.class.php @@ -527,7 +527,7 @@ public function processTag($tag, $processUncacheable = true) { */ public function getElement($class, $name) { $realname = $this->realname($name); - $binding = $content = $path = ''; + $binding = $inlineContent = $content = $path = ''; if (preg_match('#^@([A-Z]+)#', $name, $matches)) { $binding = $matches[1]; @@ -544,7 +544,9 @@ public function getElement($class, $name) { switch ($binding) { case 'CODE': case 'INLINE': - $inlineContent = $content; + if ($class == 'modChunk' || $class == 'modTemplate') { + $inlineContent = $content; + } break; case 'FILE': From db78e499e8c88d62abaf2702fd7cd8f729fdcdb3 Mon Sep 17 00:00:00 2001 From: mvoevodskiy Date: Sun, 17 Mar 2019 12:08:31 +0300 Subject: [PATCH 5/5] Fixed typo --- core/elements/{temlplates => templates}/.gitignore | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename core/elements/{temlplates => templates}/.gitignore (100%) diff --git a/core/elements/temlplates/.gitignore b/core/elements/templates/.gitignore similarity index 100% rename from core/elements/temlplates/.gitignore rename to core/elements/templates/.gitignore