Phalcon Framework 3.4.5

Exception: Файл /www/wiki.youvivu.com/public_html/public/img/original/publication/0/474_1732322640.jpg не существует

/www/wiki.youvivu.com/public_html/app/modules/Image/Storage.php (385)
#0Image\Storage->checkOriginalExists(/www/wiki.youvivu.com/public_html/public/img/original/publication/0/474_1732322640.jpg)
/www/wiki.youvivu.com/public_html/app/modules/Image/Storage.php (331)
<?php
 
namespace Image;
 
use Phalcon\Mvc\User\Component;
 
define('IMG_ROOT_REL_PATH', 'img');
define('DIR_SEP', '/');
define('IMG_ROOT_PATH', ROOT . DIR_SEP);
define('IMG_STORAGE_SERVER', '');
define('IMG_EXTENSION', 'jpg');
define('NOIMAGE', '/static/images/noimage.jpg');
 
define('IMG_DEBUG_MODE', true);
 
class Storage extends Component
{
 
    private static $STRATEGIES = [
        'w', // Масштабируем по ширине
        'wh', // Масштабируем по заданной ширине и высоте. Изображение подганяется в этот прямоугольник
        'a', // Центрируем и обрезаем изображение по заданной высоте и ширине таким образом, чтоб оно полностью заполнило пространство
    ];
    private $id = null;
    private $image_hash = null;
    private $type = 'publication';
    private $strategy = 'w';
    private $width = 100;
    private $height = null;
    private $hash = false;
    private $attributes = [];
    private $exists = true;
    private $widthHeight = true;
    private $stretch = true;
 
    public function __construct(array $params = [], array $attributes = [])
    {
        $this->setIdFromParams($params);
        $this->attributes = $attributes;
 
        $this->type = (isset($params['type'])) ? $params['type'] : 'publication';
        $this->strategy = (isset($params['strategy'])) ? $params['strategy'] : 'w';
        $this->image_hash = (isset($params['image_hash'])) ? $params['image_hash'] : null;
        $this->hash = (isset($params['hash'])) ? $params['hash'] : false;
 
        $this->setDimensionsAttributes($params);
    }
 
    private function setDimensionsAttributes(array $params = [])
    {
        $this->width = (isset($params['width'])) ? $params['width'] : 100;
        $this->height = (isset($params['height'])) ? $params['height'] : null;
 
        $this->widthHeight = (isset($params['widthHeight'])) ? $params['widthHeight'] : true;
        $this->widthHeight = (isset($params['widthHeight']) && MOBILE_DEVICE) ? false : true;
 
        $this->stretch = (isset($params['stretch'])) ? $params['stretch'] : null;
    }
 
    private function setIdFromParams($params)
    {
        if (isset($params['id'])) {
            if (preg_match('/^\d+$/', $params['id'])) {
                $this->id = (int) $params['id'];
            } else {
                $this->id = $params['id'];
            }
        } else {
            if (IMG_DEBUG_MODE) {
                throw new \Exception("ID не определен");
            }
        }
    }
 
    /**
     * HTML-тег изображения, готовый к использованию
     * <img src="" alt="" />
     */
    public function imageHtml()
    {
        //Из заданных параметров и атрибутов составляем html-тэг
        $this->attributesForImageHtml();
 
        // Получаем относительный адрес файла кешированного изображения
        $src = $this->cachedRelPath();
 
        if ($this->exists) {
            if ($this->hash) {
                $src .= '?' . microtime();
            }
        } else {
            $src = NOIMAGE;
            $this->attributes['width'] = $this->width;
            $this->attributes['height'] = $this->height;
        }
 
        $attr_src = 'src="' . $this->getDi()->get('config')->base_path . $src . '"';
        $result = '<img ' . $attr_src . $this->attributesResultForImageHtml($this->attributes) . '/>';
 
        return $result;
    }
 
    private function attributesForImageHtml()
    {
        if ($this->widthHeight) {
            if ($this->stretch && in_array($this->strategy, ['wh', 'a'])) {
                $this->stretch = false;
            }
            $this->changeAttributesInAccordanceWithStretch();
        }
        $this->attributes['alt'] = (isset($this->attributes['alt'])) ?
            htmlspecialchars($this->attributes['alt'], ENT_QUOTES) :
            '';
    }
 
    private function changeAttributesInAccordanceWithStretch()
    {
        if ($this->stretch) {
            $this->changeAttributesForStretch();
        } else {
            $this->changeAttributesWithoutStretch();
        }
    }
 
    private function changeAttributesForStretch()
    {
        if ($this->width) {
            $this->attributes['width'] = $this->width;
        }
        if ($this->height) {
            $this->attributes['height'] = $this->height;
        }
    }
 
    private function changeAttributesWithoutStretch()
    {
        $widthHeight = $this->getImageWidthHeight();
        if ($widthHeight['width']) {
            $this->attributes['width'] = $widthHeight['width'];
        }
        if ($widthHeight['height']) {
            $this->attributes['height'] = $widthHeight['height'];
        }
    }
 
    private function attributesResultForImageHtml($attributes)
    {
        $attributesHtmlArray = [];
        foreach ($attributes as $el => $val) {
            $attributesHtmlArray[] = $el . '="' . $val . '"';
        }
        $attributesHtml = implode(' ', $attributesHtmlArray);
        $attributesHtmlResult = ($attributesHtml) ? ' ' . $attributesHtml : '';
 
        return $attributesHtmlResult;
    }
 
    /**
     * Относительный адрес файла кешированного изображения
     * /img/preview/405102/405102_1_w_100.jpg
     */
    public function cachedRelPath()
    {
        // Рассчитываем по входящим параметрам относительный путь к кешированному файлу
        $cachedRelPath = $this->calculateCachedRelPath();
        // Совмещаем относительный путь с корневым, получаем абсолютный путь
        $cachedAbsPath = IMG_ROOT_PATH . $cachedRelPath;
        // Проверяем существование такого файла. если файл не существует:
        if (!file_exists($cachedAbsPath)) {
            // Генерируем кеш-файл по заданным параметрам
            $this->generateCachedImage();
        }
 
        return IMG_STORAGE_SERVER . $cachedRelPath;
    }
 
    /**
     * @return string
     */
    public function cachedAbsPath()
    {
        return IMG_ROOT_PATH . $this->cachedRelPath();
    }
 
    /**
     * Относительный адрес файла оригинального изображения
     */
    public function originalRelPath()
    {
        return IMG_STORAGE_SERVER . $this->calculateOriginalRelPath();
    }
 
    /**
     * Абсолютный адрес файла оригинального изображения
     */
    public function originalAbsPath()
    {
        return $this->getAbsPath(true);
    }
 
    /**
     * @param $file
     * @return bool
     */
    public function save($file)
    {
        if (file_exists($file)) {
            return copy($file, $this->originalAbsPath());
        }
    }
 
    /**
     * @return array
     */
    public function originalWidthHeight()
    {
        $imageSize = getimagesize($this->originalAbsPath());
        if (!empty($imageSize)) {
            return [
                'width'  => $imageSize[0],
                'height' => $imageSize[1]
            ];
        }
    }
 
    /**
     * @return int
     */
    public function cachedFileSize()
    {
        $path = $this->cachedAbsPath();
        if (file_exists($path)) {
            return filesize($path);
        }
    }
 
    /**
     * @return bool
     */
    public function isExists()
    {
        return (file_exists($this->getAbsPath(true))) ? true : false ;
    }
 
    /**
     * Рассчитываем по входящим параметрам относительный путь к кешированному файлу
     * /img/preview/405/405102_1_w_100.jpg
     */
    private function calculateCachedRelPath()
    {
        $pathParts = [];
        $pathParts[] = IMG_ROOT_REL_PATH;
        $pathParts[] = 'cache';
        $pathParts[] = $this->type;
 
        if (is_int($this->id)) {
            $idPart = floor($this->id / 1000);
        } else {
            $idPart = $this->id;
        }
        $pathParts[] = $idPart;
 
        $fileParts = [];
        $fileParts[] = $this->id;
        if ($this->image_hash) {
            $fileParts[] = $this->image_hash;
        }
        if (in_array($this->strategy, self::$STRATEGIES)) {
            $fileParts[] = $this->strategy;
 
            $fileParts[] = $this->width;
            if ($this->height) {
                $fileParts[] = $this->height;
            }
 
            // "img/preview/405"
            $path = implode(DIR_SEP, $pathParts);
            // "405102_1_w_100"
            $file = implode('_', $fileParts);
 
            return $path . DIR_SEP . $file . '.jpg';
 
        } else {
            if (IMG_DEBUG_MODE) {
                throw new \Exception("Параметр 'strategy' указан неверно");
            }
        }
    }
 
    /**
     * Рассчитываем по входящим параметрам относительный путь к оригинальному файлу
     * /img/original/preview/405/405102_1.jpg
     * @return string
     */
    private function calculateOriginalRelPath()
    {
        $pathParts = [];
        $pathParts[] = IMG_ROOT_REL_PATH;
        $pathParts[] = 'original';
        $pathParts[] = $this->type;
 
        if (is_int($this->id)) {
            $idPart = floor($this->id / 1000);
        } else {
            $idPart = $this->id;
        }
        $pathParts[] = $idPart;
 
        $fileParts = [];
        $fileParts[] = $this->id;
        if ($this->image_hash) {
            $fileParts[] = $this->image_hash;
        }
 
        // "img/original/preview/405"
        $path = implode(DIR_SEP, $pathParts);
        // "405102_1"
        $file = implode('_', $fileParts);
 
        return $path . DIR_SEP . $file . '_' . time() . '.jpg';
    }
 
    /**
     * генерируем кеш-файл по заданным параметрам
     * @throws \Exception
     */
    private function generateCachedImage()
    {
        // Абсолютный путь оригинального изображения
        $originalAbsPath = IMG_ROOT_PATH . $this->calculateOriginalRelPath();
        $this->checkOriginalExists($originalAbsPath);
 
        require_once __DIR__ . '/PHPThumb/ThumbLib.inc.php';
        $image = \PhpThumbFactory::create($originalAbsPath);
        // Для мобильных устройств отдаем изображение с качеством на уровне 60%
        if (MOBILE_DEVICE) {
            $options = ['jpegQuality' => 60];
            $image->setOptions($options);
        }
        switch ($this->strategy) {
            case 'w':
                // Масштабируем по ширине
                $image->resize($this->width);
                break;
            case 'wh':
                // Масштабируем по заданной ширине и высоте. Изображение подганяется в этот прямоугольник
                $image->resize($this->width, $this->height);
                break;
            case 'a':
                // Центрируем и обрезаем изображение по заданной высоте и ширине таким образом, чтоб оно полностью заполнило пространство
                $image->adaptiveResize($this->width, $this->height);
                break;
        }
 
        $this->saveImage($image, $originalAbsPath);
    }
 
    /**
     * @param $left
     * @param $top
     * @param $width
     * @param $height
     * @throws \Exception
     */
    public function cropOriginal($left, $top, $width, $height)
    {
        $originalAbsPath = IMG_ROOT_PATH . $this->calculateOriginalRelPath(); // Абсолютный путь оригинального изображения
        $this->checkOriginalExists($originalAbsPath);
 
        require_once __DIR__ . '/PHPThumb/ThumbLib.inc.php';
        $image = \PhpThumbFactory::create($originalAbsPath);
        $image->crop($left, $top, $width, $height);
 
        $this->saveImage($image, $originalAbsPath);
    }
 
    /**
     * @param $originalAbsPath
     * @throws \Exception
     */
    private function checkOriginalExists($originalAbsPath)
    {
        if (!file_exists($originalAbsPath)) {
            if (IMG_DEBUG_MODE) {
                throw new \Exception("Файл {$originalAbsPath} не существует");
            } else {
                $this->exists = false;
            }
        }
    }
 
    /**
     * @param $image
     * @param $originalAbsPath
     * @throws \Exception
     */
    private function saveImage($image, $originalAbsPath)
    {
        // Если оригинал не заблокирован, блокируем. Это необходимо для предотвращения множественной генерации кеш-файла параллельными запросами
        if ($this->lockOriginal($originalAbsPath)) {
            // Сохраняем кешированное изображение
            $image->save($this->getAbsPath(false));
            // Снимаем блокировку
            $this->unlockOriginal($originalAbsPath);
        } else {
            if (IMG_DEBUG_MODE) {
                throw new \Exception("Файл {$originalAbsPath} заблокирован механизмом проверки _LOCK или не существует");
            } else {
                $this->exists = false;
            }
        }
    }
 
    /**
     * Удаляет оригинальные и кешированные изображения
     * @param bool $removeAll
     */
    public function remove($removeAll = true)
    {
        $this->removeCached();
        $this->removeOriginal($removeAll);
    }
 
    /**
     * Удаляет оригинальные изображения
     * @param bool $removeAll
     */
    public function removeOriginal($removeAll = true)
    {
        if (!$removeAll) {
            if (file_exists($this->originalAbsPath())) {
                unlink($this->originalAbsPath());
            }
        } else {
            $originalAbsPath = IMG_ROOT_PATH . $this->calculateOriginalRelPath();
            $originalAbsPathDir = implode(DIR_SEP, array_slice(explode(DIR_SEP, $originalAbsPath), 0, -1)); // Абсолютный путь директории
 
            if ($this->image_hash) {
                $search = $originalAbsPathDir . "/" . $this->id . "_*.jpg";
            } else {
                $search = $originalAbsPathDir . "/" . $this->id . ".jpg";
            }
            $files = glob($search);
            if (!empty($files)) {
                foreach ($files as $file) {
                    if (is_file($file)) {
                        unlink($file);
                    }
                }
            }
        }
    }
 
    /**
     * Удаляет кешированные изображения
     */
    public function removeCached()
    {
        $cachedAbsPath = IMG_ROOT_PATH . $this->calculateCachedRelPath();
        $cachedAbsPathDir = implode(DIR_SEP, array_slice(explode(DIR_SEP, $cachedAbsPath), 0, -1)); // Абсолютный путь директории
 
        $search = $cachedAbsPathDir . "/" . $this->id . "_*.jpg";
        $files = glob($search);
        if (!empty($files)) {
            foreach ($files as $file) {
                if (is_file($file)) {
                    unlink($file);
                }
            }
        }
    }
 
    /**
     * Размеры кешированного изображения
     */
    public function getImageWidthHeight()
    {
        $cachedAbsPath = IMG_ROOT_PATH . $this->calculateCachedRelPath();
        if (file_exists($cachedAbsPath)) {
            $imageSize = getimagesize($cachedAbsPath);
            if (!empty($imageSize)) {
                return [
                    'width'  => $imageSize[0],
                    'height' => $imageSize[1]
                ];
            }
        } else {
            return [
                'width'  => null,
                'height' => null
            ];
        }
    }
 
    /**
     * Проверяем блокировку оригинала изображения. Если нет, то блокируем
     * @param string $originalAbsPath
     * @return boolean true|false
     */
    private function lockOriginal($originalAbsPath)
    {
        $lockFileName = $this->getLockFileName($originalAbsPath);
        if (file_exists($lockFileName)) {
            return false;
        } else {
            $handle = fopen($lockFileName, 'w+');
            if (flock($handle, LOCK_EX)) {
                fwrite($handle, '1');
                flock($handle, LOCK_UN);
                fclose($handle);
                return true;
            } else {
                if ($handle) {
                    fclose($handle);
                }
                return false;
            }
        }
    }
 
    /**
     * Снимаем блокировку оригинала изображения
     * @param string $originalAbsPath
     */
    private function unlockOriginal($originalAbsPath)
    {
        unlink($this->getLockFileName($originalAbsPath));
    }
 
    /**
     * Возвращает имя файла для блокировки оригинала изображения
     * @param string $originalAbsPath
     * @return string
     */
    private function getLockFileName($originalAbsPath)
    {
        return preg_replace('/\.' . IMG_EXTENSION . '/i', '_lock.' . IMG_EXTENSION, $originalAbsPath);
    }
 
    /**
     * @param bool $original
     * @return string
     * @throws \Exception
     */
    private function getAbsPath($original = true)
    {
        $absPath = IMG_ROOT_PATH . (($original) ? $this->calculateOriginalRelPath() : $this->calculateCachedRelPath());
 
        // Абсолютный путь директории
        $absPathDir = implode(DIR_SEP, array_slice(explode(DIR_SEP, $absPath), 0, -1));
 
        // Если директория отсутствует
        if (!is_dir($absPathDir)) {
            // Создаем дерево директорий
            mkdir($absPathDir, 0777, true);
        }
 
        return $absPath;
    }
 
    /**
     * @param bool $original
     * @return string
     * @throws \Exception
     */
    public function getabsPathDir($original = true)
    {
        $absPath = IMG_ROOT_PATH . (($original) ? $this->calculateOriginalRelPath() : $this->calculateCachedRelPath());
 
        // Абсолютный путь директории
        $absPathDir = implode(DIR_SEP, array_slice(explode(DIR_SEP, $absPath), 0, -1));
 
        // Если директория отсутствует
        if (!is_dir($absPathDir)) {
            // Создаем дерево директорий
            mkdir($absPathDir, 0777, true);
        }
 
        return $absPathDir;
    }
 
}
#1Image\Storage->generateCachedImage()
/www/wiki.youvivu.com/public_html/app/modules/Image/Storage.php (171)
<?php
 
namespace Image;
 
use Phalcon\Mvc\User\Component;
 
define('IMG_ROOT_REL_PATH', 'img');
define('DIR_SEP', '/');
define('IMG_ROOT_PATH', ROOT . DIR_SEP);
define('IMG_STORAGE_SERVER', '');
define('IMG_EXTENSION', 'jpg');
define('NOIMAGE', '/static/images/noimage.jpg');
 
define('IMG_DEBUG_MODE', true);
 
class Storage extends Component
{
 
    private static $STRATEGIES = [
        'w', // Масштабируем по ширине
        'wh', // Масштабируем по заданной ширине и высоте. Изображение подганяется в этот прямоугольник
        'a', // Центрируем и обрезаем изображение по заданной высоте и ширине таким образом, чтоб оно полностью заполнило пространство
    ];
    private $id = null;
    private $image_hash = null;
    private $type = 'publication';
    private $strategy = 'w';
    private $width = 100;
    private $height = null;
    private $hash = false;
    private $attributes = [];
    private $exists = true;
    private $widthHeight = true;
    private $stretch = true;
 
    public function __construct(array $params = [], array $attributes = [])
    {
        $this->setIdFromParams($params);
        $this->attributes = $attributes;
 
        $this->type = (isset($params['type'])) ? $params['type'] : 'publication';
        $this->strategy = (isset($params['strategy'])) ? $params['strategy'] : 'w';
        $this->image_hash = (isset($params['image_hash'])) ? $params['image_hash'] : null;
        $this->hash = (isset($params['hash'])) ? $params['hash'] : false;
 
        $this->setDimensionsAttributes($params);
    }
 
    private function setDimensionsAttributes(array $params = [])
    {
        $this->width = (isset($params['width'])) ? $params['width'] : 100;
        $this->height = (isset($params['height'])) ? $params['height'] : null;
 
        $this->widthHeight = (isset($params['widthHeight'])) ? $params['widthHeight'] : true;
        $this->widthHeight = (isset($params['widthHeight']) && MOBILE_DEVICE) ? false : true;
 
        $this->stretch = (isset($params['stretch'])) ? $params['stretch'] : null;
    }
 
    private function setIdFromParams($params)
    {
        if (isset($params['id'])) {
            if (preg_match('/^\d+$/', $params['id'])) {
                $this->id = (int) $params['id'];
            } else {
                $this->id = $params['id'];
            }
        } else {
            if (IMG_DEBUG_MODE) {
                throw new \Exception("ID не определен");
            }
        }
    }
 
    /**
     * HTML-тег изображения, готовый к использованию
     * <img src="" alt="" />
     */
    public function imageHtml()
    {
        //Из заданных параметров и атрибутов составляем html-тэг
        $this->attributesForImageHtml();
 
        // Получаем относительный адрес файла кешированного изображения
        $src = $this->cachedRelPath();
 
        if ($this->exists) {
            if ($this->hash) {
                $src .= '?' . microtime();
            }
        } else {
            $src = NOIMAGE;
            $this->attributes['width'] = $this->width;
            $this->attributes['height'] = $this->height;
        }
 
        $attr_src = 'src="' . $this->getDi()->get('config')->base_path . $src . '"';
        $result = '<img ' . $attr_src . $this->attributesResultForImageHtml($this->attributes) . '/>';
 
        return $result;
    }
 
    private function attributesForImageHtml()
    {
        if ($this->widthHeight) {
            if ($this->stretch && in_array($this->strategy, ['wh', 'a'])) {
                $this->stretch = false;
            }
            $this->changeAttributesInAccordanceWithStretch();
        }
        $this->attributes['alt'] = (isset($this->attributes['alt'])) ?
            htmlspecialchars($this->attributes['alt'], ENT_QUOTES) :
            '';
    }
 
    private function changeAttributesInAccordanceWithStretch()
    {
        if ($this->stretch) {
            $this->changeAttributesForStretch();
        } else {
            $this->changeAttributesWithoutStretch();
        }
    }
 
    private function changeAttributesForStretch()
    {
        if ($this->width) {
            $this->attributes['width'] = $this->width;
        }
        if ($this->height) {
            $this->attributes['height'] = $this->height;
        }
    }
 
    private function changeAttributesWithoutStretch()
    {
        $widthHeight = $this->getImageWidthHeight();
        if ($widthHeight['width']) {
            $this->attributes['width'] = $widthHeight['width'];
        }
        if ($widthHeight['height']) {
            $this->attributes['height'] = $widthHeight['height'];
        }
    }
 
    private function attributesResultForImageHtml($attributes)
    {
        $attributesHtmlArray = [];
        foreach ($attributes as $el => $val) {
            $attributesHtmlArray[] = $el . '="' . $val . '"';
        }
        $attributesHtml = implode(' ', $attributesHtmlArray);
        $attributesHtmlResult = ($attributesHtml) ? ' ' . $attributesHtml : '';
 
        return $attributesHtmlResult;
    }
 
    /**
     * Относительный адрес файла кешированного изображения
     * /img/preview/405102/405102_1_w_100.jpg
     */
    public function cachedRelPath()
    {
        // Рассчитываем по входящим параметрам относительный путь к кешированному файлу
        $cachedRelPath = $this->calculateCachedRelPath();
        // Совмещаем относительный путь с корневым, получаем абсолютный путь
        $cachedAbsPath = IMG_ROOT_PATH . $cachedRelPath;
        // Проверяем существование такого файла. если файл не существует:
        if (!file_exists($cachedAbsPath)) {
            // Генерируем кеш-файл по заданным параметрам
            $this->generateCachedImage();
        }
 
        return IMG_STORAGE_SERVER . $cachedRelPath;
    }
 
    /**
     * @return string
     */
    public function cachedAbsPath()
    {
        return IMG_ROOT_PATH . $this->cachedRelPath();
    }
 
    /**
     * Относительный адрес файла оригинального изображения
     */
    public function originalRelPath()
    {
        return IMG_STORAGE_SERVER . $this->calculateOriginalRelPath();
    }
 
    /**
     * Абсолютный адрес файла оригинального изображения
     */
    public function originalAbsPath()
    {
        return $this->getAbsPath(true);
    }
 
    /**
     * @param $file
     * @return bool
     */
    public function save($file)
    {
        if (file_exists($file)) {
            return copy($file, $this->originalAbsPath());
        }
    }
 
    /**
     * @return array
     */
    public function originalWidthHeight()
    {
        $imageSize = getimagesize($this->originalAbsPath());
        if (!empty($imageSize)) {
            return [
                'width'  => $imageSize[0],
                'height' => $imageSize[1]
            ];
        }
    }
 
    /**
     * @return int
     */
    public function cachedFileSize()
    {
        $path = $this->cachedAbsPath();
        if (file_exists($path)) {
            return filesize($path);
        }
    }
 
    /**
     * @return bool
     */
    public function isExists()
    {
        return (file_exists($this->getAbsPath(true))) ? true : false ;
    }
 
    /**
     * Рассчитываем по входящим параметрам относительный путь к кешированному файлу
     * /img/preview/405/405102_1_w_100.jpg
     */
    private function calculateCachedRelPath()
    {
        $pathParts = [];
        $pathParts[] = IMG_ROOT_REL_PATH;
        $pathParts[] = 'cache';
        $pathParts[] = $this->type;
 
        if (is_int($this->id)) {
            $idPart = floor($this->id / 1000);
        } else {
            $idPart = $this->id;
        }
        $pathParts[] = $idPart;
 
        $fileParts = [];
        $fileParts[] = $this->id;
        if ($this->image_hash) {
            $fileParts[] = $this->image_hash;
        }
        if (in_array($this->strategy, self::$STRATEGIES)) {
            $fileParts[] = $this->strategy;
 
            $fileParts[] = $this->width;
            if ($this->height) {
                $fileParts[] = $this->height;
            }
 
            // "img/preview/405"
            $path = implode(DIR_SEP, $pathParts);
            // "405102_1_w_100"
            $file = implode('_', $fileParts);
 
            return $path . DIR_SEP . $file . '.jpg';
 
        } else {
            if (IMG_DEBUG_MODE) {
                throw new \Exception("Параметр 'strategy' указан неверно");
            }
        }
    }
 
    /**
     * Рассчитываем по входящим параметрам относительный путь к оригинальному файлу
     * /img/original/preview/405/405102_1.jpg
     * @return string
     */
    private function calculateOriginalRelPath()
    {
        $pathParts = [];
        $pathParts[] = IMG_ROOT_REL_PATH;
        $pathParts[] = 'original';
        $pathParts[] = $this->type;
 
        if (is_int($this->id)) {
            $idPart = floor($this->id / 1000);
        } else {
            $idPart = $this->id;
        }
        $pathParts[] = $idPart;
 
        $fileParts = [];
        $fileParts[] = $this->id;
        if ($this->image_hash) {
            $fileParts[] = $this->image_hash;
        }
 
        // "img/original/preview/405"
        $path = implode(DIR_SEP, $pathParts);
        // "405102_1"
        $file = implode('_', $fileParts);
 
        return $path . DIR_SEP . $file . '_' . time() . '.jpg';
    }
 
    /**
     * генерируем кеш-файл по заданным параметрам
     * @throws \Exception
     */
    private function generateCachedImage()
    {
        // Абсолютный путь оригинального изображения
        $originalAbsPath = IMG_ROOT_PATH . $this->calculateOriginalRelPath();
        $this->checkOriginalExists($originalAbsPath);
 
        require_once __DIR__ . '/PHPThumb/ThumbLib.inc.php';
        $image = \PhpThumbFactory::create($originalAbsPath);
        // Для мобильных устройств отдаем изображение с качеством на уровне 60%
        if (MOBILE_DEVICE) {
            $options = ['jpegQuality' => 60];
            $image->setOptions($options);
        }
        switch ($this->strategy) {
            case 'w':
                // Масштабируем по ширине
                $image->resize($this->width);
                break;
            case 'wh':
                // Масштабируем по заданной ширине и высоте. Изображение подганяется в этот прямоугольник
                $image->resize($this->width, $this->height);
                break;
            case 'a':
                // Центрируем и обрезаем изображение по заданной высоте и ширине таким образом, чтоб оно полностью заполнило пространство
                $image->adaptiveResize($this->width, $this->height);
                break;
        }
 
        $this->saveImage($image, $originalAbsPath);
    }
 
    /**
     * @param $left
     * @param $top
     * @param $width
     * @param $height
     * @throws \Exception
     */
    public function cropOriginal($left, $top, $width, $height)
    {
        $originalAbsPath = IMG_ROOT_PATH . $this->calculateOriginalRelPath(); // Абсолютный путь оригинального изображения
        $this->checkOriginalExists($originalAbsPath);
 
        require_once __DIR__ . '/PHPThumb/ThumbLib.inc.php';
        $image = \PhpThumbFactory::create($originalAbsPath);
        $image->crop($left, $top, $width, $height);
 
        $this->saveImage($image, $originalAbsPath);
    }
 
    /**
     * @param $originalAbsPath
     * @throws \Exception
     */
    private function checkOriginalExists($originalAbsPath)
    {
        if (!file_exists($originalAbsPath)) {
            if (IMG_DEBUG_MODE) {
                throw new \Exception("Файл {$originalAbsPath} не существует");
            } else {
                $this->exists = false;
            }
        }
    }
 
    /**
     * @param $image
     * @param $originalAbsPath
     * @throws \Exception
     */
    private function saveImage($image, $originalAbsPath)
    {
        // Если оригинал не заблокирован, блокируем. Это необходимо для предотвращения множественной генерации кеш-файла параллельными запросами
        if ($this->lockOriginal($originalAbsPath)) {
            // Сохраняем кешированное изображение
            $image->save($this->getAbsPath(false));
            // Снимаем блокировку
            $this->unlockOriginal($originalAbsPath);
        } else {
            if (IMG_DEBUG_MODE) {
                throw new \Exception("Файл {$originalAbsPath} заблокирован механизмом проверки _LOCK или не существует");
            } else {
                $this->exists = false;
            }
        }
    }
 
    /**
     * Удаляет оригинальные и кешированные изображения
     * @param bool $removeAll
     */
    public function remove($removeAll = true)
    {
        $this->removeCached();
        $this->removeOriginal($removeAll);
    }
 
    /**
     * Удаляет оригинальные изображения
     * @param bool $removeAll
     */
    public function removeOriginal($removeAll = true)
    {
        if (!$removeAll) {
            if (file_exists($this->originalAbsPath())) {
                unlink($this->originalAbsPath());
            }
        } else {
            $originalAbsPath = IMG_ROOT_PATH . $this->calculateOriginalRelPath();
            $originalAbsPathDir = implode(DIR_SEP, array_slice(explode(DIR_SEP, $originalAbsPath), 0, -1)); // Абсолютный путь директории
 
            if ($this->image_hash) {
                $search = $originalAbsPathDir . "/" . $this->id . "_*.jpg";
            } else {
                $search = $originalAbsPathDir . "/" . $this->id . ".jpg";
            }
            $files = glob($search);
            if (!empty($files)) {
                foreach ($files as $file) {
                    if (is_file($file)) {
                        unlink($file);
                    }
                }
            }
        }
    }
 
    /**
     * Удаляет кешированные изображения
     */
    public function removeCached()
    {
        $cachedAbsPath = IMG_ROOT_PATH . $this->calculateCachedRelPath();
        $cachedAbsPathDir = implode(DIR_SEP, array_slice(explode(DIR_SEP, $cachedAbsPath), 0, -1)); // Абсолютный путь директории
 
        $search = $cachedAbsPathDir . "/" . $this->id . "_*.jpg";
        $files = glob($search);
        if (!empty($files)) {
            foreach ($files as $file) {
                if (is_file($file)) {
                    unlink($file);
                }
            }
        }
    }
 
    /**
     * Размеры кешированного изображения
     */
    public function getImageWidthHeight()
    {
        $cachedAbsPath = IMG_ROOT_PATH . $this->calculateCachedRelPath();
        if (file_exists($cachedAbsPath)) {
            $imageSize = getimagesize($cachedAbsPath);
            if (!empty($imageSize)) {
                return [
                    'width'  => $imageSize[0],
                    'height' => $imageSize[1]
                ];
            }
        } else {
            return [
                'width'  => null,
                'height' => null
            ];
        }
    }
 
    /**
     * Проверяем блокировку оригинала изображения. Если нет, то блокируем
     * @param string $originalAbsPath
     * @return boolean true|false
     */
    private function lockOriginal($originalAbsPath)
    {
        $lockFileName = $this->getLockFileName($originalAbsPath);
        if (file_exists($lockFileName)) {
            return false;
        } else {
            $handle = fopen($lockFileName, 'w+');
            if (flock($handle, LOCK_EX)) {
                fwrite($handle, '1');
                flock($handle, LOCK_UN);
                fclose($handle);
                return true;
            } else {
                if ($handle) {
                    fclose($handle);
                }
                return false;
            }
        }
    }
 
