bach пре 3 година
родитељ
комит
6dfae7006b

+ 18 - 0
CHANGELOG.md

@@ -1,3 +1,21 @@
+# v1.7.16
+## 06/02/2021
+
+1. [](#new)
+    * Added 'addFrame()' method to ImageMedium [#3323](https://github.com/getgrav/grav/pull/3323)
+1. [](#improved)
+    * Set `cache.clear_images_by_default` to `false` by default
+    * Improve error on bad nested form data [#3364](https://github.com/getgrav/grav/issues/3364)
+1. [](#bugfix)
+    * Improve Plugin and Theme initialization to fix PHP8 bug [#3368](https://github.com/getgrav/grav/issues/3368)
+    * Fixed `pathinfo()` twig filter in PHP7
+    * Fixed the first visible child page getting ordering number `999999.` [#3365](https://github.com/getgrav/grav/issues/3365)
+    * Fixed flex pages search using only folder name [#3316](https://github.com/getgrav/grav/issues/3316)
+    * Fixed flex pages using wrong type in `onBlueprintCreated` event [#3157](https://github.com/getgrav/grav/issues/3157)
+    * Fixed wrong SRI paths invoked when Grav instance as a sub folder [#3358](https://github.com/getgrav/grav/issues/3358)
+    * Fixed SRI trying to calculate remote assets, only ever set integrity for local files. Use the SRI provided by the remote source and manually add it in the `addJs/addCss` call for remote support. [#3358](https://github.com/getgrav/grav/issues/3358)
+    * Fix for weird regex issue with latest PHP versions on Intel Macs causing params to not parse properly in URI object
+
 # v1.7.15
 ## 05/19/2021
 

+ 1 - 1
system/blueprints/config/system.yaml

@@ -646,7 +646,7 @@ form:
               type: toggle
               label: PLUGIN_ADMIN.CLEAR_IMAGES_BY_DEFAULT
               help: PLUGIN_ADMIN.CLEAR_IMAGES_BY_DEFAULT_HELP
-              highlight: 1
+              highlight: 0
               options:
                 1: PLUGIN_ADMIN.YES
                 0: PLUGIN_ADMIN.NO

+ 1 - 1
system/config/system.yaml

@@ -96,7 +96,7 @@ cache:
   purge_at: '0 4 * * *'                          # How often to purge old file cache (using new scheduler)
   clear_at: '0 3 * * *'                           # How often to clear cache (using new scheduler)
   clear_job_type: 'standard'                     # Type to clear when processing the scheduled clear job `standard`|`all`
-  clear_images_by_default: true                  # By default grav will include processed images in cache clear, this can be disabled
+  clear_images_by_default: false                  # By default grav will include processed images in cache clear, this can be disabled
   cli_compatibility: false                       # Ensures only non-volatile drivers are used (file, redis, memcache, etc.)
   lifetime: 604800                               # Lifetime of cached data in seconds (0 = infinite)
   gzip: false                                    # GZip compress the page output

+ 1 - 1
system/defines.php

@@ -9,7 +9,7 @@
 
 // Some standard defines
 define('GRAV', true);
-define('GRAV_VERSION', '1.7.15');
+define('GRAV_VERSION', '1.7.16');
 define('GRAV_SCHEMA', '1.7.0_2020-11-20_1');
 define('GRAV_TESTING', false);
 

+ 12 - 6
system/src/Grav/Common/Assets/BaseAsset.php

@@ -15,6 +15,7 @@ use Grav\Common\Grav;
 use Grav\Common\Uri;
 use Grav\Common\Utils;
 use Grav\Framework\Object\PropertyObject;
+use RocketTheme\Toolbox\File\File;
 use SplFileInfo;
 
 /**
@@ -182,16 +183,21 @@ abstract class BaseAsset extends PropertyObject
     public static function integrityHash($input)
     {
         $grav = Grav::instance();
+        $uri = $grav['uri'];
 
         $assetsConfig = $grav['config']->get('system.assets');
 
-        if ( !empty($assetsConfig['enable_asset_sri']) && $assetsConfig['enable_asset_sri'] )
-        {
-            $dataToHash = file_get_contents( GRAV_WEBROOT . $input);
+        if (!self::isRemoteLink($input) && !empty($assetsConfig['enable_asset_sri']) && $assetsConfig['enable_asset_sri']) {
+            $input = preg_replace('#^' . $uri->rootUrl() . '#', '', $input);
+            $asset = File::instance(GRAV_WEBROOT . $input);
 
-            $hash = hash('sha256', $dataToHash, true);
-            $hash_base64 = base64_encode($hash);
-            return ' integrity="sha256-' . $hash_base64 . '"';
+            if ($asset->exists()) {
+                $dataToHash = $asset->content();
+                $hash = hash('sha256', $dataToHash, true);
+                $hash_base64 = base64_encode($hash);
+
+                return ' integrity="sha256-' . $hash_base64 . '"';
+            }
         }
 
         return '';

+ 4 - 0
system/src/Grav/Common/Data/BlueprintSchema.php

@@ -317,6 +317,10 @@ class BlueprintSchema extends BlueprintSchemaBase implements ExportInterface
                     $toggle = [];
                 }
                 // Recursively fetch the items.
+                $childData = $data[$key] ?? null;
+                if (null !== $childData && !is_array($childData)) {
+                    throw new \RuntimeException(sprintf("Bad form data for field collection '%s': %s used instead of an array", $key, gettype($childData)));
+                }
                 $data[$key] = $this->processFormRecursive($data[$key] ?? null, $toggle, $value);
             } else {
                 $field = $this->get($value);

+ 7 - 3
system/src/Grav/Common/Flex/Types/Pages/PageObject.php

@@ -367,7 +367,7 @@ class PageObject extends FlexPageObject
         $filesystem = Filesystem::getInstance(false);
         $oldParentKey = ltrim($filesystem->dirname("/{$storageKey}"), '/');
         $newParentKey = $this->getProperty('parent_key');
-        $isMoved = $oldParentKey !== $newParentKey;
+        $isMoved = $this->exists() && $oldParentKey !== $newParentKey;
         $order = !$isMoved ? $this->order() : false;
         if ($order !== false) {
             $order = (int)$order;
@@ -385,10 +385,12 @@ class PageObject extends FlexPageObject
         // Handle special case where ordering isn't given.
         if ($ordering === []) {
             if ($order >= 999999) {
-                // Set ordering to point to be the last item.
+                // Set ordering to point to be the last item, ignoring the object itself.
                 $order = 0;
                 foreach ($siblings as $sibling) {
-                    $order = max($order, (int)$sibling->order());
+                    if ($sibling->getKey() !== $this->getKey()) {
+                        $order = max($order, (int)$sibling->order());
+                    }
                 }
                 $this->order($order + 1);
             }
@@ -500,6 +502,8 @@ class PageObject extends FlexPageObject
         if ($isNew === true && $name === '') {
             // Support onBlueprintCreated event just like in Pages::blueprints($template)
             $blueprint->set('initialized', true);
+            $blueprint->setFilename($template);
+
             Grav::instance()->fireEvent('onBlueprintCreated', new Event(['blueprint' => $blueprint, 'type' => $template]));
         }
 

+ 1 - 1
system/src/Grav/Common/Media/Traits/ImageMediaTrait.php

@@ -56,7 +56,7 @@ trait ImageMediaTrait
         'resize', 'forceResize', 'cropResize', 'crop', 'zoomCrop',
         'negate', 'brightness', 'contrast', 'grayscale', 'emboss',
         'smooth', 'sharp', 'edge', 'colorize', 'sepia', 'enableProgressive',
-        'rotate', 'flip', 'fixOrientation', 'gaussianBlur', 'format'
+        'rotate', 'flip', 'fixOrientation', 'gaussianBlur', 'format', 'create', 'fill', 'merge'
     ];
 
     /** @var array */

+ 32 - 0
system/src/Grav/Common/Page/Medium/ImageMedium.php

@@ -337,6 +337,37 @@ class ImageMedium extends Medium implements ImageMediaInterface, ImageManipulate
         return $this;
     }
 
+    /**
+     * Add a frame to image
+     *
+     * @return $this
+     */
+    public function addFrame(int $border = 10, string $color = '0x000000')
+    {
+      if(is_int(intval($border)) && $border>0 && preg_match('/^0x[a-f0-9]{6}$/i', $color)) { // $border must be an integer and bigger than 0; $color must be formatted as an HEX value (0x??????).
+        $image = ImageFile::open($this->path());
+      }
+      else {
+        return $this;
+      }
+
+      $dst_width = $image->width()+2*$border;
+      $dst_height = $image->height()+2*$border;
+
+      $frame = ImageFile::create($dst_width, $dst_height);
+
+      $frame->__call('fill', [$color]);
+
+      $this->image = $frame;
+
+      $this->__call('merge', [$image, $border, $border]);
+
+      $this->saveImage();
+
+      return $this;
+
+    }
+
     /**
      * Forward the call to the image processing method.
      *
@@ -344,6 +375,7 @@ class ImageMedium extends Medium implements ImageMediaInterface, ImageManipulate
      * @param mixed $args
      * @return $this|mixed
      */
+    
     public function __call($method, $args)
     {
         if (!in_array($method, static::$magic_actions, true)) {

+ 25 - 16
system/src/Grav/Common/Plugins.php

@@ -287,33 +287,42 @@ class Plugins extends Iterator
     {
         // NOTE: ALL THE LOCAL VARIABLES ARE USED INSIDE INCLUDED FILE, DO NOT REMOVE THEM!
         $grav = Grav::instance();
+        /** @var UniformResourceLocator $locator */
         $locator = $grav['locator'];
-        $file = $locator->findResource('plugins://' . $name . DS . $name . PLUGIN_EXT);
+        $class = null;
 
+        // Start by attempting to load the plugin_name.php file.
+        $file = $locator->findResource('plugins://' . $name . DS . $name . PLUGIN_EXT);
         if (is_file($file)) {
             // Local variables available in the file: $grav, $name, $file
             $class = include_once $file;
+            if (!is_object($class) || !is_subclass_of($class, Plugin::class, true)) {
+                $class = null;
+            }
+        }
 
-            if (!$class || !is_subclass_of($class, Plugin::class, true)) {
-                $className = Inflector::camelize($name);
-                $pluginClassFormat = [
-                    'Grav\\Plugin\\' . ucfirst($name). 'Plugin',
-                    'Grav\\Plugin\\' . $className . 'Plugin',
-                    'Grav\\Plugin\\' . $className
-                ];
-
-                foreach ($pluginClassFormat as $pluginClass) {
-                    if (is_subclass_of($pluginClass, Plugin::class, true)) {
-                        $class = new $pluginClass($name, $grav);
-                        break;
-                    }
+        // If the class hasn't been initialized yet, guess the class name and create a new instance.
+        if (null === $class) {
+            $className = Inflector::camelize($name);
+            $pluginClassFormat = [
+                'Grav\\Plugin\\' . ucfirst($name). 'Plugin',
+                'Grav\\Plugin\\' . $className . 'Plugin',
+                'Grav\\Plugin\\' . $className
+            ];
+
+            foreach ($pluginClassFormat as $pluginClass) {
+                if (is_subclass_of($pluginClass, Plugin::class, true)) {
+                    $class = new $pluginClass($name, $grav);
+                    break;
                 }
             }
-        } else {
+        }
+
+        // Log a warning if plugin cannot be found.
+        if (null === $class) {
             $grav['log']->addWarning(
                 sprintf("Plugin '%s' enabled but not found! Try clearing cache with `bin/grav clearcache`", $name)
             );
-            return null;
         }
 
         return $class;

+ 23 - 17
system/src/Grav/Common/Themes.php

@@ -224,28 +224,18 @@ class Themes extends Iterator
         $grav = $this->grav;
         $config = $this->config;
         $name = $this->current();
+        $class = null;
 
         /** @var UniformResourceLocator $locator */
         $locator = $grav['locator'];
-        $file = $locator('theme://theme.php') ?: $locator("theme://{$name}.php");
 
+        // Start by attempting to load the theme.php file.
+        $file = $locator('theme://theme.php') ?: $locator("theme://{$name}.php");
         if ($file) {
             // Local variables available in the file: $grav, $config, $name, $file
             $class = include $file;
-
-            if (!$class || !is_subclass_of($class, Plugin::class, true)) {
-                $className = Inflector::camelize($name);
-                $themeClassFormat = [
-                    'Grav\\Theme\\' . $className,
-                    'Grav\\Theme\\' . ucfirst($name)
-                ];
-
-                foreach ($themeClassFormat as $themeClass) {
-                    if (is_subclass_of($themeClass, Theme::class, true)) {
-                        $class = new $themeClass($grav, $config, $name);
-                        break;
-                    }
-                }
+            if (!\is_object($class) || !is_subclass_of($class, Theme::class, true)) {
+                $class = null;
             }
         } elseif (!$locator('theme://') && !defined('GRAV_CLI')) {
             $response = new Response(500, [], "Theme '$name' does not exist, unable to display page.");
@@ -253,12 +243,28 @@ class Themes extends Iterator
             $grav->close($response);
         }
 
-        $this->config->set('theme', $config->get('themes.' . $name));
+        // If the class hasn't been initialized yet, guess the class name and create a new instance.
+        if (null === $class) {
+            $themeClassFormat = [
+                'Grav\\Theme\\' . Inflector::camelize($name),
+                'Grav\\Theme\\' . ucfirst($name)
+            ];
+
+            foreach ($themeClassFormat as $themeClass) {
+                if (is_subclass_of($themeClass, Theme::class, true)) {
+                    $class = new $themeClass($grav, $config, $name);
+                    break;
+                }
+            }
+        }
 
-        if (empty($class)) {
+        // Finally if everything else fails, just create a new instance from the default Theme class.
+        if (null === $class) {
             $class = new Theme($grav, $config, $name);
         }
 
+        $this->config->set('theme', $config->get('themes.' . $name));
+
         return $class;
     }
 

+ 6 - 2
system/src/Grav/Common/Twig/Extension/FilesystemExtension.php

@@ -368,11 +368,15 @@ class FilesystemExtension extends AbstractExtension
 
     /**
      * @param string $path
-     * @param int $flags
+     * @param int|null $flags
      * @return string|string[]
      */
-    public function pathinfo($path, $flags = PATHINFO_ALL)
+    public function pathinfo($path, $flags = null)
     {
+        if (null !== $flags) {
+            return pathinfo($path, (int)$flags);
+        }
+
         return pathinfo($path);
     }
 

+ 2 - 2
system/src/Grav/Common/Uri.php

@@ -665,7 +665,7 @@ class Uri
      */
     public static function paramsRegex()
     {
-        return '/\/([^\:\#\/\?]*' . Grav::instance()['config']->get('system.param_sep') . '[^\:\#\/\?]*)/';
+        return '/\/{1,}([^\:\#\/\?]*' . Grav::instance()['config']->get('system.param_sep') . '[^\:\#\/\?]*)/';
     }
 
     /**
@@ -1498,7 +1498,7 @@ class Uri
      * @param string $delimiter
      * @return string
      */
-    private function processParams($uri, $delimiter = ':')
+    private function processParams(string $uri, string $delimiter = ':'): string
     {
         if (strpos($uri, $delimiter) !== false) {
             preg_match_all(static::paramsRegex(), $uri, $matches, PREG_SET_ORDER);

+ 5 - 1
system/src/Grav/Framework/Flex/FlexObject.php

@@ -298,7 +298,11 @@ class FlexObject implements FlexObjectInterface, FlexAuthorizeInterface
 
         $weight = 0;
         foreach ($properties as $property) {
-            $weight += $this->searchNestedProperty($property, $search, $options);
+            if (strpos($property, '.')) {
+                $weight += $this->searchNestedProperty($property, $search, $options);
+            } else {
+                $weight += $this->searchProperty($property, $search, $options);
+            }
         }
 
         return $weight > 0 ? min($weight, 1) : 0;

+ 3 - 1
user/config/versions.yaml

@@ -1,4 +1,6 @@
 core:
   grav:
-    version: 1.7.15
+    version: 1.7.16
     schema: 1.7.0_2020-11-20_1
+    history:
+      - { version: 1.7.16, date: '2021-06-10 14:03:35' }