From 8dfb9d08c4ddc5c0fb942025eea7001d4cbac38a Mon Sep 17 00:00:00 2001 From: Gert Date: Thu, 29 Jan 2015 05:01:31 +0100 Subject: [PATCH 01/29] refactor medium and basic implementation of video --- system/src/Grav/Common/Grav.php | 2 +- .../Common/Markdown/ParsedownGravTrait.php | 4 +- system/src/Grav/Common/Page/Media.php | 93 ++++--- .../{Medium.php => Medium/ImageMedium.php} | 214 +++----------- system/src/Grav/Common/Page/Medium/Medium.php | 262 ++++++++++++++++++ system/src/Grav/Common/Page/Medium/README.md | 16 ++ .../Grav/Common/Page/Medium/VideoMedium.php | 187 +++++++++++++ 7 files changed, 566 insertions(+), 212 deletions(-) rename system/src/Grav/Common/Page/{Medium.php => Medium/ImageMedium.php} (62%) create mode 100644 system/src/Grav/Common/Page/Medium/Medium.php create mode 100644 system/src/Grav/Common/Page/Medium/README.md create mode 100644 system/src/Grav/Common/Page/Medium/VideoMedium.php diff --git a/system/src/Grav/Common/Grav.php b/system/src/Grav/Common/Grav.php index b9e5ce6af..ee40691d9 100644 --- a/system/src/Grav/Common/Grav.php +++ b/system/src/Grav/Common/Grav.php @@ -10,7 +10,7 @@ use Grav\Common\Service\StreamsServiceProvider; use RocketTheme\Toolbox\DI\Container; use RocketTheme\Toolbox\Event\Event; use RocketTheme\Toolbox\Event\EventDispatcher; -use Grav\Common\Page\Medium; +use Grav\Common\Page\Medium\Medium; /** * Grav diff --git a/system/src/Grav/Common/Markdown/ParsedownGravTrait.php b/system/src/Grav/Common/Markdown/ParsedownGravTrait.php index 9ba39e423..ea129a425 100644 --- a/system/src/Grav/Common/Markdown/ParsedownGravTrait.php +++ b/system/src/Grav/Common/Markdown/ParsedownGravTrait.php @@ -4,7 +4,7 @@ namespace Grav\Common\Markdown; use Grav\Common\Config\Config; use Grav\Common\Debugger; use Grav\Common\GravTrait; -use Grav\Common\Page\Medium; +use Grav\Common\Page\Medium\Medium; use Grav\Common\Uri; /** @@ -141,7 +141,7 @@ trait ParsedownGravTrait // loop through actions for the image and call them foreach ($actions as $action => $params) { // as long as it's a valid action - if (in_array($action, Medium::$valid_actions)) { + if (in_array($action, $medium::$valid_actions)) { call_user_func_array(array(&$medium, $action), explode(',', $params)); } } diff --git a/system/src/Grav/Common/Page/Media.php b/system/src/Grav/Common/Page/Media.php index afbdeeca4..deeebe5ed 100644 --- a/system/src/Grav/Common/Page/Media.php +++ b/system/src/Grav/Common/Page/Media.php @@ -5,6 +5,7 @@ use Grav\Common\Getters; use Grav\Common\Grav; use Grav\Common\Config\Config; use Grav\Common\GravTrait; +use Grav\Common\Page\Medium\Medium; /** * Media is a holder object that contains references to the media of page. This object is created and @@ -49,23 +50,30 @@ class Media extends Getters // Find out the real filename, in case of we are at the metadata. $filename = $info->getFilename(); - list($basename, $ext, $meta, $alternative) = $this->getFileParts($filename); + list($basename, $ext, $type, $extra) = $this->getFileParts($filename); // Get medium instance if it already exists. $medium = $this->get("{$basename}.{$ext}"); - if (!$alternative) { + if ($type !== 'alternative') { - $medium = $medium ? $medium : $this->createMedium($info->getPathname()); + $medium = $medium ? $medium : $this->createMedium("{$path}/{$basename}.{$ext}"); if (!$medium) { continue; } - if ($meta) { - $medium->addMetaFile($meta); - } else { - $medium->set('size', $info->getSize()); + switch ($type) { + case 'base': + $medium->set('size', $info->getSize()); + break; + case 'meta': + $medium->addMetaFile("{$path}/{$basename}.{$ext}{$extra}"); + break; + case 'thumb': + $thumbnail = $this->createMedium("{$path}/{$basename}.{$ext}{$extra}"); + $thumbnail->set('size', $info->getSize()); + $medium->set('thumb', $thumbnail); } } else { @@ -93,23 +101,38 @@ class Media extends Getters $this->add("{$basename}.{$ext}", $medium); } - foreach ($this->images() as $medium) { + foreach ($this->all() as $medium) { - $alternatives = $medium->getAlternatives(); + $thumb = $medium->get('thumb'); - if (empty($alternatives)) { - continue; + if ($thumb && !$thumb instanceof Medium) { + $thumb = $this->createMedium($thumb); + + if ($thumb) { + $thumb->set('size', filesize($thumb)); + $medium->set('thumb', $thumb); + } else { + $medium->set('thumb', null); + } } - $max = max(array_keys($alternatives)); + if ($medium->get('type') == 'image') { + $alternatives = $medium->getAlternatives(); - for ($i=2; $i < $max; $i++) { - - if (isset($alternatives[$i])) { + if (empty($alternatives)) { continue; } - $medium->addAlternative($i, $this->scaleMedium($alternatives[$max], $max, $i)); + $max = max(array_keys($alternatives)); + + for ($i=2; $i < $max; $i++) { + + if (isset($alternatives[$i])) { + continue; + } + + $medium->addAlternative($i, $this->scaleMedium($alternatives[$max], $max, $i)); + } } } } @@ -216,7 +239,7 @@ class Media extends Getters 'type' => 'file', 'thumb' => 'media/thumb.png', 'mime' => 'application/octet-stream', - 'name' => $filename, + 'filepath' => $file, 'filename' => $filename, 'basename' => $basename, 'extension' => $ext, @@ -234,7 +257,7 @@ class Media extends Getters } } - return new Medium($params); + return Medium::factory($params); } protected function scaleMedium($medium, $from, $to) @@ -302,27 +325,31 @@ class Media extends Getters $fileParts = explode('.', $filename); $name = array_shift($fileParts); - $alternative = false; + $type = 'base'; + $extra = null; - if (preg_match('/(.*)@(\d+x)$/', $name, $matches)) { + if (preg_match('/(.+)@(\d+x)\.(.+)$/', $name, $matches)) { $name = $matches[1]; - $alternative = $matches[2]; - } - - $extension = null; - while (($part = array_shift($fileParts)) !== null) { - if ($part != 'meta') { - if (isset($extension)) { - $name .= '.' . $extension; + $extension = $matches[3]; + $type = 'alternative'; + $extra = $matches[2]; + } else { + $extension = null; + while (($part = array_shift($fileParts)) !== null) { + if ($part != 'meta' && $part != 'thumb') { + if (isset($extension)) { + $name .= '.' . $extension; + } + $extension = $part; + } else { + $type = $part; + $extra = '.' . $part . '.' . implode('.', $fileParts); + break; } - $extension = $part; - } else { - break; } } - $meta = implode('.', $fileParts); - return array($name, $extension, $meta, $alternative); + return array($name, $extension, $type, $extra); } protected function parseRatio($ratio) diff --git a/system/src/Grav/Common/Page/Medium.php b/system/src/Grav/Common/Page/Medium/ImageMedium.php similarity index 62% rename from system/src/Grav/Common/Page/Medium.php rename to system/src/Grav/Common/Page/Medium/ImageMedium.php index 56bf1cf0a..01d938d85 100644 --- a/system/src/Grav/Common/Page/Medium.php +++ b/system/src/Grav/Common/Page/Medium/ImageMedium.php @@ -1,5 +1,5 @@ [ 0, 1 ] ]; - /** - * @var array - */ - protected $meta = array(); - - /** - * @var array - */ - protected $alternatives = array(); - - /** - * @var string - */ - protected $linkTarget; - - /** - * @var string - */ - protected $linkSrcset; - - /** - * @var string - */ - protected $linkAttributes = []; - /** * Construct. * @@ -103,34 +73,13 @@ class Medium extends Data { parent::__construct($items, $blueprint); - $file_path = $this->get('path') . '/' . $this->get('filename'); - $file_parts = pathinfo($file_path); + $image_info = getimagesize($this->get('filepath')); + $this->def('width', $image_info[0]); + $this->def('height', $image_info[1]); + $this->def('mime', $image_info['mime']); + $this->def('debug', self::$grav['config']->get('system.images.debug')); - $this->set('thumb', $file_path); - $this->set('extension', $file_parts['extension']); - $this->set('filename', $this->get('filename')); - - if ($this->get('type') == 'image') { - $image_info = getimagesize($file_path); - $this->def('width', $image_info[0]); - $this->def('height', $image_info[1]); - $this->def('mime', $image_info['mime']); - $this->reset(); - } else { - $this->def('mime', 'application/octet-stream'); - } - - $this->set('debug', self::$grav['config']->get('system.images.debug')); - } - - /** - * Return string representation of the object (html or url). - * - * @return string - */ - public function __toString() - { - return $this->linkImage ? $this->html() : $this->url(); + $this->reset(); } /** @@ -138,16 +87,13 @@ class Medium extends Data * * @return string path to file */ - public function path() + public function path($reset = true) { - if ($this->image) { - $output = $this->saveImage(); - $this->reset(); - $output = GRAV_ROOT . '/' . $output; - } else { - $output = $this->get('path') . '/' . $this->get('filename'); - } - return $output; + $output = $this->saveImage(); + + if ($reset) $this->reset(); + + return GRAV_ROOT . '/' . $output; } /** @@ -158,14 +104,10 @@ class Medium extends Data */ public function url($reset = true) { - if ($this->image) { - $output = '/' . $this->saveImage(); + $output = '/' . $this->saveImage(); - if ($reset) { - $this->reset(); - } - } else { - $output = preg_replace('|^' . GRAV_ROOT . '|', '', $this->get('path')) . '/' . $this->get('filename'); + if ($reset) { + $this->reset(); } return self::$grav['base_url'] . $output; @@ -196,27 +138,6 @@ class Medium extends Data return implode(', ', $srcset); } - /** - * Returns tag from the medium. - * - * @param string $title - * @param string $class - * @param string $type - * @param int $quality - * @param bool $reset - * @return string - */ - public function img($title = null, $class = null, $type = null, $quality = 80, $reset = true) - { - if (!$this->image) { - $this->image(); - } - - $output = $this->html($title, $class, $type, $quality, $reset); - - return $output; - } - /** * Return HTML markup from the medium. * @@ -232,12 +153,8 @@ class Medium extends Data $title = $title ? $title : $this->get('title'); $class = $class ? $class : ''; - if ($this->image) { - $attributes = $data['img_srcset'] ? ' srcset="' . $data['img_srcset'] . '" sizes="100vw"' : ''; - $output = '' . $title . ''; - } else { - $output = $data['text']; - } + $attributes = $data['img_srcset'] ? ' srcset="' . $data['img_srcset'] . '" sizes="100vw"' : ''; + $output = '' . $title . ''; if (isset($data['a_href'])) { $attributes = ''; @@ -263,12 +180,8 @@ class Medium extends Data { $output = []; - if ($this->image) { - $output['img_src'] = $this->url(false); - $output['img_srcset'] = $this->srcset($reset); - } else { - $output['text'] = $title; - } + $output['img_src'] = $this->url(false); + $output['img_srcset'] = $this->srcset($reset); if ($this->linkTarget) { $output['a_href'] = $this->linkTarget; @@ -301,10 +214,6 @@ class Medium extends Data */ public function format($type = null, $quality = 80) { - if (!$this->image) { - $this->image(); - } - $this->type = $type; $this->quality = $quality; return $this; @@ -319,39 +228,20 @@ class Medium extends Data */ public function link($width = null, $height = null) { - if ($this->image) { - if ($width && $height) { - $this->cropResize($width, $height); - } + if ($width && $height) { + $this->cropResize($width, $height); + } - $this->linkTarget = $this->url(false); - $srcset = $this->srcset(); + $this->linkTarget = $this->url(false); + $srcset = $this->srcset(); - if ($srcset) { - $this->linkAttributes['data-srcset'] = $srcset; - } - } else { - // TODO: we need to find out URI in a bit better way. - $this->linkTarget = self::$grav['base_url'] . preg_replace('|^' . GRAV_ROOT . '|', '', $this->get('path')) . '/' . $this->get('filename'); + if ($srcset) { + $this->linkAttributes['data-srcset'] = $srcset; } return $this; } - /** - * Enable lightbox for the medium. - * - * @param null $width - * @param null $height - * @return Medium - */ - public function lightbox($width = null, $height = null) - { - $this->linkAttributes['rel'] = 'lightbox'; - - return $this->link($width, $height); - } - /** * Reset image. * @@ -361,10 +251,9 @@ class Medium extends Data { $this->image = null; - if ($this->get('type') == 'image') { - $this->image(); - $this->filter(); - } + $this->image(); + $this->filter(); + $this->type = 'guess'; $this->quality = 80; $this->debug_watermarked = false; @@ -420,12 +309,12 @@ class Medium extends Data * @param string $variable * @return $this */ - public function image($variable = 'thumb') + public function image() { $locator = self::$grav['locator']; // TODO: add default file - $file = $this->get($variable); + $file = $this->get('filepath'); $this->image = ImageFile::open($file) ->setCacheDir($locator->findResource('cache://images', false)) ->setActualCacheDir($locator->findResource('cache://images', true)) @@ -467,43 +356,16 @@ class Medium extends Data * @param $type * @return $this */ - public function addMetaFile($type) + public function addMetaFile($filepath) { - $this->meta[$type] = $type; + parent::addMetaFile($filepath); - $path = $this->get('path') . '/' . $this->get('filename') . '.meta.' . $type; - if ($type == 'yaml') { - $this->merge(CompiledYamlFile::instance($path)->content()); - } elseif (in_array($type, array('jpg', 'jpeg', 'png', 'gif'))) { - $this->set('thumb', $path); - } + // Apply filters in meta file $this->reset(); return $this; } - /** - * Add alternative Medium to this Medium. - * - * @param $ratio - * @param Medium $alternative - */ - public function addAlternative($ratio, Medium $alternative) - { - if (!is_numeric($ratio) || $ratio === 0) { - return; - } - - $alternative->set('ratio', $ratio); - - $this->alternatives[(float) $ratio] = $alternative; - } - - public function getAlternatives() - { - return $this->alternatives; - } - /** * Filter image by using user defined filter parameters. * diff --git a/system/src/Grav/Common/Page/Medium/Medium.php b/system/src/Grav/Common/Page/Medium/Medium.php new file mode 100644 index 000000000..fafaf124d --- /dev/null +++ b/system/src/Grav/Common/Page/Medium/Medium.php @@ -0,0 +1,262 @@ +def('mime', 'application/octet-stream'); + } + + /** + * Return string representation of the object (html or url). + * + * @return string + */ + public function __toString() + { + return $this->linkImage ? $this->html() : $this->url(); + } + + /** + * Return PATH to file. + * + * @return string path to file + */ + public function path($reset = true) + { + if ($reset) $this->reset(); + + return $this->get('filepath'); + } + + /** + * Return URL to file. + * + * @param bool $reset + * @return string + */ + public function url($reset = true) + { + $output = preg_replace('|^' . GRAV_ROOT . '|', '', $this->get('filepath')); + + return self::$grav['base_url'] . $output; + } + + /** + * Return HTML markup from the medium. + * + * @param string $title + * @param string $class + * @param bool $reset + * @return string + */ + public function html($title = null, $class = null, $reset = true) + { + $data = $this->htmlRaw($reset); + + $output = $data['text']; + + if (isset($data['a_href'])) { + + $attributes = ''; + foreach ($data['a_attributes'] as $prop => $value) { + $attributes .= " {$prop}=\"{$value}\""; + } + + $output = '' . $output . ''; + } + + return $output; + } + + /** + * Return HTML array from medium. + * + * @param bool $reset + * @param string $title + * + * @return array + */ + public function htmlRaw($reset = true, $title = '') + { + $data = [ + 'text' => $title ? $title : $this->path($reset) + ]; + + if ($this->linkTarget) { + $output['a_href'] = $this->linkTarget; + $output['a_attributes'] = $this->linkAttributes; + + $this->linkTarget = null; + $this->linkAttributes = []; + } + + return $output; + } + + /** + * Enable link for the medium object. + * + * @param null $width + * @param null $height + * @return $this + */ + public function link($width = null, $height = null) + { + // TODO: we need to find out URI in a bit better way. + $this->linkTarget = self::$grav['base_url'] . preg_replace('|^' . GRAV_ROOT . '|', '', $this->get('filepath')); + + return $this; + } + + /** + * Enable lightbox for the medium. + * + * @param null $width + * @param null $height + * @return Medium + */ + public function lightbox($width = null, $height = null) + { + $this->linkAttributes['rel'] = 'lightbox'; + + return $this->link($width, $height); + } + + /** + * Reset image. + * + * @return $this + */ + public function reset() + { + return $this; + } + + /** + * Forward the call to the image processing method. + * + * @param string $method + * @param mixed $args + * @return $this|mixed + */ + public function __call($method, $args) + { + return $this; + } + + /** + * Add meta file for the medium. + * + * @param $type + * @return $this + */ + public function addMetaFile($filepath) + { + self::$grav['debugger']->addMessage($filepath); + $this->merge(CompiledYamlFile::instance($filepath)->content()); + + return $this; + } + + /** + * Add alternative Medium to this Medium. + * + * @param $ratio + * @param Medium $alternative + */ + public function addAlternative($ratio, Medium $alternative) + { + if (!is_numeric($ratio) || $ratio === 0) { + return; + } + + $alternative->set('ratio', $ratio); + $this->alternatives[(float) $ratio] = $alternative; + } + + public function getAlternatives() + { + return $this->alternatives; + } +} diff --git a/system/src/Grav/Common/Page/Medium/README.md b/system/src/Grav/Common/Page/Medium/README.md new file mode 100644 index 000000000..fa1e3a256 --- /dev/null +++ b/system/src/Grav/Common/Page/Medium/README.md @@ -0,0 +1,16 @@ +# Video + +- link +- lightbox +- thumbnail? if you only want the thumbnail, operate on the thumbnail instead + +- html + + +# TODO + +- default thumb in Media: 'media/thumb.jpg' check if exists +- What to do when calling functions that do not exist? grav log? i.e. call cropResize on video, call resize on (unknown) Medium +- Parsedown media + --> generalize htmlRaw or add parseDownTag function to Medium so it can handle any kind of media in parsedown, + stretching the meaning of ![]() tag in markdown \ No newline at end of file diff --git a/system/src/Grav/Common/Page/Medium/VideoMedium.php b/system/src/Grav/Common/Page/Medium/VideoMedium.php new file mode 100644 index 000000000..a553ed04b --- /dev/null +++ b/system/src/Grav/Common/Page/Medium/VideoMedium.php @@ -0,0 +1,187 @@ +htmlRaw(false); + if ($reset) { + $this->reset(); + } + + $title = $title ? $title : $this->get('title'); + $class = $class ? $class : ''; + + if (isset($data['a_href'])) { + + $thumb = $this->get('thumb'); + if ($thumb) { + $output = $thumb->html($reset); + } else { + $output = $title ? $title : $this->get('basename'); + } + + $attributes = ''; + foreach ($data['a_attributes'] as $prop => $value) { + $attributes .= " {$prop}=\"{$value}\""; + } + + $output = '' . $output . ''; + } else { + $attributes = ''; + foreach ($data['video_attributes'] as $prop => $value) { + $attributes .= " {$prop}=\"{$value}\""; + } + + $output = ''; + } + + return $output; + } + + public function htmlRaw($reset = true, $title = '') + { + $output = []; + + if ($this->linkTarget) { + $output['a_href'] = $this->linkTarget; + $output['a_attributes'] = $this->linkAttributes; + + $this->linkTarget = null; + $this->linkAttributes = []; + + $thumb = $this->get('thumb'); + if ($thumb) { + $raw_thumb = $thumb->htmlRaw($reset); + + $output['thumb_src'] = $raw_thumb['img_src']; + } + } else { + $output['video_src'] = $this->url($reset); + $output['video_attributes'] = $this->videoAttributes; + } + + return $output; + } + + /** + * Enable link for the medium object. + * + * @param null $width + * @param null $height + * @return $this + */ + public function link($width = null, $height = null) + { + // TODO: we need to find out URI in a bit better way. + $this->linkTarget = $this->url(); + + $this->mode = 'thumb'; + + return $this; + } + + protected function _resize($width = null, $height = null) + { + $this->videoAttributes['width'] = $width; + $this->videoAttributes['height'] = $height; + + return $this; + } + + /** + * Forward the call to the image processing method. + * + * @param string $method + * @param mixed $args + * @return $this|mixed + */ + public function __call($method, $args) + { + if ($method == 'cropZoom') { + $method = 'zoomCrop'; + } + + $mode = $this->mode; + $target = null; + + if ($mode == 'video') { + + $target = $this; + $method = '_' . $method; + + } else if ($mode == 'thumb') { + + $target = $this->get('thumb'); + + } + + self::$grav['debugger']->addMessage('Calling ' . $method . ' on ' . $mode); + + if ($target) { + try { + $result = call_user_func_array(array($target, $method), $args); + } catch (\BadFunctionCallException $e) { + $result = null; + } + } + + if ($mode == 'thumb' && $result) { + $this->set('thumb', $result); + } + + return $this; + } +} \ No newline at end of file From 6f06e0c4249c0e5e3398f7da91d02ce987dd88f2 Mon Sep 17 00:00:00 2001 From: Gert Date: Thu, 29 Jan 2015 05:04:38 +0100 Subject: [PATCH 02/29] fix var name --- system/src/Grav/Common/Page/Media.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/system/src/Grav/Common/Page/Media.php b/system/src/Grav/Common/Page/Media.php index deeebe5ed..1c588e3c2 100644 --- a/system/src/Grav/Common/Page/Media.php +++ b/system/src/Grav/Common/Page/Media.php @@ -93,9 +93,9 @@ class Media extends Getters } } - $medium = $medium ? $medium : $this->scaleMedium($altMedium, $alternative, 1); + $medium = $medium ? $medium : $this->scaleMedium($altMedium, $extra, 1); - $medium->addAlternative($this->parseRatio($alternative), $altMedium); + $medium->addAlternative($this->parseRatio($extra), $altMedium); } $this->add("{$basename}.{$ext}", $medium); From 640ba16f8b7945d7854c0ce5244e560b72b78a8c Mon Sep 17 00:00:00 2001 From: Gert Date: Wed, 4 Feb 2015 22:38:24 +0100 Subject: [PATCH 03/29] fix alternatives detect --- system/src/Grav/Common/Page/Media.php | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/system/src/Grav/Common/Page/Media.php b/system/src/Grav/Common/Page/Media.php index 1c588e3c2..174e883fe 100644 --- a/system/src/Grav/Common/Page/Media.php +++ b/system/src/Grav/Common/Page/Media.php @@ -76,7 +76,6 @@ class Media extends Getters $medium->set('thumb', $thumbnail); } } else { - $altMedium = $this->createMedium($info->getPathname()); if (!$altMedium) { @@ -100,7 +99,6 @@ class Media extends Getters $this->add("{$basename}.{$ext}", $medium); } - foreach ($this->all() as $medium) { $thumb = $medium->get('thumb'); @@ -328,7 +326,7 @@ class Media extends Getters $type = 'base'; $extra = null; - if (preg_match('/(.+)@(\d+x)\.(.+)$/', $name, $matches)) { + if (preg_match('/(.*)@(\d+x)\.(.*)$/', $filename, $matches)) { $name = $matches[1]; $extension = $matches[3]; $type = 'alternative'; From 1423375312dbc808896e7b81405b840b88397a0e Mon Sep 17 00:00:00 2001 From: Gert Date: Wed, 4 Feb 2015 22:39:34 +0100 Subject: [PATCH 04/29] enable markdown for any medium object and further cleanup --- .../Common/Markdown/ParsedownGravTrait.php | 68 ++------ .../Grav/Common/Page/Medium/ImageMedium.php | 164 ++++++++---------- system/src/Grav/Common/Page/Medium/Medium.php | 74 ++++---- system/src/Grav/Common/Page/Medium/README.md | 16 -- .../Grav/Common/Page/Medium/VideoMedium.php | 136 ++++++--------- 5 files changed, 167 insertions(+), 291 deletions(-) delete mode 100644 system/src/Grav/Common/Page/Medium/README.md diff --git a/system/src/Grav/Common/Markdown/ParsedownGravTrait.php b/system/src/Grav/Common/Markdown/ParsedownGravTrait.php index ea129a425..03d3e4bf3 100644 --- a/system/src/Grav/Common/Markdown/ParsedownGravTrait.php +++ b/system/src/Grav/Common/Markdown/ParsedownGravTrait.php @@ -36,6 +36,17 @@ trait ParsedownGravTrait $this->special_chars = array('>' => 'gt', '<' => 'lt', '"' => 'quot'); } + /** + * Make the element function publicly accessible, Medium uses this to render from Twig + * + * @param array $Element + * @return string markup + */ + public function elementToHtml(array $Element) + { + return $this->element($Element); + } + /** * Setter for special chars * @@ -101,6 +112,7 @@ trait ParsedownGravTrait $alt = $excerpt['element']['attributes']['alt'] ?: ''; $title = $excerpt['element']['attributes']['title'] ?: ''; + $class = isset($excerpt['element']['attributes']['class']) ? $excerpt['element']['attributes']['class'] : ''; //get the url and parse it $url = parse_url(htmlspecialchars_decode($excerpt['element']['attributes']['src'])); @@ -129,9 +141,9 @@ trait ParsedownGravTrait } // if there is a media file that matches the path referenced.. - if ($media && isset($media->images()[$url['path']])) { + if ($media && isset($media->all()[$url['path']])) { // get the medium object - $medium = $media->images()[$url['path']]; + $medium = $media->all()[$url['path']]; // if there is a query, then parse it and build action calls if (isset($url['query'])) { @@ -140,58 +152,10 @@ trait ParsedownGravTrait // loop through actions for the image and call them foreach ($actions as $action => $params) { - // as long as it's a valid action - if (in_array($action, $medium::$valid_actions)) { - call_user_func_array(array(&$medium, $action), explode(',', $params)); - } + call_user_func_array(array(&$medium, $action), explode(',', $params)); } - $data = $medium->htmlRaw(); - - // set the src element with the new generated url - if (!isset($actions['lightbox'])) { - $excerpt['element']['attributes']['src'] = $data['img_src']; - - if ($data['img_srcset']) { - $excerpt['element']['attributes']['srcset'] = $data['img_srcset'];; - $excerpt['element']['attributes']['sizes'] = '100vw'; - } - - } else { - // Create the custom lightbox element - - $attributes = $data['a_attributes']; - $attributes['href'] = $data['a_href']; - - $img_attributes = [ - 'src' => $data['img_src'], - 'alt' => $alt, - 'title' => $title - ]; - - if ($data['img_srcset']) { - $img_attributes['srcset'] = $data['img_srcset']; - $img_attributes['sizes'] = '100vw'; - } - - $element = array( - 'name' => 'a', - 'attributes' => $attributes, - 'handler' => 'element', - 'text' => array( - 'name' => 'img', - 'attributes' => $img_attributes - ) - ); - - // Set any custom classes on the lightbox element - if (isset($excerpt['element']['attributes']['class'])) { - $element['attributes']['class'] = $excerpt['element']['attributes']['class']; - } - - // Set the lightbox element on the Excerpt - $excerpt['element'] = $element; - } + $excerpt['element'] = $medium->parseDownElement($title, $alt, $class); } else { // not a current page media file, see if it needs converting to relative $excerpt['element']['attributes']['src'] = Uri::build_url($url); diff --git a/system/src/Grav/Common/Page/Medium/ImageMedium.php b/system/src/Grav/Common/Page/Medium/ImageMedium.php index 01d938d85..fcf93892d 100644 --- a/system/src/Grav/Common/Page/Medium/ImageMedium.php +++ b/system/src/Grav/Common/Page/Medium/ImageMedium.php @@ -9,30 +9,6 @@ use Grav\Common\Data\Blueprint; use Grav\Common\Data\Data; use Gregwar\Image\Image as ImageFile; -/** - * The Image medium holds information related to an individual image. These are then stored in the Media object. - * - * @author RocketTheme - * @license MIT - * - * @property string $file_name - * @property string $type - * @property string $name Alias of file_name - * @property string $description - * @property string $url - * @property string $path - * @property string $thumb - * @property int $width - * @property int $height - * @property string $mime - * @property int $modified - * - * Medium can have up to 3 files: - * - video.mov Medium file itself. - * - video.mov.meta.yaml Metadata for the medium. - * - video.mov.thumb.jpg Thumbnail image for the medium. - * - */ class ImageMedium extends Medium { /** @@ -46,13 +22,11 @@ class ImageMedium extends Medium protected $debug_watermarked = false; - public static $valid_actions = [ - // Medium functions - 'format', 'lightbox', 'link', 'reset', - - // Gregwar Image functions - 'resize', 'forceResize', 'cropResize', 'crop', 'cropZoom', - 'negate', 'brightness', 'contrast', 'grayscale', 'emboss', 'smooth', 'sharp', 'edge', 'colorize', 'sepia' ]; + public static $magic_actions = [ + 'resize', 'forceResize', 'cropResize', 'crop', 'zoomCrop', + 'negate', 'brightness', 'contrast', 'grayscale', 'emboss', + 'smooth', 'sharp', 'edge', 'colorize', 'sepia' + ]; public static $size_param_actions = [ 'resize' => [ 0, 1 ], @@ -139,62 +113,77 @@ class ImageMedium extends Medium } /** - * Return HTML markup from the medium. - * - * @param string $title - * @param string $class - * @param bool $reset - * @return string + * Called from Parsedown (ParsedownGravTrait::inlineImage calls this method on the Medium) */ - public function html($title = null, $class = null, $reset = true) + public function parsedownElement($title = null, $alt = null, $class = null, $reset = true) { - $data = $this->htmlRaw($reset); - - $title = $title ? $title : $this->get('title'); - $class = $class ? $class : ''; - - $attributes = $data['img_srcset'] ? ' srcset="' . $data['img_srcset'] . '" sizes="100vw"' : ''; - $output = '' . $title . ''; - - if (isset($data['a_href'])) { - $attributes = ''; - foreach ($data['a_attributes'] as $prop => $value) { - $attributes .= " {$prop}=\"{$value}\""; - } - - $output = '' . $output . ''; + $outer_attributes = []; + $image_attributes = [ + 'src' => $this->url(false), + ]; + + $srcset = $this->srcset($reset); + if ($srcset) { + $image_attributes['srcset'] = $srcset; + $image_attributes['sizes'] = '100vw'; } - return $output; - } + if ($title) { + $image_attributes['title'] = $title; + $outer_attributes['title'] = $title; + } - /** - * Return HTML array from medium. - * - * @param bool $reset - * @param string $title - * - * @return array - */ - public function htmlRaw($reset = true, $title = '') - { - $output = []; + if ($alt) { + $image_attributes['alt'] = $alt; + } - $output['img_src'] = $this->url(false); - $output['img_srcset'] = $this->srcset($reset); + if ($class) { + $image_attributes['class'] = $class; + $outer_attributes['class'] = $class; + } - if ($this->linkTarget) { - $output['a_href'] = $this->linkTarget; - $output['a_attributes'] = $this->linkAttributes; + $element = [ 'name' => 'image', 'attributes' => $image_attributes ]; + + if ($this->linkAttributes) { + $element = [ + 'name' => 'a', + 'handler' => 'element', + 'text' => $element, + 'attributes' => $this->linkAttributes + ]; - $this->linkTarget = null; $this->linkAttributes = []; } - return $output; + $element['attributes'] = array_merge($outer_attributes, $element['attributes']); + + return $element; } /** + * Enable link for the medium object. + * + * @param null $width + * @param null $height + * @return $this + */ + public function link($width = null, $height = null, $reset = true) + { + if ($width && $height) { + $this->cropResize($width, $height); + } + + $this->linkAttributes['href'] = $this->url(false); + $srcset = $this->srcset($reset); + + if ($srcset) { + $this->linkAttributes['data-srcset'] = $srcset; + } + + return $this; + } + + /** * Sets the quality of the image * @param Int $quality 0-100 quality * @return Medium @@ -219,29 +208,6 @@ class ImageMedium extends Medium return $this; } - /** - * Enable link for the medium object. - * - * @param null $width - * @param null $height - * @return $this - */ - public function link($width = null, $height = null) - { - if ($width && $height) { - $this->cropResize($width, $height); - } - - $this->linkTarget = $this->url(false); - $srcset = $this->srcset(); - - if ($srcset) { - $this->linkAttributes['data-srcset'] = $srcset; - } - - return $this; - } - /** * Reset image. * @@ -274,6 +240,10 @@ class ImageMedium extends Medium $method = 'zoomCrop'; } + if (!in_array($method, self::$magic_actions)) { + return $this; + } + // Always initialize image. if (!$this->image) { $this->image(); @@ -285,6 +255,8 @@ class ImageMedium extends Medium foreach ($this->alternatives as $ratio => $medium) { $args_copy = $args; + // regular image: resize 400x400 -> 200x200 + // --> @2x: resize 800x800->400x400 if (isset(self::$size_param_actions[$method])) { foreach (self::$size_param_actions[$method] as $param) { if (isset($args_copy[$param])) { diff --git a/system/src/Grav/Common/Page/Medium/Medium.php b/system/src/Grav/Common/Page/Medium/Medium.php index fafaf124d..0232e6c52 100644 --- a/system/src/Grav/Common/Page/Medium/Medium.php +++ b/system/src/Grav/Common/Page/Medium/Medium.php @@ -7,6 +7,7 @@ use Grav\Common\Grav; use Grav\Common\GravTrait; use Grav\Common\Data\Blueprint; use Grav\Common\Data\Data; +use Grav\Common\Markdown\Parsedown; use Gregwar\Image\Image as ImageFile; /** @@ -38,20 +39,16 @@ class Medium extends Data { use GravTrait; - public static $valid_actions = [ - 'format', 'lightbox', 'link', 'reset', - ]; + /** + * @var \Grav\Common\Markdown\Parsedown + */ + protected $parsedown = null; /** * @var Medium[] */ protected $alternatives = array(); - /** - * @var string - */ - protected $linkTarget; - /** * @var string */ @@ -130,48 +127,44 @@ class Medium extends Data * @param bool $reset * @return string */ - public function html($title = null, $class = null, $reset = true) + public function html($title = null, $alt = null, $class = null, $reset = true) { - $data = $this->htmlRaw($reset); + $element = $this->parsedownElement($title, $alt, $class, $reset); - $output = $data['text']; - - if (isset($data['a_href'])) { - - $attributes = ''; - foreach ($data['a_attributes'] as $prop => $value) { - $attributes .= " {$prop}=\"{$value}\""; - } - - $output = '' . $output . ''; + if (!$this->parsedown) { + $this->parsedown = new Parsedown(null); } - return $output; + return $this->parsedown->elementToHtml($element); } - /** - * Return HTML array from medium. - * - * @param bool $reset - * @param string $title - * - * @return array - */ - public function htmlRaw($reset = true, $title = '') + public function parsedownElement($title = null, $alt = null, $class = null, $reset = true) { - $data = [ - 'text' => $title ? $title : $this->path($reset) + $text = $title ? $title : $this->path($reset); + $text_attributes = []; + + if ($class) { + $text_attributes['class'] = $class; + } + + $element = [ + 'name' => 'p', + 'text' => $text, + 'attributes' => $attributes ]; - if ($this->linkTarget) { - $output['a_href'] = $this->linkTarget; - $output['a_attributes'] = $this->linkAttributes; + if ($this->linkAttributes) { + $element = [ + 'name' => 'a', + 'handler' => 'element', + 'text' => $element, + 'attributes' => $this->linkAttributes + ]; - $this->linkTarget = null; $this->linkAttributes = []; } - return $output; + return $element; } /** @@ -181,10 +174,10 @@ class Medium extends Data * @param null $height * @return $this */ - public function link($width = null, $height = null) + public function link($width = null, $height = null, $reset = true) { // TODO: we need to find out URI in a bit better way. - $this->linkTarget = self::$grav['base_url'] . preg_replace('|^' . GRAV_ROOT . '|', '', $this->get('filepath')); + $this->linkAttributes['href'] = self::$grav['base_url'] . preg_replace('|^' . GRAV_ROOT . '|', '', $this->get('filepath')); return $this; } @@ -196,7 +189,7 @@ class Medium extends Data * @param null $height * @return Medium */ - public function lightbox($width = null, $height = null) + public function lightbox($width = null, $height = null, $reset = true) { $this->linkAttributes['rel'] = 'lightbox'; @@ -233,7 +226,6 @@ class Medium extends Data */ public function addMetaFile($filepath) { - self::$grav['debugger']->addMessage($filepath); $this->merge(CompiledYamlFile::instance($filepath)->content()); return $this; diff --git a/system/src/Grav/Common/Page/Medium/README.md b/system/src/Grav/Common/Page/Medium/README.md deleted file mode 100644 index fa1e3a256..000000000 --- a/system/src/Grav/Common/Page/Medium/README.md +++ /dev/null @@ -1,16 +0,0 @@ -# Video - -- link -- lightbox -- thumbnail? if you only want the thumbnail, operate on the thumbnail instead - -- html - - -# TODO - -- default thumb in Media: 'media/thumb.jpg' check if exists -- What to do when calling functions that do not exist? grav log? i.e. call cropResize on video, call resize on (unknown) Medium -- Parsedown media - --> generalize htmlRaw or add parseDownTag function to Medium so it can handle any kind of media in parsedown, - stretching the meaning of ![]() tag in markdown \ No newline at end of file diff --git a/system/src/Grav/Common/Page/Medium/VideoMedium.php b/system/src/Grav/Common/Page/Medium/VideoMedium.php index a553ed04b..5b7f723d2 100644 --- a/system/src/Grav/Common/Page/Medium/VideoMedium.php +++ b/system/src/Grav/Common/Page/Medium/VideoMedium.php @@ -9,112 +9,70 @@ use Grav\Common\Data\Blueprint; use Grav\Common\Data\Data; use Gregwar\Image\Image as ImageFile; -/** - * The Image medium holds information related to an individual image. These are then stored in the Media object. - * - * @author RocketTheme - * @license MIT - * - * @property string $file_name - * @property string $type - * @property string $name Alias of file_name - * @property string $description - * @property string $url - * @property string $path - * @property string $thumb - * @property int $width - * @property int $height - * @property string $mime - * @property int $modified - * - * Medium can have up to 3 files: - * - video.mov Medium file itself. - * - video.mov.meta.yaml Metadata for the medium. - * - video.mov.thumb.jpg Thumbnail image for the medium. - * - */ class VideoMedium extends Medium { protected $mode = 'video'; protected $videoAttributes = []; - public static $valid_actions = [ - // Medium functions - 'format', 'lightbox', 'link', 'reset', - + public static $magic_actions = [ // Gregwar OR internal depending on context 'resize', // Gregwar Image functions 'forceResize', 'cropResize', 'crop', 'cropZoom', - 'negate', 'brightness', 'contrast', 'grayscale', 'emboss', 'smooth', 'sharp', 'edge', 'colorize', 'sepia' ]; - - public static $valid_video_actions = [ - 'lightbox', 'link', 'reset', 'resize' + 'negate', 'brightness', 'contrast', 'grayscale', + 'emboss', 'smooth', 'sharp', 'edge', 'colorize', 'sepia' ]; - public function html($title = null, $class = null, $reset = true) - { - $data = $this->htmlRaw(false); - if ($reset) { - $this->reset(); - } + public function parsedownElement($title = null, $alt = null, $class = null, $reset = true) + { + $element; - $title = $title ? $title : $this->get('title'); - $class = $class ? $class : ''; + if (!$this->linkAttributes) { + $video_location = $this->url(false); + $video_attributes = $this->video_attributes; + $video_attributes['controls'] = true; - if (isset($data['a_href'])) { + if ($reset) { + $this->reset(); + } - $thumb = $this->get('thumb'); - if ($thumb) { - $output = $thumb->html($reset); + $element = [ + 'name' => 'video', + 'text' => 'Your browser does not support the video tag.', + 'attributes' => $video_attributes + ]; + } else { + + $thumbnail = $this->get('thumb'); + if ($thumbnail) { + $innerElement = $thumbnail->parsedownElement($title, $alt, $class, $reset); } else { - $output = $title ? $title : $this->get('basename'); + $innerElement = $title ? $title : $this->path(false); } - $attributes = ''; - foreach ($data['a_attributes'] as $prop => $value) { - $attributes .= " {$prop}=\"{$value}\""; + $link_attributes = $this->linkAttributes; + + if ($class) { + $link_attributes['class'] = $class; } - $output = '' . $output . ''; - } else { - $attributes = ''; - foreach ($data['video_attributes'] as $prop => $value) { - $attributes .= " {$prop}=\"{$value}\""; - } + $element = [ + 'name' => 'a', + 'attributes' => $this->linkAttributes, + 'handler' => is_string($innerElement) ? 'line' : 'element', + 'text' => $innerElement + ]; - $output = ''; - } - - return $output; - } - - public function htmlRaw($reset = true, $title = '') - { - $output = []; - - if ($this->linkTarget) { - $output['a_href'] = $this->linkTarget; - $output['a_attributes'] = $this->linkAttributes; - - $this->linkTarget = null; $this->linkAttributes = []; - - $thumb = $this->get('thumb'); - if ($thumb) { - $raw_thumb = $thumb->htmlRaw($reset); - - $output['thumb_src'] = $raw_thumb['img_src']; + if ($reset) { + $this->reset(); } - } else { - $output['video_src'] = $this->url($reset); - $output['video_attributes'] = $this->videoAttributes; } - return $output; - } + return $element; + } /** * Enable link for the medium object. @@ -123,16 +81,20 @@ class VideoMedium extends Medium * @param null $height * @return $this */ - public function link($width = null, $height = null) + public function link($width = null, $height = null, $reset = true) { - // TODO: we need to find out URI in a bit better way. - $this->linkTarget = $this->url(); + $this->linkAttributes['href'] = $this->url(); $this->mode = 'thumb'; return $this; } + public function reset() + { + $this->videoAttributes = []; + } + protected function _resize($width = null, $height = null) { $this->videoAttributes['width'] = $width; @@ -160,17 +122,19 @@ class VideoMedium extends Medium if ($mode == 'video') { $target = $this; + $valid = in_array($method, self::$magic_actions); + $method = '_' . $method; } else if ($mode == 'thumb') { $target = $this->get('thumb'); + $target_class = get_class($target); + $valid = $target && in_array($method, $target_class::$magic_actions); } - self::$grav['debugger']->addMessage('Calling ' . $method . ' on ' . $mode); - - if ($target) { + if ($valid) { try { $result = call_user_func_array(array($target, $method), $args); } catch (\BadFunctionCallException $e) { From 5b08a8605e79e5e6b83b61094bce30a1bbb29768 Mon Sep 17 00:00:00 2001 From: Gert Date: Sat, 7 Feb 2015 00:05:40 +0100 Subject: [PATCH 05/29] various bugfixes, thumbnail support for files --- system/config/streams.yaml | 1 + system/src/Grav/Common/Page/Media.php | 6 +- system/src/Grav/Common/Page/Medium/Medium.php | 97 +++++++++++++++---- .../Grav/Common/Page/Medium/VideoMedium.php | 84 +++------------- 4 files changed, 95 insertions(+), 93 deletions(-) diff --git a/system/config/streams.yaml b/system/config/streams.yaml index a38b5805e..c06ec3547 100644 --- a/system/config/streams.yaml +++ b/system/config/streams.yaml @@ -8,6 +8,7 @@ schemes: type: ReadOnlyStream paths: - user://images + - system://images page: type: ReadOnlyStream diff --git a/system/src/Grav/Common/Page/Media.php b/system/src/Grav/Common/Page/Media.php index 174e883fe..a43653808 100644 --- a/system/src/Grav/Common/Page/Media.php +++ b/system/src/Grav/Common/Page/Media.php @@ -107,7 +107,7 @@ class Media extends Getters $thumb = $this->createMedium($thumb); if ($thumb) { - $thumb->set('size', filesize($thumb)); + $thumb->set('size', filesize($thumb->path())); $medium->set('thumb', $thumb); } else { $medium->set('thumb', null); @@ -249,8 +249,8 @@ class Media extends Getters $lookup = $locator->findResources('image://'); foreach ($lookup as $lookupPath) { - if (is_file($lookupPath . $params['thumb'])) { - $params['thumb'] = $lookupPath . $params['thumb']; + if (is_file($lookupPath . '/' . $params['thumb'])) { + $params['thumb'] = $lookupPath . '/' . $params['thumb']; break; } } diff --git a/system/src/Grav/Common/Page/Medium/Medium.php b/system/src/Grav/Common/Page/Medium/Medium.php index 0232e6c52..2393bd6e8 100644 --- a/system/src/Grav/Common/Page/Medium/Medium.php +++ b/system/src/Grav/Common/Page/Medium/Medium.php @@ -39,6 +39,10 @@ class Medium extends Data { use GravTrait; + protected $mode = 'medium'; + + public static $magic_actions = []; + /** * @var \Grav\Common\Markdown\Parsedown */ @@ -140,28 +144,47 @@ class Medium extends Data public function parsedownElement($title = null, $alt = null, $class = null, $reset = true) { - $text = $title ? $title : $this->path($reset); - $text_attributes = []; + $element; - if ($class) { - $text_attributes['class'] = $class; - } + if (!$this->linkAttributes) { + $text = $title ? $title : $this->url($reset); + $text_attributes = []; - $element = [ - 'name' => 'p', - 'text' => $text, - 'attributes' => $attributes - ]; + if ($class) { + $text_attributes['class'] = $class; + } + + $element = [ + 'name' => 'p', + 'text' => $text, + 'attributes' => $text_attributes + ]; + } else { + + $thumbnail = $this->get('thumb'); + if ($thumbnail) { + $innerElement = $thumbnail->parsedownElement($title, $alt, $class, $reset); + } else { + $innerElement = $title ? $title : $this->url(false); + } + + $link_attributes = $this->linkAttributes; + + if ($class) { + $link_attributes['class'] = $class; + } - if ($this->linkAttributes) { $element = [ 'name' => 'a', - 'handler' => 'element', - 'text' => $element, - 'attributes' => $this->linkAttributes + 'attributes' => $this->linkAttributes, + 'handler' => is_string($innerElement) ? 'line' : 'element', + 'text' => $innerElement ]; $this->linkAttributes = []; + if ($reset) { + $this->reset(); + } } return $element; @@ -175,9 +198,15 @@ class Medium extends Data * @return $this */ public function link($width = null, $height = null, $reset = true) - { - // TODO: we need to find out URI in a bit better way. - $this->linkAttributes['href'] = self::$grav['base_url'] . preg_replace('|^' . GRAV_ROOT . '|', '', $this->get('filepath')); + { + $this->linkAttributes['href'] = $this->url(); + + if ($width && $height) { + $this->linkAttributes['data-width'] = $width; + $this->linkAttributes['data-height'] = $height; + } + + $this->mode = 'thumb'; return $this; } @@ -215,6 +244,40 @@ class Medium extends Data */ public function __call($method, $args) { + if ($method == 'cropZoom') { + $method = 'zoomCrop'; + } + + $mode = $this->mode; + $target = null; + + if ($mode == 'medium') { + + $target = $this; + $valid = in_array($method, static::$magic_actions); + + $method = '_' . $method; + + } else if ($mode == 'thumb') { + + $target = $this->get('thumb'); + $target_class = get_class($target); + $valid = $target && in_array($method, $target_class::$magic_actions); + + } + + if ($valid) { + try { + $result = call_user_func_array(array($target, $method), $args); + } catch (\BadFunctionCallException $e) { + $result = null; + } + + if ($mode == 'thumb' && $result) { + $this->set('thumb', $result); + } + } + return $this; } diff --git a/system/src/Grav/Common/Page/Medium/VideoMedium.php b/system/src/Grav/Common/Page/Medium/VideoMedium.php index 5b7f723d2..314cc458a 100644 --- a/system/src/Grav/Common/Page/Medium/VideoMedium.php +++ b/system/src/Grav/Common/Page/Medium/VideoMedium.php @@ -11,18 +11,10 @@ use Gregwar\Image\Image as ImageFile; class VideoMedium extends Medium { - protected $mode = 'video'; - protected $videoAttributes = []; public static $magic_actions = [ - // Gregwar OR internal depending on context - 'resize', - - // Gregwar Image functions - 'forceResize', 'cropResize', 'crop', 'cropZoom', - 'negate', 'brightness', 'contrast', 'grayscale', - 'emboss', 'smooth', 'sharp', 'edge', 'colorize', 'sepia' + 'resize' ]; public function parsedownElement($title = null, $alt = null, $class = null, $reset = true) @@ -31,7 +23,7 @@ class VideoMedium extends Medium if (!$this->linkAttributes) { $video_location = $this->url(false); - $video_attributes = $this->video_attributes; + $video_attributes = $this->videoAttributes; $video_attributes['controls'] = true; if ($reset) { @@ -54,13 +46,21 @@ class VideoMedium extends Medium $link_attributes = $this->linkAttributes; + if (!empty($this->videoAttributes['width']) && empty($link_attributes['data-width'])) { + $link_attributes['data-width'] = $this->videoAttributes['width']; + } + + if (!empty($this->videoAttributes['height']) && empty($link_attributes['data-height'])) { + $link_attributes['data-height'] = $this->videoAttributes['height']; + } + if ($class) { $link_attributes['class'] = $class; } $element = [ 'name' => 'a', - 'attributes' => $this->linkAttributes, + 'attributes' => $link_attributes, 'handler' => is_string($innerElement) ? 'line' : 'element', 'text' => $innerElement ]; @@ -74,22 +74,6 @@ class VideoMedium extends Medium return $element; } - /** - * Enable link for the medium object. - * - * @param null $width - * @param null $height - * @return $this - */ - public function link($width = null, $height = null, $reset = true) - { - $this->linkAttributes['href'] = $this->url(); - - $this->mode = 'thumb'; - - return $this; - } - public function reset() { $this->videoAttributes = []; @@ -102,50 +86,4 @@ class VideoMedium extends Medium return $this; } - - /** - * Forward the call to the image processing method. - * - * @param string $method - * @param mixed $args - * @return $this|mixed - */ - public function __call($method, $args) - { - if ($method == 'cropZoom') { - $method = 'zoomCrop'; - } - - $mode = $this->mode; - $target = null; - - if ($mode == 'video') { - - $target = $this; - $valid = in_array($method, self::$magic_actions); - - $method = '_' . $method; - - } else if ($mode == 'thumb') { - - $target = $this->get('thumb'); - $target_class = get_class($target); - $valid = $target && in_array($method, $target_class::$magic_actions); - - } - - if ($valid) { - try { - $result = call_user_func_array(array($target, $method), $args); - } catch (\BadFunctionCallException $e) { - $result = null; - } - } - - if ($mode == 'thumb' && $result) { - $this->set('thumb', $result); - } - - return $this; - } } \ No newline at end of file From 73c42313fa546a1f4f74f9d821d66d04878c5b28 Mon Sep 17 00:00:00 2001 From: Gert Date: Sun, 22 Feb 2015 00:00:52 +0100 Subject: [PATCH 06/29] media overhaul --- system/src/Grav/Common/Page/Media.php | 216 +++--------- .../src/Grav/Common/Page/Medium/Factory.php | 128 +++++++ .../Grav/Common/Page/Medium/ImageMedium.php | 242 ++++++------- system/src/Grav/Common/Page/Medium/Medium.php | 324 ++++++++++-------- .../Common/Page/Medium/MediumInterface.php | 157 +++++++++ .../Common/Page/Medium/StaticImageMedium.php | 68 ++++ .../Page/Medium/ThumbnailImageMedium.php | 62 ++++ .../Grav/Common/Page/Medium/VideoMedium.php | 103 +++--- 8 files changed, 812 insertions(+), 488 deletions(-) create mode 100644 system/src/Grav/Common/Page/Medium/Factory.php create mode 100644 system/src/Grav/Common/Page/Medium/MediumInterface.php create mode 100644 system/src/Grav/Common/Page/Medium/StaticImageMedium.php create mode 100644 system/src/Grav/Common/Page/Medium/ThumbnailImageMedium.php diff --git a/system/src/Grav/Common/Page/Media.php b/system/src/Grav/Common/Page/Media.php index 8c2d38a53..b54d26db3 100644 --- a/system/src/Grav/Common/Page/Media.php +++ b/system/src/Grav/Common/Page/Media.php @@ -6,6 +6,7 @@ use Grav\Common\Grav; use Grav\Common\Config\Config; use Grav\Common\GravTrait; use Grav\Common\Page\Medium\Medium; +use Grav\Common\Page\Medium\Factory as MediumFactory; /** * Media is a holder object that contains references to the media of page. This object is created and @@ -41,6 +42,8 @@ class Media extends Getters $iterator = new \DirectoryIterator($path); + $media = []; + /** @var \DirectoryIterator $info */ foreach ($iterator as $info) { // Ignore folders and Markdown files. @@ -48,79 +51,57 @@ class Media extends Getters continue; } - // Find out the real filename, in case of we are at the metadata. - $filename = $info->getFilename(); - list($basename, $ext, $type, $extra) = $this->getFileParts($filename); + // Find out what type we're dealing with + list($basename, $ext, $type, $extra) = $this->getFileParts($info->getFilename()); - // Get medium instance if it already exists. - $medium = $this->get("{$basename}.{$ext}"); + $media["{$basename}.{$ext}"] = isset($media["{$basename}.{$ext}"]) ? $media["{$basename}.{$ext}"] : []; - if ($type !== 'alternative') { - - $medium = $medium ? $medium : $this->createMedium("{$path}/{$basename}.{$ext}"); - - if (!$medium) { - continue; - } - - switch ($type) { - case 'base': - $medium->set('size', $info->getSize()); - break; - case 'meta': - $medium->addMetaFile("{$path}/{$basename}.{$ext}{$extra}"); - break; - case 'thumb': - $thumbnail = $this->createMedium("{$path}/{$basename}.{$ext}{$extra}"); - $thumbnail->set('size', $info->getSize()); - $medium->set('thumb', $thumbnail); - } + if ($type === 'alternative') { + $media["{$basename}.{$ext}"][$type] = isset($media["{$basename}.{$ext}"][$type]) ? $media["{$basename}.{$ext}"][$type] : []; + $media["{$basename}.{$ext}"][$type][$extra] = $info->getPathname(); } else { - $altMedium = $this->createMedium($info->getPathname()); - - if (!$altMedium) { - continue; - } - - $altMedium->set('size', $info->getSize()); - - if (!$medium) { - $medium = $this->createMedium("{$path}/${basename}.${ext}"); - - if ($medium) { - $medium->set('size', filesize("{$path}/${basename}.${ext}")); - } - } - - $medium = $medium ? $medium : $this->scaleMedium($altMedium, $extra, 1); - - $medium->addAlternative($this->parseRatio($extra), $altMedium); + $media["{$basename}.{$ext}"][$type] = $info->getPathname(); } - - $this->add("{$basename}.{$ext}", $medium); } - foreach ($this->all() as $medium) { - $thumb = $medium->get('thumb'); - - if ($thumb && !$thumb instanceof Medium) { - $thumb = $this->createMedium($thumb); - - if ($thumb) { - $thumb->set('size', filesize($thumb->path())); - $medium->set('thumb', $thumb); - } else { - $medium->set('thumb', null); + foreach ($media as $name => $types) { + // First prepare the alternatives in case there is no base medium + if (!empty($types['alternative'])) { + foreach ($types['alternative'] as $ratio => &$file) { + $file = MediumFactory::fromFile($file); } } - if ($medium->get('type') == 'image') { - $alternatives = $medium->getAlternatives(); + // Create the base medium + if (!empty($types['base'])) { + $medium = MediumFactory::fromFile($types['base']); + } else if (!empty($types['alternative'])) { + + $altMedium = reset($types['alternative']); + $ratio = key($types['alternative']); - if (empty($alternatives)) { - continue; - } + $medium = MediumFactory::scaledFromMedium($altMedium, $ratio, 1); + } + if (!$medium) { + continue; + } + + if (!empty($types['meta'])) { + $medium->addMetaFile($types['meta']); + } + + if (!empty($types['thumb'])) { + // We will not turn it into medium yet because user might never request the thumbnail + // not wasting any resources on that, maybe we should do this for medium in general? + $medium->set('thumbnails.page', $types['thumb']); + } + + // Build missing alternatives + if (!empty($types['alternative'])) { + + $alternatives = $types['alternative']; + $max = max(array_keys($alternatives)); for ($i=2; $i < $max; $i++) { @@ -129,14 +110,18 @@ class Media extends Getters continue; } - $medium->addAlternative($i, $this->scaleMedium($alternatives[$max], $max, $i)); + $types['alternative'][$i] = MediumFactory::scaledFromMedium($alternatives[$max], $max, $i); + } + + foreach ($types['alternative'] as $ratio => $altMedium) { + $medium->addAlternative($ratio, $altMedium); } } + + $this->add($name, $medium); } } - - /** * Get medium by filename. * @@ -203,94 +188,6 @@ class Media extends Getters return $this->files; } - /** - * Create a Medium object from a file - * - * @param string $file - * - * @return Medium|null - */ - protected function createMedium($file) - { - if (!file_exists($file)) { - return null; - } - - $path = dirname($file); - $filename = basename($file); - $parts = explode('.', $filename); - $ext = array_pop($parts); - $basename = implode('.', $parts); - - /** @var Config $config */ - $config = self::getGrav()['config']; - - // Check if medium type has been configured. - $params = $config->get("media.".strtolower($ext)); - if (!$params) { - return null; - } - - // Add default settings for undefined variables. - $params += $config->get('media.defaults'); - $params += array( - 'type' => 'file', - 'thumb' => 'media/thumb.png', - 'mime' => 'application/octet-stream', - 'filepath' => $file, - 'filename' => $filename, - 'basename' => $basename, - 'extension' => $ext, - 'path' => $path, - 'modified' => filemtime($file), - ); - - $locator = self::getGrav()['locator']; - - $lookup = $locator->findResources('image://'); - foreach ($lookup as $lookupPath) { - if (is_file($lookupPath . '/' . $params['thumb'])) { - $params['thumb'] = $lookupPath . '/' . $params['thumb']; - break; - } - } - - return Medium::factory($params); - } - - protected function scaleMedium($medium, $from, $to) - { - $from = $this->parseRatio($from); - $to = $this->parseRatio($to); - - if ($to > $from) { - return $medium; - } - - $ratio = $to / $from; - $width = (int) ($medium->get('width') * $ratio); - $height = (int) ($medium->get('height') * $ratio); - - $basename = $medium->get('basename'); - $basename = str_replace('@'.$from.'x', '@'.$to.'x', $basename); - - $debug = $medium->get('debug'); - $medium->set('debug', false); - - $file = $medium->resize($width, $height)->setPrettyName($basename)->url(); - $file = preg_replace('|'. preg_quote(self::getGrav()['base_url_relative']) .'$|', '', GRAV_ROOT) . $file; - - $medium->set('debug', $debug); - - $size = filesize($file); - - $medium = $this->createMedium($file); - $medium->set('size', $size); - - return $medium; - } - - /** * @internal */ @@ -326,11 +223,11 @@ class Media extends Getters $type = 'base'; $extra = null; - if (preg_match('/(.*)@(\d+x)\.(.*)$/', $filename, $matches)) { + if (preg_match('/(.*)@(\d+)x\.(.*)$/', $filename, $matches)) { $name = $matches[1]; $extension = $matches[3]; $type = 'alternative'; - $extra = $matches[2]; + $extra = (int) $matches[2]; } else { $extension = null; while (($part = array_shift($fileParts)) !== null) { @@ -349,13 +246,4 @@ class Media extends Getters return array($name, $extension, $type, $extra); } - - protected function parseRatio($ratio) - { - if (!is_numeric($ratio)) { - $ratio = (float) trim($ratio, 'x'); - } - - return $ratio; - } } diff --git a/system/src/Grav/Common/Page/Medium/Factory.php b/system/src/Grav/Common/Page/Medium/Factory.php new file mode 100644 index 000000000..2f0beeb74 --- /dev/null +++ b/system/src/Grav/Common/Page/Medium/Factory.php @@ -0,0 +1,128 @@ +get("media.".strtolower($ext)); + if (!$media_params) { + return null; + } + + $params += $media_params; + + // Add default settings for undefined variables. + $params += $config->get('media.defaults'); + $params += array( + 'type' => 'file', + 'thumb' => 'media/thumb.png', + 'mime' => 'application/octet-stream', + 'filepath' => $file, + 'filename' => $filename, + 'basename' => $basename, + 'extension' => $ext, + 'path' => $path, + 'modified' => filemtime($file), + 'thumbnails' => [] + ); + + $locator = self::getGrav()['locator']; + + $lookup = $locator->findResources('image://'); + foreach ($lookup as $lookupPath) { + if (is_file($lookupPath . '/' . $params['thumb'])) { + $params['thumbnails']['default'] = $lookupPath . '/' . $params['thumb']; + break; + } + } + + return static::fromArray($params); + } + + public static function fromArray($items = array(), Blueprint $blueprint = null) + { + $type = isset($items['type']) ? $items['type'] : null; + + switch ($type) { + case 'image': + return new ImageMedium($items, $blueprint); + break; + case 'thumbnail': + return new ThumbnailImageMedium($items, $blueprint); + break; + case 'animated': + case 'vector': + return new StaticImageMedium($items, $blueprint); + break; + case 'video': + return new VideoMedium($items, $blueprint); + break; + default: + return new Medium($items, $blueprint); + break; + } + } + + public static function scaledFromMedium($medium, $from, $to) + { + if (! $medium instanceof ImageMedium) + return $medium; + + if ($to > $from) { + return $medium; + } + + $ratio = $to / $from; + $width = (int) ($medium->get('width') * $ratio); + $height = (int) ($medium->get('height') * $ratio); + + $basename = $medium->get('basename'); + $basename = str_replace('@'.$from.'x', '@'.$to.'x', $basename); + + $debug = $medium->get('debug'); + $medium->set('debug', false); + + $file = $medium->resize($width, $height)->setPrettyName($basename)->url(); + $file = preg_replace('|'. preg_quote(self::getGrav()['base_url_relative']) .'$|', '', GRAV_ROOT) . $file; + + $medium->set('debug', $debug); + + $size = filesize($file); + + $medium = self::fromFile($file); + $medium->set('size', $size); + + return $medium; + } +} \ No newline at end of file diff --git a/system/src/Grav/Common/Page/Medium/ImageMedium.php b/system/src/Grav/Common/Page/Medium/ImageMedium.php index fcf93892d..80cb85a09 100644 --- a/system/src/Grav/Common/Page/Medium/ImageMedium.php +++ b/system/src/Grav/Common/Page/Medium/ImageMedium.php @@ -11,24 +11,44 @@ use Gregwar\Image\Image as ImageFile; class ImageMedium extends Medium { + /** + * @var array + */ + protected $thumbnailTypes = [ 'page', 'media', 'default' ]; + /** * @var ImageFile */ protected $image; - protected $type = 'guess'; + /** + * @var string + */ + protected $format = 'guess'; + /** + * @var int + */ protected $quality = 85; + /** + * @var boolean + */ protected $debug_watermarked = false; + /** + * @var array + */ public static $magic_actions = [ 'resize', 'forceResize', 'cropResize', 'crop', 'zoomCrop', 'negate', 'brightness', 'contrast', 'grayscale', 'emboss', 'smooth', 'sharp', 'edge', 'colorize', 'sepia' ]; - public static $size_param_actions = [ + /** + * @var array + */ + public static $magic_resize_actions = [ 'resize' => [ 0, 1 ], 'forceResize' => [ 0, 1 ], 'cropResize' => [ 0, 1 ], @@ -53,13 +73,31 @@ class ImageMedium extends Medium $this->def('mime', $image_info['mime']); $this->def('debug', self::$grav['config']->get('system.images.debug')); + $this->set('thumbnails.media', $this->get('filepath')); + $this->reset(); } /** - * Return PATH to file. + * Add meta file for the medium. * - * @return string path to file + * @param $format + * @return $this + */ + public function addMetaFile($filepath) + { + parent::addMetaFile($filepath); + + // Apply filters in meta file + $this->reset(); + + return $this; + } + + /** + * Return PATH to image. + * + * @return string path to image */ public function path($reset = true) { @@ -71,7 +109,7 @@ class ImageMedium extends Medium } /** - * Return URL to file. + * Return URL to image. * * @param bool $reset * @return string @@ -115,97 +153,17 @@ class ImageMedium extends Medium /** * Called from Parsedown (ParsedownGravTrait::inlineImage calls this method on the Medium) */ - public function parsedownElement($title = null, $alt = null, $class = null, $reset = true) + public function sourceParsedownElement($attributes, $reset = true) { - $outer_attributes = []; - $image_attributes = [ - 'src' => $this->url(false), - ]; + empty($attributes['src']) && $attributes['src'] = $this->url(false); $srcset = $this->srcset($reset); if ($srcset) { - $image_attributes['srcset'] = $srcset; - $image_attributes['sizes'] = '100vw'; + empty($attributes['srcset']) && $attributes['srcset'] = $srcset; + empty($attributes['sizes']) && $attributes['sizes'] = '100vw'; } - if ($title) { - $image_attributes['title'] = $title; - $outer_attributes['title'] = $title; - } - - if ($alt) { - $image_attributes['alt'] = $alt; - } - - if ($class) { - $image_attributes['class'] = $class; - $outer_attributes['class'] = $class; - } - - $element = [ 'name' => 'image', 'attributes' => $image_attributes ]; - - if ($this->linkAttributes) { - $element = [ - 'name' => 'a', - 'handler' => 'element', - 'text' => $element, - 'attributes' => $this->linkAttributes - ]; - - $this->linkAttributes = []; - } - - $element['attributes'] = array_merge($outer_attributes, $element['attributes']); - - return $element; - } - - /** - * Enable link for the medium object. - * - * @param null $width - * @param null $height - * @return $this - */ - public function link($width = null, $height = null, $reset = true) - { - if ($width && $height) { - $this->cropResize($width, $height); - } - - $this->linkAttributes['href'] = $this->url(false); - $srcset = $this->srcset($reset); - - if ($srcset) { - $this->linkAttributes['data-srcset'] = $srcset; - } - - return $this; - } - - /** - * Sets the quality of the image - * @param Int $quality 0-100 quality - * @return Medium - */ - public function quality($quality) - { - $this->quality = $quality; - return $this; - } - - /** - * Sets image output format. - * - * @param string $type - * @param int $quality - * @return $this - */ - public function format($type = null, $quality = 80) - { - $this->type = $type; - $this->quality = $quality; - return $this; + return [ 'name' => 'image', 'attributes' => $attributes ]; } /** @@ -220,10 +178,81 @@ class ImageMedium extends Medium $this->image(); $this->filter(); - $this->type = 'guess'; + $this->format = 'guess'; $this->quality = 80; $this->debug_watermarked = false; + return parent::reset(); + } + + /** + * Enable link for the medium object. + * + * @param null $width + * @param null $height + * @return $this + */ + public function link($reset = true) + { + if ($this->mode !== 'source') { + $this->display('source'); + } + + $this->linkAttributes['href'] = $this->url(false); + $srcset = $this->srcset($reset); + + if ($srcset) { + $this->linkAttributes['data-srcset'] = $srcset; + } + + $this->thumbnail('auto'); + $thumb = $this->display('thumbnail'); + $thumb->linked = true; + + return $thumb; + } + + /** + * Enable lightbox for the medium. + * + * @param null $width + * @param null $height + * @return Medium + */ + public function lightbox($width = null, $height = null, $reset = true) + { + if ($this->mode !== 'source') { + $this->display('source'); + } + + if ($width && $height) { + $this->cropResize($width, $height); + } + + return parent::lightbox($width, $height, $reset); + } + + /** + * Sets the quality of the image + * @param Int $quality 0-100 quality + * @return Medium + */ + public function quality($quality) + { + $this->quality = $quality; + return $this; + } + + /** + * Sets image output format. + * + * @param string $format + * @param int $quality + * @return $this + */ + public function format($format) + { + $this->format = $format; return $this; } @@ -257,8 +286,8 @@ class ImageMedium extends Medium // regular image: resize 400x400 -> 200x200 // --> @2x: resize 800x800->400x400 - if (isset(self::$size_param_actions[$method])) { - foreach (self::$size_param_actions[$method] as $param) { + if (isset(self::$magic_resize_actions[$method])) { + foreach (self::$magic_resize_actions[$method] as $param) { if (isset($args_copy[$param])) { $args_copy[$param] = (int) $args_copy[$param] * $ratio; } @@ -267,12 +296,9 @@ class ImageMedium extends Medium call_user_func_array(array($medium, $method), $args_copy); } - } catch (\BadFunctionCallException $e) { - $result = null; - } + } catch (\BadFunctionCallException $e) { } - // Returns either current object or result of the action. - return $result instanceof ImageFile ? $this : $result; + return $this; } /** @@ -281,7 +307,7 @@ class ImageMedium extends Medium * @param string $variable * @return $this */ - public function image() + protected function image() { $locator = self::$grav['locator']; @@ -319,23 +345,7 @@ class ImageMedium extends Medium $this->image->merge(ImageFile::open($overlay)); } - return $this->image->cacheFile($this->type, $this->quality); - } - - /** - * Add meta file for the medium. - * - * @param $type - * @return $this - */ - public function addMetaFile($filepath) - { - parent::addMetaFile($filepath); - - // Apply filters in meta file - $this->reset(); - - return $this; + return $this->image->cacheFile($this->format, $this->quality); } /** diff --git a/system/src/Grav/Common/Page/Medium/Medium.php b/system/src/Grav/Common/Page/Medium/Medium.php index 2393bd6e8..3fc255d8f 100644 --- a/system/src/Grav/Common/Page/Medium/Medium.php +++ b/system/src/Grav/Common/Page/Medium/Medium.php @@ -13,35 +13,28 @@ use Gregwar\Image\Image as ImageFile; /** * The Image medium holds information related to an individual image. These are then stored in the Media object. * - * @author RocketTheme + * @author Grav * @license MIT * - * @property string $file_name - * @property string $type - * @property string $name Alias of file_name - * @property string $description - * @property string $url - * @property string $path - * @property string $thumb - * @property int $width - * @property int $height - * @property string $mime - * @property int $modified - * - * Medium can have a few files: - * - video.mov Medium file itself. - * - video.mov.meta.yaml Metadata for the medium. - * - video.mov.thumb.jpg Thumbnail image for the medium. - * - video@2x.mov Alternate sizes of medium - * */ class Medium extends Data { use GravTrait; - protected $mode = 'medium'; + /** + * @var string + */ + protected $mode = 'source'; - public static $magic_actions = []; + /** + * @var Medium + */ + protected $_thumbnail = null; + + /** + * @var array + */ + protected $thumbnailTypes = [ 'page', 'default' ]; /** * @var \Grav\Common\Markdown\Parsedown @@ -54,27 +47,15 @@ class Medium extends Data protected $alternatives = array(); /** - * @var string + * @var array + */ + protected $attributes = []; + + /** + * @var array */ protected $linkAttributes = []; - public static function factory($items = array(), Blueprint $blueprint = null) - { - $type = isset($items['type']) ? $items['type'] : null; - - switch ($type) { - case 'image': - return new ImageMedium($items, $blueprint); - break; - case 'video': - return new VideoMedium($items, $blueprint); - break; - default: - return new self($items, $blueprint); - break; - } - } - /** * Construct. * @@ -89,18 +70,45 @@ class Medium extends Data } /** - * Return string representation of the object (html or url). + * Add meta file for the medium. + * + * @param $filepath + */ + public function addMetaFile($filepath) + { + $this->merge(CompiledYamlFile::instance($filepath)->content()); + } + + /** + * Add alternative Medium to this Medium. + * + * @param $ratio + * @param Medium $alternative + */ + public function addAlternative($ratio, Medium $alternative) + { + if (!is_numeric($ratio) || $ratio === 0) { + return; + } + + $alternative->set('ratio', $ratio); + $this->alternatives[(float) $ratio] = $alternative; + } + + /** + * Return string representation of the object (html). * * @return string */ public function __toString() { - return $this->linkImage ? $this->html() : $this->url(); + return $this->html(); } /** * Return PATH to file. * + * @param bool $reset * @return string path to file */ public function path($reset = true) @@ -146,34 +154,28 @@ class Medium extends Data { $element; - if (!$this->linkAttributes) { - $text = $title ? $title : $this->url($reset); - $text_attributes = []; + $attributes = $this->attributes; + $link_attributes = $this->linkAttributes; - if ($class) { - $text_attributes['class'] = $class; - } + !empty($title) && empty($attributes['title']) && $attributes['title'] = $title; + !empty($alt) && empty($attributes['alt']) && $attributes['alt'] = $alt; + !empty($class) && empty($attributes['class']) && $attributes['class'] = $class; - $element = [ - 'name' => 'p', - 'text' => $text, - 'attributes' => $text_attributes - ]; - } else { - - $thumbnail = $this->get('thumb'); - if ($thumbnail) { - $innerElement = $thumbnail->parsedownElement($title, $alt, $class, $reset); - } else { - $innerElement = $title ? $title : $this->url(false); - } - - $link_attributes = $this->linkAttributes; - - if ($class) { - $link_attributes['class'] = $class; - } + switch ($this->mode) { + case 'text': + $element = $this->textParsedownElement($attributes, $reset); + break; + case 'thumbnail': + $element = $this->getThumbnail()->sourceParsedownElement($attributes, $reset); + break; + case 'source': + $element = $this->sourceParsedownElement($attributes, $reset); + break; + } + if ($link_attributes) { + + $innerElement = $element; $element = [ 'name' => 'a', 'attributes' => $this->linkAttributes, @@ -181,15 +183,86 @@ class Medium extends Data 'text' => $innerElement ]; - $this->linkAttributes = []; if ($reset) { - $this->reset(); + $this->linkAttributes = []; } } + $this->display('source'); + return $element; } + public function sourceParsedownElement($attributes, $reset) + { + return $this->textParsedownElement($attributes, $reset); + } + + public function textParsedownElement($attributes, $reset) + { + $text = empty($attributes['title']) ? empty($attributes['alt']) ? $this->get('filename') : $attributes['alt'] : $attributes['title']; + + $element = [ + 'name' => 'p', + 'attributes' => $attributes, + 'text' => $text + ]; + + if ($reset) { + $this->reset(); + } + + return $element; + } + + /** + * Reset medium. + * + * @return $this + */ + public function reset() + { + return $this; + } + + /** + * Switch display mode. + * + * @param string $mode + * + * @return $this + */ + public function display($mode) + { + if ($this->mode === $mode) + return $this; + + $this->mode = $mode; + + return $mode === 'thumbnail' ? $this->getThumbnail()->reset() : $this->reset(); + } + + /** + * Switch thumbnail. + * + * @param string $type + * + * @return $this + */ + public function thumbnail($type) + { + if (!in_array($type, $this->thumbnailTypes)) + return; + + if ($this->thumbnailType !== $type) { + $this->_thumbnail = null; + } + + $this->thumbnailType = $type; + + return $this; + } + /** * Enable link for the medium object. * @@ -197,18 +270,19 @@ class Medium extends Data * @param null $height * @return $this */ - public function link($width = null, $height = null, $reset = true) + public function link($reset = true) { - $this->linkAttributes['href'] = $this->url(); - - if ($width && $height) { - $this->linkAttributes['data-width'] = $width; - $this->linkAttributes['data-height'] = $height; + if ($this->mode !== 'source') { + $this->display('source'); } - - $this->mode = 'thumb'; - return $this; + $this->linkAttributes['href'] = $this->url(); + + $this->thumbnail('auto'); + $thumb = $this->display('thumbnail'); + $thumb->linked = true; + + return $thumb; } /** @@ -222,17 +296,12 @@ class Medium extends Data { $this->linkAttributes['rel'] = 'lightbox'; - return $this->link($width, $height); - } + if ($width && $height) { + $this->linkAttributes['data-width'] = $width; + $this->linkAttributes['data-height'] = $height; + } - /** - * Reset image. - * - * @return $this - */ - public function reset() - { - return $this; + return $this->link($reset); } /** @@ -244,74 +313,33 @@ class Medium extends Data */ public function __call($method, $args) { - if ($method == 'cropZoom') { - $method = 'zoomCrop'; - } - - $mode = $this->mode; - $target = null; - - if ($mode == 'medium') { - - $target = $this; - $valid = in_array($method, static::$magic_actions); - - $method = '_' . $method; - - } else if ($mode == 'thumb') { - - $target = $this->get('thumb'); - $target_class = get_class($target); - $valid = $target && in_array($method, $target_class::$magic_actions); - - } - - if ($valid) { - try { - $result = call_user_func_array(array($target, $method), $args); - } catch (\BadFunctionCallException $e) { - $result = null; - } - - if ($mode == 'thumb' && $result) { - $this->set('thumb', $result); - } - } - return $this; } - /** - * Add meta file for the medium. - * - * @param $type - * @return $this - */ - public function addMetaFile($filepath) + protected function getThumbnail() { - $this->merge(CompiledYamlFile::instance($filepath)->content()); + if (!$this->_thumbnail) { + $types = $this->thumbnailTypes; - return $this; - } + if ($this->thumbnailType !== 'auto') { + array_unshift($types, $this->thumbnailType); + } - /** - * Add alternative Medium to this Medium. - * - * @param $ratio - * @param Medium $alternative - */ - public function addAlternative($ratio, Medium $alternative) - { - if (!is_numeric($ratio) || $ratio === 0) { - return; + foreach ($types as $type) { + $thumb = $this->get('thumbnails.' . $type, false); + + if ($thumb) { + $thumb = $thumb instanceof ThumbnailMedium ? $thumb : Factory::fromFile($thumb, ['type' => 'thumbnail']); + $thumb->parent = $this; + } + + if ($thumb) { + $this->_thumbnail = $thumb; + break; + } + } } - $alternative->set('ratio', $ratio); - $this->alternatives[(float) $ratio] = $alternative; - } - - public function getAlternatives() - { - return $this->alternatives; + return $this->_thumbnail; } } diff --git a/system/src/Grav/Common/Page/Medium/MediumInterface.php b/system/src/Grav/Common/Page/Medium/MediumInterface.php new file mode 100644 index 000000000..6343bed8a --- /dev/null +++ b/system/src/Grav/Common/Page/Medium/MediumInterface.php @@ -0,0 +1,157 @@ +url($reset); + + !empty($this->width) && $attributes['width'] = $this->width; + !empty($this->height) && $attributes['height'] = $this->height; + + return [ 'name' => 'image', 'attributes' => $attributes ]; + } + + /** + * Enable link for the medium object. + * + * @param null $width + * @param null $height + * @return $this + */ + public function link($reset = true) + { + if ($this->mode !== 'source') { + $this->display('source'); + } + + !empty($this->width) && $this->linkAttributes['data-width'] = $this->width; + !empty($this->height) && $this->linkAttributes['data-height'] = $this->height; + + return parent::link($reset); + } + + protected function resize($width = null, $height = null) + { + $this->attributes['width'] = $width; + $this->attributes['height'] = $height; + + return $this; + } +} diff --git a/system/src/Grav/Common/Page/Medium/ThumbnailImageMedium.php b/system/src/Grav/Common/Page/Medium/ThumbnailImageMedium.php new file mode 100644 index 000000000..de8ead96c --- /dev/null +++ b/system/src/Grav/Common/Page/Medium/ThumbnailImageMedium.php @@ -0,0 +1,62 @@ +bubble('parsedownElement', [$title, $alt, $class, $reset]); + } + + public function html($title = null, $alt = null, $class = null, $reset = true) + { + return $this->bubble('html', [$title, $alt, $class, $reset]); + } + + public function display($mode) + { + return $this->bubble('display', [$mode], false); + } + + public function link($reset = true) + { + return $this->bubble('link', [$reset], false); + } + + public function lightbox($width = null, $height = null, $reset = true) + { + return $this->bubble('lightbox', [$width, $height, $reset], false); + } + + public function bubble($method, $arguments = [], $testLinked = true) + { + if (!$testLinked || $this->linked) { + return call_user_func_array(array($this->parent, $method), $arguments); + } else { + return call_user_func_array(array($this, 'parent::' . $method), $arguments); + } + } +} diff --git a/system/src/Grav/Common/Page/Medium/VideoMedium.php b/system/src/Grav/Common/Page/Medium/VideoMedium.php index 314cc458a..3a9dd5440 100644 --- a/system/src/Grav/Common/Page/Medium/VideoMedium.php +++ b/system/src/Grav/Common/Page/Medium/VideoMedium.php @@ -11,78 +11,61 @@ use Gregwar\Image\Image as ImageFile; class VideoMedium extends Medium { - protected $videoAttributes = []; + /** + * @var int + */ + protected $width = null; - public static $magic_actions = [ - 'resize' - ]; + /** + * @var int + */ + protected $height = null; - public function parsedownElement($title = null, $alt = null, $class = null, $reset = true) + public function __construct($items = array(), Blueprint $blueprint = null) { - $element; + parent::__construct($items, $blueprint); - if (!$this->linkAttributes) { - $video_location = $this->url(false); - $video_attributes = $this->videoAttributes; - $video_attributes['controls'] = true; + $this->attributes['controls'] = true; + } - if ($reset) { - $this->reset(); - } + public function sourceParsedownElement($attributes, $reset) + { + $attributes = $this->attributes; + $location = $this->url($reset); - $element = [ - 'name' => 'video', - 'text' => 'Your browser does not support the video tag.', - 'attributes' => $video_attributes - ]; - } else { + !empty($this->width) && $attributes['width'] = $this->width; + !empty($this->height) && $attributes['height'] = $this->height; + + return [ + 'name' => 'video', + 'text' => 'Your browser does not support the video tag.', + 'attributes' => $attributes + ]; + } - $thumbnail = $this->get('thumb'); - if ($thumbnail) { - $innerElement = $thumbnail->parsedownElement($title, $alt, $class, $reset); - } else { - $innerElement = $title ? $title : $this->path(false); - } - - $link_attributes = $this->linkAttributes; - - if (!empty($this->videoAttributes['width']) && empty($link_attributes['data-width'])) { - $link_attributes['data-width'] = $this->videoAttributes['width']; - } - - if (!empty($this->videoAttributes['height']) && empty($link_attributes['data-height'])) { - $link_attributes['data-height'] = $this->videoAttributes['height']; - } - - if ($class) { - $link_attributes['class'] = $class; - } - - $element = [ - 'name' => 'a', - 'attributes' => $link_attributes, - 'handler' => is_string($innerElement) ? 'line' : 'element', - 'text' => $innerElement - ]; - - $this->linkAttributes = []; - if ($reset) { - $this->reset(); - } + /** + * Enable link for the medium object. + * + * @param null $width + * @param null $height + * @return $this + */ + public function link($reset = true) + { + if ($this->mode !== 'source') { + $this->display('source'); } - return $element; + !empty($this->width) && $this->linkAttributes['data-width'] = $this->width; + !empty($this->height) && $this->linkAttributes['data-height'] = $this->height; + + return parent::link($reset); } - public function reset() + protected function resize($width = null, $height = null) { - $this->videoAttributes = []; - } - - protected function _resize($width = null, $height = null) - { - $this->videoAttributes['width'] = $width; - $this->videoAttributes['height'] = $height; + $this->attributes['width'] = $width; + $this->attributes['height'] = $height; return $this; } From a5d31e7187ded61bdb2bb4eb536be94ce51eb11e Mon Sep 17 00:00:00 2001 From: Gert Date: Sun, 22 Feb 2015 00:01:44 +0100 Subject: [PATCH 07/29] allow duplicated actions and follow medium on action --- .../src/Grav/Common/Markdown/ParsedownGravTrait.php | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/system/src/Grav/Common/Markdown/ParsedownGravTrait.php b/system/src/Grav/Common/Markdown/ParsedownGravTrait.php index ef6c8b12c..fe5aa5167 100644 --- a/system/src/Grav/Common/Markdown/ParsedownGravTrait.php +++ b/system/src/Grav/Common/Markdown/ParsedownGravTrait.php @@ -154,12 +154,18 @@ trait ParsedownGravTrait // if there is a query, then parse it and build action calls if (isset($url['query'])) { - parse_str($url['query'], $actions); + $actions = array_reduce(explode('&', $url['query']), function ($carry, $item) { + $parts = explode('=', $item, 2); + $value = isset($parts[1]) ? $parts[1] : null; + $carry[] = [ 'method' => $parts[0], 'params' => $value ]; + + return $carry; + }, []); } // loop through actions for the image and call them - foreach ($actions as $action => $params) { - call_user_func_array(array(&$medium, $action), explode(',', $params)); + foreach ($actions as $action) { + $medium = call_user_func_array(array($medium, $action['method']), explode(',', $action['params'])); } $excerpt['element'] = $medium->parseDownElement($title, $alt, $class); From f30a3c137e9735bbc55c84997b538c8deda75fcf Mon Sep 17 00:00:00 2001 From: Gert Date: Sun, 22 Feb 2015 00:01:55 +0100 Subject: [PATCH 08/29] define new types --- system/config/media.yaml | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/system/config/media.yaml b/system/config/media.yaml index 057d8be91..62dfa75eb 100644 --- a/system/config/media.yaml +++ b/system/config/media.yaml @@ -20,10 +20,15 @@ png: thumb: media/thumb-png.png mime: image/png gif: - type: image + type: animated thumb: media/thumb-gif.png mime: image/gif +svg: + type: vector + thumb: media/thumb-gif.png + mime: image/svg+xml + mp4: type: video thumb: media/thumb-mp4.png From 68a561d4fb0b1b832452f77400d1aad486b7a86b Mon Sep 17 00:00:00 2001 From: Andy Miller Date: Thu, 26 Mar 2015 11:24:22 -0600 Subject: [PATCH 09/29] Missing 'quality' in valid image functions --- system/src/Grav/Common/Page/Medium.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/system/src/Grav/Common/Page/Medium.php b/system/src/Grav/Common/Page/Medium.php index 224317b79..0bf438133 100644 --- a/system/src/Grav/Common/Page/Medium.php +++ b/system/src/Grav/Common/Page/Medium.php @@ -56,7 +56,7 @@ class Medium extends Data 'format', 'lightbox', 'link', 'reset', // Gregwar Image functions - 'resize', 'forceResize', 'cropResize', 'crop', 'cropZoom', + 'resize', 'forceResize', 'cropResize', 'crop', 'cropZoom', 'quality', 'negate', 'brightness', 'contrast', 'grayscale', 'emboss', 'smooth', 'sharp', 'edge', 'colorize', 'sepia' ]; public static $size_param_actions = [ From 0d9ddb92d588b4b0100fca295feaa4f784db2554 Mon Sep 17 00:00:00 2001 From: Andy Miller Date: Thu, 26 Mar 2015 11:32:17 -0600 Subject: [PATCH 10/29] Moved default image quality to defines.php --- system/defines.php | 3 +++ system/src/Grav/Common/Page/Medium.php | 8 ++++---- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/system/defines.php b/system/defines.php index f915c3815..91ec2ac70 100644 --- a/system/defines.php +++ b/system/defines.php @@ -40,3 +40,6 @@ define('RAW_CONTENT', 1); define('TWIG_CONTENT', 2); define('TWIG_CONTENT_LIST', 3); define('TWIG_TEMPLATES', 4); + +// Other defines +define('DEFAULT_IMG_QUALITY', 85); diff --git a/system/src/Grav/Common/Page/Medium.php b/system/src/Grav/Common/Page/Medium.php index 0bf438133..1e3264147 100644 --- a/system/src/Grav/Common/Page/Medium.php +++ b/system/src/Grav/Common/Page/Medium.php @@ -48,7 +48,7 @@ class Medium extends Data protected $image; protected $type = 'guess'; - protected $quality = 85; + protected $quality = DEFAULT_IMG_QUALITY; protected $debug_watermarked = false; public static $valid_actions = [ @@ -206,7 +206,7 @@ class Medium extends Data * @param bool $reset * @return string */ - public function img($title = null, $class = null, $type = null, $quality = 80, $reset = true) + public function img($title = null, $class = null, $type = null, $quality = DEFAULT_IMG_QUALITY, $reset = true) { if (!$this->image) { $this->image(); @@ -299,7 +299,7 @@ class Medium extends Data * @param int $quality * @return $this */ - public function format($type = null, $quality = 80) + public function format($type = null, $quality = DEFAULT_IMG_QUALITY) { if (!$this->image) { $this->image(); @@ -366,7 +366,7 @@ class Medium extends Data $this->filter(); } $this->type = 'guess'; - $this->quality = 80; + $this->quality = DEFAULT_IMG_QUALITY; $this->debug_watermarked = false; return $this; From e4a130c9194466f8832ad9dd0ab3f82f4b237e9f Mon Sep 17 00:00:00 2001 From: Andy Miller Date: Sat, 28 Mar 2015 14:52:35 -0600 Subject: [PATCH 11/29] switched to && operator --- system/src/Grav/Common/Markdown/ParsedownGravTrait.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/system/src/Grav/Common/Markdown/ParsedownGravTrait.php b/system/src/Grav/Common/Markdown/ParsedownGravTrait.php index c507606bd..3d24860c9 100644 --- a/system/src/Grav/Common/Markdown/ParsedownGravTrait.php +++ b/system/src/Grav/Common/Markdown/ParsedownGravTrait.php @@ -227,7 +227,7 @@ trait ParsedownGravTrait $url = parse_url(htmlspecialchars_decode($excerpt['element']['attributes']['href'])); // if there is no scheme, the file is local - if (!isset($url['scheme']) and (count($url) > 0)) { + if (!isset($url['scheme']) && (count($url) > 0)) { // convert the URl is required $excerpt['element']['attributes']['href'] = $this->convertUrl(Uri::buildUrl($url)); } From 53dd6c0860ae5fa1cea417bc6a9e650f4e34014d Mon Sep 17 00:00:00 2001 From: Gert Date: Tue, 31 Mar 2015 21:23:14 +0200 Subject: [PATCH 12/29] multimedia refactor finishing touches --- .../Common/Markdown/ParsedownGravTrait.php | 7 +- system/src/Grav/Common/Page/Media.php | 5 +- .../src/Grav/Common/Page/Medium/Factory.php | 41 +++-- .../Grav/Common/Page/Medium/ImageMedium.php | 133 ++++++++------- system/src/Grav/Common/Page/Medium/Link.php | 64 +++++++ system/src/Grav/Common/Page/Medium/Medium.php | 153 +++++++++-------- .../Common/Page/Medium/MediumInterface.php | 157 ------------------ .../Common/Page/Medium/ParsedownHtmlTrait.php | 31 ++++ .../Page/Medium/RenderableInterface.php | 34 ++++ .../Common/Page/Medium/StaticImageMedium.php | 54 +----- .../Common/Page/Medium/StaticResizeTrait.php | 20 +++ .../Page/Medium/ThumbnailImageMedium.php | 70 ++++++-- .../Grav/Common/Page/Medium/VideoMedium.php | 50 ++---- 13 files changed, 420 insertions(+), 399 deletions(-) create mode 100644 system/src/Grav/Common/Page/Medium/Link.php delete mode 100644 system/src/Grav/Common/Page/Medium/MediumInterface.php create mode 100644 system/src/Grav/Common/Page/Medium/ParsedownHtmlTrait.php create mode 100644 system/src/Grav/Common/Page/Medium/RenderableInterface.php create mode 100644 system/src/Grav/Common/Page/Medium/StaticResizeTrait.php diff --git a/system/src/Grav/Common/Markdown/ParsedownGravTrait.php b/system/src/Grav/Common/Markdown/ParsedownGravTrait.php index 4674af187..55e4e3b47 100644 --- a/system/src/Grav/Common/Markdown/ParsedownGravTrait.php +++ b/system/src/Grav/Common/Markdown/ParsedownGravTrait.php @@ -45,7 +45,7 @@ trait ParsedownGravTrait /** * Make the element function publicly accessible, Medium uses this to render from Twig - * + * * @param array $Element * @return string markup */ @@ -168,6 +168,11 @@ trait ParsedownGravTrait $medium = call_user_func_array(array($medium, $action['method']), explode(',', $action['params'])); } + if (isset($url['fragment'])) { + $medium->urlHash($url['fragment']); + } + self::$grav['debugger']->addMessage($url); + $excerpt['element'] = $medium->parseDownElement($title, $alt, $class); } else { diff --git a/system/src/Grav/Common/Page/Media.php b/system/src/Grav/Common/Page/Media.php index b54d26db3..65bcba96a 100644 --- a/system/src/Grav/Common/Page/Media.php +++ b/system/src/Grav/Common/Page/Media.php @@ -76,7 +76,6 @@ class Media extends Getters if (!empty($types['base'])) { $medium = MediumFactory::fromFile($types['base']); } else if (!empty($types['alternative'])) { - $altMedium = reset($types['alternative']); $ratio = key($types['alternative']); @@ -101,7 +100,7 @@ class Media extends Getters if (!empty($types['alternative'])) { $alternatives = $types['alternative']; - + $max = max(array_keys($alternatives)); for ($i=2; $i < $max; $i++) { @@ -112,7 +111,7 @@ class Media extends Getters $types['alternative'][$i] = MediumFactory::scaledFromMedium($alternatives[$max], $max, $i); } - + foreach ($types['alternative'] as $ratio => $altMedium) { $medium->addAlternative($ratio, $altMedium); } diff --git a/system/src/Grav/Common/Page/Medium/Factory.php b/system/src/Grav/Common/Page/Medium/Factory.php index 2f0beeb74..7babbeae9 100644 --- a/system/src/Grav/Common/Page/Medium/Factory.php +++ b/system/src/Grav/Common/Page/Medium/Factory.php @@ -1,17 +1,12 @@ get('media.defaults'); - $params += array( + $params += [ 'type' => 'file', 'thumb' => 'media/thumb.png', 'mime' => 'application/octet-stream', @@ -55,7 +57,7 @@ class Factory 'path' => $path, 'modified' => filemtime($file), 'thumbnails' => [] - ); + ]; $locator = self::getGrav()['locator']; @@ -70,7 +72,14 @@ class Factory return static::fromArray($params); } - public static function fromArray($items = array(), Blueprint $blueprint = null) + /** + * Create Medium from array of parameters + * + * @param array $items + * @param Blueprint|null $blueprint + * @return Medium + */ + public static function fromArray(array $items = [], Blueprint $blueprint = null) { $type = isset($items['type']) ? $items['type'] : null; @@ -94,6 +103,14 @@ class Factory } } + /** + * Create a new ImageMedium by scaling another ImageMedium object. + * + * @param ImageMedium $medium + * @param int $from + * @param int $to + * @return Medium + */ public static function scaledFromMedium($medium, $from, $to) { if (! $medium instanceof ImageMedium) @@ -125,4 +142,4 @@ class Factory return $medium; } -} \ No newline at end of file +} diff --git a/system/src/Grav/Common/Page/Medium/ImageMedium.php b/system/src/Grav/Common/Page/Medium/ImageMedium.php index 80cb85a09..588af85c1 100644 --- a/system/src/Grav/Common/Page/Medium/ImageMedium.php +++ b/system/src/Grav/Common/Page/Medium/ImageMedium.php @@ -1,12 +1,7 @@ saveImage(); if ($reset) $this->reset(); - - return GRAV_ROOT . '/' . $output; + + return $output; } /** @@ -116,13 +111,11 @@ class ImageMedium extends Medium */ public function url($reset = true) { - $output = '/' . $this->saveImage(); + $output = preg_replace('|^' . GRAV_ROOT . '|', '', $this->saveImage()); - if ($reset) { - $this->reset(); - } + if ($reset) $this->reset(); - return self::$grav['base_url'] . $output; + return self::$grav['base_url'] . $output . $this->urlHash(); } @@ -151,16 +144,20 @@ class ImageMedium extends Medium } /** - * Called from Parsedown (ParsedownGravTrait::inlineImage calls this method on the Medium) + * Parsedown element for source display mode + * + * @param array $attributes + * @param boolean $reset + * @return array */ - public function sourceParsedownElement($attributes, $reset = true) + public function sourceParsedownElement(array $attributes, $reset = true) { empty($attributes['src']) && $attributes['src'] = $this->url(false); - + $srcset = $this->srcset($reset); if ($srcset) { empty($attributes['srcset']) && $attributes['srcset'] = $srcset; - empty($attributes['sizes']) && $attributes['sizes'] = '100vw'; + empty($attributes['sizes']) && $attributes['sizes'] = $this->sizes(); } return [ 'name' => 'image', 'attributes' => $attributes ]; @@ -173,51 +170,46 @@ class ImageMedium extends Medium */ public function reset() { - $this->image = null; + parent::reset(); - $this->image(); - $this->filter(); + if ($this->image) { + $this->image(); + $this->filter(); + } $this->format = 'guess'; - $this->quality = 80; + $this->quality = 85; + $this->debug_watermarked = false; - return parent::reset(); + return $this; } /** - * Enable link for the medium object. + * Turn the current Medium into a Link * - * @param null $width - * @param null $height - * @return $this + * @param boolean $reset + * @param array $attributes + * @return Link */ - public function link($reset = true) + public function link($reset = true, array $attributes = []) { - if ($this->mode !== 'source') { - $this->display('source'); - } - - $this->linkAttributes['href'] = $this->url(false); - $srcset = $this->srcset($reset); - + $attributes['href'] = $this->url(false); + $srcset = $this->srcset(false); if ($srcset) { - $this->linkAttributes['data-srcset'] = $srcset; + $attributes['data-srcset'] = $srcset; } - $this->thumbnail('auto'); - $thumb = $this->display('thumbnail'); - $thumb->linked = true; - - return $thumb; + return parent::link($reset, $attributes); } /** - * Enable lightbox for the medium. + * Turn the current Medium inta a Link with lightbox enabled * - * @param null $width - * @param null $height - * @return Medium + * @param int $width + * @param int $height + * @param boolean $reset + * @return Link */ public function lightbox($width = null, $height = null, $reset = true) { @@ -234,11 +226,16 @@ class ImageMedium extends Medium /** * Sets the quality of the image - * @param Int $quality 0-100 quality + * + * @param int $quality 0-100 quality * @return Medium */ public function quality($quality) { + if (!$this->image) { + $this->image(); + } + $this->quality = $quality; return $this; } @@ -247,15 +244,34 @@ class ImageMedium extends Medium * Sets image output format. * * @param string $format - * @param int $quality * @return $this */ public function format($format) { + if (!$this->image) { + $this->image(); + } + $this->format = $format; return $this; } + /** + * Set or get sizes parameter for srcset media action + * + * @param string $sizes + * @return $this + */ + public function sizes($sizes = null) { + + if ($sizes) { + $this->attributes['sizes'] = $sizes; + return $this; + } + + return empty($this->attributes['sizes']) ? '100vw' : $this->attributes['sizes']; + } + /** * Forward the call to the image processing method. * @@ -279,7 +295,7 @@ class ImageMedium extends Medium } try { - $result = call_user_func_array(array($this->image, $method), $args); + $result = call_user_func_array([$this->image, $method], $args); foreach ($this->alternatives as $ratio => $medium) { $args_copy = $args; @@ -294,7 +310,7 @@ class ImageMedium extends Medium } } - call_user_func_array(array($medium, $method), $args_copy); + call_user_func_array([$medium, $method], $args_copy); } } catch (\BadFunctionCallException $e) { } @@ -311,11 +327,12 @@ class ImageMedium extends Medium { $locator = self::$grav['locator']; - // TODO: add default file $file = $this->get('filepath'); + $cacheDir = $locator->findResource('cache://images', true); + $this->image = ImageFile::open($file) - ->setCacheDir($locator->findResource('cache://images', false)) - ->setActualCacheDir($locator->findResource('cache://images', true)) + ->setCacheDir($cacheDir) + ->setActualCacheDir($cacheDir) ->setPrettyName(basename($this->get('basename'))); $this->filter(); @@ -331,7 +348,7 @@ class ImageMedium extends Medium protected function saveImage() { if (!$this->image) { - $this->image(); + return parent::path(false); } if ($this->get('debug') && !$this->debug_watermarked) { @@ -345,7 +362,9 @@ class ImageMedium extends Medium $this->image->merge(ImageFile::open($overlay)); } - return $this->image->cacheFile($this->format, $this->quality); + $result = $this->image->cacheFile($this->format, $this->quality); + + return $result; } /** @@ -355,7 +374,7 @@ class ImageMedium extends Medium */ public function filter($filter = 'image.filters.default') { - $filters = (array) $this->get($filter, array()); + $filters = (array) $this->get($filter, []); foreach ($filters as $params) { $params = (array) $params; $method = array_shift($params); diff --git a/system/src/Grav/Common/Page/Medium/Link.php b/system/src/Grav/Common/Page/Medium/Link.php new file mode 100644 index 000000000..88c8bb08d --- /dev/null +++ b/system/src/Grav/Common/Page/Medium/Link.php @@ -0,0 +1,64 @@ +attributes = $attributes; + $this->source = $medium->reset()->thumbnail('auto')->display('thumbnail'); + $this->source->linked = true; + } + + /** + * Get an element (is array) that can be rendered by the Parsedown engine + * + * @param string $title + * @param string $alt + * @param string $class + * @param boolean $reset + * @return array + */ + public function parsedownElement($title = null, $alt = null, $class = null, $reset = true) + { + $innerElement = $this->source->parsedownElement($title, $alt, $class, $reset); + + return [ + 'name' => 'a', + 'attributes' => $this->attributes, + 'handler' => is_string($innerElement) ? 'line' : 'element', + 'text' => $innerElement + ]; + } + + /** + * Forward the call to the source element + * + * @param string $method + * @param mixed $args + * @return $this|mixed + */ + public function __call($method, $args) + { + $this->source = call_user_func_array(array($this->source, $method), $args); + + // Don't start nesting links, if user has multiple link calls in his + // actions, we will drop the previous links. + return $this->source instanceof LinkMedium ? $this->source : $this; + } +} diff --git a/system/src/Grav/Common/Page/Medium/Medium.php b/system/src/Grav/Common/Page/Medium/Medium.php index 3fc255d8f..0c2ca4845 100644 --- a/system/src/Grav/Common/Page/Medium/Medium.php +++ b/system/src/Grav/Common/Page/Medium/Medium.php @@ -1,25 +1,21 @@ get('filepath')); - return self::$grav['base_url'] . $output; + if ($reset) $this->reset(); + + return self::$grav['base_url'] . $output . $this->urlHash(); } /** - * Return HTML markup from the medium. + * Get/set hash for the file's url * - * @param string $title - * @param string $class - * @param bool $reset + * @param string $hash + * @param boolean $withHash * @return string */ - public function html($title = null, $alt = null, $class = null, $reset = true) + public function urlHash($hash = null, $withHash = true) { - $element = $this->parsedownElement($title, $alt, $class, $reset); - - if (!$this->parsedown) { - $this->parsedown = new Parsedown(null); + if ($hash) { + $this->set('urlHash', ltrim($hash, '#')); } - return $this->parsedown->elementToHtml($element); + $hash = $this->get('urlHash', ''); + + if ($withHash && !empty($hash)) { + return '#' . $hash; + } else { + return $hash; + } } + /** + * Get an element (is array) that can be rendered by the Parsedown engine + * + * @param string $title + * @param string $alt + * @param string $class + * @param boolean $reset + * @return array + */ public function parsedownElement($title = null, $alt = null, $class = null, $reset = true) { $element; $attributes = $this->attributes; - $link_attributes = $this->linkAttributes; !empty($title) && empty($attributes['title']) && $attributes['title'] = $title; !empty($alt) && empty($attributes['alt']) && $attributes['alt'] = $alt; @@ -163,29 +162,18 @@ class Medium extends Data switch ($this->mode) { case 'text': - $element = $this->textParsedownElement($attributes, $reset); + $element = $this->textParsedownElement($attributes, false); break; case 'thumbnail': - $element = $this->getThumbnail()->sourceParsedownElement($attributes, $reset); + $element = $this->getThumbnail()->sourceParsedownElement($attributes, false); break; case 'source': - $element = $this->sourceParsedownElement($attributes, $reset); + $element = $this->sourceParsedownElement($attributes, false); break; } - if ($link_attributes) { - - $innerElement = $element; - $element = [ - 'name' => 'a', - 'attributes' => $this->linkAttributes, - 'handler' => is_string($innerElement) ? 'line' : 'element', - 'text' => $innerElement - ]; - - if ($reset) { - $this->linkAttributes = []; - } + if ($reset) { + $this->reset(); } $this->display('source'); @@ -193,12 +181,26 @@ class Medium extends Data return $element; } - public function sourceParsedownElement($attributes, $reset) + /** + * Parsedown element for source display mode + * + * @param array $attributes + * @param boolean $reset + * @return array + */ + protected function sourceParsedownElement(array $attributes, $reset = true) { return $this->textParsedownElement($attributes, $reset); } - public function textParsedownElement($attributes, $reset) + /** + * Parsedown element for text display mode + * + * @param array $attributes + * @param boolean $reset + * @return array + */ + protected function textParsedownElement(array $attributes, $reset = true) { $text = empty($attributes['title']) ? empty($attributes['alt']) ? $this->get('filename') : $attributes['alt'] : $attributes['title']; @@ -222,6 +224,7 @@ class Medium extends Data */ public function reset() { + $this->attributes = []; return $this; } @@ -232,7 +235,7 @@ class Medium extends Data * * @return $this */ - public function display($mode) + public function display($mode = 'source') { if ($this->mode === $mode) return $this; @@ -249,10 +252,10 @@ class Medium extends Data * * @return $this */ - public function thumbnail($type) + public function thumbnail($type = 'auto') { if (!in_array($type, $this->thumbnailTypes)) - return; + return $this; if ($this->thumbnailType !== $type) { $this->_thumbnail = null; @@ -264,58 +267,64 @@ class Medium extends Data } /** - * Enable link for the medium object. + * Turn the current Medium into a Link * - * @param null $width - * @param null $height - * @return $this + * @param boolean $reset + * @param array $attributes + * @return Link */ - public function link($reset = true) + public function link($reset = true, array $attributes = []) { if ($this->mode !== 'source') { $this->display('source'); } - $this->linkAttributes['href'] = $this->url(); + foreach ($this->attributes as $key => $value) { + empty($attributes['data-' . $key]) && $attributes['data-' . $key] = $value; + } - $this->thumbnail('auto'); - $thumb = $this->display('thumbnail'); - $thumb->linked = true; + empty($attributes['href']) && $attributes['href'] = $this->url(); - return $thumb; + return new Link($attributes, $this); } /** - * Enable lightbox for the medium. + * Turn the current Medium inta a Link with lightbox enabled * - * @param null $width - * @param null $height - * @return Medium + * @param int $width + * @param int $height + * @param boolean $reset + * @return Link */ public function lightbox($width = null, $height = null, $reset = true) { - $this->linkAttributes['rel'] = 'lightbox'; + $attributes = ['rel' => 'lightbox']; if ($width && $height) { - $this->linkAttributes['data-width'] = $width; - $this->linkAttributes['data-height'] = $height; + $attributes['data-width'] = $width; + $attributes['data-height'] = $height; } - return $this->link($reset); + return $this->link($reset, $attributes); } /** - * Forward the call to the image processing method. + * Allow any action to be called on this medium from twig or markdown * * @param string $method * @param mixed $args - * @return $this|mixed + * @return $this */ public function __call($method, $args) { return $this; } + /** + * Get the thumbnail Medium object + * + * @return ThumbnailImageMedium + */ protected function getThumbnail() { if (!$this->_thumbnail) { diff --git a/system/src/Grav/Common/Page/Medium/MediumInterface.php b/system/src/Grav/Common/Page/Medium/MediumInterface.php deleted file mode 100644 index 6343bed8a..000000000 --- a/system/src/Grav/Common/Page/Medium/MediumInterface.php +++ /dev/null @@ -1,157 +0,0 @@ -parsedownElement($title, $alt, $class, $reset); + + if (!$this->parsedown) { + $this->parsedown = new Parsedown(null); + } + + return $this->parsedown->elementToHtml($element); + } +} diff --git a/system/src/Grav/Common/Page/Medium/RenderableInterface.php b/system/src/Grav/Common/Page/Medium/RenderableInterface.php new file mode 100644 index 000000000..f1ebf0dfc --- /dev/null +++ b/system/src/Grav/Common/Page/Medium/RenderableInterface.php @@ -0,0 +1,34 @@ +url($reset); - !empty($this->width) && $attributes['width'] = $this->width; - !empty($this->height) && $attributes['height'] = $this->height; - return [ 'name' => 'image', 'attributes' => $attributes ]; } - - /** - * Enable link for the medium object. - * - * @param null $width - * @param null $height - * @return $this - */ - public function link($reset = true) - { - if ($this->mode !== 'source') { - $this->display('source'); - } - - !empty($this->width) && $this->linkAttributes['data-width'] = $this->width; - !empty($this->height) && $this->linkAttributes['data-height'] = $this->height; - - return parent::link($reset); - } - - protected function resize($width = null, $height = null) - { - $this->attributes['width'] = $width; - $this->attributes['height'] = $height; - - return $this; - } } diff --git a/system/src/Grav/Common/Page/Medium/StaticResizeTrait.php b/system/src/Grav/Common/Page/Medium/StaticResizeTrait.php new file mode 100644 index 000000000..6b37cef4b --- /dev/null +++ b/system/src/Grav/Common/Page/Medium/StaticResizeTrait.php @@ -0,0 +1,20 @@ +attributes['width'] = $width; + $this->attributes['height'] = $height; + + return $this; + } +} diff --git a/system/src/Grav/Common/Page/Medium/ThumbnailImageMedium.php b/system/src/Grav/Common/Page/Medium/ThumbnailImageMedium.php index de8ead96c..ff916b4f6 100644 --- a/system/src/Grav/Common/Page/Medium/ThumbnailImageMedium.php +++ b/system/src/Grav/Common/Page/Medium/ThumbnailImageMedium.php @@ -1,18 +1,16 @@ bubble('parsedownElement', [$title, $alt, $class, $reset]); } + /** + * Return HTML markup from the medium. + * + * @param string $title + * @param string $alt + * @param string $class + * @param bool $reset + * @return string + */ public function html($title = null, $alt = null, $class = null, $reset = true) { return $this->bubble('html', [$title, $alt, $class, $reset]); } - public function display($mode) + /** + * Switch display mode. + * + * @param string $mode + * + * @return $this + */ + public function display($mode = 'source') { return $this->bubble('display', [$mode], false); } - public function link($reset = true) + /** + * Turn the current Medium into a Link + * + * @param boolean $reset + * @param array $attributes + * @return Link + */ + public function link($reset = true, array $attributes = []) { - return $this->bubble('link', [$reset], false); + return $this->bubble('link', [$reset, $attributes], false); } + /** + * Turn the current Medium inta a Link with lightbox enabled + * + * @param int $width + * @param int $height + * @param boolean $reset + * @return Link + */ public function lightbox($width = null, $height = null, $reset = true) { return $this->bubble('lightbox', [$width, $height, $reset], false); } - public function bubble($method, $arguments = [], $testLinked = true) + /** + * Bubble a function call up to either the superclass function or the parent Medium instance + * + * @param string $method + * @param array $arguments + * @param boolean $testLinked + * @return Medium + */ + protected function bubble($method, array $arguments = [], $testLinked = true) { if (!$testLinked || $this->linked) { return call_user_func_array(array($this->parent, $method), $arguments); diff --git a/system/src/Grav/Common/Page/Medium/VideoMedium.php b/system/src/Grav/Common/Page/Medium/VideoMedium.php index 3a9dd5440..e67d3fbfc 100644 --- a/system/src/Grav/Common/Page/Medium/VideoMedium.php +++ b/system/src/Grav/Common/Page/Medium/VideoMedium.php @@ -11,31 +11,19 @@ use Gregwar\Image\Image as ImageFile; class VideoMedium extends Medium { - /** - * @var int - */ - protected $width = null; + use StaticResizeTrait; /** - * @var int + * Parsedown element for source display mode + * + * @param array $attributes + * @param boolean $reset + * @return array */ - protected $height = null; - - public function __construct($items = array(), Blueprint $blueprint = null) + protected function sourceParsedownElement(array $attributes, $reset = true) { - parent::__construct($items, $blueprint); - - $this->attributes['controls'] = true; - } - - public function sourceParsedownElement($attributes, $reset) - { - $attributes = $this->attributes; $location = $this->url($reset); - !empty($this->width) && $attributes['width'] = $this->width; - !empty($this->height) && $attributes['height'] = $this->height; - return [ 'name' => 'video', 'text' => 'Your browser does not support the video tag.', @@ -44,29 +32,15 @@ class VideoMedium extends Medium } /** - * Enable link for the medium object. + * Reset medium. * - * @param null $width - * @param null $height * @return $this */ - public function link($reset = true) + public function reset() { - if ($this->mode !== 'source') { - $this->display('source'); - } - - !empty($this->width) && $this->linkAttributes['data-width'] = $this->width; - !empty($this->height) && $this->linkAttributes['data-height'] = $this->height; - - return parent::link($reset); - } - - protected function resize($width = null, $height = null) - { - $this->attributes['width'] = $width; - $this->attributes['height'] = $height; + parent::reset(); + $this->attributes['controls'] = true; return $this; } -} \ No newline at end of file +} From 0ce364697789f5e4405c80ae6f0d0f1358393987 Mon Sep 17 00:00:00 2001 From: Gert Date: Tue, 31 Mar 2015 22:50:55 +0200 Subject: [PATCH 13/29] use style for static resize --- system/src/Grav/Common/Page/Medium/Medium.php | 11 +++++++++++ .../src/Grav/Common/Page/Medium/StaticResizeTrait.php | 4 ++-- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/system/src/Grav/Common/Page/Medium/Medium.php b/system/src/Grav/Common/Page/Medium/Medium.php index 0c2ca4845..e764e32ee 100644 --- a/system/src/Grav/Common/Page/Medium/Medium.php +++ b/system/src/Grav/Common/Page/Medium/Medium.php @@ -42,6 +42,11 @@ class Medium extends Data implements RenderableInterface */ protected $attributes = []; + /** + * @var array + */ + protected $styleAttributes = []; + /** * Construct. * @@ -156,6 +161,12 @@ class Medium extends Data implements RenderableInterface $attributes = $this->attributes; + $style = ''; + foreach ($this->styleAttributes as $key => $value) { + $style .= $key . ': ' . $value . ';'; + } + $attributes['style'] = $style; + !empty($title) && empty($attributes['title']) && $attributes['title'] = $title; !empty($alt) && empty($attributes['alt']) && $attributes['alt'] = $alt; !empty($class) && empty($attributes['class']) && $attributes['class'] = $class; diff --git a/system/src/Grav/Common/Page/Medium/StaticResizeTrait.php b/system/src/Grav/Common/Page/Medium/StaticResizeTrait.php index 6b37cef4b..df42dcf14 100644 --- a/system/src/Grav/Common/Page/Medium/StaticResizeTrait.php +++ b/system/src/Grav/Common/Page/Medium/StaticResizeTrait.php @@ -12,8 +12,8 @@ trait StaticResizeTrait */ public function resize($width = null, $height = null) { - $this->attributes['width'] = $width; - $this->attributes['height'] = $height; + $this->styleAttributes['width'] = $width . 'px'; + $this->styleAttributes['height'] = $height . 'px'; return $this; } From 467eb00f0f9a170c9a28913035d1bd17bfa5f32b Mon Sep 17 00:00:00 2001 From: Gert Date: Tue, 31 Mar 2015 22:52:41 +0200 Subject: [PATCH 14/29] rename factory to mediumfactory --- system/src/Grav/Common/Page/Media.php | 2 +- system/src/Grav/Common/Page/Medium/Medium.php | 2 +- .../Common/Page/Medium/{Factory.php => MediumFactory.php} | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) rename system/src/Grav/Common/Page/Medium/{Factory.php => MediumFactory.php} (96%) diff --git a/system/src/Grav/Common/Page/Media.php b/system/src/Grav/Common/Page/Media.php index 65bcba96a..037838c7f 100644 --- a/system/src/Grav/Common/Page/Media.php +++ b/system/src/Grav/Common/Page/Media.php @@ -6,7 +6,7 @@ use Grav\Common\Grav; use Grav\Common\Config\Config; use Grav\Common\GravTrait; use Grav\Common\Page\Medium\Medium; -use Grav\Common\Page\Medium\Factory as MediumFactory; +use Grav\Common\Page\Medium\MediumFactory; /** * Media is a holder object that contains references to the media of page. This object is created and diff --git a/system/src/Grav/Common/Page/Medium/Medium.php b/system/src/Grav/Common/Page/Medium/Medium.php index e764e32ee..de7e93250 100644 --- a/system/src/Grav/Common/Page/Medium/Medium.php +++ b/system/src/Grav/Common/Page/Medium/Medium.php @@ -349,7 +349,7 @@ class Medium extends Data implements RenderableInterface $thumb = $this->get('thumbnails.' . $type, false); if ($thumb) { - $thumb = $thumb instanceof ThumbnailMedium ? $thumb : Factory::fromFile($thumb, ['type' => 'thumbnail']); + $thumb = $thumb instanceof ThumbnailMedium ? $thumb : MediumFactory::fromFile($thumb, ['type' => 'thumbnail']); $thumb->parent = $this; } diff --git a/system/src/Grav/Common/Page/Medium/Factory.php b/system/src/Grav/Common/Page/Medium/MediumFactory.php similarity index 96% rename from system/src/Grav/Common/Page/Medium/Factory.php rename to system/src/Grav/Common/Page/Medium/MediumFactory.php index 7babbeae9..e26b8110a 100644 --- a/system/src/Grav/Common/Page/Medium/Factory.php +++ b/system/src/Grav/Common/Page/Medium/MediumFactory.php @@ -5,14 +5,14 @@ use Grav\Common\GravTrait; use Grav\Common\Data\Blueprint; /** - * Factory can be used to more easily create various Medium objects from files or arrays, it should + * MediumFactory can be used to more easily create various Medium objects from files or arrays, it should * contain most logic for instantiating a Medium object. * * @author Grav * @license MIT * */ -class Factory +class MediumFactory { use GravTrait; From d473f72eddcba184687d9e733713a52dac0b4f83 Mon Sep 17 00:00:00 2001 From: Gert Date: Wed, 1 Apr 2015 16:14:18 +0200 Subject: [PATCH 15/29] remove debugger line --- system/src/Grav/Common/Markdown/ParsedownGravTrait.php | 1 - 1 file changed, 1 deletion(-) diff --git a/system/src/Grav/Common/Markdown/ParsedownGravTrait.php b/system/src/Grav/Common/Markdown/ParsedownGravTrait.php index dde10eac4..dd4380b5c 100644 --- a/system/src/Grav/Common/Markdown/ParsedownGravTrait.php +++ b/system/src/Grav/Common/Markdown/ParsedownGravTrait.php @@ -171,7 +171,6 @@ trait ParsedownGravTrait if (isset($url['fragment'])) { $medium->urlHash($url['fragment']); } - self::$grav['debugger']->addMessage($url); $excerpt['element'] = $medium->parseDownElement($title, $alt, $class); From e014b1262674f2474bcaa2c39b4c8698d6b2b2b1 Mon Sep 17 00:00:00 2001 From: Gert Date: Wed, 1 Apr 2015 16:17:10 +0200 Subject: [PATCH 16/29] thumbnail selection fixes --- system/src/Grav/Common/Page/Medium/Medium.php | 2 +- .../Common/Page/Medium/ThumbnailImageMedium.php | 15 ++++++++++++++- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/system/src/Grav/Common/Page/Medium/Medium.php b/system/src/Grav/Common/Page/Medium/Medium.php index de7e93250..b47d97791 100644 --- a/system/src/Grav/Common/Page/Medium/Medium.php +++ b/system/src/Grav/Common/Page/Medium/Medium.php @@ -265,7 +265,7 @@ class Medium extends Data implements RenderableInterface */ public function thumbnail($type = 'auto') { - if (!in_array($type, $this->thumbnailTypes)) + if ($type !== 'auto' && !in_array($type, $this->thumbnailTypes)) return $this; if ($this->thumbnailType !== $type) { diff --git a/system/src/Grav/Common/Page/Medium/ThumbnailImageMedium.php b/system/src/Grav/Common/Page/Medium/ThumbnailImageMedium.php index ff916b4f6..3f40200cb 100644 --- a/system/src/Grav/Common/Page/Medium/ThumbnailImageMedium.php +++ b/system/src/Grav/Common/Page/Medium/ThumbnailImageMedium.php @@ -64,6 +64,19 @@ class ThumbnailImageMedium extends ImageMedium return $this->bubble('display', [$mode], false); } + /** + * Switch thumbnail. + * + * @param string $type + * + * @return $this + */ + public function thumbnail($type = 'auto') + { + $this->bubble('thumbnail', [$type], false); + return $this->bubble('getThumbnail', [], false); + } + /** * Turn the current Medium into a Link * @@ -100,7 +113,7 @@ class ThumbnailImageMedium extends ImageMedium protected function bubble($method, array $arguments = [], $testLinked = true) { if (!$testLinked || $this->linked) { - return call_user_func_array(array($this->parent, $method), $arguments); + return $this->parent ? call_user_func_array(array($this->parent, $method), $arguments) : $this; } else { return call_user_func_array(array($this, 'parent::' . $method), $arguments); } From 96b2b327b2a77f2362834a400d4cd7d7ce9549e9 Mon Sep 17 00:00:00 2001 From: Gert Date: Wed, 1 Apr 2015 16:51:24 +0200 Subject: [PATCH 17/29] reset on construct --- system/src/Grav/Common/Page/Medium/Medium.php | 1 + 1 file changed, 1 insertion(+) diff --git a/system/src/Grav/Common/Page/Medium/Medium.php b/system/src/Grav/Common/Page/Medium/Medium.php index b47d97791..52f8e8e95 100644 --- a/system/src/Grav/Common/Page/Medium/Medium.php +++ b/system/src/Grav/Common/Page/Medium/Medium.php @@ -58,6 +58,7 @@ class Medium extends Data implements RenderableInterface parent::__construct($items, $blueprint); $this->def('mime', 'application/octet-stream'); + $this->reset(); } /** From 0d8b46a1579ac592c9f8a3ad2d716ded9e1fc31c Mon Sep 17 00:00:00 2001 From: Andy Miller Date: Wed, 1 Apr 2015 17:27:51 -0600 Subject: [PATCH 18/29] fixed image element name --- system/src/Grav/Common/Page/Medium/ImageMedium.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/system/src/Grav/Common/Page/Medium/ImageMedium.php b/system/src/Grav/Common/Page/Medium/ImageMedium.php index 588af85c1..76854fe1d 100644 --- a/system/src/Grav/Common/Page/Medium/ImageMedium.php +++ b/system/src/Grav/Common/Page/Medium/ImageMedium.php @@ -160,7 +160,7 @@ class ImageMedium extends Medium empty($attributes['sizes']) && $attributes['sizes'] = $this->sizes(); } - return [ 'name' => 'image', 'attributes' => $attributes ]; + return [ 'name' => 'img', 'attributes' => $attributes ]; } /** From 105dc34b2aaf3616e1af3ca2b9704c9cb00c1066 Mon Sep 17 00:00:00 2001 From: Gert Date: Fri, 3 Apr 2015 11:30:35 +0200 Subject: [PATCH 19/29] don't scale @1x images, use them as base --- system/src/Grav/Common/Page/Media.php | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/system/src/Grav/Common/Page/Media.php b/system/src/Grav/Common/Page/Media.php index 037838c7f..bfa91267f 100644 --- a/system/src/Grav/Common/Page/Media.php +++ b/system/src/Grav/Common/Page/Media.php @@ -225,8 +225,12 @@ class Media extends Getters if (preg_match('/(.*)@(\d+)x\.(.*)$/', $filename, $matches)) { $name = $matches[1]; $extension = $matches[3]; - $type = 'alternative'; $extra = (int) $matches[2]; + + if ($extra === 1) { + $type = 'base'; + $extra = null; + } } else { $extension = null; while (($part = array_shift($fileParts)) !== null) { From 9c541ee20b36b79079f01251ed12c044c2958804 Mon Sep 17 00:00:00 2001 From: Gert Date: Sat, 4 Apr 2015 14:00:52 +0200 Subject: [PATCH 20/29] add filter function to iterator --- system/src/Grav/Common/Iterator.php | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/system/src/Grav/Common/Iterator.php b/system/src/Grav/Common/Iterator.php index 9105c0630..c9b0ee776 100644 --- a/system/src/Grav/Common/Iterator.php +++ b/system/src/Grav/Common/Iterator.php @@ -197,4 +197,23 @@ class Iterator implements \ArrayAccess, \Iterator, \Countable, \Serializable return $this; } + + /** + * Filter elements from the list + * @param callable|null $callback A function the receives ($value, $key) and must return a boolean to indicate filter status + * @return $this + */ + public function filter(callable $callback = null) + { + foreach ($this->items as $key => $value) { + if ( + ($callback && !call_user_func($callback, $value, $key)) || + (!$callback && !(bool) $value) + ) { + unset($this->items[$key]); + } + } + + return $this; + } } From d92d9bafc62257cdedde6b78e0632988bbd3ffec Mon Sep 17 00:00:00 2001 From: Gert Date: Sat, 4 Apr 2015 14:01:46 +0200 Subject: [PATCH 21/29] refactor Common/GPM namespace for more unified approach to installed vs remote packages --- .../Collection.php => AbstractCollection.php} | 14 ++-- .../GPM/Common/AbstractPackageCollection.php | 34 ++++++++ .../Common/GPM/Common/CachedCollection.php | 21 +++++ system/src/Grav/Common/GPM/Common/Package.php | 42 ++++++++++ .../GPM/Local/AbstractPackageCollection.php | 16 ++++ system/src/Grav/Common/GPM/Local/Package.php | 84 ++++--------------- system/src/Grav/Common/GPM/Local/Packages.php | 25 ++---- system/src/Grav/Common/GPM/Local/Plugins.php | 10 +-- system/src/Grav/Common/GPM/Local/Themes.php | 21 +++-- .../src/Grav/Common/GPM/PackageInterface.php | 58 +++++++++++++ ...tion.php => AbstractPackageCollection.php} | 43 +++------- system/src/Grav/Common/GPM/Remote/Grav.php | 18 ++-- system/src/Grav/Common/GPM/Remote/Package.php | 32 ++----- .../src/Grav/Common/GPM/Remote/Packages.php | 25 ++---- system/src/Grav/Common/GPM/Remote/Plugins.php | 27 +++--- system/src/Grav/Common/GPM/Remote/Themes.php | 27 +++--- system/src/Grav/Common/GPM/Response.php | 1 - 17 files changed, 283 insertions(+), 215 deletions(-) rename system/src/Grav/Common/GPM/{Local/Collection.php => AbstractCollection.php} (50%) create mode 100644 system/src/Grav/Common/GPM/Common/AbstractPackageCollection.php create mode 100644 system/src/Grav/Common/GPM/Common/CachedCollection.php create mode 100644 system/src/Grav/Common/GPM/Common/Package.php create mode 100644 system/src/Grav/Common/GPM/Local/AbstractPackageCollection.php create mode 100644 system/src/Grav/Common/GPM/PackageInterface.php rename system/src/Grav/Common/GPM/Remote/{Collection.php => AbstractPackageCollection.php} (61%) diff --git a/system/src/Grav/Common/GPM/Local/Collection.php b/system/src/Grav/Common/GPM/AbstractCollection.php similarity index 50% rename from system/src/Grav/Common/GPM/Local/Collection.php rename to system/src/Grav/Common/GPM/AbstractCollection.php index 9e3cf3638..7c1974d22 100644 --- a/system/src/Grav/Common/GPM/Local/Collection.php +++ b/system/src/Grav/Common/GPM/AbstractCollection.php @@ -1,19 +1,19 @@ items as $name => $theme) { - $items[$name] = $theme->toArray(); + foreach ($this->items as $name => $package) { + $items[$name] = $package->toArray(); } return json_encode($items); @@ -23,8 +23,8 @@ class Collection extends Iterator { $items = []; - foreach ($this->items as $name => $theme) { - $items[$name] = $theme->toArray(); + foreach ($this->items as $name => $package) { + $items[$name] = $package->toArray(); } return $items; diff --git a/system/src/Grav/Common/GPM/Common/AbstractPackageCollection.php b/system/src/Grav/Common/GPM/Common/AbstractPackageCollection.php new file mode 100644 index 000000000..46c9e894a --- /dev/null +++ b/system/src/Grav/Common/GPM/Common/AbstractPackageCollection.php @@ -0,0 +1,34 @@ +items as $name => $package) { + $items[$name] = $package->toArray(); + } + + return json_encode($items); + } + + public function toArray() + { + $items = []; + + foreach ($this->items as $name => $package) { + $items[$name] = $package->toArray(); + } + + return $items; + } +} diff --git a/system/src/Grav/Common/GPM/Common/CachedCollection.php b/system/src/Grav/Common/GPM/Common/CachedCollection.php new file mode 100644 index 000000000..fd6ae9420 --- /dev/null +++ b/system/src/Grav/Common/GPM/Common/CachedCollection.php @@ -0,0 +1,21 @@ + $item) { + $this->append([$name => $item]); + } + } +} diff --git a/system/src/Grav/Common/GPM/Common/Package.php b/system/src/Grav/Common/GPM/Common/Package.php new file mode 100644 index 000000000..ff9a087c9 --- /dev/null +++ b/system/src/Grav/Common/GPM/Common/Package.php @@ -0,0 +1,42 @@ +data = $package; + + if ($type) { + $this->data->set('package_type', $type); + } + } + + public function getData() { + return $this->data; + } + + public function __get($key) { + return $this->data->get($key); + } + + public function __isset($key) { + return isset($this->data->$key); + } + + public function __toString() { + return $this->toJson(); + } + + public function toJson() { + return $this->data->toJson(); + } + + public function toArray() { + return $this->data->toArray(); + } + +} diff --git a/system/src/Grav/Common/GPM/Local/AbstractPackageCollection.php b/system/src/Grav/Common/GPM/Local/AbstractPackageCollection.php new file mode 100644 index 000000000..314829378 --- /dev/null +++ b/system/src/Grav/Common/GPM/Local/AbstractPackageCollection.php @@ -0,0 +1,16 @@ + $data) { + $this->items[$name] = new Package($data, $this->type); + } + } +} diff --git a/system/src/Grav/Common/GPM/Local/Package.php b/system/src/Grav/Common/GPM/Local/Package.php index 4ba7bc0b4..6af4a4e1a 100644 --- a/system/src/Grav/Common/GPM/Local/Package.php +++ b/system/src/Grav/Common/GPM/Local/Package.php @@ -2,39 +2,24 @@ namespace Grav\Common\GPM\Local; use Grav\Common\Data\Data; +use Grav\Common\GPM\Common\Package as BasePackage; -/** - * Class Package - * @package Grav\Common\GPM\Local - */ -class Package +class Package extends BasePackage { - /** - * @var Data - */ - protected $data; - /** - * @var \Grav\Common\Data\Blueprint - */ - protected $blueprints; + protected $settings; - /** - * @param Data $package - * @param bool $package_type - */ - public function __construct(Data $package, $package_type = false) + public function __construct(Data $package, $package_type = null) { - $this->data = $package; - $this->blueprints = $this->data->blueprints(); + $data = new Data($package->blueprints()->toArray()); + parent::__construct($data, $package_type); - if ($package_type) { - $html_description = \Parsedown::instance()->line($this->blueprints->get('description')); - $this->blueprints->set('package_type', $package_type); - $this->blueprints->set('slug', $this->blueprints->name); - $this->blueprints->set('description_html', $html_description); - $this->blueprints->set('description_plain', strip_tags($html_description)); - $this->blueprints->set('symlink', is_link(USER_DIR . $package_type . DS . $this->blueprints->name)); - } + $this->settings = $package->toArray(); + + $html_description = \Parsedown::instance()->line($this->description); + $this->data->set('slug', $this->name); + $this->data->set('description_html', $html_description); + $this->data->set('description_plain', strip_tags($html_description)); + $this->data->set('symlink', is_link(USER_DIR . $package_type . DS . $this->name)); } /** @@ -42,47 +27,6 @@ class Package */ public function isEnabled() { - return $this->data['enabled']; - } - - /** - * @return Data - */ - public function getData() - { - return $this->data; - } - - /** - * @param $key - * @return mixed - */ - public function __get($key) - { - return $this->blueprints->get($key); - } - - /** - * @return string - */ - public function __toString() - { - return $this->toJson(); - } - - /** - * @return string - */ - public function toJson() - { - return $this->blueprints->toJson(); - } - - /** - * @return array - */ - public function toArray() - { - return $this->blueprints->toArray(); + return $this->settings['enabled']; } } diff --git a/system/src/Grav/Common/GPM/Local/Packages.php b/system/src/Grav/Common/GPM/Local/Packages.php index 4498e6895..a8ed6a455 100644 --- a/system/src/Grav/Common/GPM/Local/Packages.php +++ b/system/src/Grav/Common/GPM/Local/Packages.php @@ -1,28 +1,17 @@ new Plugins(), - 'themes' => new Themes() - ]; - } + $items = [ + 'plugins' => new Plugins(), + 'themes' => new Themes() + ]; - $this->plugins = self::$cache[__METHOD__]['plugins']; - $this->themes = self::$cache[__METHOD__]['themes']; - - $this->append(['plugins' => $this->plugins]); - $this->append(['themes' => $this->themes]); + parent::__construct($items); } } diff --git a/system/src/Grav/Common/GPM/Local/Plugins.php b/system/src/Grav/Common/GPM/Local/Plugins.php index b52efea93..b1c3c64a7 100644 --- a/system/src/Grav/Common/GPM/Local/Plugins.php +++ b/system/src/Grav/Common/GPM/Local/Plugins.php @@ -5,22 +5,18 @@ namespace Grav\Common\GPM\Local; * Class Plugins * @package Grav\Common\GPM\Local */ -class Plugins extends Collection +class Plugins extends AbstractPackageCollection { /** * @var string */ - private $type = 'plugins'; + protected $type = 'plugins'; /** * Local Plugins Constructor */ public function __construct() { - $grav = self::getGrav(); - - foreach ($grav['plugins']->all() as $name => $data) { - $this->items[$name] = new Package($data, $this->type); - } + parent::__construct(self::getGrav()['plugins']->all()); } } diff --git a/system/src/Grav/Common/GPM/Local/Themes.php b/system/src/Grav/Common/GPM/Local/Themes.php index 673490144..64d23b903 100644 --- a/system/src/Grav/Common/GPM/Local/Themes.php +++ b/system/src/Grav/Common/GPM/Local/Themes.php @@ -1,15 +1,22 @@ all() as $name => $data) { - $this->items[$name] = new Package($data, $this->type); - } + parent::__construct(self::getGrav()['themes']->all()); } } diff --git a/system/src/Grav/Common/GPM/PackageInterface.php b/system/src/Grav/Common/GPM/PackageInterface.php new file mode 100644 index 000000000..ad856c08f --- /dev/null +++ b/system/src/Grav/Common/GPM/PackageInterface.php @@ -0,0 +1,58 @@ +findResource('cache://gpm', true, true); @@ -35,28 +35,11 @@ class Collection extends Iterator { $this->repository = $repository; $this->raw = $this->cache->fetch(md5($this->repository)); - } - public function toJson() - { - $items = []; - - foreach ($this->items as $name => $theme) { - $items[$name] = $theme->toArray(); + $this->fetch($refresh, $callback); + foreach (json_decode($this->raw, true) as $slug => $data) { + $this->items[$slug] = new Package($data, $this->type); } - - return json_encode($items); - } - - public function toArray() - { - $items = []; - - foreach ($this->items as $name => $theme) { - $items[$name] = $theme->toArray(); - } - - return $items; } public function fetch($refresh = false, $callback = null) diff --git a/system/src/Grav/Common/GPM/Remote/Grav.php b/system/src/Grav/Common/GPM/Remote/Grav.php index 8e6510060..ed5582d57 100644 --- a/system/src/Grav/Common/GPM/Remote/Grav.php +++ b/system/src/Grav/Common/GPM/Remote/Grav.php @@ -1,9 +1,11 @@ repository); + $cache_dir = self::getGrav()['locator']->findResource('cache://gpm', true, true); + $this->cache = new FilesystemCache($cache_dir); + $this->raw = $this->cache->fetch(md5($this->repository)); $this->fetch($refresh, $callback); - $this->data = json_decode($this->raw); - $this->version = @$this->data->version ?: '-'; - $this->date = @$this->data->date ?: '-'; + $this->data = json_decode($this->raw, true); + $this->version = @$this->data['version'] ?: '-'; + $this->date = @$this->data['date'] ?: '-'; - foreach ($this->data->assets as $slug => $data) { + foreach ($this->data['assets'] as $slug => $data) { $this->items[$slug] = new Package($data); } } diff --git a/system/src/Grav/Common/GPM/Remote/Package.php b/system/src/Grav/Common/GPM/Remote/Package.php index 45da29478..9b0367f66 100644 --- a/system/src/Grav/Common/GPM/Remote/Package.php +++ b/system/src/Grav/Common/GPM/Remote/Package.php @@ -1,32 +1,12 @@ data = $package; - if ($package_type) { - $this->data->package_type = $package_type; - } - } +use Grav\Common\Data\Data; +use Grav\Common\GPM\Common\Package as BasePackage; - public function getData() { - return $this->data; +class Package extends BasePackage { + public function __construct($package, $package_type = null) { + $data = new Data($package); + parent::__construct($data, $package_type); } - - public function __get($key) { - return $this->data->$key; - } - - public function __toString() { - return $this->toJson(); - } - - public function toJson() { - return json_encode($this->data); - } - - public function toArray() { - return $this->data; - } - } diff --git a/system/src/Grav/Common/GPM/Remote/Packages.php b/system/src/Grav/Common/GPM/Remote/Packages.php index f78e9c67e..75f397fa3 100644 --- a/system/src/Grav/Common/GPM/Remote/Packages.php +++ b/system/src/Grav/Common/GPM/Remote/Packages.php @@ -1,28 +1,17 @@ new Plugins($refresh, $callback), - 'themes' => new Themes($refresh, $callback) - ]; - } + $items = [ + 'plugins' => new Plugins($refresh, $callback), + 'themes' => new Themes($refresh, $callback) + ]; - $this->plugins = self::$cache[__METHOD__]['plugins']->toArray(); - $this->themes = self::$cache[__METHOD__]['themes']->toArray(); - - $this->append(['plugins' => $this->plugins]); - $this->append(['themes' => $this->themes]); + parent::__construct($items); } } diff --git a/system/src/Grav/Common/GPM/Remote/Plugins.php b/system/src/Grav/Common/GPM/Remote/Plugins.php index fa71fbab6..ec6d64521 100644 --- a/system/src/Grav/Common/GPM/Remote/Plugins.php +++ b/system/src/Grav/Common/GPM/Remote/Plugins.php @@ -1,21 +1,24 @@ repository); - - $this->fetch($refresh, $callback); - $this->data = json_decode($this->raw); - - foreach ($this->data as $slug => $data) { - $this->items[$slug] = new Package($data, $this->type); - } + parent::__construct($this->repository, $refresh, $callback); } } diff --git a/system/src/Grav/Common/GPM/Remote/Themes.php b/system/src/Grav/Common/GPM/Remote/Themes.php index fcb5a34c4..759b7e10a 100644 --- a/system/src/Grav/Common/GPM/Remote/Themes.php +++ b/system/src/Grav/Common/GPM/Remote/Themes.php @@ -1,21 +1,24 @@ repository); - - $this->fetch($refresh, $callback); - $this->data = json_decode($this->raw); - - foreach ($this->data as $slug => $data) { - $this->items[$slug] = new Package($data, $this->type); - } + parent::__construct($this->repository, $refresh, $callback); } } diff --git a/system/src/Grav/Common/GPM/Response.php b/system/src/Grav/Common/GPM/Response.php index 211b2a415..530415870 100644 --- a/system/src/Grav/Common/GPM/Response.php +++ b/system/src/Grav/Common/GPM/Response.php @@ -78,7 +78,6 @@ class Response $method = 'get' . ucfirst(strtolower(self::$method)); self::$callback = $callback; - return static::$method($uri, $options, $callback); } From 82bd54eb0bbeabc65d682e9cce91ced01c15c861 Mon Sep 17 00:00:00 2001 From: Gert Date: Sat, 4 Apr 2015 14:02:28 +0200 Subject: [PATCH 22/29] update Console/GPM for refactored Common/GPM --- system/src/Grav/Console/Gpm/InfoCommand.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/system/src/Grav/Console/Gpm/InfoCommand.php b/system/src/Grav/Console/Gpm/InfoCommand.php index 721583032..53290b8ec 100644 --- a/system/src/Grav/Console/Gpm/InfoCommand.php +++ b/system/src/Grav/Console/Gpm/InfoCommand.php @@ -78,12 +78,12 @@ class InfoCommand extends Command $this->output->writeln(''); $packageURL = ''; - if (isset($foundPackage->author->url)) { - $packageURL = '<' . $foundPackage->author->url . '>'; + if (isset($foundPackage->author['url'])) { + $packageURL = '<' . $foundPackage->author['url'] . '>'; } $this->output->writeln("" . str_pad("Author", - 12) . ": " . $foundPackage->author->name . ' <' . $foundPackage->author->email . '> ' . $packageURL); + 12) . ": " . $foundPackage->author['name'] . ' <' . $foundPackage->author['email'] . '> ' . $packageURL); foreach (array( 'version', From 0a26772e354969930f8aeb51d53eb97c46faae6e Mon Sep 17 00:00:00 2001 From: Gert Date: Mon, 6 Apr 2015 23:26:53 +0200 Subject: [PATCH 23/29] fix alternative type not detected anymore --- system/src/Grav/Common/Page/Media.php | 1 + 1 file changed, 1 insertion(+) diff --git a/system/src/Grav/Common/Page/Media.php b/system/src/Grav/Common/Page/Media.php index bfa91267f..15296c9ac 100644 --- a/system/src/Grav/Common/Page/Media.php +++ b/system/src/Grav/Common/Page/Media.php @@ -226,6 +226,7 @@ class Media extends Getters $name = $matches[1]; $extension = $matches[3]; $extra = (int) $matches[2]; + $type = 'alternative'; if ($extra === 1) { $type = 'base'; From 8179d8eac15f28870b8c5ea40beb0887a8422340 Mon Sep 17 00:00:00 2001 From: Andy Miller Date: Tue, 7 Apr 2015 09:10:42 -0600 Subject: [PATCH 24/29] updated composer packages --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index eae309e79..53bcf0113 100644 --- a/composer.json +++ b/composer.json @@ -15,7 +15,7 @@ "doctrine/cache": "~1.3", "maximebf/debugbar": "dev-master", "filp/whoops": "1.2.*@dev", - "monolog/monolog": "~1.1", + "monolog/monolog": "~1.0", "gregwar/image": "~2.0", "ircmaxell/password-compat": "1.0.*", "mrclay/minify": "dev-master", From 4b3abc282a0610c992a59bcf01556e74bfa532df Mon Sep 17 00:00:00 2001 From: Andy Miller Date: Tue, 7 Apr 2015 12:42:48 -0600 Subject: [PATCH 25/29] PSR Fixes --- system/src/Grav/Common/Page/Media.php | 2 -- .../Grav/Common/Page/Medium/ImageMedium.php | 24 ++++++++++++------- system/src/Grav/Common/Page/Medium/Link.php | 1 + system/src/Grav/Common/Page/Medium/Medium.php | 20 +++++++++++----- .../Grav/Common/Page/Medium/MediumFactory.php | 3 ++- system/src/Grav/Common/Page/Page.php | 1 - system/src/Grav/Common/Page/Pages.php | 6 ----- 7 files changed, 32 insertions(+), 25 deletions(-) diff --git a/system/src/Grav/Common/Page/Media.php b/system/src/Grav/Common/Page/Media.php index 15296c9ac..1495eddbd 100644 --- a/system/src/Grav/Common/Page/Media.php +++ b/system/src/Grav/Common/Page/Media.php @@ -98,13 +98,11 @@ class Media extends Getters // Build missing alternatives if (!empty($types['alternative'])) { - $alternatives = $types['alternative']; $max = max(array_keys($alternatives)); for ($i=2; $i < $max; $i++) { - if (isset($alternatives[$i])) { continue; } diff --git a/system/src/Grav/Common/Page/Medium/ImageMedium.php b/system/src/Grav/Common/Page/Medium/ImageMedium.php index 76854fe1d..5dbe114ca 100644 --- a/system/src/Grav/Common/Page/Medium/ImageMedium.php +++ b/system/src/Grav/Common/Page/Medium/ImageMedium.php @@ -24,7 +24,7 @@ class ImageMedium extends Medium /** * @var int */ - protected $quality = 85; + protected $quality = DEFAULT_IMG_QUALITY; /** * @var boolean @@ -76,7 +76,7 @@ class ImageMedium extends Medium /** * Add meta file for the medium. * - * @param $format + * @param $filepath * @return $this */ public function addMetaFile($filepath) @@ -92,13 +92,16 @@ class ImageMedium extends Medium /** * Return PATH to image. * - * @return string path to image + * @param bool $reset + * @return string path to image */ public function path($reset = true) { $output = $this->saveImage(); - if ($reset) $this->reset(); + if ($reset) { + $this->reset(); + } return $output; } @@ -113,7 +116,9 @@ class ImageMedium extends Medium { $output = preg_replace('|^' . GRAV_ROOT . '|', '', $this->saveImage()); - if ($reset) $this->reset(); + if ($reset) { + $this->reset(); + } return self::$grav['base_url'] . $output . $this->urlHash(); } @@ -178,7 +183,7 @@ class ImageMedium extends Medium } $this->format = 'guess'; - $this->quality = 85; + $this->quality = DEFAULT_IMG_QUALITY; $this->debug_watermarked = false; @@ -262,7 +267,8 @@ class ImageMedium extends Medium * @param string $sizes * @return $this */ - public function sizes($sizes = null) { + public function sizes($sizes = null) + { if ($sizes) { $this->attributes['sizes'] = $sizes; @@ -312,7 +318,8 @@ class ImageMedium extends Medium call_user_func_array([$medium, $method], $args_copy); } - } catch (\BadFunctionCallException $e) { } + } catch (\BadFunctionCallException $e) { + } return $this; } @@ -320,7 +327,6 @@ class ImageMedium extends Medium /** * Gets medium image, resets image manipulation operations. * - * @param string $variable * @return $this */ protected function image() diff --git a/system/src/Grav/Common/Page/Medium/Link.php b/system/src/Grav/Common/Page/Medium/Link.php index 88c8bb08d..1262bddf9 100644 --- a/system/src/Grav/Common/Page/Medium/Link.php +++ b/system/src/Grav/Common/Page/Medium/Link.php @@ -12,6 +12,7 @@ class Link implements RenderableInterface * @var array */ protected $attributes = []; + protected $source; /** * Construct. diff --git a/system/src/Grav/Common/Page/Medium/Medium.php b/system/src/Grav/Common/Page/Medium/Medium.php index 52f8e8e95..e001ec3c6 100644 --- a/system/src/Grav/Common/Page/Medium/Medium.php +++ b/system/src/Grav/Common/Page/Medium/Medium.php @@ -4,6 +4,7 @@ namespace Grav\Common\Page\Medium; use Grav\Common\File\CompiledYamlFile; use Grav\Common\GravTrait; use Grav\Common\Data\Data; +use Grav\Common\Data\Blueprint; /** * The Medium is a general class for multimedia objects in Grav pages, specific implementations will derive from @@ -32,6 +33,8 @@ class Medium extends Data implements RenderableInterface */ protected $thumbnailTypes = [ 'page', 'default' ]; + protected $thumbnailType = null; + /** * @var Medium[] */ @@ -105,7 +108,9 @@ class Medium extends Data implements RenderableInterface */ public function path($reset = true) { - if ($reset) $this->reset(); + if ($reset) { + $this->reset(); + } return $this->get('filepath'); } @@ -120,7 +125,9 @@ class Medium extends Data implements RenderableInterface { $output = preg_replace('|^' . GRAV_ROOT . '|', '', $this->get('filepath')); - if ($reset) $this->reset(); + if ($reset) { + $this->reset(); + } return self::$grav['base_url'] . $output . $this->urlHash(); } @@ -158,8 +165,6 @@ class Medium extends Data implements RenderableInterface */ public function parsedownElement($title = null, $alt = null, $class = null, $reset = true) { - $element; - $attributes = $this->attributes; $style = ''; @@ -249,8 +254,10 @@ class Medium extends Data implements RenderableInterface */ public function display($mode = 'source') { - if ($this->mode === $mode) + if ($this->mode === $mode) { return $this; + } + $this->mode = $mode; @@ -266,8 +273,9 @@ class Medium extends Data implements RenderableInterface */ public function thumbnail($type = 'auto') { - if ($type !== 'auto' && !in_array($type, $this->thumbnailTypes)) + if ($type !== 'auto' && !in_array($type, $this->thumbnailTypes)) { return $this; + } if ($this->thumbnailType !== $type) { $this->_thumbnail = null; diff --git a/system/src/Grav/Common/Page/Medium/MediumFactory.php b/system/src/Grav/Common/Page/Medium/MediumFactory.php index e26b8110a..9ff05d4b9 100644 --- a/system/src/Grav/Common/Page/Medium/MediumFactory.php +++ b/system/src/Grav/Common/Page/Medium/MediumFactory.php @@ -113,8 +113,9 @@ class MediumFactory */ public static function scaledFromMedium($medium, $from, $to) { - if (! $medium instanceof ImageMedium) + if (! $medium instanceof ImageMedium) { return $medium; + } if ($to > $from) { return $medium; diff --git a/system/src/Grav/Common/Page/Page.php b/system/src/Grav/Common/Page/Page.php index 44a5665e2..95b558f18 100644 --- a/system/src/Grav/Common/Page/Page.php +++ b/system/src/Grav/Common/Page/Page.php @@ -960,7 +960,6 @@ class Page // Build an array of meta objects.. foreach ((array)$page_header->metadata as $key => $value) { - // If this is a property type metadata: "og", "twitter", "facebook" etc if (is_array($value)) { foreach ($value as $property => $prop_value) { diff --git a/system/src/Grav/Common/Page/Pages.php b/system/src/Grav/Common/Page/Pages.php index bbff00e8d..fd70981d6 100644 --- a/system/src/Grav/Common/Page/Pages.php +++ b/system/src/Grav/Common/Page/Pages.php @@ -523,7 +523,6 @@ class Pages /** @var \DirectoryIterator $file */ foreach ($iterator as $file) { - if ($file->isDot()) { continue; } @@ -531,14 +530,12 @@ class Pages $name = $file->getFilename(); if ($file->isFile()) { - // Update the last modified if it's newer than already found if ($file->getBasename() !== '.DS_Store' && ($modified = $file->getMTime()) > $last_modified) { $last_modified = $modified; } if (Utils::endsWith($name, CONTENT_EXT)) { - $page->init($file); $content_exists = true; @@ -547,7 +544,6 @@ class Pages } } } elseif ($file->isDir()) { - if (!$page->path()) { $page->path($file->getPath()); } @@ -593,7 +589,6 @@ class Pages // Build routes and taxonomy map. /** @var $page Page */ foreach ($this->instances as $page) { - $parent = $page->parent(); if ($parent) { @@ -643,7 +638,6 @@ class Pages } foreach ($pages as $key => $info) { - $child = isset($this->instances[$key]) ? $this->instances[$key] : null; if (!$child) { throw new \RuntimeException("Page does not exist: {$key}"); From 01c7eadc92f8da620b818db8b03a92b49827979c Mon Sep 17 00:00:00 2001 From: Andy Miller Date: Tue, 7 Apr 2015 12:55:29 -0600 Subject: [PATCH 26/29] Added new default_image_quality system configuration option --- system/config/system.yaml | 1 + system/defines.php | 3 --- system/src/Grav/Common/Page/Medium/ImageMedium.php | 11 +++++++++-- 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/system/config/system.yaml b/system/config/system.yaml index aaafeef79..59f4b36a9 100644 --- a/system/config/system.yaml +++ b/system/config/system.yaml @@ -69,4 +69,5 @@ debugger: close_connection: true # Close the connection before calling onShutdown(). false for debugging images: + default_image_quality: 85 # Default image quality to use when resampling images (85%) debug: false # Show an overlay over images indicating the pixel depth of the image when working with retina for example diff --git a/system/defines.php b/system/defines.php index 91ec2ac70..f915c3815 100644 --- a/system/defines.php +++ b/system/defines.php @@ -40,6 +40,3 @@ define('RAW_CONTENT', 1); define('TWIG_CONTENT', 2); define('TWIG_CONTENT_LIST', 3); define('TWIG_TEMPLATES', 4); - -// Other defines -define('DEFAULT_IMG_QUALITY', 85); diff --git a/system/src/Grav/Common/Page/Medium/ImageMedium.php b/system/src/Grav/Common/Page/Medium/ImageMedium.php index 5dbe114ca..ede065f09 100644 --- a/system/src/Grav/Common/Page/Medium/ImageMedium.php +++ b/system/src/Grav/Common/Page/Medium/ImageMedium.php @@ -24,7 +24,12 @@ class ImageMedium extends Medium /** * @var int */ - protected $quality = DEFAULT_IMG_QUALITY; + protected $quality; + + /** + * @var int + */ + protected $default_quality; /** * @var boolean @@ -70,6 +75,8 @@ class ImageMedium extends Medium $this->set('thumbnails.media', $this->get('filepath')); + $this->default_quality = self::$grav['config']->get('system.images.default_image_quality', 85); + $this->reset(); } @@ -183,7 +190,7 @@ class ImageMedium extends Medium } $this->format = 'guess'; - $this->quality = DEFAULT_IMG_QUALITY; + $this->quality = $this->default_quality; $this->debug_watermarked = false; From be12f350cb6c3c3a4dc1ea676cf2f4812ad85487 Mon Sep 17 00:00:00 2001 From: Andy Miller Date: Tue, 7 Apr 2015 13:05:21 -0600 Subject: [PATCH 27/29] changelog updated --- CHANGELOG.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index a58998227..56b1eb85e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,15 @@ +# v0.9.21 +## 04/07/2015 + +1. [](#new) + * Major Media functionality enhancements: SVG, Animated GIF, Video support! + * Added ability to configure default image quality in system configuration +2. [](#improved) + * Don't scale @1x retina images + * Add filter to Iterator class + * Updated various composer packages + * Various PSR fixes + # v0.9.20 ## 03/24/2015 From 0c84392d0f6ea85d66969d70b7374970c713b5e6 Mon Sep 17 00:00:00 2001 From: Andy Miller Date: Tue, 7 Apr 2015 13:18:59 -0600 Subject: [PATCH 28/29] sizes reference in changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 56b1eb85e..b7f03a163 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ 1. [](#new) * Major Media functionality enhancements: SVG, Animated GIF, Video support! * Added ability to configure default image quality in system configuration + * Added `sizes` attributes for custom retina image breakpoints 2. [](#improved) * Don't scale @1x retina images * Add filter to Iterator class From a04a79af3e54c14506b4184c9d700be2f31a3f32 Mon Sep 17 00:00:00 2001 From: Andy Miller Date: Tue, 7 Apr 2015 13:53:32 -0600 Subject: [PATCH 29/29] version update --- system/defines.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/system/defines.php b/system/defines.php index f915c3815..4413c4a24 100644 --- a/system/defines.php +++ b/system/defines.php @@ -2,7 +2,7 @@ // Some standard defines define('GRAV', true); -define('GRAV_VERSION', '0.9.20'); +define('GRAV_VERSION', '0.9.21'); define('DS', '/'); // Directories and Paths