    /**
     * Снимаем блокировку оригинала изображения
     * @param string $originalAbsPath
     */
    private function unlockOriginal($originalAbsPath)
    {
        unlink($this->getLockFileName($originalAbsPath));
    }
 
    /**
     * Возвращает имя файла для блокировки оригинала изображения
     * @param string $originalAbsPath
     * @return string
     */
    private function getLockFileName($originalAbsPath)
    {
        return preg_replace('/\.' . IMG_EXTENSION . '/i', '_lock.' . IMG_EXTENSION, $originalAbsPath);
    }
 
    /**
     * @param bool $original
     * @return string
     * @throws \Exception
     */
    private function getAbsPath($original = true)
    {
        $absPath = IMG_ROOT_PATH . (($original) ? $this->calculateOriginalRelPath() : $this->calculateCachedRelPath());
 
        // Абсолютный путь директории
        $absPathDir = implode(DIR_SEP, array_slice(explode(DIR_SEP, $absPath), 0, -1));
 
        // Если директория отсутствует
        if (!is_dir($absPathDir)) {
            // Создаем дерево директорий
            mkdir($absPathDir, 0777, true);
        }
 
        return $absPath;
    }
 
    /**
     * @param bool $original
     * @return string
     * @throws \Exception
     */
    public function getabsPathDir($original = true)
    {
        $absPath = IMG_ROOT_PATH . (($original) ? $this->calculateOriginalRelPath() : $this->calculateCachedRelPath());
 
        // Абсолютный путь директории
        $absPathDir = implode(DIR_SEP, array_slice(explode(DIR_SEP, $absPath), 0, -1));
 
        // Если директория отсутствует
        if (!is_dir($absPathDir)) {
            // Создаем дерево директорий
            mkdir($absPathDir, 0777, true);
        }
 
        return $absPathDir;
    }
 
}
#2Image\Storage->cachedRelPath()
/www/wiki.youvivu.com/public_html/app/modules/Image/Storage.php (85)
<?php
 
namespace Image;
 
use Phalcon\Mvc\User\Component;
 
define('IMG_ROOT_REL_PATH', 'img');
define('DIR_SEP', '/');
define('IMG_ROOT_PATH', ROOT . DIR_SEP);
define('IMG_STORAGE_SERVER', '');
define('IMG_EXTENSION', 'jpg');
define('NOIMAGE', '/static/images/noimage.jpg');
 
define('IMG_DEBUG_MODE', true);
 
class Storage extends Component
{
 
    private static $STRATEGIES = [
        'w', // Масштабируем по ширине
        'wh', // Масштабируем по заданной ширине и высоте. Изображение подганяется в этот прямоугольник
        'a', // Центрируем и обрезаем изображение по заданной высоте и ширине таким образом, чтоб оно полностью заполнило пространство
    ];
    private $id = null;
    private $image_hash = null;
    private $type = 'publication';
    private $strategy = 'w';
    private $width = 100;
    private $height = null;
    private $hash = false;
    private $attributes = [];
    private $exists = true;
    private $widthHeight = true;
    private $stretch = true;
 
    public function __construct(array $params = [], array $attributes = [])
    {
        $this->setIdFromParams($params);
        $this->attributes = $attributes;
 
        $this->type = (isset($params['type'])) ? $params['type'] : 'publication';
        $this->strategy = (isset($params['strategy'])) ? $params['strategy'] : 'w';
        $this->image_hash = (isset($params['image_hash'])) ? $params['image_hash'] : null;
        $this->hash = (isset($params['hash'])) ? $params['hash'] : false;
 
        $this->setDimensionsAttributes($params);
    }
 
    private function setDimensionsAttributes(array $params = [])
    {
        $this->width = (isset($params['width'])) ? $params['width'] : 100;
        $this->height = (isset($params['height'])) ? $params['height'] : null;
 
        $this->widthHeight = (isset($params['widthHeight'])) ? $params['widthHeight'] : true;
        $this->widthHeight = (isset($params['widthHeight']) && MOBILE_DEVICE) ? false : true;
 
        $this->stretch = (isset($params['stretch'])) ? $params['stretch'] : null;
    }
 
    private function setIdFromParams($params)
    {
        if (isset($params['id'])) {
            if (preg_match('/^\d+$/', $params['id'])) {
                $this->id = (int) $params['id'];
            } else {
                $this->id = $params['id'];
            }
        } else {
            if (IMG_DEBUG_MODE) {
                throw new \Exception("ID не определен");
            }
        }
    }
 
    /**
     * HTML-тег изображения, готовый к использованию
     * <img src="" alt="" />
     */
    public function imageHtml()
    {
        //Из заданных параметров и атрибутов составляем html-тэг
        $this->attributesForImageHtml();
 
        // Получаем относительный адрес файла кешированного изображения
        $src = $this->cachedRelPath();
 
        if ($this->exists) {
            if ($this->hash) {
                $src .= '?' . microtime();
            }
        } else {
            $src = NOIMAGE;
            $this->attributes['width'] = $this->width;
            $this->attributes['height'] = $this->height;
        }
 
        $attr_src = 'src="' . $this->getDi()->get('config')->base_path . $src . '"';
        $result = '<img ' . $attr_src . $this->attributesResultForImageHtml($this->attributes) . '/>';
 
        return $result;
    }
 
    private function attributesForImageHtml()
    {
        if ($this->widthHeight) {
            if ($this->stretch && in_array($this->strategy, ['wh', 'a'])) {
                $this->stretch = false;
            }
            $this->changeAttributesInAccordanceWithStretch();
        }
        $this->attributes['alt'] = (isset($this->attributes['alt'])) ?
            htmlspecialchars($this->attributes['alt'], ENT_QUOTES) :
            '';
    }
 
    private function changeAttributesInAccordanceWithStretch()
    {
        if ($this->stretch) {
            $this->changeAttributesForStretch();
        } else {
            $this->changeAttributesWithoutStretch();
        }
    }
 
    private function changeAttributesForStretch()
    {
        if ($this->width) {
            $this->attributes['width'] = $this->width;
        }
        if ($this->height) {
            $this->attributes['height'] = $this->height;
        }
    }
 
    private function changeAttributesWithoutStretch()
    {
        $widthHeight = $this->getImageWidthHeight();
        if ($widthHeight['width']) {
            $this->attributes['width'] = $widthHeight['width'];
        }
        if ($widthHeight['height']) {
            $this->attributes['height'] = $widthHeight['height'];
        }
    }
 
    private function attributesResultForImageHtml($attributes)
    {
        $attributesHtmlArray = [];
        foreach ($attributes as $el => $val) {
            $attributesHtmlArray[] = $el . '="' . $val . '"';
        }
        $attributesHtml = implode(' ', $attributesHtmlArray);
        $attributesHtmlResult = ($attributesHtml) ? ' ' . $attributesHtml : '';
 
        return $attributesHtmlResult;
    }
 
    /**
     * Относительный адрес файла кешированного изображения
     * /img/preview/405102/405102_1_w_100.jpg
     */
    public function cachedRelPath()
    {
        // Рассчитываем по входящим параметрам относительный путь к кешированному файлу
        $cachedRelPath = $this->calculateCachedRelPath();
        // Совмещаем относительный путь с корневым, получаем абсолютный путь
        $cachedAbsPath = IMG_ROOT_PATH . $cachedRelPath;
        // Проверяем существование такого файла. если файл не существует:
        if (!file_exists($cachedAbsPath)) {
            // Генерируем кеш-файл по заданным параметрам
            $this->generateCachedImage();
        }
 
        return IMG_STORAGE_SERVER . $cachedRelPath;
    }
 
    /**
     * @return string
     */
    public function cachedAbsPath()
    {
        return IMG_ROOT_PATH . $this->cachedRelPath();
    }
 
    /**
     * Относительный адрес файла оригинального изображения
     */
    public function originalRelPath()
    {
        return IMG_STORAGE_SERVER . $this->calculateOriginalRelPath();
    }
 
    /**
     * Абсолютный адрес файла оригинального изображения
     */
    public function originalAbsPath()
    {
        return $this->getAbsPath(true);
    }
 
    /**
     * @param $file
     * @return bool
     */
    public function save($file)
    {
        if (file_exists($file)) {
            return copy($file, $this->originalAbsPath());
        }
    }
 
    /**
     * @return array
     */
    public function originalWidthHeight()
    {
        $imageSize = getimagesize($this->originalAbsPath());
        if (!empty($imageSize)) {
            return [
                'width'  => $imageSize[0],
                'height' => $imageSize[1]
            ];
        }
    }
 
    /**
     * @return int
     */
    public function cachedFileSize()
    {
        $path = $this->cachedAbsPath();
        if (file_exists($path)) {
            return filesize($path);
        }
    }
 
    /**
     * @return bool
     */
    public function isExists()
    {
        return (file_exists($this->getAbsPath(true))) ? true : false ;
    }
 
    /**
     * Рассчитываем по входящим параметрам относительный путь к кешированному файлу
     * /img/preview/405/405102_1_w_100.jpg
     */
    private function calculateCachedRelPath()
    {
        $pathParts = [];
        $pathParts[] = IMG_ROOT_REL_PATH;
        $pathParts[] = 'cache';
        $pathParts[] = $this->type;
 
        if (is_int($this->id)) {
            $idPart = floor($this->id / 1000);
        } else {
            $idPart = $this->id;
        }
        $pathParts[] = $idPart;
 
        $fileParts = [];
        $fileParts[] = $this->id;
        if ($this->image_hash) {
            $fileParts[] = $this->image_hash;
        }
        if (in_array($this->strategy, self::$STRATEGIES)) {
            $fileParts[] = $this->strategy;
 
            $fileParts[] = $this->width;
            if ($this->height) {
                $fileParts[] = $this->height;
            }
 
            // "img/preview/405"
            $path = implode(DIR_SEP, $pathParts);
            // "405102_1_w_100"
            $file = implode('_', $fileParts);
 
            return $path . DIR_SEP . $file . '.jpg';
 
        } else {
            if (IMG_DEBUG_MODE) {
                throw new \Exception("Параметр 'strategy' указан неверно");
            }
        }
    }
 
    /**
     * Рассчитываем по входящим параметрам относительный путь к оригинальному файлу
     * /img/original/preview/405/405102_1.jpg
     * @return string
     */
    private function calculateOriginalRelPath()
    {
        $pathParts = [];
        $pathParts[] = IMG_ROOT_REL_PATH;
        $pathParts[] = 'original';
        $pathParts[] = $this->type;
 
        if (is_int($this->id)) {
            $idPart = floor($this->id / 1000);
        } else {
            $idPart = $this->id;
        }
        $pathParts[] = $idPart;
 
        $fileParts = [];
        $fileParts[] = $this->id;
        if ($this->image_hash) {
            $fileParts[] = $this->image_hash;
        }
 
        // "img/original/preview/405"
        $path = implode(DIR_SEP, $pathParts);
        // "405102_1"
        $file = implode('_', $fileParts);
 
        return $path . DIR_SEP . $file . '_' . time() . '.jpg';
    }
 
    /**
     * генерируем кеш-файл по заданным параметрам
     * @throws \Exception
     */
    private function generateCachedImage()
    {
        // Абсолютный путь оригинального изображения
        $originalAbsPath = IMG_ROOT_PATH . $this->calculateOriginalRelPath();
        $this->checkOriginalExists($originalAbsPath);
 
        require_once __DIR__ . '/PHPThumb/ThumbLib.inc.php';
        $image = \PhpThumbFactory::create($originalAbsPath);
        // Для мобильных устройств отдаем изображение с качеством на уровне 60%
        if (MOBILE_DEVICE) {
            $options = ['jpegQuality' => 60];
            $image->setOptions($options);
        }
        switch ($this->strategy) {
            case 'w':
                // Масштабируем по ширине
                $image->resize($this->width);
                break;
            case 'wh':
                // Масштабируем по заданной ширине и высоте. Изображение подганяется в этот прямоугольник
                $image->resize($this->width, $this->height);
                break;
            case 'a':
                // Центрируем и обрезаем изображение по заданной высоте и ширине таким образом, чтоб оно полностью заполнило пространство
                $image->adaptiveResize($this->width, $this->height);
                break;
        }
 
        $this->saveImage($image, $originalAbsPath);
    }
 
    /**
     * @param $left
     * @param $top
     * @param $width
     * @param $height
     * @throws \Exception
     */
    public function cropOriginal($left, $top, $width, $height)
    {
        $originalAbsPath = IMG_ROOT_PATH . $this->calculateOriginalRelPath(); // Абсолютный путь оригинального изображения
        $this->checkOriginalExists($originalAbsPath);
 
        require_once __DIR__ . '/PHPThumb/ThumbLib.inc.php';
        $image = \PhpThumbFactory::create($originalAbsPath);
        $image->crop($left, $top, $width, $height);
 
        $this->saveImage($image, $originalAbsPath);
    }
 
    /**
     * @param $originalAbsPath
     * @throws \Exception
     */
    private function checkOriginalExists($originalAbsPath)
    {
        if (!file_exists($originalAbsPath)) {
            if (IMG_DEBUG_MODE) {
                throw new \Exception("Файл {$originalAbsPath} не существует");
            } else {
                $this->exists = false;
            }
        }
    }
 
    /**
     * @param $image
     * @param $originalAbsPath
     * @throws \Exception
     */
    private function saveImage($image, $originalAbsPath)
    {
        // Если оригинал не заблокирован, блокируем. Это необходимо для предотвращения множественной генерации кеш-файла параллельными запросами
        if ($this->lockOriginal($originalAbsPath)) {
            // Сохраняем кешированное изображение
            $image->save($this->getAbsPath(false));
            // Снимаем блокировку
            $this->unlockOriginal($originalAbsPath);
        } else {
            if (IMG_DEBUG_MODE) {
                throw new \Exception("Файл {$originalAbsPath} заблокирован механизмом проверки _LOCK или не существует");
            } else {
                $this->exists = false;
            }
        }
    }
 
    /**
     * Удаляет оригинальные и кешированные изображения
     * @param bool $removeAll
     */
    public function remove($removeAll = true)
    {
        $this->removeCached();
        $this->removeOriginal($removeAll);
    }
 
    /**
     * Удаляет оригинальные изображения
     * @param bool $removeAll
     */
    public function removeOriginal($removeAll = true)
    {
        if (!$removeAll) {
            if (file_exists($this->originalAbsPath())) {
                unlink($this->originalAbsPath());
            }
        } else {
            $originalAbsPath = IMG_ROOT_PATH . $this->calculateOriginalRelPath();
            $originalAbsPathDir = implode(DIR_SEP, array_slice(explode(DIR_SEP, $originalAbsPath), 0, -1)); // Абсолютный путь директории
 
            if ($this->image_hash) {
                $search = $originalAbsPathDir . "/" . $this->id . "_*.jpg";
            } else {
                $search = $originalAbsPathDir . "/" . $this->id . ".jpg";
            }
            $files = glob($search);
            if (!empty($files)) {
                foreach ($files as $file) {
                    if (is_file($file)) {
                        unlink($file);
                    }
                }
            }
        }
    }
 
    /**
     * Удаляет кешированные изображения
     */
    public function removeCached()
    {
        $cachedAbsPath = IMG_ROOT_PATH . $this->calculateCachedRelPath();
        $cachedAbsPathDir = implode(DIR_SEP, array_slice(explode(DIR_SEP, $cachedAbsPath), 0, -1)); // Абсолютный путь директории
 
        $search = $cachedAbsPathDir . "/" . $this->id . "_*.jpg";
        $files = glob($search);
        if (!empty($files)) {
            foreach ($files as $file) {
                if (is_file($file)) {
                    unlink($file);
                }
            }
        }
    }
 
