Skip to content

Instantly share code, notes, and snippets.

@AgelxNash
Last active December 30, 2015 08:59
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save AgelxNash/7806132 to your computer and use it in GitHub Desktop.
Save AgelxNash/7806132 to your computer and use it in GitHub Desktop.
PHPThumb под MODX Evolution с поддержкой очереди сжатия картинок
<?php
/**
* QueuePHPThumb
*
* @category snippet
* @version 1.0
* @license GNU General Public License (GPL), http://www.gnu.org/copyleft/gpl.html
* @author Agel_Nash <Agel_Nash@xaker.ru>
* @internal @properties &queue=Использовать очередь;list;true,false;true
*
* [[phpthumb? &input=`[+tvimagename+]` &options=`w_255,h=200` &queue=`false`]]
*/
if(!defined('MODX_BASE_PATH')){die('What are you doing? Get out of here!');}
require_once MODX_BASE_PATH."/assets/snippets/phpthumb/QueuePHPThumb.class.php";
$qthumb = new QueuePHPThumb($modx);
$qthumb->init($modx->Event->params);
return $qthumb->makeFile();
<?php
class QueuePHPThumb{
/** @var \DocumentParser|null */
protected $_modx = null;
/** @var PhpThumb */
protected $phpThumb = null;
protected $options = array();
protected $image = null;
protected $noFile = null;
protected $queue = false;
protected $allowOptions = array();
protected $_allowExt = array('png', 'gif', 'jpg');
const DEFAULT_EXT = 'jpg';
const DEFAULT_QUALITY = '96';
const NO_IMAGE = 'assets/images/noimage.jpg';
const CACHE_NOIMAGE_FOLDER = 'assets/images/noimage/';
const CACHE_IMAGE_FOLDER = 'assets/thumbs/';
const TABLE = 'images';
/**
* @param $modx DocumentParser
*/
public function __construct(DocumentParser $modx){
$this->_modx = $modx;
}
/**
* Создать кэш файл с картинкой noImage
*
* @param string $fileName куда сохранить картинку
* @return array|string
*/
public function getNoFile($fileName = ''){
$to = MODX_BASE_PATH . QueuePHPThumb::CACHE_NOIMAGE_FOLDER . md5(serialize($this->options).$this->noFile) . "." . $this->getParam('f');
if(!file_exists($to)){
$to = $this->createFile(MODX_BASE_PATH.$this->noFile, $to);
}
if(file_exists($to)){
copy($to, $fileName);
}
return $this->clearPath($fileName, false);
}
/**
* Запуск сниппета
*
* @param array $params
*/
public function init(array $params = array()){
$this->noFile = (isset($params['noimage']) && $this->checkFile($params['noimage'])) ? $params['noimage'] : QueuePHPThumb::NO_IMAGE;
$this->image = (isset($params['input']) && $this->checkFile($params['input'])) ? $params['input'] : $this->noFile;
$this->queue = (empty($params['queue']) || $params['queue']=='false') ? false : true;
$this->options = isset($params['options']) && is_scalar($params['options']) ? $params['options'] : '';
$this->options = explode("&", strtr($this->options, array("," => "&", "_" => "=")));
$this->options = $this->getOptions();
}
/**
* Получение настроек сжатия
* @return array
*/
protected function getOptions(){
$allow = $this->getAllow();
$need=array_keys($allow);
$op = array();
foreach ($this->options as $value) {
$thumb = explode("=", $value);
$key = str_replace('[]','',$thumb[0]);
if (!empty($key)) {
if (isset($need[$key])) {
if (is_string($need[$key])) {
$need[$key] = array($need[$key]);
}
$need[$key][] = $thumb[1];
} else {
$need[$key] = $thumb[1];
}
unset($allow[$key]);
}
$op[$key]=$need[$key];
}
foreach($allow as $key=>$value){
$op[$key]=$value;
}
$this->options = $op;
return $this->options;
}
/**
* Сохранение задания в очередь
*
* @param $oldImage Оригинальная картинка
* @param $newImage Путь к кэш файлу
* @param array $options Параметры сжатия
* @return $this
*/
public function saveQueue($oldImage, $newImage, array $options = array()){
$oldImage = $this->_modx->db->escape($oldImage);
$newImage = $this->_modx->db->escape($newImage);
$options = $this->_modx->db->escape(serialize($options));
$table = $this->_modx->getFullTableName(QueuePHPThumb::TABLE);
$q = $this->_modx->db->getValue("SELECT count(`id`) FROM ".$table." WHERE `image` = '".$oldImage."' AND `cache_image` = '".$newImage."' AND `config` = '".$options."'");
if($q==0){
$this->_modx->db->insert(array(
'image' => $oldImage,
'cache_image' => $newImage,
'config' => $options,
'isend' => 0
), $table);
}
return $this;
}
/**
* Проверка обязательных параметров для сжатия
*
* @return array
*/
protected function getAllow(){
$this->allowOptions = array();
$this->allowOptions['q'] = QueuePHPThumb::DEFAULT_QUALITY;
$path_parts=pathinfo($this->getImage());
if(in_array(strtolower($path_parts['extension']), $this->_allowExt)){
$this->allowOptions['f'] = strtolower($path_parts['extension']);
}else{
$this->allowOptions['f'] = QueuePHPThumb::DEFAULT_EXT;
}
return $this->allowOptions;
}
/**
* Путь к файлу от корня сайта
*
* @param $file
* @param bool $full
* @return mixed|string
*/
public function clearPath($file, $full = true){
$out = '';
if(is_scalar($file)){
$out = preg_replace("#^".MODX_BASE_PATH."#", '', $file);
if($full && !empty($out)){
$out = MODX_BASE_PATH.$out;
}
}
return $out;
}
/**
* Определение файла которй нужно будет сжать
* @return mixed|string
*/
protected function getImage(){
$file = !empty($this->image) ? $this->image : $this->noFile;
return $this->clearPath($file);
}
/**
* Загрузка phpThumb и установка параметров
* @param $image
* @return $this
*/
protected function loadPhpThumb($image){
require_once MODX_BASE_PATH."/assets/snippets/phpthumb/phpthumb.class.php";
$this->phpThumb = new phpthumb();
$this->phpThumb->config_ttf_directory = dirname(__FILE__).'/fonts';
$this->phpThumb->setSourceFilename($image);
foreach($this->options as $key=>$value){
if(!empty($key)){
$this->phpThumb->setParameter($key, $value);
}
}
return $this;
}
/**
* Сфрмировать путь и имя кэш файла
*
* @return string
*/
public function getCacheName(){
$image = $this->getImage();
$path_parts=pathinfo($image);
$tmp = preg_replace("#^".MODX_BASE_PATH."#", "", $path_parts['dirname']);
$tmp = ($tmp=='assets/images' ? '' : preg_replace("#^assets/images/#", "/", ltrim($tmp,'/')));
$ftime=filemtime($image);
$tmp=QueuePHPThumb::CACHE_IMAGE_FOLDER.ltrim($tmp, '/');
$tmp=explode("/",$tmp);
$tmp[] = substr(md5(serialize($this->options)),0,3);
$tmp[]=date("Y-m",$ftime);
$folder = '';
for($i=0;$i<count($tmp);$i++){
$folder.="/".$tmp[$i];
if(!is_dir(MODX_BASE_PATH . $folder) || !file_exists(MODX_BASE_PATH . $folder)){
mkdir(MODX_BASE_PATH . $folder);
}
}
$outputFilename =MODX_BASE_PATH.$folder."/".date("d_h_i_s",$ftime)."_".$path_parts['extension']."_".$path_parts['filename'].".".$this->getParam('f');
return $outputFilename;
}
/**
* Получение значения из конифга
*
* @param $key ключ в конфиге
* @return null
*/
public function getParam($key){
return (!empty($key) && is_scalar($key) && isset($this->options[$key])) ? $this->options[$key] : null;
}
/**
* Создания кэш файла
*
* @param $from оригинальнфй файл
* @param $to куда сохранять
* @return array|string
*/
public function createFile($from, $to){
if (!file_exists($to) || filemtime($from) > filemtime($to)){
$this->loadPhpThumb($from);
if($this->phpThumb->GenerateThumbnail()){
$this->phpThumb->RenderToFile($to) ;
}
}
$res = explode("/assets", $to, 2);
$res = "/assets".$res[1];
return $res;
}
/**
* Проверка файла на существование
*
* @param $file Путь к файлу
* @return bool флаг доступности файла
*/
protected function checkFile($file){
$out = false;
if(is_scalar($file) && !preg_match("/^http(s)?:\/\/\w+/",$file)){
$file = MODX_BASE_PATH . preg_replace("#^".MODX_BASE_PATH."#", '', $file);
$out = (file_exists($file) && is_file($file) && is_readable($file));
}
return $out;
}
/**
* Постановка задания очередь
*
* @return mixed|string
*/
public function makeFile(){
$tmpName = $this->getCacheName();
$image = $this->getImage();
if(!file_exists($tmpName) || filemtime($image) > filemtime($tmpName)){
if($this->queue){
$res = $this->saveQueue($this->clearPath($image, false), $this->clearPath($tmpName, false), $this->options)->getNoFile($tmpName);
}else{
$res = $this->createFile($image, $tmpName);
}
}else{
$res = $this->clearPath($tmpName, false);
}
return $res;
}
/**
* Выполнения задания из очереди
*
* @return bool|null Результат выполнения задания в очереди
*/
public function runQueue(){
$flag = null;
$table = $this->_modx->getFullTableName(QueuePHPThumb::TABLE);
$q = $this->_modx->db->query("SELECT * FROM ".$table." WHERE `isend` = 0 ORDER BY RAND() LIMIT 1");
if($this->_modx->db->getRecordCount($q)==1){
$q = $this->_modx->db->getRow($q);
$this->options = unserialize($q['config']);
if(file_exists(MODX_BASE_PATH.$q['cache_image'])){
unlink(MODX_BASE_PATH.$q['cache_image']);
}
if(file_exists(MODX_BASE_PATH.$q['image'])){
$this->createFile(MODX_BASE_PATH.$q['image'], MODX_BASE_PATH.$q['cache_image']);
$this->_modx->db->update(array('isend'=>1), $table, "id = ".$q['id']);
$flag = true;
}else{
$this->_modx->db->delete($table, "id = ".$q['id']);
$flag = false;
}
}
return $flag;
}
}
DROP TABLE IF EXISTS `modx_images`;
CREATE TABLE `modx_images` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`image` varchar(255) DEFAULT NULL,
`cache_image` varchar(255) DEFAULT NULL,
`isend` tinyint(1) unsigned NOT NULL DEFAULT '0',
`config` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `image` (`image`),
KEY `isend` (`isend`),
KEY `config` (`config`)
) ENGINE=MyISAM AUTO_INCREMENT=11 DEFAULT CHARSET=utf8;
<?php
define('MODX_API_MODE', true);
include_once(dirname(__FILE__)."/index.php");
require_once MODX_BASE_PATH."/assets/snippets/phpthumb/phpthumb.class.php";
$modx->db->connect();
if (empty ($modx->config)) {
$modx->getSettings();
}
require_once MODX_BASE_PATH."/assets/snippets/phpthumb/QueuePHPThumb.class.php";
$qthumb = new QueuePHPThumb($modx);
$flag = $qthumb->runQueue();
if($flag === null){
echo 'Empty';
}else if($flag === true){
echo 'Good';
}else{
echo 'Fatal';
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment