/** * @param $path */ public function __construct($path) { // Handle special cases where page doesn't exist in filesystem. if (!is_dir($path)) { return; } $this->path = $path; $iterator = new \FilesystemIterator($path, \FilesystemIterator::UNIX_PATHS | \FilesystemIterator::SKIP_DOTS); $media = []; /** @var \DirectoryIterator $info */ foreach ($iterator as $path => $info) { // Ignore folders and Markdown files. if (!$info->isFile() || $info->getExtension() == 'md' || $info->getBasename() === '.DS_Store') { continue; } // Find out what type we're dealing with list($basename, $ext, $type, $extra) = $this->getFileParts($info->getFilename()); $media["{$basename}.{$ext}"] = isset($media["{$basename}.{$ext}"]) ? $media["{$basename}.{$ext}"] : []; if ($type === 'alternative') { $media["{$basename}.{$ext}"][$type] = isset($media["{$basename}.{$ext}"][$type]) ? $media["{$basename}.{$ext}"][$type] : []; $media["{$basename}.{$ext}"][$type][$extra] = ['file' => $path, 'size' => $info->getSize()]; } else { $media["{$basename}.{$ext}"][$type] = ['file' => $path, 'size' => $info->getSize()]; } } 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 => &$alt) { $alt['file'] = MediumFactory::fromFile($alt['file']); if (!$alt['file']) { unset($types['alternative'][$ratio]); } else { $alt['file']->set('size', $alt['size']); } } } // Create the base medium if (!empty($types['base'])) { $medium = MediumFactory::fromFile($types['base']['file']); $medium && $medium->set('size', $types['base']['size']); } else { if (!empty($types['alternative'])) { $altMedium = reset($types['alternative']); $ratio = key($types['alternative']); $altMedium = $altMedium['file']; $medium = MediumFactory::scaledFromMedium($altMedium, $ratio, 1)['file']; } } if (!$medium) { continue; } if (!empty($types['meta'])) { $medium->addMetaFile($types['meta']['file']); } 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']['file']); } // 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; } $types['alternative'][$i] = MediumFactory::scaledFromMedium($alternatives[$max]['file'], $max, $i); } foreach ($types['alternative'] as $ratio => $altMedium) { $medium->addAlternative($ratio, $altMedium['file']); } } $this->add($name, $medium); } }
/** * Generate derivatives * * @param int $min_width * @param int $max_width * @param int $step * @return $this */ public function derivatives($min_width, $max_width, $step = 200) { $width = $min_width; // Do not upscale images. if ($max_width > $this->get('width')) { $max_width = $this->get('width'); } while ($width <= $max_width) { $ratio = $width / $this->get('width'); $derivative = MediumFactory::scaledFromMedium($this, 1, $ratio); if (is_array($derivative)) { $this->addDerivative($derivative['file']); } $width += $step; } return $this; }
/** * Get the thumbnail Medium object * * @return ThumbnailImageMedium */ protected function getThumbnail() { if (!$this->_thumbnail) { $types = $this->thumbnailTypes; if ($this->thumbnailType !== 'auto') { array_unshift($types, $this->thumbnailType); } foreach ($types as $type) { $thumb = $this->get('thumbnails.' . $type, false); if ($thumb) { $thumb = $thumb instanceof ThumbnailImageMedium ? $thumb : MediumFactory::fromFile($thumb, ['type' => 'thumbnail']); $thumb->parent = $this; } if ($thumb) { $this->_thumbnail = $thumb; break; } } } return $this->_thumbnail; }
/** * Generate derivatives * * @param int $min_width * @param int $max_width * @param int $step * @return $this */ public function derivatives($min_width, $max_width, $step = 200) { if (!empty($this->alternatives)) { $max = max(array_keys($this->alternatives)); $base = $this->alternatives[$max]; } else { $base = $this; } // Do not upscale images. $max_width = min($max_width, $base->get('width')); for ($width = $min_width; $width < $max_width; $width = $width + $step) { // Only generate image alternatives that don't already exist if (array_key_exists((int) $width, $this->alternatives)) { continue; } $derivative = MediumFactory::fromFile($base->get('filepath')); // It's possible that MediumFactory::fromFile returns null if the // original image file no longer exists and this class instance was // retrieved from the page cache if (isset($derivative)) { $index = 2; $widths = array_keys($this->alternatives); sort($widths); foreach ($widths as $i => $key) { if ($width > $key) { $index += max($i, 1); } } $basename = preg_replace('/(@\\d+x){0,1}$/', "@{$width}w", $base->get('basename'), 1); $derivative->setImagePrettyName($basename); $ratio = $base->get('width') / $width; $height = $derivative->get('height') / $ratio; $derivative->resize($width, $height); $derivative->set('width', $width); $derivative->set('height', $height); $this->addAlternative($ratio, $derivative); } } return $this; }