    /**
     * Размеры кешированного изображения
     */
    public function getImageWidthHeight()
    {
        $cachedAbsPath = IMG_ROOT_PATH . $this->calculateCachedRelPath();
        if (file_exists($cachedAbsPath)) {
            $imageSize = getimagesize($cachedAbsPath);
            if (!empty($imageSize)) {
                return [
                    'width'  => $imageSize[0],
                    'height' => $imageSize[1]
                ];
            }
        } else {
            return [
                'width'  => null,
                'height' => null
            ];
        }
    }
 
    /**
     * Проверяем блокировку оригинала изображения. Если нет, то блокируем
     * @param string $originalAbsPath
     * @return boolean true|false
     */
    private function lockOriginal($originalAbsPath)
    {
        $lockFileName = $this->getLockFileName($originalAbsPath);
        if (file_exists($lockFileName)) {
            return false;
        } else {
            $handle = fopen($lockFileName, 'w+');
            if (flock($handle, LOCK_EX)) {
                fwrite($handle, '1');
                flock($handle, LOCK_UN);
                fclose($handle);
                return true;
            } else {
                if ($handle) {
                    fclose($handle);
                }
                return false;
            }
        }
    }
 
    /**
     * Снимаем блокировку оригинала изображения
     * @param string $originalAbsPath
     */
    private function unlockOriginal($originalAbsPath)
    {
        unlink($this->getLockFileName($originalAbsPath));
    }
 
    /**
     * Возвращает имя файла для блокировки оригинала изображения
     * @param string $originalAbsPath
     * @return string
     */
    private function getLockFileName($originalAbsPath)
    {
        return preg_replace('/\.' . IMG_EXTENSION . '/i', '_lock.' . IMG_EXTENSION, $originalAbsPath);
    }
 
    /**
     * @param bool $original
     * @return string
     * @throws \Exception
     */
    private function getAbsPath($original = true)
    {
        $absPath = IMG_ROOT_PATH . (($original) ? $this->calculateOriginalRelPath() : $this->calculateCachedRelPath());
 
        // Абсолютный путь директории
        $absPathDir = implode(DIR_SEP, array_slice(explode(DIR_SEP, $absPath), 0, -1));
 
        // Если директория отсутствует
        if (!is_dir($absPathDir)) {
            // Создаем дерево директорий
            mkdir($absPathDir, 0777, true);
        }
 
        return $absPath;
    }
 
    /**
     * @param bool $original
     * @return string
     * @throws \Exception
     */
    public function getabsPathDir($original = true)
    {
        $absPath = IMG_ROOT_PATH . (($original) ? $this->calculateOriginalRelPath() : $this->calculateCachedRelPath());
 
        // Абсолютный путь директории
        $absPathDir = implode(DIR_SEP, array_slice(explode(DIR_SEP, $absPath), 0, -1));
 
        // Если директория отсутствует
        if (!is_dir($absPathDir)) {
            // Создаем дерево директорий
            mkdir($absPathDir, 0777, true);
        }
 
        return $absPathDir;
    }
 
}
#3Image\Storage->imageHtml()
/www/wiki.youvivu.com/public_html/data/cache/volt/%%www%%wiki.youvivu.com%%public_html%%app%%modules%%publication%%views%%index%%publication.volt.php (992)
<style>
    .destination-container img {
        width: 100%;
        height: auto;
    }
 
    ul.listBlogInLocation li a img {
        float: left;
        padding: 1px;
        border: 1px solid #ddd;
    }
 
    ul.listBlogInLocation li a > img {
        width: 54px;
    }
 
    ul.listBlogInLocation li a span {
        float: left;
        width: 70%;
        margin-left: 5px;
        color: #777 !important;
        font-size: 13px !important;
        line-height: 18px;
    }
 
    ul#cat_nav.listBlogInLocation i {
        font-size: 13px !important;
    }
    .mfp-container {
        text-align: center;
        position: absolute;
        width: 100%;
        height: auto;
        left: 0;
        top: 0;
        padding: 0 8px;
        -webkit-box-sizing: border-box;
        -moz-box-sizing: border-box;
        box-sizing: border-box;
    }
    #youviu-modal-culture-detail {
        background: #FFF;
        padding: 20px;
        width: auto;
        max-width: 840px;
        margin: 62px auto;
    }
    .mfp-close-btn-in .mfp-close {
        color: #333;
        background: #fff;
    }
</style>
<div class="mfp-bg mfp-ready"></div>
<div class="mfp-wrap mfp-close-btn-in mfp-auto-cursor mfp-ready" tabindex="-1"
     style="overflow-x: hidden; overflow-y: auto; display: none">
    <div class="mfp-container mfp-s-ready mfp-inline-holder">
        <div class="mfp-content">
            <div id="youviu-modal-culture-detail" class="white-popup">
                <div class="body">
 
                    <div class="row">
                        <div class="col-md-12" id="cul_content">
 
                        </div>
                    </div>
                </div>
                <button title="Close (Esc)" type="button" class="mfp-close">×</button>
            </div>
        </div>
        <div class="mfp-preloader">Loading...</div>
    </div>
</div>
<?php if (($publicationResult->p->getTypeSlug() != 'locations')) { ?>
 
    <section class="parallax-window" data-parallax="scroll"
             data-image-src="<?= $this->url->path() ?><?= $publicationResult->p->banner_src ?>" data-natural-width="1400"
             data-natural-height="470">
        <div class="parallax-content-1">
            <div class="animated fadeInDown">
                <h1>KHÁM PHÁ VIỆT NAM</h1>
                <p>Hãy khám phá việt nam qua những địa điểm phượt vô cùng thú vị, thơ mộng và hùng vĩ.</p>
            </div>
        </div>
    </section><!-- End section -->
    <div class="container margin_60">
        <div id="tour_guide"><p><img class="img-circle styled lazy" src="<?= $publicationResult->p->preview_src ?>"
                                     alt="<?= $publicationResult->title ?>"
                                     style="width: 250px; height: 250px; display: inline;"
                                     data-original="/<?= $publicationResult->p->preview_src ?>"></p>
            <span class="rating"><i class="icon-star voted"></i><i class="icon-star voted"></i><i
                        class="icon-star voted"></i><i class="icon-star voted"></i><i
                        class="icon-star-empty"></i></span>
            <h2>Khám phá <span><?= $publicationResult->title ?></span> Việt Nam</h2>
            <p class="lead destination-lead add_bottom_30">
                <?= $publicationResult->p->meta_description ?>. </p></div>
        <div class="row">
            <div class="col-md-8" id="single_tour_desc">
                <h3>Nét đẹp <span><?= $publicationResult->title ?></span></h3>
                <p class="visible-sm visible-xs"><a class="btn_map" data-toggle="collapse" href="#collapseMap"
                                                    aria-expanded="false" aria-controls="collapseMap"
                                                    data-text-swap="Hide map" data-text-original="View on map">View on
                        map</a></p><!-- Map button for tablets/mobiles -->
 
                <div class="row">
                    <div class="col-md-12 destination-container">
                        <?= $publicationResult->text ?>
                    </div>
                </div>
                <div style="padding-top: 10px">
                    <div class="fb-like" data-href='<?php echo "http://$_SERVER[HTTP_HOST]$_SERVER[REQUEST_URI]"; ?>' data-layout="standard" data-action="like" data-size="small" data-show-faces="true" data-share="true"></div>
                    <div style="width:100% !important;" class="fb-comments" data-href='<?php echo "http://$_SERVER[HTTP_HOST]$_SERVER[REQUEST_URI]"; ?>' data-numposts="5"></div>
                </div>
 
            </div><!--End  single_tour_desc-->
 
            <aside class="col-md-4">
                <p class="hidden-sm hidden-xs" style="display: none;">
                    <a class="btn_map" data-toggle="collapse" href="#collapseMap" aria-expanded="false"
                       aria-controls="collapseMap" data-text-swap="Hide map" data-text-original="View on map">View on
                        map</a>
                </p>
                <div style="display: none;">
                    <?php foreach($cul as $cu) { ?>
                    <div id="cul_<?php echo $cu->id ?>" style="display: none;"><?php echo  ($cu->text) ?></div>
                    <?php } ?>
                </div>
                <div class="box_style_cat youviu-box-culture-common youviu-box-culture-destination"><h3
                            style="text-align: center">Văn hóa &amp; con người</h3>
                    <ul id="cat_nav" class="listBlogInLocation">
 
                        <?php foreach($cul as $cu) { ?>
                        <li><a class="youviu-culture-popup-detail" rel="nofollow" data-title="<?php echo $cu->title ?>"
                               data-href="showcul(<?php echo $cu->id ?>)" onclick="showcul(<?php echo $cu->id ?>)"
                               href="javascript:void(0)">
                                <img style="width: 54px;height: 54px;" class="lazy"
                                                              alt="<?php echo $cu->title ?>"
                                                              data-original="/<?php echo $cu->preview_src ?>"
                                                              src="/assets/ba871a56/img/loading.gif"><span>
<?php echo $cu->title ?><br><div class="rating"><i class="icon-star voted"></i><i class="icon-star voted"></i><i
                                                class="icon-star voted"></i><i class="icon-star voted"></i><i
                                                class="icon-star-empty"></i></div><br><i
                                            class="icon-calendar-empty"></i> Đăng ngày 01/01/2017 </span>
                                <div style="clear:both"></div>
                            </a></li>
                        <?php } ?>
                        <div id="youviu-modal-culture-detail" class="white-popup mfp-hide">
                            <div class="body"></div>
                        </div>
                    </ul>
                </div>
            </aside>
        </div><!--End row -->
    </div><!--End container -->
 
    <article id="content" class="publication clearfix" style="display: none;">
 
        <?php if ($this->helper->isAdminSession()) { ?>
            <p style="font-weight: bold;font-size:120%;">
                <a class="noajax"
                   href="<?= $this->url->get() ?>publication/admin/edit/<?= $publicationResult->p->getId() ?>?lang=<?= constant('LANG') ?>"><?= $this->helper->at('Edit publication') ?></a>
            </p>
        <?php } ?>
 
        <h1><?= $publicationResult->title ?></h1>
 
        <?php if ($publicationResult->p->getTypeDisplayDate()) { ?>
            <section class="date"><?= $publicationResult->p->getDate('d.m.Y') ?></section>
        <?php } ?>
 
        <?php if ($publicationResult->p->preview_inner) { ?>
            <?php $image = $this->helper->image(['id' => $publicationResult->p->getId(), 'type' => 'publication', 'width' => 300, 'strategy' => 'w']); ?>
            <div class="image inner">
                <?= $image->imageHTML() ?>
            </div>
        <?php } ?>
 
        <?= $publicationResult->text ?>
 
        <a href="<?= $this->helper->langUrl(['for' => 'publications', 'type' => $publicationResult->t_slug]) ?>"
           class="back">&larr; <?= $this->helper->translate('Back to publications list') ?></a>
 
    </article>
 
<?php } ?>
 
<?php if (($publicationResult->p->getTypeSlug() == 'locations')) { ?>
 
    <section class="parallax-window" data-parallax="scroll"
             data-image-src="<?= $this->url->path() ?><?= $publicationResult->p->banner_src ?>" data-natural-width="1400"
             data-natural-height="470">
        <div class="parallax-content-1">
            <div class="animated fadeInDown">
                <h1><?= $publicationResult->title ?></h1>
                <p>Hãy khám phá việt nam qua những địa điểm phượt vô cùng thú vị, thơ mộng và hùng vĩ.</p>
            </div>
        </div>
    </section><!-- End section -->
    <style>
        .slider-pro {
            position: relative;
            margin: 0 auto;
            -moz-box-sizing: content-box;
            box-sizing: content-box
        }
 
        .sp-slides-container {
            position: relative
        }
 
        .sp-mask {
            position: relative;
            overflow: hidden
        }
 
        .sp-slides {
            position: relative;
            -webkit-backface-visibility: hidden;
            -webkit-perspective: 1000
        }
 
        .sp-slide {
            position: absolute
        }
 
        .sp-image-container {
            overflow: hidden
        }
 
        .sp-image {
            position: relative;
            display: block;
            border: none
        }
 
        .sp-no-js {
            overflow: hidden;
            max-width: 100%
        }
 
        .sp-thumbnails-container {
            position: relative;
            overflow: hidden
        }
 
        .sp-bottom-thumbnails, .sp-top-thumbnails {
            left: 0;
            margin: 0 auto
        }
 
        .sp-top-thumbnails {
            position: absolute;
            top: 0;
            margin-bottom: 4px
        }
 
        .sp-bottom-thumbnails {
            margin-top: 4px
        }
 
        .sp-left-thumbnails, .sp-right-thumbnails {
            position: absolute;
            top: 0
        }
 
        .sp-right-thumbnails {
            right: 0;
            margin-left: 4px
        }
 
        .sp-left-thumbnails {
            left: 0;
            margin-right: 4px
        }
 
        .sp-thumbnails {
            position: relative
        }
 
        .sp-thumbnail {
            border: none
        }
 
        .sp-thumbnail-container {
            position: relative;
            display: block;
            overflow: hidden;
            float: left;
            -moz-box-sizing: border-box;
            box-sizing: border-box
        }
 
        .sp-bottom-thumbnails .sp-thumbnail-container, .sp-top-thumbnails .sp-thumbnail-container {
            margin-left: 2px;
            margin-right: 2px
        }
 
        .sp-bottom-thumbnails .sp-thumbnail-container:first-child, .sp-top-thumbnails .sp-thumbnail-container:first-child {
            margin-left: 0
        }
 
        .sp-bottom-thumbnails .sp-thumbnail-container:last-child, .sp-top-thumbnails .sp-thumbnail-container:last-child {
            margin-right: 0
        }
 
        .sp-left-thumbnails .sp-thumbnail-container, .sp-right-thumbnails .sp-thumbnail-container {
            margin-top: 2px;
            margin-bottom: 2px
        }
 
        .sp-left-thumbnails .sp-thumbnail-container:first-child, .sp-right-thumbnails .sp-thumbnail-container:first-child {
            margin-top: 0
        }
 
        .sp-left-thumbnails .sp-thumbnail-container:last-child, .sp-right-thumbnails .sp-thumbnail-container:last-child {
            margin-bottom: 0
        }
 
        .sp-right-thumbnails.sp-has-pointer {
            margin-left: -13px
        }
 
        .sp-right-thumbnails.sp-has-pointer .sp-thumbnail {
            position: absolute;
            left: 18px;
            margin-left: 0 !important
        }
 
        .sp-right-thumbnails.sp-has-pointer .sp-selected-thumbnail:before {
            content: '';
            position: absolute;
            height: 100%;
            border-left: 5px solid red;
            left: 0;
            top: 0;
            margin-left: 13px
        }
 
        .sp-right-thumbnails.sp-has-pointer .sp-selected-thumbnail:after {
            content: '';
            position: absolute;
            width: 0;
            height: 0;
            left: 0;
            top: 50%;
            margin-top: -8px;
            border-right: 13px solid red;
            border-top: 8px solid transparent;
            border-bottom: 8px solid transparent
        }
 
        .sp-left-thumbnails.sp-has-pointer {
            margin-right: -13px
        }
 
        .sp-left-thumbnails.sp-has-pointer .sp-thumbnail {
            position: absolute;
            right: 18px
        }
 
        .sp-left-thumbnails.sp-has-pointer .sp-selected-thumbnail:before {
            content: '';
            position: absolute;
            height: 100%;
            border-left: 5px solid red;
            right: 0;
            top: 0;
            margin-right: 13px
        }
 
        .sp-left-thumbnails.sp-has-pointer .sp-selected-thumbnail:after {
            content: '';
            position: absolute;
            width: 0;
            height: 0;
            right: 0;
            top: 50%;
            margin-top: -8px;
            border-left: 13px solid red;
            border-top: 8px solid transparent;
            border-bottom: 8px solid transparent
        }
 
        .sp-bottom-thumbnails.sp-has-pointer {
            margin-top: -13px
        }
 
        .sp-bottom-thumbnails.sp-has-pointer .sp-thumbnail {
            position: absolute;
            top: 18px;
            margin-top: 0 !important
        }
 
        .sp-bottom-thumbnails.sp-has-pointer .sp-selected-thumbnail:before {
            content: '';
            position: absolute;
            width: 100%;
            border-bottom: 5px solid red;
            top: 0;
            margin-top: 13px
        }
 
        .sp-bottom-thumbnails.sp-has-pointer .sp-selected-thumbnail:after {
            content: '';
            position: absolute;
            width: 0;
            height: 0;
            left: 50%;
            top: 0;
            margin-left: -8px;
            border-bottom: 13px solid red;
            border-left: 8px solid transparent;
            border-right: 8px solid transparent
        }
 
        .sp-top-thumbnails.sp-has-pointer {
            margin-bottom: -13px
        }
 
        .sp-top-thumbnails.sp-has-pointer .sp-thumbnail {
            position: absolute;
            bottom: 18px
        }
 
        .sp-top-thumbnails.sp-has-pointer .sp-selected-thumbnail:before {
            content: '';
            position: absolute;
            width: 100%;
            border-bottom: 5px solid red;
            bottom: 0;
            margin-bottom: 13px
        }
 
        .sp-top-thumbnails.sp-has-pointer .sp-selected-thumbnail:after {
            content: '';
            position: absolute;
            width: 0;
            height: 0;
            left: 50%;
            bottom: 0;
            margin-left: -8px;
            border-top: 13px solid red;
            border-left: 8px solid transparent;
            border-right: 8px solid transparent
        }
 
        .sp-layer {
            position: absolute;
            margin: 0;
            box-sizing: border-box;
            -moz-box-sizing: border-box;
            -webkit-box-sizing: border-box;
            -webkit-font-smoothing: subpixel-antialiased;
            -webkit-backface-visibility: hidden
        }
 
        .sp-black {
            color: #FFF;
            background: #000;
            background: rgba(0, 0, 0, .7)
        }
 
        .sp-white {
            color: #000;
            background: #fff;
            background: rgba(255, 255, 255, .7)
        }
 
        .sp-rounded {
            border-radius: 10px
        }
 
        .sp-padding {
            padding: 10px
        }
 
        .sp-grab {
            cursor: url(images/openhand.cur), move
        }
 
        .sp-grabbing {
            cursor: url(images/closedhand.cur), move
        }
 
        .sp-selectable {
            cursor: default
        }
 
        .sp-caption-container {
            text-align: center;
            margin-top: 10px
        }
 
        .sp-full-screen {
            margin: 0 !important;
            background-color: #000
        }
 
        .sp-full-screen-button {
            position: absolute;
            top: 5px;
            right: 10px;
            font-size: 30px;
            line-height: 1;
            cursor: pointer;
            -webkit-transform: rotate(45deg);
            -ms-transform: rotate(45deg);
            transform: rotate(45deg)
        }
 
        .sp-full-screen-button:before {
            content: '\2195'
        }
 
        .sp-fade-full-screen {
            opacity: 0;
            -webkit-transition: opacity .5s;
            transition: opacity .5s
        }
 
        .slider-pro:hover .sp-fade-full-screen {
            opacity: 1
        }
 
        .sp-buttons {
            position: relative;
            width: 100%;
            text-align: center;
            padding-top: 10px
        }
 
        .sp-button {
            width: 10px;
            height: 10px;
            border: 2px solid #000;
            border-radius: 50%;
            margin: 4px;
            display: inline-block;
            -moz-box-sizing: border-box;
            -webkit-box-sizing: border-box;
            box-sizing: border-box;
            cursor: pointer
        }
 
        .sp-selected-button {
            background-color: #000
        }
 
        @media only screen and (min-width: 768px) and (max-width: 1024px) {
            .sp-button {
                width: 14px;
                height: 14px
            }
        }
 
        @media only screen and (min-width: 568px) and (max-width: 768px) {
            .sp-button {
                width: 16px;
                height: 16px
            }
        }
 
        @media only screen and (min-width: 320px) and (max-width: 568px) {
            .sp-button {
                width: 18px;
                height: 18px
            }
        }
 
        .sp-arrows {
            position: absolute
        }
 
        .sp-fade-arrows {
            opacity: 0;
            -webkit-transition: opacity .5s;
            transition: opacity .5s
        }
 
        .sp-slides-container:hover .sp-fade-arrows {
            opacity: 1
        }
 
        .sp-horizontal .sp-arrows {
            width: 100%;
            left: 0;
            top: 50%;
            margin-top: -15px
        }
 
        .sp-vertical .sp-arrows {
            height: 100%;
            left: 50%;
            top: 0;
            margin-left: -10px
        }
 
        .sp-arrow {
            position: absolute;
            display: block;
            width: 20px;
            height: 30px;
            cursor: pointer
        }
 
        .sp-vertical .sp-arrow {
            -webkit-transform: rotate(90deg);
            -ms-transform: rotate(90deg);
            transform: rotate(90deg)
        }
 
        .sp-horizontal .sp-previous-arrow {
            left: 20px
        }
 
        .sp-horizontal .sp-next-arrow {
            right: 20px
        }
 
        .sp-vertical .sp-previous-arrow {
            top: 20px
        }
 
        .sp-vertical .sp-next-arrow {
            bottom: 20px
        }
 
        .sp-next-arrow:after, .sp-next-arrow:before, .sp-previous-arrow:after, .sp-previous-arrow:before {
            content: '';
            position: absolute;
            width: 50%;
            height: 50%;
            background-color: #FFF
        }
 
        .sp-previous-arrow:before {
            left: 30%;
            top: 0;
            -webkit-transform: skew(145deg, 0deg);
            -ms-transform: skew(145deg, 0deg);
            transform: skew(145deg, 0deg)
        }
 
        .sp-previous-arrow:after {
            left: 30%;
            top: 50%;
            -webkit-transform: skew(-145deg, 0deg);
            -ms-transform: skew(-145deg, 0deg);
            transform: skew(-145deg, 0deg)
        }
 
        .sp-next-arrow:before {
            right: 30%;
            top: 0;
            -webkit-transform: skew(35deg, 0deg);
            -ms-transform: skew(35deg, 0deg);
            transform: skew(35deg, 0deg)
        }
 
        .sp-next-arrow:after {
            right: 30%;
            top: 50%;
            -webkit-transform: skew(-35deg, 0deg);
            -ms-transform: skew(-35deg, 0deg);
            transform: skew(-35deg, 0deg)
        }
 
        .ie7 .sp-arrow, .ie8 .sp-arrow {
            width: 0;
            height: 0
        }
 
        .ie7 .sp-arrow:after, .ie7 .sp-arrow:before, .ie8 .sp-arrow:after, .ie8 .sp-arrow:before {
            content: none
        }
 
        .ie7.sp-horizontal .sp-previous-arrow, .ie8.sp-horizontal .sp-previous-arrow {
            border-right: 20px solid #FFF;
            border-top: 20px solid transparent;
            border-bottom: 20px solid transparent
        }
 
        .ie7.sp-horizontal .sp-next-arrow, .ie8.sp-horizontal .sp-next-arrow {
            border-left: 20px solid #FFF;
            border-top: 20px solid transparent;
            border-bottom: 20px solid transparent
        }
 
        .ie7.sp-vertical .sp-previous-arrow, .ie8.sp-vertical .sp-previous-arrow {
            border-bottom: 20px solid #FFF;
            border-left: 20px solid transparent;
            border-right: 20px solid transparent
        }
 
        .ie7.sp-vertical .sp-next-arrow, .ie8.sp-vertical .sp-next-arrow {
            border-top: 20px solid #FFF;
            border-left: 20px solid transparent;
            border-right: 20px solid transparent
        }
 
        .sp-thumbnail-arrows {
            position: absolute
        }
 
        .sp-fade-thumbnail-arrows {
            opacity: 0;
            -webkit-transition: opacity .5s;
            transition: opacity .5s
        }
 
        .sp-thumbnails-container:hover .sp-fade-thumbnail-arrows {
            opacity: 1
        }
 
        .sp-bottom-thumbnails .sp-thumbnail-arrows, .sp-top-thumbnails .sp-thumbnail-arrows {
            width: 100%;
            top: 50%;
            left: 0;
            margin-top: -12px
        }
 
        .sp-left-thumbnails .sp-thumbnail-arrows, .sp-right-thumbnails .sp-thumbnail-arrows {
            height: 100%;
            top: 0;
            left: 50%;
            margin-left: -7px
        }
 
        .sp-thumbnail-arrow {
            position: absolute;
            display: block;
            width: 15px;
            height: 25px;
            cursor: pointer
        }
 
        .sp-left-thumbnails .sp-thumbnail-arrows .sp-thumbnail-arrow, .sp-right-thumbnails .sp-thumbnail-arrows .sp-thumbnail-arrow {
            -webkit-transform: rotate(90deg);
            -ms-transform: rotate(90deg);
            transform: rotate(90deg)
        }
 
        .sp-bottom-thumbnails .sp-previous-thumbnail-arrow, .sp-top-thumbnails .sp-previous-thumbnail-arrow {
            left: 0
        }
 
        .sp-bottom-thumbnails .sp-next-thumbnail-arrow, .sp-top-thumbnails .sp-next-thumbnail-arrow {
            right: 0
        }
 
        .sp-left-thumbnails .sp-previous-thumbnail-arrow, .sp-right-thumbnails .sp-previous-thumbnail-arrow {
            top: 0
        }
 
        .sp-left-thumbnails .sp-next-thumbnail-arrow, .sp-right-thumbnails .sp-next-thumbnail-arrow {
            bottom: 0
        }
 
        .sp-next-thumbnail-arrow:after, .sp-next-thumbnail-arrow:before, .sp-previous-thumbnail-arrow:after, .sp-previous-thumbnail-arrow:before {
            content: '';
            position: absolute;
            width: 50%;
            height: 50%;
            background-color: #FFF
        }
 
        .sp-previous-thumbnail-arrow:before {
            left: 30%;
            top: 0;
            -webkit-transform: skew(145deg, 0deg);
            -ms-transform: skew(145deg, 0deg);
            transform: skew(145deg, 0deg)
        }
 
        .sp-previous-thumbnail-arrow:after {
            left: 30%;
            top: 50%;
            -webkit-transform: skew(-145deg, 0deg);
            -ms-transform: skew(-145deg, 0deg);
            transform: skew(-145deg, 0deg)
        }
 
        .sp-next-thumbnail-arrow:before {
            right: 30%;
            top: 0;
            -webkit-transform: skew(35deg, 0deg);
            -ms-transform: skew(35deg, 0deg);
            transform: skew(35deg, 0deg)
        }
 
        .sp-next-thumbnail-arrow:after {
            right: 30%;
            top: 50%;
            -webkit-transform: skew(-35deg, 0deg);
            -ms-transform: skew(-35deg, 0deg);
            transform: skew(-35deg, 0deg)
        }
 
        .ie7 .sp-thumbnail-arrow, .ie8 .sp-thumbnail-arrow {
            width: 0;
            height: 0
        }
 
        .ie7 .sp-thumbnail-arrow:after, .ie7 .sp-thumbnail-arrow:before, .ie8 .sp-thumbnail-arrow:after, .ie8 .sp-thumbnail-arrow:before {
            content: none
        }
 
        .ie7 .sp-bottom-thumbnails .sp-previous-thumbnail-arrow, .ie7 .sp-top-thumbnails .sp-previous-thumbnail-arrow, .ie8 .sp-bottom-thumbnails .sp-previous-thumbnail-arrow, .ie8 .sp-top-thumbnails .sp-previous-thumbnail-arrow {
            border-right: 12px solid #FFF;
            border-top: 12px solid transparent;
            border-bottom: 12px solid transparent
        }
 
        .ie7 .sp-bottom-thumbnails .sp-next-thumbnail-arrow, .ie7 .sp-top-thumbnails .sp-next-thumbnail-arrow, .ie8 .sp-bottom-thumbnails .sp-next-thumbnail-arrow, .ie8 .sp-top-thumbnails .sp-next-thumbnail-arrow {
            border-left: 12px solid #FFF;
            border-top: 12px solid transparent;
            border-bottom: 12px solid transparent
        }
 
        .ie7 .sp-left-thumbnails .sp-previous-thumbnail-arrow, .ie7 .sp-right-thumbnails .sp-previous-thumbnail-arrow, .ie8 .sp-left-thumbnails .sp-previous-thumbnail-arrow, .ie8 .sp-right-thumbnails .sp-previous-thumbnail-arrow {
            border-bottom: 12px solid #FFF;
            border-left: 12px solid transparent;
            border-right: 12px solid transparent
        }
 
        .ie7 .sp-left-thumbnails .sp-next-thumbnail-arrow, .ie7 .sp-right-thumbnails .sp-next-thumbnail-arrow, .ie8 .sp-left-thumbnails .sp-next-thumbnail-arrow, .ie8 .sp-right-thumbnails .sp-next-thumbnail-arrow {
            border-top: 12px solid #FFF;
            border-left: 12px solid transparent;
            border-right: 12px solid transparent
        }
 
        a.sp-video {
            text-decoration: none
        }
 
        a.sp-video img {
            -webkit-backface-visibility: hidden;
            border: none
        }
 
        a.sp-video:after {
            content: '\25B6';
            position: absolute;
            width: 45px;
            padding-left: 5px;
            height: 50px;
            border: 2px solid #FFF;
            text-align: center;
            font-size: 30px;
            border-radius: 30px;
            top: 0;
            color: #FFF;
            bottom: 0;
            left: 0;
            right: 0;
            background-color: rgba(0, 0, 0, .2);
            margin: auto;
            line-height: 52px
        }
 
        .slider-pro img.sp-image, .slider-pro img.sp-thumbnail {
            max-width: none;
            max-height: none;
            border: none !important;
            border-radius: 0 !important;
            padding: 0 !important;
            -webkit-box-shadow: none !important;
            -mox-box-shadow: none !important;
            box-shadow: none !important;
            transition: none;
            -moz-transition: none;
            -webkit-transition: none;
            -o-transition: none
        }
 
        .slider-pro a {
            position: static;
            transition: none !important;
            -moz-transition: none !important;
            -webkit-transition: none !important;
            -o-transition: none !important
        }
 
        .slider-pro canvas, .slider-pro embed, .slider-pro iframe, .slider-pro object, .slider-pro video {
            max-width: none;
            max-height: none
        }
 
        .slider-pro p.sp-layer {
            font-size: 14px;
            line-height: 1.4;
            margin: 0
        }
 
        .slider-pro h1.sp-layer {
            font-size: 32px;
            line-height: 1.4;
            margin: 0
        }
 
        .slider-pro h2.sp-layer {
            font-size: 24px;
            line-height: 1.4;
            margin: 0
        }
 
        .slider-pro h3.sp-layer {
            font-size: 19px;
            line-height: 1.4;
            margin: 0
        }
 
        .slider-pro h4.sp-layer {
            font-size: 16px;
            line-height: 1.4;
            margin: 0
        }
 
        .slider-pro h5.sp-layer {
            font-size: 13px;
            line-height: 1.4;
            margin: 0
        }
 
        .slider-pro h6.sp-layer {
            font-size: 11px;
            line-height: 1.4;
            margin: 0
        }
 
        .slider-pro img.sp-layer {
            border: none
        }
    </style>
 
    <?php
        $slide_ = explode("\n",$slide_img);
    ?>
 
    <div class="container margin_60">
        <div0 class="row">
            <div class="col-md-8" id="single_tour_desc">
                <p class="visible-sm visible-xs"><a class="btn_map" data-toggle="collapse" href="#collapseMap"
                                                    aria-expanded="false" aria-controls="collapseMap"
                                                    data-text-swap="Hide map" data-text-original="View on map">View on
                        map</a></p><!-- Map button for tablets/mobiles -->
                <div id="Img_carousel" class="slider-pro">
                    <div class="sp-slides">
                        <?php foreach($slide_ as $sl) { ?>
                        <div class="sp-slide">
                            <img alt="Image" class="sp-image" src="css/images/blank.gif"
                                 data-src="/<?php echo $sl ?>"
                                 data-small="/<?php echo $sl ?>"
                                 data-medium="/<?php echo $sl ?>"
                                 data-large="/<?php echo $sl ?>"
                                 data-retina="/<?php echo $sl ?>">
                        </div>
                        <?php } ?>
                    </div>
                    <div class="sp-thumbnails">
                        <?php foreach($slide_ as $sl) {
                            echo '<img alt="Image" class="sp-thumbnail" src="/'.$sl.'">';
                        }
                        ?>
                    </div>
                </div>
 
                <hr>
 
                <div class="row">
                    <div class="col-md-12">
                        <?= $publicationResult->text ?>
                    </div>
 
                    <article id="content" class="publication clearfix" style="display: none;">
 
                        <?php if ($this->helper->isAdminSession()) { ?>
                            <p style="font-weight: bold;font-size:120%;">
                                <a class="noajax"
                                   href="<?= $this->url->get() ?>publication/admin/edit/<?= $publicationResult->p->getId() ?>?lang=<?= constant('LANG') ?>"><?= $this->helper->at('Edit publication') ?></a>
                            </p>
                        <?php } ?>
 
                        <h1><?= $publicationResult->title ?></h1>
 
                        <?php if ($publicationResult->p->getTypeDisplayDate()) { ?>
                            <section class="date"><?= $publicationResult->p->getDate('d.m.Y') ?></section>
                        <?php } ?>
 
                        <?php if ($publicationResult->p->preview_inner) { ?>
                            <?php $image = $this->helper->image(['id' => $publicationResult->p->getId(), 'type' => 'publication', 'width' => 300, 'strategy' => 'w']); ?>
                            <div class="image inner">
                                <?= $image->imageHTML() ?>
                            </div>
                        <?php } ?>
 
                        <?= $publicationResult->text ?>
 
                        <a href="<?= $this->helper->langUrl(['for' => 'publications', 'type' => $publicationResult->t_slug]) ?>"
                           class="back">&larr; <?= $this->helper->translate('Back to publications list') ?></a>
 
                    </article>
                    <div style="clear:both"></div>
                    <div class="row">
                        <h3 style="margin: 25px">
                            Khám phá
                            <a href="<?= $this->url->path() ?>locations?loc=<?php echo $parent;?>"><span><?= $totalLocation ?></span></a> địa điểm ở <a href="<?= $this->url->path() ?>locations?loc=<?php echo $parent;?>"><span style="color: #74d62f"><?php echo $locdt[$parent];?></span></a></h3>
                        <?php
                        foreach($des_more as $loc) :
                            if ($loc->preview_src) {
                                $preview_src =  $loc->preview_src;
                            } else {
                                $slide_ = explode("\n", $loc->slide_img);
                                $preview_src = @reset($slide_);
                            }
                        ?>
                        <div class="col-md-4 col-sm-6 wow zoomIn" data-wow-delay="0.1s">
                            <div class="tour_container">
                                <div class="ribbon_3 popular" style="display: none;"><span>Popular</span></div>
                                <div class="img_container">
                                    <a href='<?= $this->url->path() ?><?php echo "locations/".$loc->slug.".html";?>' title="<?php echo $loc->preview_src;?>">
                                        <img src="<?= $this->url->path() ?><?= $preview_src ?>" class="img-responsive" alt="image">
                                        <div class="short_info">
                                            <i class="icon_set_1_icon-44"></i> <?php echo $locdt[$loc->des_parent];?><span class="price"><sup></sup></span>
                                        </div>
                                    </a>
                                </div>
                                <div class="tour_title">
                                    <h3><strong style="font-size: 16px !important;    text-transform: none !important;"><?php echo $loc->title;?></strong> </h3>
                                    <div class="rating">
                                        <i class="icon-smile voted"></i><i class="icon-smile voted"></i><i class="icon-smile voted"></i><i class="icon-smile voted"></i><i class="icon-smile"></i><small><?php echo rand(100,1000) ?></small>
                                    </div><!-- end rating -->
                                    <div class="wishlist">
                                        <a class="tooltip_flip tooltip-effect-1" href="javascript:void(0);">+<span class="tooltip-content-flip"><span class="tooltip-back">Add to wishlist</span></span></a>
                                    </div><!-- End wish list-->
                                </div>
                            </div><!-- End box tour -->
                        </div><!-- End col-md-4 -->
                        <?php
                            endforeach;
                        ?>
 
                    </div>
 
                    <div class="MapsNearestLocationDetail" data-latitude="<?= ($publicationResult->p->latitude ? $publicationResult->p->latitude : 0) ?>" data-longitude="<?= ($publicationResult->p->longitude ? $publicationResult->p->longitude : 0) ?>">
                        <div class="main_title">
                            <h3>Điểm <span>phượt</span> gần <span><?= $publicationResult->title ?></span></h3>
                        </div>
                        <div id="map" class="map"></div>
                    </div>
                    <div style="padding-top: 10px">
                        <div class="fb-like" data-href='<?php echo "http://$_SERVER[HTTP_HOST]$_SERVER[REQUEST_URI]"; ?>' data-layout="standard" data-action="like" data-size="small" data-show-faces="true" data-share="true"></div>
                        <div style="width:100% !important;" class="fb-comments" data-href='<?php echo "http://$_SERVER[HTTP_HOST]$_SERVER[REQUEST_URI]"; ?>' data-numposts="5"></div>
                    </div>
                </div><!-- End row  -->
 
            </div><!--End  single_tour_desc-->
 
            <aside class="col-md-4">
                <p class="hidden-sm hidden-xs" style="display: none;">
                    <a class="btn_map" data-toggle="collapse" href="#collapseMap" aria-expanded="false"
                       aria-controls="collapseMap" data-text-swap="Hide map" data-text-original="View on map">View on
                        map</a>
                </p>
                <input type="text" id="y_rating" class="rating-loading" name="y_rating" value="<?php if (!(empty($rate))) { ?><?= $rate->num_rate ?><?php } else { ?>0<?php } ?>" >
                <div class="box_style_4 other_tours youvivu-location-box_style_4">
                    <?php $location_id = $publicationResult->p->id; ?>
                    <?php $media = \Publication\Model\Helper\PublicationHelper::getAllMedia($location_id);?>
 
                   <ul class="">
                     <li>
                     <a data-object-id="<?= $publicationResult->p->id ?>" data-action="L"
                       class="click-show-media" rel="nofollow" href="javascript:void(0)" data-title="Đã yêu thích">
                     <i class="icon_set_1_icon-82"></i>Đã yêu thích<span class="other_tours_price">
                     <strong>
                        <?php
                            if(!empty($media) && !empty($media["L"])) {
                                echo $media['L'];
                            }else{
                                echo '0';
                            }
                        ?>
                     </strong>
                     </span>
                     </a>
                     </li>
                     <li><a data-object-id="<?= $location_id ?>" data-action="W" class="click-show-media" rel="nofollow" href="javascript:void(0)" data-title="Đã đến đây"><i class=" icon_set_1_icon-30"></i>Đã đến đây
                     <span class="other_tours_price">
                       <strong>
                            <?php
                            if(!empty($media) && !empty($media["W"])) {
                                echo $media['W'];
                            }else{
                                echo '0';
                            }
                            ?>
                       </strong></span>
                     </a>
                     </li>
                       <li>
                           <a data-object-id="<?= $location_id ?>" data-action="R" class="click-show-media" rel="nofollow"
                              href="javascript:void(0)" data-title="Đã đánh giá">
                               <i class="icon_set_1_icon-81"></i>Đã đánh giá
                               <span class="other_tours_price">
                                 <strong>
                                    <?php
                                        if(!empty($media) && !empty($media["R"])) {
                                            echo $media['R'];
                                        }else{
                                            echo '0';
                                        }
                                     ?>
                                 </strong>
                               </span>
                           </a>
                       </li>
                   </ul>
                </div>
 
                <?php $userLikeMedia = \Publication\Model\Helper\PublicationHelper::getMediaByUserID($location_id, 'L') ?>
                <?php $liked = 'like'; ?>
                <?php $object_type_like = 1; ?>
                <?php $original_title_like = 'Yêu thích'; ?>
 
                <?php if (!empty($userLikeMedia)) { ?>
                <?php $liked = 'unlike'; ?>
                    <?php $original_title_like = 'Bỏ thích'; ?>
                    <?php $object_type_like = 0; ?>
                <?php } ?>
 
                <?php $userWentMedia = \Publication\Model\Helper\PublicationHelper::getMediaByUserID($location_id, 'W') ?>
                <?php $wented = 'maskWent'; ?>
                <?php $object_type_went = 1; ?>
                <?php $original_title_went = 'Đánh dấu đã đến đây'; ?>
                <?php if (!empty($userWentMedia)) { ?>
                    <?php $wented = 'maskUnWent'; ?>
                    <?php $object_type_went = 0; ?>
                    <?php $original_title_went = 'Bạn đã đánh dấu là đã đến đây'; ?>
                <?php } ?>
                <ul class="add_info youvivu-location-add_info">
                    <li>
                        <a rel="<?= $liked ?>" data-object-type="<?= $object_type_like ?>" data-object-id="<?= $location_id ?>" href="javascript:void(0);" class="tooltip-1 youvivu-object-like" data-placement="top" title="" data-original-title="<?= $original_title_like ?>">
                            <i class="icon_set_1_icon-18"></i>
                        </a>
                    </li>
                    <li>
                        <a rel="<?= $wented ?>" data-object-type="<?= $object_type_went ?>" data-object-id="<?= $location_id ?>" href="javascript:void(0);" class="tooltip-1 youvivu-object-location-mask-went" data-placement="top" title="" data-original-title="<?= $original_title_went ?>">
                            <i class=" icon_set_1_icon-30"></i>
                        </a>
                    </li>
                    <li>
                        <a rel="addPlan" data-object-type="1" data-object-id="<?= $location_id ?>" href="javascript:void(0);" class="tooltip-1 youvivu-object-location-add-to-plan" data-placement="top" title="" data-original-title="Thêm vào kế hoạch đến đây">
                            <i class="icon_set_1_icon-83"></i></a>
                    </li>
                    <li>
                        <a data-object-type="1" data-object-id="<?= $location_id ?>" href="/modal/map?locationId=<?= $location_id ?>" class="tooltip-1 ajax-maps-popup" data-placement="top" title="" data-original-title="Xem trên bản đồ">
                            <i class="icon_set_1_icon-41"></i></a>
                    </li>
                </ul>
                <div class="box_style_4">
                    <i class="icon_set_1_icon-90"></i>
                    <h4><span>Book</span> by phone</h4>
                    <a href="tel://004542344599" class="phone">+84 983 035 435</a>
                    <small>Monday to Friday 9.00am - 7.30pm</small>
                </div>
 
                <div style="display: none;">
                    <?php foreach($cul as $cu) { ?>
                    <div id="cul_<?php echo $cu->id ?>" style="display: none;"><?php echo  ($cu->text) ?></div>
                    <?php } ?>
                </div>
                <div class="box_style_cat youviu-box-culture-common youviu-box-culture-destination"><h3
                            style="text-align: center">Văn hóa &amp; con người</h3>
                    <ul id="cat_nav" class="listBlogInLocation">
 
                        <?php foreach($cul as $cu) { ?>
                        <li><a class="youviu-culture-popup-detail" rel="nofollow" data-title="<?php echo $cu->title ?>"
                               data-href="showcul(<?php echo $cu->id ?>)" onclick="showcul(<?php echo $cu->id ?>)"
                               href="javascript:void(0)">
                                <img style="width: 54px;height: 54px;" class="lazy"
                                     alt="<?php echo $cu->title ?>"
                                     data-original="/<?php echo $cu->preview_src ?>"
                                     src="/assets/ba871a56/img/loading.gif"><span>
<?php echo $cu->title ?><br><div class="rating"><i class="icon-star voted"></i><i class="icon-star voted"></i><i
                                                class="icon-star voted"></i><i class="icon-star voted"></i><i
                                                class="icon-star-empty"></i></div><br><i
                                            class="icon-calendar-empty"></i> Đăng ngày 01/01/2017 </span>
                                <div style="clear:both"></div>
                            </a></li>
                        <?php } ?>
                        <div id="youviu-modal-culture-detail" class="white-popup mfp-hide">
                            <div class="body"></div>
                        </div>
                    </ul>
                </div>
 
            </aside>
        </div><!--End row -->
    </div><!--End container -->
 
 
    <!-- Carousel -->
    <script src="<?= $this->url->path() ?>static/js/jquery.sliderPro.min.js"></script>
    <script src="<?= $this->url->path() ?>static/js/jquery.magnific-popup.js"></script>
    <script type="text/javascript">
        $(document).ready(function ($) {
            $('#Img_carousel').sliderPro({
                width: 960,
                height: 500,
                fade: true,
                arrows: true,
                buttons: false,
                fullScreen: false,
                smallSize: 500,
                startSlide: 0,
                mediumSize: 1000,
                largeSize: 3000,
                thumbnailArrows: true,
                autoplay: false
            });
        });
    </script>
    <script src="<?= $this->url->path() ?>static/js/owl.carousel.min.js"></script>
    <script>
        $(document).ready(function () {
            $(".carousel").owlCarousel({
                items: 4,
                itemsDesktop: [1199, 3],
                itemsDesktopSmall: [979, 3]
            });
        });
    </script>
<?php } ?>
 
<script>
    $("img.lazy").each(function () {
        $(this).attr("src", $(this).attr("data-original"));
        $(this).removeAttr("data-original");
    });
 
    $(document).ready(function () {
        $(".mfp-close").click(function(){
            $(".mfp-wrap").hide();
            $(".mfp-bg").hide();
        });
        $(".mfp-content").click(function(){
//           alert(1);
        });
        $(".mfp-bg").hide();
 
        $(".mfp-content").click(function(){
//            alert(1);
        });
    });
    function showcul(id){
        $("#cul_content").html($("#cul_"+id).html());
        $(".mfp-wrap").show();
        $(".mfp-bg").show();
    }
</script>
<script src="https://maps.googleapis.com/maps/api/js?libraries=places&key=<?= $map_key ?>"></script>
<script>
    (function (A) {
        if (!Array.prototype.forEach)
            A.forEach = A.forEach || function (action, that) {
                        for (var i = 0, l = this.length; i < l; i++)
                            if (i in this)
                                action.call(that, this[i], i, this);
                    };
 
    })(Array.prototype);
    jQuery(document).ready(function () {
        jQuery('#y_rating').on('rating.change', function (event, value, caption) {
            rating(value, <?= $publicationResult->p->id ?>, 'change')
        });
        jQuery('#y_rating').on('rating.clear', function (event) {
            rating(0, <?= $publicationResult->p->id ?>, 'clear')
        });
    });
</script>
<script src="<?= $this->url->path() ?>static/js/infoBox.js"></script>
#4Phalcon\Mvc\View\Engine\Volt->render(/www/wiki.youvivu.com/public_html/app/modules/Publication/views/index/publication.volt, Array(10), true)
#5Phalcon\Mvc\View->_engineRender(Array([.volt] => Object(Application\Mvc\View\Engine\Volt), [.phtml] => Object(Phalcon\Mvc\View\Engine\Php)), index/publication, true, true, null)
#6Phalcon\Mvc\View->render(index, publication, Array([type] => locations, [slug] => den-hung))
/www/wiki.youvivu.com/public_html/app/Bootstrap.php (349)
<?php
 
namespace YonaCMS;
use Application\Cache\Manager as CacheManager;
use Phalcon\Http\Response\Cookies;
use Phalcon\UserPlugin\Auth\Auth;
 
/**
 * Bootstrap
 * @copyright Copyright (c) 2011 - 2014 Aleksandr Torosh (http://wezoom.com.ua)
 * @author Aleksandr Torosh <webtorua@gmail.com>
 */
class Bootstrap
{
 
    public function run()
    {
        $di = new \Phalcon\DI\FactoryDefault();
 
        // Config
        require_once APPLICATION_PATH . '/modules/Cms/Config.php';
        $config = \Cms\Config::get();
        $di->set('config', $config);
 
        // Registry
        $registry = new \Phalcon\Registry();
        $di->set('registry', $registry);
 
        // Loader
        $loader = new \Phalcon\Loader();
        $loader->registerNamespaces($config->loader->namespaces->toArray());
        $loader->registerDirs([APPLICATION_PATH . "/plugins/"]);
        $loader->registerFiles([APPLICATION_PATH . '/../vendor/autoload.php']);
        $loader->register();
 
        // Database
        $db = new \Phalcon\Db\Adapter\Pdo\Mysql([
            "host"     => $config->database->host,
            "username" => $config->database->username,
            "password" => $config->database->password,
            "dbname"   => $config->database->dbname,
            "charset"  => $config->database->charset,
        ]);
        $di->set('db', $db);
 
        // View
        $this->initView($di);
 
        // URL
        $url = new \Phalcon\Mvc\Url();
        $url->setBasePath($config->base_path);
        $url->setBaseUri($config->base_path);
        $di->set('url', $url);
 
        // Cache
        $this->initCache($di);
 
        // CMS
        $cmsModel = new \Cms\Model\Configuration();
        $registry->cms = $cmsModel->getConfig(); // Отправляем в Registry
 
        // Application
        $application = new \Phalcon\Mvc\Application();
        $application->registerModules($config->modules->toArray());
 
        // Events Manager, Dispatcher
        $this->initEventManager($di);
 
        // Session
        $session = new \Phalcon\Session\Adapter\Files();
        $session->start();
        $di->set('session', $session);
 
        $di->set(
            "cookies",
            function () {
                $cookies = new Cookies();
 
                $cookies->useEncryption(false);
 
                return $cookies;
            }
        );
 
        $di->setShared(
            'auth',
            function () {
                return new Auth();
            }
        );
 
        $acl = new \Application\Acl\DefaultAcl();
        $di->set('acl', $acl);
 
        // JS Assets
        $this->initAssetsManager($di);
 
        // Flash helper
        $flash = new \Phalcon\Flash\Session([
            'error'   => 'ui red inverted segment alert alert-danger',
            'success' => 'ui green inverted segment alert alert-success',
            'notice'  => 'ui blue inverted segment alert alert-info',
            'warning' => 'ui orange inverted segment alert alert-warning',
        ]);
        $di->set('flash', $flash);
 
        $di->set('helper', new \Application\Mvc\Helper());
 
        // Routing
        $this->initRouting($application, $di);
 
        $application->setDI($di);
 
        // Main dispatching process
        $response = $this->dispatch($di);
        $response->send();
 
    }
 
    private function initRouting($application, $di)
    {
        $router = new \Application\Mvc\Router\DefaultRouter();
        $router->setDi($di);
        foreach ($application->getModules() as $module) {
            $routesClassName = str_replace('Module', 'Routes', $module['className']);
            if (class_exists($routesClassName)) {
                $routesClass = new $routesClassName();
                $router = $routesClass->init($router);
            }
            $initClassName = str_replace('Module', 'Init', $module['className']);
            if (class_exists($initClassName)) {
                new $initClassName();
            }
        }
        $di->set('router', $router);
    }
 
    private function initAssetsManager($di)
    {
        $config = $di->get('config');
        $assetsManager = new \Application\Assets\Manager();
        $js_collection = $assetsManager->collection('js')
            ->setLocal(true)
            ->addFilter(new \Phalcon\Assets\Filters\Jsmin())
            ->setTargetPath(ROOT . '/assets/js.js')
            ->setTargetUri('assets/js.js')
            ->join(true);
        if ($config->assets->js) {
            foreach ($config->assets->js as $js) {
                $js_collection->addJs(ROOT . '/' . $js);
            }
        }
 
        // Admin JS Assets
        $assetsManager->collection('modules-admin-js')
            ->setLocal(true)
            ->addFilter(new \Phalcon\Assets\Filters\Jsmin())
            ->setTargetPath(ROOT . '/assets/modules-admin.js')
            ->setTargetUri('assets/modules-admin.js')
            ->join(true);
 
        // Admin LESS Assets
        $assetsManager->collection('modules-admin-less')
            ->setLocal(true)
            ->addFilter(new \Application\Assets\Filter\Less())
            ->setTargetPath(ROOT . '/assets/modules-admin.less')
            ->setTargetUri('assets/modules-admin.less')
            ->join(true)
            ->addCss(APPLICATION_PATH . '/modules/Admin/assets/admin.less');
 
        $di->set('assets', $assetsManager);
    }
 
    private function initEventManager($di)
    {
        $eventsManager = new \Phalcon\Events\Manager();
        $dispatcher = new \Phalcon\Mvc\Dispatcher();
 
        $eventsManager->attach("dispatch:beforeDispatchLoop", function ($event, $dispatcher) use ($di) {
            new \YonaCMS\Plugin\CheckPoint($di->get('request'));
            new \YonaCMS\Plugin\Localization($dispatcher);
            new \YonaCMS\Plugin\AdminLocalization($di->get('config'));
            new \YonaCMS\Plugin\Acl($di->get('acl'), $dispatcher, $di->get('view'));
            new \YonaCMS\Plugin\MobileDetect($di->get('session'), $di->get('view'), $di->get('request'));
        });
 
        $eventsManager->attach("dispatch:afterDispatchLoop", function ($event, $dispatcher) use ($di) {
            new \Seo\Plugin\SeoManager($dispatcher, $di->get('request'), $di->get('router'), $di->get('view'));
            new \YonaCMS\Plugin\Title($di);
        });
 
        // Profiler
        $registry = $di->get('registry');
        if ($registry->cms['PROFILER']) {
            $profiler = new \Phalcon\Db\Profiler();
            $di->set('profiler', $profiler);
 
            $eventsManager->attach('db', function ($event, $db) use ($profiler) {
                if ($event->getType() == 'beforeQuery') {
                    $profiler->startProfile($db->getSQLStatement());
                }
                if ($event->getType() == 'afterQuery') {
                    $profiler->stopProfile();
                }
            });
        }
 
        $db = $di->get('db');
        $db->setEventsManager($eventsManager);
 
        $dispatcher->setEventsManager($eventsManager);
        $di->set('dispatcher', $dispatcher);
    }
 
    private function initView($di)
    {
        $view = new \Phalcon\Mvc\View();
 
        define('MAIN_VIEW_PATH', '../../../views/');
        $view->setMainView(MAIN_VIEW_PATH . 'main');
        $view->setLayoutsDir(MAIN_VIEW_PATH . '/layouts/');
        $view->setLayout('main');
        $view->setPartialsDir(MAIN_VIEW_PATH . '/partials/');
 
        // Volt
        $volt = new \Application\Mvc\View\Engine\Volt($view, $di);
        $volt->setOptions(['compiledPath' => APPLICATION_PATH . '/../data/cache/volt/']);
        $volt->initCompiler();
 
 
        $phtml = new \Phalcon\Mvc\View\Engine\Php($view, $di);
        $viewEngines = [
            ".volt"  => $volt,
            ".phtml" => $phtml,
        ];
 
        $view->registerEngines($viewEngines);
 
        $ajax = $di->get('request')->getQuery('_ajax');
        if ($ajax) {
            $view->setRenderLevel(\Phalcon\Mvc\View::LEVEL_LAYOUT);
        }
 
        $di->set('view', $view);
 
        return $view;
    }
 
    private function initCache($di)
    {
        $config = $di->get('config');
 
        $cacheFrontend = new \Phalcon\Cache\Frontend\Data([
            "lifetime" => 60,
            "prefix"   => HOST_HASH,
        ]);
 
        $cache = null;
        switch ($config->cache) {
            case 'file':
                $cache = new \Phalcon\Cache\Backend\File($cacheFrontend, [
                    "cacheDir" => APPLICATION_PATH . "/../data/cache/backend/"
                ]);
                break;
            case 'memcache':
                $cache = new \Phalcon\Cache\Backend\Memcache(
                    $cacheFrontend, [
                    "host" => $config->memcache->host,
                    "port" => $config->memcache->port,
                ]);
                break;
            case 'memcached':
                $cache = new \Phalcon\Cache\Backend\Libmemcached(
                    $cacheFrontend, [
                    "host" => $config->memcached->host,
                    "port" => $config->memcached->port,
                ]);
                break;
        }
        $di->set('cache', $cache, true);
        $di->set('modelsCache', $cache, true);
 
        \Application\Widget\Proxy::$cache = $cache; // Modules Widget System
 
        $modelsMetadata = new \Phalcon\Mvc\Model\Metadata\Memory();
        $di->set('modelsMetadata', $modelsMetadata);
 
        $di->set('cacheManager', new CacheManager());
    }
 
    private function dispatch($di)
    {
        $router = $di['router'];
 
        $router->handle();
 
        $view = $di['view'];
 
        $dispatcher = $di['dispatcher'];
 
        $response = $di['response'];
 
        $dispatcher->setModuleName($router->getModuleName());
        $dispatcher->setControllerName($router->getControllerName());
        $dispatcher->setActionName($router->getActionName());
        $dispatcher->setParams($router->getParams());
 
        $moduleName = \Application\Utils\ModuleName::camelize($router->getModuleName());
 
        $ModuleClassName = $moduleName . '\Module';
        if (class_exists($ModuleClassName)) {
            $module = new $ModuleClassName;
            $module->registerAutoloaders();
            $module->registerServices($di);
        }
        $view->start();
 
        $registry = $di['registry'];
        if ($registry->cms['DEBUG_MODE']) {
            $debug = new \Phalcon\Debug();
            $debug->listen();
            $dispatcher->dispatch();
        } else {
            try {
                $dispatcher->dispatch();
            } catch (\Phalcon\Exception $e) {
                // Errors catching
 
                $view->setViewsDir(__DIR__ . '/modules/Index/views/');
                $view->setPartialsDir('');
                $view->e = $e;
 
                if ($e instanceof \Phalcon\Mvc\Dispatcher\Exception) {
                    $response->setStatusCode(404, 'Not Found');
                    $view->partial('error/error404');
                } else {
                    $response->setStatusCode(503, 'Service Unavailable');
                    $view->partial('error/error503');
                }
 
                return $response;
            }
        }
 
        $view->render(
            $dispatcher->getControllerName(),
            $dispatcher->getActionName(),
            $dispatcher->getParams()
        );
 
        $view->finish();
 
        // AJAX
        $request = $di['request'];
        $_ajax = $request->getQuery('_ajax');
        if ($_ajax) {
            $contents = $view->getContent();
 
            $return = new \stdClass();
            $return->html = $contents;
            $return->title = $di->get('helper')->title()->get();
            $return->success = true;
 
            if ($view->bodyClass) {
                $return->bodyClass = $view->bodyClass;
            }
 
            $headers = $response->getHeaders()->toArray();
            if (isset($headers[404]) || isset($headers[503])) {
                $return->success = false;
            }
            $response->setContentType('application/json', 'UTF-8');
            $response->setContent(json_encode($return));
        } else {
            $response->setContent($view->getContent());
        }
 
        return $response;
    }
 
}
#7YonaCMS\Bootstrap->dispatch(Object(Phalcon\Di\FactoryDefault))
/www/wiki.youvivu.com/public_html/app/Bootstrap.php (115)
<?php
 
namespace YonaCMS;
use Application\Cache\Manager as CacheManager;
use Phalcon\Http\Response\Cookies;
use Phalcon\UserPlugin\Auth\Auth;
 
/**
 * Bootstrap
 * @copyright Copyright (c) 2011 - 2014 Aleksandr Torosh (http://wezoom.com.ua)
 * @author Aleksandr Torosh <webtorua@gmail.com>
 */
class Bootstrap
{
 
    public function run()
    {
        $di = new \Phalcon\DI\FactoryDefault();
 
        // Config
        require_once APPLICATION_PATH . '/modules/Cms/Config.php';
        $config = \Cms\Config::get();
        $di->set('config', $config);
 
        // Registry
        $registry = new \Phalcon\Registry();
        $di->set('registry', $registry);
 
        // Loader
        $loader = new \Phalcon\Loader();
        $loader->registerNamespaces($config->loader->namespaces->toArray());
        $loader->registerDirs([APPLICATION_PATH . "/plugins/"]);
        $loader->registerFiles([APPLICATION_PATH . '/../vendor/autoload.php']);
        $loader->register();
 
        // Database
        $db = new \Phalcon\Db\Adapter\Pdo\Mysql([
            "host"     => $config->database->host,
            "username" => $config->database->username,
            "password" => $config->database->password,
            "dbname"   => $config->database->dbname,
            "charset"  => $config->database->charset,
        ]);
        $di->set('db', $db);
 
        // View
        $this->initView($di);
 
        // URL
        $url = new \Phalcon\Mvc\Url();
        $url->setBasePath($config->base_path);
        $url->setBaseUri($config->base_path);
        $di->set('url', $url);
 
        // Cache
        $this->initCache($di);
 
        // CMS
        $cmsModel = new \Cms\Model\Configuration();
        $registry->cms = $cmsModel->getConfig(); // Отправляем в Registry
 
        // Application
        $application = new \Phalcon\Mvc\Application();
        $application->registerModules($config->modules->toArray());
 
        // Events Manager, Dispatcher
        $this->initEventManager($di);
 
        // Session
        $session = new \Phalcon\Session\Adapter\Files();
        $session->start();
        $di->set('session', $session);
 
        $di->set(
            "cookies",
            function () {
                $cookies = new Cookies();
 
                $cookies->useEncryption(false);
 
                return $cookies;
            }
        );
 
        $di->setShared(
            'auth',
            function () {
                return new Auth();
            }
        );
 
        $acl = new \Application\Acl\DefaultAcl();
        $di->set('acl', $acl);
 
        // JS Assets
        $this->initAssetsManager($di);
 
        // Flash helper
        $flash = new \Phalcon\Flash\Session([
            'error'   => 'ui red inverted segment alert alert-danger',
            'success' => 'ui green inverted segment alert alert-success',
            'notice'  => 'ui blue inverted segment alert alert-info',
            'warning' => 'ui orange inverted segment alert alert-warning',
        ]);
        $di->set('flash', $flash);
 
        $di->set('helper', new \Application\Mvc\Helper());
 
        // Routing
        $this->initRouting($application, $di);
 
        $application->setDI($di);
 
        // Main dispatching process
        $response = $this->dispatch($di);
        $response->send();
 
    }
 
    private function initRouting($application, $di)
    {
        $router = new \Application\Mvc\Router\DefaultRouter();
        $router->setDi($di);
        foreach ($application->getModules() as $module) {
            $routesClassName = str_replace('Module', 'Routes', $module['className']);
            if (class_exists($routesClassName)) {
                $routesClass = new $routesClassName();
                $router = $routesClass->init($router);
            }
            $initClassName = str_replace('Module', 'Init', $module['className']);
            if (class_exists($initClassName)) {
                new $initClassName();
            }
        }
        $di->set('router', $router);
    }
 
    private function initAssetsManager($di)
    {
        $config = $di->get('config');
        $assetsManager = new \Application\Assets\Manager();
        $js_collection = $assetsManager->collection('js')
            ->setLocal(true)
            ->addFilter(new \Phalcon\Assets\Filters\Jsmin())
            ->setTargetPath(ROOT . '/assets/js.js')
            ->setTargetUri('assets/js.js')
            ->join(true);
        if ($config->assets->js) {
            foreach ($config->assets->js as $js) {
                $js_collection->addJs(ROOT . '/' . $js);
            }
        }
 
        // Admin JS Assets
        $assetsManager->collection('modules-admin-js')
            ->setLocal(true)
            ->addFilter(new \Phalcon\Assets\Filters\Jsmin())
            ->setTargetPath(ROOT . '/assets/modules-admin.js')
            ->setTargetUri('assets/modules-admin.js')
            ->join(true);
 
        // Admin LESS Assets
        $assetsManager->collection('modules-admin-less')
            ->setLocal(true)
            ->addFilter(new \Application\Assets\Filter\Less())
            ->setTargetPath(ROOT . '/assets/modules-admin.less')
            ->setTargetUri('assets/modules-admin.less')
            ->join(true)
            ->addCss(APPLICATION_PATH . '/modules/Admin/assets/admin.less');
 
        $di->set('assets', $assetsManager);
    }
 
    private function initEventManager($di)
    {
        $eventsManager = new \Phalcon\Events\Manager();
        $dispatcher = new \Phalcon\Mvc\Dispatcher();
 
        $eventsManager->attach("dispatch:beforeDispatchLoop", function ($event, $dispatcher) use ($di) {
            new \YonaCMS\Plugin\CheckPoint($di->get('request'));
            new \YonaCMS\Plugin\Localization($dispatcher);
            new \YonaCMS\Plugin\AdminLocalization($di->get('config'));
            new \YonaCMS\Plugin\Acl($di->get('acl'), $dispatcher, $di->get('view'));
            new \YonaCMS\Plugin\MobileDetect($di->get('session'), $di->get('view'), $di->get('request'));
        });
 
        $eventsManager->attach("dispatch:afterDispatchLoop", function ($event, $dispatcher) use ($di) {
            new \Seo\Plugin\SeoManager($dispatcher, $di->get('request'), $di->get('router'), $di->get('view'));
            new \YonaCMS\Plugin\Title($di);
        });
 
        // Profiler
        $registry = $di->get('registry');
        if ($registry->cms['PROFILER']) {
            $profiler = new \Phalcon\Db\Profiler();
            $di->set('profiler', $profiler);
 
            $eventsManager->attach('db', function ($event, $db) use ($profiler) {
                if ($event->getType() == 'beforeQuery') {
                    $profiler->startProfile($db->getSQLStatement());
                }
                if ($event->getType() == 'afterQuery') {
                    $profiler->stopProfile();
                }
            });
        }
 
        $db = $di->get('db');
        $db->setEventsManager($eventsManager);
 
        $dispatcher->setEventsManager($eventsManager);
        $di->set('dispatcher', $dispatcher);
    }
 
    private function initView($di)
    {
        $view = new \Phalcon\Mvc\View();
 
        define('MAIN_VIEW_PATH', '../../../views/');
        $view->setMainView(MAIN_VIEW_PATH . 'main');
        $view->setLayoutsDir(MAIN_VIEW_PATH . '/layouts/');
        $view->setLayout('main');
        $view->setPartialsDir(MAIN_VIEW_PATH . '/partials/');
 
        // Volt
        $volt = new \Application\Mvc\View\Engine\Volt($view, $di);
        $volt->setOptions(['compiledPath' => APPLICATION_PATH . '/../data/cache/volt/']);
        $volt->initCompiler();
 
 
        $phtml = new \Phalcon\Mvc\View\Engine\Php($view, $di);
        $viewEngines = [
            ".volt"  => $volt,
            ".phtml" => $phtml,
        ];
 
        $view->registerEngines($viewEngines);
 
        $ajax = $di->get('request')->getQuery('_ajax');
        if ($ajax) {
            $view->setRenderLevel(\Phalcon\Mvc\View::LEVEL_LAYOUT);
        }
 
        $di->set('view', $view);
 
        return $view;
    }
 
    private function initCache($di)
    {
        $config = $di->get('config');
 
        $cacheFrontend = new \Phalcon\Cache\Frontend\Data([
            "lifetime" => 60,
            "prefix"   => HOST_HASH,
        ]);
 
        $cache = null;
        switch ($config->cache) {
            case 'file':
                $cache = new \Phalcon\Cache\Backend\File($cacheFrontend, [
                    "cacheDir" => APPLICATION_PATH . "/../data/cache/backend/"
                ]);
                break;
            case 'memcache':
                $cache = new \Phalcon\Cache\Backend\Memcache(
                    $cacheFrontend, [
                    "host" => $config->memcache->host,
                    "port" => $config->memcache->port,
                ]);
                break;
            case 'memcached':
                $cache = new \Phalcon\Cache\Backend\Libmemcached(
                    $cacheFrontend, [
                    "host" => $config->memcached->host,
                    "port" => $config->memcached->port,
                ]);
                break;
        }
        $di->set('cache', $cache, true);
        $di->set('modelsCache', $cache, true);
 
        \Application\Widget\Proxy::$cache = $cache; // Modules Widget System
 
        $modelsMetadata = new \Phalcon\Mvc\Model\Metadata\Memory();
        $di->set('modelsMetadata', $modelsMetadata);
 
        $di->set('cacheManager', new CacheManager());
    }
 
    private function dispatch($di)
    {
        $router = $di['router'];
 
        $router->handle();
 
        $view = $di['view'];
 
        $dispatcher = $di['dispatcher'];
 
        $response = $di['response'];
 
        $dispatcher->setModuleName($router->getModuleName());
        $dispatcher->setControllerName($router->getControllerName());
        $dispatcher->setActionName($router->getActionName());
        $dispatcher->setParams($router->getParams());
 
        $moduleName = \Application\Utils\ModuleName::camelize($router->getModuleName());
 
        $ModuleClassName = $moduleName . '\Module';
        if (class_exists($ModuleClassName)) {
            $module = new $ModuleClassName;
            $module->registerAutoloaders();
            $module->registerServices($di);
        }
        $view->start();
 
        $registry = $di['registry'];
        if ($registry->cms['DEBUG_MODE']) {
            $debug = new \Phalcon\Debug();
            $debug->listen();
            $dispatcher->dispatch();
        } else {
            try {
                $dispatcher->dispatch();
            } catch (\Phalcon\Exception $e) {
                // Errors catching
 
                $view->setViewsDir(__DIR__ . '/modules/Index/views/');
                $view->setPartialsDir('');
                $view->e = $e;
 
                if ($e instanceof \Phalcon\Mvc\Dispatcher\Exception) {
                    $response->setStatusCode(404, 'Not Found');
                    $view->partial('error/error404');
                } else {
                    $response->setStatusCode(503, 'Service Unavailable');
                    $view->partial('error/error503');
                }
 
                return $response;
            }
        }
 
        $view->render(
            $dispatcher->getControllerName(),
            $dispatcher->getActionName(),
            $dispatcher->getParams()
        );
 
        $view->finish();
 
        // AJAX
        $request = $di['request'];
        $_ajax = $request->getQuery('_ajax');
        if ($_ajax) {
            $contents = $view->getContent();
 
            $return = new \stdClass();
            $return->html = $contents;
            $return->title = $di->get('helper')->title()->get();
            $return->success = true;
 
            if ($view->bodyClass) {
                $return->bodyClass = $view->bodyClass;
            }
 
            $headers = $response->getHeaders()->toArray();
            if (isset($headers[404]) || isset($headers[503])) {
                $return->success = false;
            }
            $response->setContentType('application/json', 'UTF-8');
            $response->setContent(json_encode($return));
        } else {
            $response->setContent($view->getContent());
        }
 
        return $response;
    }
 
}
#8YonaCMS\Bootstrap->run()
/www/wiki.youvivu.com/public_html/public/index.php (20)
<?php
 
chdir(dirname(__DIR__));
 
define('ROOT', __DIR__);
define('HOST_HASH', substr(md5($_SERVER['HTTP_HOST']), 0, 12));
 
if (isset($_SERVER['APPLICATION_ENV'])) {
    $applicationEnv = ($_SERVER['APPLICATION_ENV'] ? $_SERVER['APPLICATION_ENV'] : 'production');
} else {
    $applicationEnv = (getenv('APPLICATION_ENV') ? getenv('APPLICATION_ENV') : 'production');
}
define('APPLICATION_ENV', $applicationEnv);
 
 
define('APPLICATION_PATH', __DIR__ . '/../app');
 
require_once APPLICATION_PATH . '/Bootstrap.php';
$bootstrap = new YonaCMS\Bootstrap();
$bootstrap->run();
KeyValue
_url/locations/den-hung.html
KeyValue
TEMP/tmp
TMPDIR/tmp
TMP/tmp
PATH/usr/local/bin:/usr/bin:/bin
HOSTNAME
USERnginx
HOME/var/lib/nginx
FCGI_ROLERESPONDER
QUERY_STRING_url=/locations/den-hung.html
REQUEST_METHODGET
CONTENT_TYPE
CONTENT_LENGTH
SCRIPT_NAME/index.php
REQUEST_URI/locations/den-hung.html
DOCUMENT_URI/index.php
DOCUMENT_ROOT/www/wiki.youvivu.com/public_html/public
SERVER_PROTOCOLHTTP/2.0
REQUEST_SCHEMEhttps
HTTPSon
GATEWAY_INTERFACECGI/1.1
SERVER_SOFTWAREnginx/1.20.1
REMOTE_ADDR3.139.235.177
REMOTE_PORT29820
SERVER_ADDR10.148.0.4
SERVER_PORT443
SERVER_NAMEwiki.youvivu.com
REDIRECT_STATUS200
PATH_INFO
APPLICATION_ENVproduction
SCRIPT_FILENAME/www/wiki.youvivu.com/public_html/public/index.php
HTTP_HOSTwiki.youvivu.com
HTTP_ACCEPT*/*
HTTP_USER_AGENTMozilla/5.0 AppleWebKit/537.36 (KHTML, like Gecko; compatible; ClaudeBot/1.0; +claudebot@anthropic.com)
HTTP_ACCEPT_ENCODINGgzip, br, zstd, deflate
HTTP_COOKIEfikker-61vm-nk2N=MgPGRI6oXLV7DSLWJk4y6wNi63F1ZE0E
PHP_SELF
REQUEST_TIME_FLOAT1732322640.5521
REQUEST_TIME1732322640
#Path
0/www/wiki.youvivu.com/public_html/public/index.php
1/www/wiki.youvivu.com/public_html/app/Bootstrap.php
2/www/wiki.youvivu.com/public_html/app/modules/Cms/Config.php
3/www/wiki.youvivu.com/public_html/app/config/environment/production.php
4/www/wiki.youvivu.com/public_html/app/config/global.php
5/www/wiki.youvivu.com/public_html/app/config/modules.php
6/www/wiki.youvivu.com/public_html/app/modules/Application/Loader/Modules.php
7/www/wiki.youvivu.com/public_html/vendor/autoload.php
8/www/wiki.youvivu.com/public_html/vendor/composer/autoload_real.php
9/www/wiki.youvivu.com/public_html/vendor/composer/ClassLoader.php
10/www/wiki.youvivu.com/public_html/vendor/composer/autoload_static.php
11/www/wiki.youvivu.com/public_html/vendor/swiftmailer/swiftmailer/lib/swift_required.php
12/www/wiki.youvivu.com/public_html/vendor/swiftmailer/swiftmailer/lib/classes/Swift.php
13/www/wiki.youvivu.com/public_html/vendor/facebook/graph-sdk/src/Facebook/polyfills.php
14/www/wiki.youvivu.com/public_html/vendor/facebook/php-sdk-v4/src/Facebook/polyfills.php
15/www/wiki.youvivu.com/public_html/vendor/crada/phalcon-user-plugin/lib/swift_required.php
16/www/wiki.youvivu.com/public_html/app/modules/Application/Mvc/View/Engine/Volt.php
17/www/wiki.youvivu.com/public_html/app/modules/Application/Widget/Proxy.php
18/www/wiki.youvivu.com/public_html/app/modules/Application/Cache/Manager.php
19/www/wiki.youvivu.com/public_html/app/modules/Cms/Model/Configuration.php
20/www/wiki.youvivu.com/public_html/app/modules/Application/Acl/DefaultAcl.php
21/www/wiki.youvivu.com/public_html/app/config/acl.php
22/www/wiki.youvivu.com/public_html/app/modules/Application/Assets/Manager.php
23/www/wiki.youvivu.com/public_html/app/modules/Application/Assets/Filter/Less.php
24/www/wiki.youvivu.com/public_html/app/modules/Application/Mvc/Helper.php
25/www/wiki.youvivu.com/public_html/app/modules/Menu/Helper/Menu.php
26/www/wiki.youvivu.com/public_html/app/modules/Application/Mvc/Router/DefaultRouter.php
27/www/wiki.youvivu.com/public_html/app/modules/Index/Routes.php
28/www/wiki.youvivu.com/public_html/app/modules/Application/Mvc/Helper/CmsCache.php
29/www/wiki.youvivu.com/public_html/app/modules/Admin/Routes.php
30/www/wiki.youvivu.com/public_html/app/modules/Page/Routes.php
31/www/wiki.youvivu.com/public_html/app/modules/Publication/Routes.php
32/www/wiki.youvivu.com/public_html/app/modules/Publication/Model/Type.php
33/www/wiki.youvivu.com/public_html/app/modules/Application/Mvc/Model/Model.php
34/www/wiki.youvivu.com/public_html/app/modules/Seo/Routes.php
35/www/wiki.youvivu.com/public_html/app/modules/Tree/Init.php
36/www/wiki.youvivu.com/public_html/app/modules/Tree/Mvc/Helper.php
37/www/wiki.youvivu.com/public_html/app/modules/Sitemap/Routes.php
38/www/wiki.youvivu.com/public_html/app/modules/Api/Routes.php
39/www/wiki.youvivu.com/public_html/app/modules/Account/Routes.php
40/www/wiki.youvivu.com/public_html/app/modules/Media/Routes.php
41/www/wiki.youvivu.com/public_html/app/modules/Application/Utils/ModuleName.php
42/www/wiki.youvivu.com/public_html/app/modules/Publication/Module.php
43/www/wiki.youvivu.com/public_html/app/plugins/CheckPoint.php
44/www/wiki.youvivu.com/public_html/app/plugins/Localization.php
45/www/wiki.youvivu.com/public_html/app/modules/Cms/Model/Translate.php
46/www/wiki.youvivu.com/public_html/app/plugins/AdminLocalization.php
47/www/wiki.youvivu.com/public_html/data/translations/admin/en.php
48/www/wiki.youvivu.com/public_html/app/plugins/Acl.php
49/www/wiki.youvivu.com/public_html/app/plugins/MobileDetect.php
50/www/wiki.youvivu.com/public_html/app/modules/Publication/Controller/IndexController.php
51/www/wiki.youvivu.com/public_html/app/modules/Application/Mvc/Controller.php
52/www/wiki.youvivu.com/public_html/app/modules/Publication/Model/Helper/PublicationHelper.php
53/www/wiki.youvivu.com/public_html/app/modules/Publication/Model/Publication.php
54/www/wiki.youvivu.com/public_html/app/modules/Application/Cache/Keys.php
55/www/wiki.youvivu.com/public_html/app/modules/Publication/Model/Translate/PublicationTranslate.php
56/www/wiki.youvivu.com/public_html/app/modules/Application/Mvc/Model/Translate.php
57/www/wiki.youvivu.com/public_html/app/modules/Publication/Model/Translate/TypeTranslate.php
58/www/wiki.youvivu.com/public_html/app/modules/Application/Mvc/Helper/Title.php
59/www/wiki.youvivu.com/public_html/app/modules/Application/Mvc/Helper/Meta.php
60/www/wiki.youvivu.com/public_html/app/modules/Page/Model/Helper/PageHelper.php
61/www/wiki.youvivu.com/public_html/app/modules/Page/Model/Page.php
62/www/wiki.youvivu.com/public_html/vendor/crada/phalcon-user-plugin/lib/Auth/Auth.php
63/www/wiki.youvivu.com/public_html/app/modules/Seo/Plugin/SeoManager.php
64/www/wiki.youvivu.com/public_html/app/modules/Seo/Model/Manager.php
65/www/wiki.youvivu.com/public_html/app/plugins/Title.php
66/www/wiki.youvivu.com/public_html/data/cache/volt/%%www%%wiki.youvivu.com%%public_html%%app%%modules%%publication%%views%%index%%publication.volt.php
67/www/wiki.youvivu.com/public_html/app/modules/Image/Storage.php
Memory
Usage3932160