* Code for task #5688.
This commit is contained in:
@@ -16,3 +16,5 @@ REPLACE INTO `zt_config` (`owner`, `module`, `section`, `key`, `value`) VALUES (
|
||||
|
||||
ALTER TABLE `zt_project` DROP `storyConcept`;
|
||||
ALTER TABLE `zt_product` DROP `storyConcept`;
|
||||
|
||||
ALTER TABLE `zt_user` CHANGE `avatar` `avatar` text NOT NULL AFTER `commiter`;
|
||||
|
||||
+1
-1
@@ -1232,7 +1232,7 @@ CREATE TABLE IF NOT EXISTS `zt_user` (
|
||||
`realname` varchar(100) NOT NULL default '',
|
||||
`nickname` char(60) NOT NULL default '',
|
||||
`commiter` varchar(100) NOT NULL,
|
||||
`avatar` char(30) NOT NULL default '',
|
||||
`avatar` text NOT NULL,
|
||||
`birthday` date NOT NULL default '0000-00-00',
|
||||
`gender` enum('f','m') NOT NULL default 'f',
|
||||
`email` char(90) NOT NULL default '',
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,247 @@
|
||||
<?php
|
||||
/**
|
||||
* PhpThumb Library Definition File
|
||||
*
|
||||
* This file contains the definitions for the PhpThumb class.
|
||||
*
|
||||
* PHP Version 5 with GD 2.0+
|
||||
* PhpThumb : PHP Thumb Library <http://phpthumb.gxdlabs.com>
|
||||
* Copyright (c) 2009, Ian Selby/Gen X Design
|
||||
*
|
||||
* Author(s): Ian Selby <ian@gen-x-design.com>
|
||||
*
|
||||
* Licensed under the MIT License
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @author Ian Selby <ian@gen-x-design.com>
|
||||
* @copyright Copyright (c) 2009 Gen X Design
|
||||
* @link http://phpthumb.gxdlabs.com
|
||||
* @license http://www.opensource.org/licenses/mit-license.php The MIT License
|
||||
* @version 3.0
|
||||
* @package PhpThumb
|
||||
* @filesource
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* PhpThumb Object
|
||||
*
|
||||
* This singleton object is essentially a function library that helps with core validation
|
||||
* and loading of the core classes and plugins. There isn't really any need to access it directly,
|
||||
* unless you're developing a plugin and need to take advantage of any of the functionality contained
|
||||
* within.
|
||||
*
|
||||
* If you're not familiar with singleton patterns, here's how you get an instance of this class (since you
|
||||
* can't create one via the new keyword):
|
||||
* <code>$pt = PhpThumb::getInstance();</code>
|
||||
*
|
||||
* It's that simple! Outside of that, there's no need to modify anything within this class, unless you're doing
|
||||
* some crazy customization... then knock yourself out! :)
|
||||
*
|
||||
* @package PhpThumb
|
||||
* @subpackage Core
|
||||
*/
|
||||
class PhpThumb
|
||||
{
|
||||
/**
|
||||
* Instance of self
|
||||
*
|
||||
* @var object PhpThumb
|
||||
*/
|
||||
protected static $_instance;
|
||||
/**
|
||||
* The plugin registry
|
||||
*
|
||||
* This is where all plugins to be loaded are stored. Data about the plugin is
|
||||
* provided, and currently consists of:
|
||||
* - loaded: true/false
|
||||
* - implementation: gd/imagick/both
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $_registry;
|
||||
/**
|
||||
* What implementations are available
|
||||
*
|
||||
* This stores what implementations are available based on the loaded
|
||||
* extensions in PHP, NOT whether or not the class files are present.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $_implementations;
|
||||
|
||||
/**
|
||||
* Returns an instance of self
|
||||
*
|
||||
* This is the usual singleton function that returns / instantiates the object
|
||||
*
|
||||
* @return PhpThumb
|
||||
*/
|
||||
public static function getInstance ()
|
||||
{
|
||||
if(!(self::$_instance instanceof self))
|
||||
{
|
||||
self::$_instance = new self();
|
||||
}
|
||||
|
||||
return self::$_instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Class constructor
|
||||
*
|
||||
* Initializes all the variables, and does some preliminary validation / checking of stuff
|
||||
*
|
||||
*/
|
||||
private function __construct ()
|
||||
{
|
||||
$this->_registry = array();
|
||||
$this->_implementations = array('gd' => false, 'imagick' => false);
|
||||
|
||||
$this->getImplementations();
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds out what implementations are available
|
||||
*
|
||||
* This function loops over $this->_implementations and validates that the required extensions are loaded.
|
||||
*
|
||||
* I had planned on attempting to load them dynamically via dl(), but that would provide more overhead than I
|
||||
* was comfortable with (and would probably fail 99% of the time anyway)
|
||||
*
|
||||
*/
|
||||
private function getImplementations ()
|
||||
{
|
||||
foreach($this->_implementations as $extension => $loaded)
|
||||
{
|
||||
if($loaded)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if(extension_loaded($extension))
|
||||
{
|
||||
$this->_implementations[$extension] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether or not $implementation is valid (available)
|
||||
*
|
||||
* If 'all' is passed, true is only returned if ALL implementations are available.
|
||||
*
|
||||
* You can also pass 'n/a', which always returns true
|
||||
*
|
||||
* @return bool
|
||||
* @param string $implementation
|
||||
*/
|
||||
public function isValidImplementation ($implementation)
|
||||
{
|
||||
if ($implementation == 'n/a')
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if ($implementation == 'all')
|
||||
{
|
||||
foreach ($this->_implementations as $imp => $value)
|
||||
{
|
||||
if ($value == false)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
if (array_key_exists($implementation, $this->_implementations))
|
||||
{
|
||||
return $this->_implementations[$implementation];
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a plugin in the registry
|
||||
*
|
||||
* Adds a plugin to the registry if it isn't already loaded, and if the provided
|
||||
* implementation is valid. Note that you can pass the following special keywords
|
||||
* for implementation:
|
||||
* - all - Requires that all implementations be available
|
||||
* - n/a - Doesn't require any implementation
|
||||
*
|
||||
* When a plugin is added to the registry, it's added as a key on $this->_registry with the value
|
||||
* being an array containing the following keys:
|
||||
* - loaded - whether or not the plugin has been "loaded" into the core class
|
||||
* - implementation - what implementation this plugin is valid for
|
||||
*
|
||||
* @return bool
|
||||
* @param string $pluginName
|
||||
* @param string $implementation
|
||||
*/
|
||||
public function registerPlugin ($pluginName, $implementation)
|
||||
{
|
||||
if (!array_key_exists($pluginName, $this->_registry) && $this->isValidImplementation($implementation))
|
||||
{
|
||||
$this->_registry[$pluginName] = array('loaded' => false, 'implementation' => $implementation);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads all the plugins in $pluginPath
|
||||
*
|
||||
* All this function does is include all files inside the $pluginPath directory. The plugins themselves
|
||||
* will not be added to the registry unless you've properly added the code to do so inside your plugin file.
|
||||
*
|
||||
* @param string $pluginPath
|
||||
*/
|
||||
public function loadPlugins ($pluginPath)
|
||||
{
|
||||
// strip the trailing slash if present
|
||||
if (substr($pluginPath, strlen($pluginPath) - 1, 1) == '/')
|
||||
{
|
||||
$pluginPath = substr($pluginPath, 0, strlen($pluginPath) - 1);
|
||||
}
|
||||
|
||||
if ($handle = opendir($pluginPath))
|
||||
{
|
||||
while (false !== ($file = readdir($handle)))
|
||||
{
|
||||
if ($file == '.' || $file == '..' || $file == '.svn')
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
include_once($pluginPath . '/' . $file);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the plugin registry for the supplied implementation
|
||||
*
|
||||
* @return array
|
||||
* @param string $implementation
|
||||
*/
|
||||
public function getPluginRegistry ($implementation)
|
||||
{
|
||||
$returnArray = array();
|
||||
|
||||
foreach ($this->_registry as $plugin => $meta)
|
||||
{
|
||||
if ($meta['implementation'] == 'n/a' || $meta['implementation'] == $implementation)
|
||||
{
|
||||
$returnArray[$plugin] = $meta;
|
||||
}
|
||||
}
|
||||
|
||||
return $returnArray;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,323 @@
|
||||
<?php
|
||||
/**
|
||||
* PhpThumb Base Class Definition File
|
||||
*
|
||||
* This file contains the definition for the ThumbBase object
|
||||
*
|
||||
* PHP Version 5 with GD 2.0+
|
||||
* PhpThumb : PHP Thumb Library <http://phpthumb.gxdlabs.com>
|
||||
* Copyright (c) 2009, Ian Selby/Gen X Design
|
||||
*
|
||||
* Author(s): Ian Selby <ian@gen-x-design.com>
|
||||
*
|
||||
* Licensed under the MIT License
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @author Ian Selby <ian@gen-x-design.com>
|
||||
* @copyright Copyright (c) 2009 Gen X Design
|
||||
* @link http://phpthumb.gxdlabs.com
|
||||
* @license http://www.opensource.org/licenses/mit-license.php The MIT License
|
||||
* @version 3.0
|
||||
* @package PhpThumb
|
||||
* @filesource
|
||||
*/
|
||||
|
||||
/**
|
||||
* ThumbBase Class Definition
|
||||
*
|
||||
* This is the base class that all implementations must extend. It contains the
|
||||
* core variables and functionality common to all implementations, as well as the functions that
|
||||
* allow plugins to augment those classes.
|
||||
*
|
||||
* @package PhpThumb
|
||||
* @subpackage Core
|
||||
*/
|
||||
abstract class ThumbBase
|
||||
{
|
||||
/**
|
||||
* All imported objects
|
||||
*
|
||||
* An array of imported plugin objects
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $imported;
|
||||
/**
|
||||
* All imported object functions
|
||||
*
|
||||
* An array of all methods added to this class by imported plugin objects
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $importedFunctions;
|
||||
/**
|
||||
* The last error message raised
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $errorMessage;
|
||||
/**
|
||||
* Whether or not the current instance has any errors
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected $hasError;
|
||||
/**
|
||||
* The name of the file we're manipulating
|
||||
*
|
||||
* This must include the path to the file (absolute paths recommended)
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $fileName;
|
||||
/**
|
||||
* What the file format is (mime-type)
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $format;
|
||||
/**
|
||||
* Whether or not the image is hosted remotely
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected $remoteImage;
|
||||
/**
|
||||
* Whether or not the current image is an actual file, or the raw file data
|
||||
*
|
||||
* By "raw file data" it's meant that we're actually passing the result of something
|
||||
* like file_get_contents() or perhaps from a database blob
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected $isDataStream;
|
||||
|
||||
/**
|
||||
* Class constructor
|
||||
*
|
||||
* @return ThumbBase
|
||||
*/
|
||||
public function __construct ($fileName, $isDataStream = false)
|
||||
{
|
||||
$this->imported = array();
|
||||
$this->importedFunctions = array();
|
||||
$this->errorMessage = null;
|
||||
$this->hasError = false;
|
||||
$this->fileName = $fileName;
|
||||
$this->remoteImage = false;
|
||||
$this->isDataStream = $isDataStream;
|
||||
|
||||
$this->fileExistsAndReadable();
|
||||
}
|
||||
|
||||
/**
|
||||
* Imports plugins in $registry to the class
|
||||
*
|
||||
* @param array $registry
|
||||
*/
|
||||
public function importPlugins ($registry)
|
||||
{
|
||||
foreach ($registry as $plugin => $meta)
|
||||
{
|
||||
$this->imports($plugin);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Imports a plugin
|
||||
*
|
||||
* This is where all the plugins magic happens! This function "loads" the plugin functions, making them available as
|
||||
* methods on the class.
|
||||
*
|
||||
* @param string $object The name of the object to import / "load"
|
||||
*/
|
||||
protected function imports ($object)
|
||||
{
|
||||
// the new object to import
|
||||
$newImport = new $object();
|
||||
// the name of the new object (class name)
|
||||
$importName = get_class($newImport);
|
||||
// the new functions to import
|
||||
$importFunctions = get_class_methods($newImport);
|
||||
|
||||
// add the object to the registry
|
||||
array_push($this->imported, array($importName, $newImport));
|
||||
|
||||
// add the methods to the registry
|
||||
foreach ($importFunctions as $key => $functionName)
|
||||
{
|
||||
$this->importedFunctions[$functionName] = &$newImport;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks to see if $this->fileName exists and is readable
|
||||
*
|
||||
*/
|
||||
protected function fileExistsAndReadable ()
|
||||
{
|
||||
if ($this->isDataStream === true)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (stristr($this->fileName, 'http://') !== false)
|
||||
{
|
||||
$this->remoteImage = true;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!file_exists($this->fileName))
|
||||
{
|
||||
$this->triggerError('Image file not found: ' . $this->fileName);
|
||||
}
|
||||
elseif (!is_readable($this->fileName))
|
||||
{
|
||||
$this->triggerError('Image file not readable: ' . $this->fileName);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets $this->errorMessage to $errorMessage and throws an exception
|
||||
*
|
||||
* Also sets $this->hasError to true, so even if the exceptions are caught, we don't
|
||||
* attempt to proceed with any other functions
|
||||
*
|
||||
* @param string $errorMessage
|
||||
*/
|
||||
protected function triggerError ($errorMessage)
|
||||
{
|
||||
$this->hasError = true;
|
||||
$this->errorMessage = $errorMessage;
|
||||
|
||||
throw new Exception ($errorMessage);
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls plugin / imported functions
|
||||
*
|
||||
* This is also where a fair amount of plugins magaic happens. This magic method is called whenever an "undefined" class
|
||||
* method is called in code, and we use that to call an imported function.
|
||||
*
|
||||
* You should NEVER EVER EVER invoke this function manually. The universe will implode if you do... seriously ;)
|
||||
*
|
||||
* @param string $method
|
||||
* @param array $args
|
||||
*/
|
||||
public function __call ($method, $args)
|
||||
{
|
||||
if( array_key_exists($method, $this->importedFunctions))
|
||||
{
|
||||
$args[] = $this;
|
||||
return call_user_func_array(array($this->importedFunctions[$method], $method), $args);
|
||||
}
|
||||
|
||||
throw new BadMethodCallException ('Call to undefined method/class function: ' . $method);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns $imported.
|
||||
* @see ThumbBase::$imported
|
||||
* @return array
|
||||
*/
|
||||
public function getImported ()
|
||||
{
|
||||
return $this->imported;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns $importedFunctions.
|
||||
* @see ThumbBase::$importedFunctions
|
||||
* @return array
|
||||
*/
|
||||
public function getImportedFunctions ()
|
||||
{
|
||||
return $this->importedFunctions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns $errorMessage.
|
||||
*
|
||||
* @see ThumbBase::$errorMessage
|
||||
*/
|
||||
public function getErrorMessage ()
|
||||
{
|
||||
return $this->errorMessage;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets $errorMessage.
|
||||
*
|
||||
* @param object $errorMessage
|
||||
* @see ThumbBase::$errorMessage
|
||||
*/
|
||||
public function setErrorMessage ($errorMessage)
|
||||
{
|
||||
$this->errorMessage = $errorMessage;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns $fileName.
|
||||
*
|
||||
* @see ThumbBase::$fileName
|
||||
*/
|
||||
public function getFileName ()
|
||||
{
|
||||
return $this->fileName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets $fileName.
|
||||
*
|
||||
* @param object $fileName
|
||||
* @see ThumbBase::$fileName
|
||||
*/
|
||||
public function setFileName ($fileName)
|
||||
{
|
||||
$this->fileName = $fileName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns $format.
|
||||
*
|
||||
* @see ThumbBase::$format
|
||||
*/
|
||||
public function getFormat ()
|
||||
{
|
||||
return $this->format;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets $format.
|
||||
*
|
||||
* @param object $format
|
||||
* @see ThumbBase::$format
|
||||
*/
|
||||
public function setFormat ($format)
|
||||
{
|
||||
$this->format = $format;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns $hasError.
|
||||
*
|
||||
* @see ThumbBase::$hasError
|
||||
*/
|
||||
public function getHasError ()
|
||||
{
|
||||
return $this->hasError;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets $hasError.
|
||||
*
|
||||
* @param object $hasError
|
||||
* @see ThumbBase::$hasError
|
||||
*/
|
||||
public function setHasError ($hasError)
|
||||
{
|
||||
$this->hasError = $hasError;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,146 @@
|
||||
<?php
|
||||
/**
|
||||
* PhpThumb Library Definition File
|
||||
*
|
||||
* This file contains the definitions for the PhpThumbFactory class.
|
||||
* It also includes the other required base class files.
|
||||
*
|
||||
* If you've got some auto-loading magic going on elsewhere in your code, feel free to
|
||||
* remove the include_once statements at the beginning of this file... just make sure that
|
||||
* these files get included one way or another in your code.
|
||||
*
|
||||
* PHP Version 5 with GD 2.0+
|
||||
* PhpThumb : PHP Thumb Library <http://phpthumb.gxdlabs.com>
|
||||
* Copyright (c) 2009, Ian Selby/Gen X Design
|
||||
*
|
||||
* Author(s): Ian Selby <ian@gen-x-design.com>
|
||||
*
|
||||
* Licensed under the MIT License
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @author Ian Selby <ian@gen-x-design.com>
|
||||
* @copyright Copyright (c) 2009 Gen X Design
|
||||
* @link http://phpthumb.gxdlabs.com
|
||||
* @license http://www.opensource.org/licenses/mit-license.php The MIT License
|
||||
* @version 3.0
|
||||
* @package PhpThumb
|
||||
* @filesource
|
||||
*/
|
||||
|
||||
// define some useful constants
|
||||
define('THUMBLIB_BASE_PATH', dirname(__FILE__));
|
||||
define('THUMBLIB_PLUGIN_PATH', THUMBLIB_BASE_PATH . '/thumb_plugins/');
|
||||
define('DEFAULT_THUMBLIB_IMPLEMENTATION', 'gd');
|
||||
|
||||
/**
|
||||
* Include the PhpThumb Class
|
||||
*/
|
||||
require_once THUMBLIB_BASE_PATH . '/PhpThumb.inc.php';
|
||||
/**
|
||||
* Include the ThumbBase Class
|
||||
*/
|
||||
require_once THUMBLIB_BASE_PATH . '/ThumbBase.inc.php';
|
||||
/**
|
||||
* Include the GdThumb Class
|
||||
*/
|
||||
require_once THUMBLIB_BASE_PATH . '/GdThumb.inc.php';
|
||||
|
||||
/**
|
||||
* PhpThumbFactory Object
|
||||
*
|
||||
* This class is responsible for making sure everything is set up and initialized properly,
|
||||
* and returning the appropriate thumbnail class instance. It is the only recommended way
|
||||
* of using this library, and if you try and circumvent it, the sky will fall on your head :)
|
||||
*
|
||||
* Basic use is easy enough. First, make sure all the settings meet your needs and environment...
|
||||
* these are the static variables defined at the beginning of the class.
|
||||
*
|
||||
* Once that's all set, usage is pretty easy. You can simply do something like:
|
||||
* <code>$thumb = PhpThumbFactory::create('/path/to/file.png');</code>
|
||||
*
|
||||
* Refer to the documentation for the create function for more information
|
||||
*
|
||||
* @package PhpThumb
|
||||
* @subpackage Core
|
||||
*/
|
||||
class PhpThumbFactory
|
||||
{
|
||||
/**
|
||||
* Which implemenation of the class should be used by default
|
||||
*
|
||||
* Currently, valid options are:
|
||||
* - imagick
|
||||
* - gd
|
||||
*
|
||||
* These are defined in the implementation map variable, inside the create function
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public static $defaultImplemenation = DEFAULT_THUMBLIB_IMPLEMENTATION;
|
||||
/**
|
||||
* Where the plugins can be loaded from
|
||||
*
|
||||
* Note, it's important that this path is properly defined. It is very likely that you'll
|
||||
* have to change this, as the assumption here is based on a relative path.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public static $pluginPath = THUMBLIB_PLUGIN_PATH;
|
||||
|
||||
/**
|
||||
* Factory Function
|
||||
*
|
||||
* This function returns the correct thumbnail object, augmented with any appropriate plugins.
|
||||
* It does so by doing the following:
|
||||
* - Getting an instance of PhpThumb
|
||||
* - Loading plugins
|
||||
* - Validating the default implemenation
|
||||
* - Returning the desired default implementation if possible
|
||||
* - Returning the GD implemenation if the default isn't available
|
||||
* - Throwing an exception if no required libraries are present
|
||||
*
|
||||
* @return GdThumb
|
||||
* @uses PhpThumb
|
||||
* @param string $filename The path and file to load [optional]
|
||||
*/
|
||||
public static function create ($filename = null, $options = array(), $isDataStream = false)
|
||||
{
|
||||
// map our implementation to their class names
|
||||
$implementationMap = array
|
||||
(
|
||||
'imagick' => 'ImagickThumb',
|
||||
'gd' => 'GdThumb'
|
||||
);
|
||||
|
||||
// grab an instance of PhpThumb
|
||||
$pt = PhpThumb::getInstance();
|
||||
// load the plugins
|
||||
$pt->loadPlugins(self::$pluginPath);
|
||||
|
||||
$toReturn = null;
|
||||
$implementation = self::$defaultImplemenation;
|
||||
|
||||
// attempt to load the default implementation
|
||||
if ($pt->isValidImplementation(self::$defaultImplemenation))
|
||||
{
|
||||
$imp = $implementationMap[self::$defaultImplemenation];
|
||||
$toReturn = new $imp($filename, $options, $isDataStream);
|
||||
}
|
||||
// load the gd implementation if default failed
|
||||
else if ($pt->isValidImplementation('gd'))
|
||||
{
|
||||
$imp = $implementationMap['gd'];
|
||||
$implementation = 'gd';
|
||||
$toReturn = new $imp($filename, $options, $isDataStream);
|
||||
}
|
||||
// throw an exception if we can't load
|
||||
else
|
||||
{
|
||||
throw new Exception('You must have either the GD or iMagick extension loaded to use this library');
|
||||
}
|
||||
|
||||
$registry = $pt->getPluginRegistry($implementation);
|
||||
$toReturn->importPlugins($registry);
|
||||
return $toReturn;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,180 @@
|
||||
<?php
|
||||
/**
|
||||
* GD Reflection Lib Plugin Definition File
|
||||
*
|
||||
* This file contains the plugin definition for the GD Reflection Lib for PHP Thumb
|
||||
*
|
||||
* PHP Version 5 with GD 2.0+
|
||||
* PhpThumb : PHP Thumb Library <http://phpthumb.gxdlabs.com>
|
||||
* Copyright (c) 2009, Ian Selby/Gen X Design
|
||||
*
|
||||
* Author(s): Ian Selby <ian@gen-x-design.com>
|
||||
*
|
||||
* Licensed under the MIT License
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @author Ian Selby <ian@gen-x-design.com>
|
||||
* @copyright Copyright (c) 2009 Gen X Design
|
||||
* @link http://phpthumb.gxdlabs.com
|
||||
* @license http://www.opensource.org/licenses/mit-license.php The MIT License
|
||||
* @version 3.0
|
||||
* @package PhpThumb
|
||||
* @filesource
|
||||
*/
|
||||
|
||||
/**
|
||||
* GD Reflection Lib Plugin
|
||||
*
|
||||
* This plugin allows you to create those fun Apple(tm)-style reflections in your images
|
||||
*
|
||||
* @package PhpThumb
|
||||
* @subpackage Plugins
|
||||
*/
|
||||
class GdReflectionLib
|
||||
{
|
||||
/**
|
||||
* Instance of GdThumb passed to this class
|
||||
*
|
||||
* @var GdThumb
|
||||
*/
|
||||
protected $parentInstance;
|
||||
protected $currentDimensions;
|
||||
protected $workingImage;
|
||||
protected $newImage;
|
||||
protected $options;
|
||||
|
||||
public function createReflection ($percent, $reflection, $white, $border, $borderColor, &$that)
|
||||
{
|
||||
// bring stuff from the parent class into this class...
|
||||
$this->parentInstance = $that;
|
||||
$this->currentDimensions = $this->parentInstance->getCurrentDimensions();
|
||||
$this->workingImage = $this->parentInstance->getWorkingImage();
|
||||
$this->newImage = $this->parentInstance->getOldImage();
|
||||
$this->options = $this->parentInstance->getOptions();
|
||||
|
||||
$width = $this->currentDimensions['width'];
|
||||
$height = $this->currentDimensions['height'];
|
||||
$reflectionHeight = intval($height * ($reflection / 100));
|
||||
$newHeight = $height + $reflectionHeight;
|
||||
$reflectedPart = $height * ($percent / 100);
|
||||
|
||||
$this->workingImage = imagecreatetruecolor($width, $newHeight);
|
||||
|
||||
imagealphablending($this->workingImage, true);
|
||||
|
||||
$colorToPaint = imagecolorallocatealpha($this->workingImage,255,255,255,0);
|
||||
imagefilledrectangle($this->workingImage,0,0,$width,$newHeight,$colorToPaint);
|
||||
|
||||
imagecopyresampled
|
||||
(
|
||||
$this->workingImage,
|
||||
$this->newImage,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
$reflectedPart,
|
||||
$width,
|
||||
$reflectionHeight,
|
||||
$width,
|
||||
($height - $reflectedPart)
|
||||
);
|
||||
|
||||
$this->imageFlipVertical();
|
||||
|
||||
imagecopy($this->workingImage, $this->newImage, 0, 0, 0, 0, $width, $height);
|
||||
|
||||
imagealphablending($this->workingImage, true);
|
||||
|
||||
for ($i = 0; $i < $reflectionHeight; $i++)
|
||||
{
|
||||
$colorToPaint = imagecolorallocatealpha($this->workingImage, 255, 255, 255, ($i/$reflectionHeight*-1+1)*$white);
|
||||
|
||||
imagefilledrectangle($this->workingImage, 0, $height + $i, $width, $height + $i, $colorToPaint);
|
||||
}
|
||||
|
||||
if($border == true)
|
||||
{
|
||||
$rgb = $this->hex2rgb($borderColor, false);
|
||||
$colorToPaint = imagecolorallocate($this->workingImage, $rgb[0], $rgb[1], $rgb[2]);
|
||||
|
||||
imageline($this->workingImage, 0, 0, $width, 0, $colorToPaint); //top line
|
||||
imageline($this->workingImage, 0, $height, $width, $height, $colorToPaint); //bottom line
|
||||
imageline($this->workingImage, 0, 0, 0, $height, $colorToPaint); //left line
|
||||
imageline($this->workingImage, $width-1, 0, $width-1, $height, $colorToPaint); //right line
|
||||
}
|
||||
|
||||
if ($this->parentInstance->getFormat() == 'PNG')
|
||||
{
|
||||
$colorTransparent = imagecolorallocatealpha
|
||||
(
|
||||
$this->workingImage,
|
||||
$this->options['alphaMaskColor'][0],
|
||||
$this->options['alphaMaskColor'][1],
|
||||
$this->options['alphaMaskColor'][2],
|
||||
0
|
||||
);
|
||||
|
||||
imagefill($this->workingImage, 0, 0, $colorTransparent);
|
||||
imagesavealpha($this->workingImage, true);
|
||||
}
|
||||
|
||||
$this->parentInstance->setOldImage($this->workingImage);
|
||||
$this->currentDimensions['width'] = $width;
|
||||
$this->currentDimensions['height'] = $newHeight;
|
||||
$this->parentInstance->setCurrentDimensions($this->currentDimensions);
|
||||
|
||||
return $that;
|
||||
}
|
||||
|
||||
/**
|
||||
* Flips the image vertically
|
||||
*
|
||||
*/
|
||||
protected function imageFlipVertical ()
|
||||
{
|
||||
$x_i = imagesx($this->workingImage);
|
||||
$y_i = imagesy($this->workingImage);
|
||||
|
||||
for ($x = 0; $x < $x_i; $x++)
|
||||
{
|
||||
for ($y = 0; $y < $y_i; $y++)
|
||||
{
|
||||
imagecopy($this->workingImage, $this->workingImage, $x, $y_i - $y - 1, $x, $y, 1, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a hex color to rgb tuples
|
||||
*
|
||||
* @return mixed
|
||||
* @param string $hex
|
||||
* @param bool $asString
|
||||
*/
|
||||
protected function hex2rgb ($hex, $asString = false)
|
||||
{
|
||||
// strip off any leading #
|
||||
if (0 === strpos($hex, '#'))
|
||||
{
|
||||
$hex = substr($hex, 1);
|
||||
}
|
||||
elseif (0 === strpos($hex, '&H'))
|
||||
{
|
||||
$hex = substr($hex, 2);
|
||||
}
|
||||
|
||||
// break into hex 3-tuple
|
||||
$cutpoint = ceil(strlen($hex) / 2)-1;
|
||||
$rgb = explode(':', wordwrap($hex, $cutpoint, ':', $cutpoint), 3);
|
||||
|
||||
// convert each tuple to decimal
|
||||
$rgb[0] = (isset($rgb[0]) ? hexdec($rgb[0]) : 0);
|
||||
$rgb[1] = (isset($rgb[1]) ? hexdec($rgb[1]) : 0);
|
||||
$rgb[2] = (isset($rgb[2]) ? hexdec($rgb[2]) : 0);
|
||||
|
||||
return ($asString ? "{$rgb[0]} {$rgb[1]} {$rgb[2]}" : $rgb);
|
||||
}
|
||||
}
|
||||
|
||||
$pt = PhpThumb::getInstance();
|
||||
$pt->registerPlugin('GdReflectionLib', 'gd');
|
||||
@@ -288,7 +288,7 @@ class commonModel extends model
|
||||
echo '<div class="user-profile-name">' . (empty($app->user->realname) ? $app->user->account : $app->user->realname) . '</div>';
|
||||
if(isset($lang->user->roleList[$app->user->role])) echo '<div class="user-profile-role">' . $lang->user->roleList[$app->user->role] . '</div>';
|
||||
echo '</a></li><li class="divider"></li>';
|
||||
echo '<li>' . html::a(helper::createLink('my', 'profile', '', '', true), "<i class='icon icon-account'></i> " . $lang->profile, '', "class='iframe' data-width='600'") . '</li>';
|
||||
echo '<li>' . html::a(helper::createLink('my', 'profile', '', '', true), "<i class='icon icon-account'></i> " . $lang->profile, '', "class='iframe' data-width='800'") . '</li>';
|
||||
echo '<li>' . html::a(helper::createLink('my', 'preference', '', '', true), "<i class='icon icon-controls'></i> " . $lang->preference, '', "class='iframe' data-width='650'") . '</li>';
|
||||
echo '<li>' . html::a(helper::createLink('my', 'changepassword', '', '', true), "<i class='icon icon-cog-outline'></i> " . $lang->changePassword, '', "class='iframe' data-width='600'") . '</li>';
|
||||
echo "<li id='menuToggleItem'><a type='button' class='menu-toggle'><i class='icon icon-sm icon-menu-collapse'></i> <span class='is-unfold'>$lang->unfoldMenu</span><span class='is-collapse'>$lang->collapseMenu</span></a></li>";
|
||||
|
||||
@@ -489,6 +489,32 @@ class fileModel extends model
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Compress image to config configured size.
|
||||
*
|
||||
* @param string $rawImage
|
||||
* @param string $target
|
||||
* @param int $x
|
||||
* @param int $y
|
||||
* @param int $width
|
||||
* @param int $height
|
||||
* @param int $resizeWidth
|
||||
* @param int $resizeHeight
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function cropImage($rawImage, $target, $x, $y, $width, $height, $resizeWidth = 0, $resizeHeight = 0)
|
||||
{
|
||||
$this->app->loadClass('phpthumb', true);
|
||||
|
||||
if(!extension_loaded('gd')) return false;
|
||||
|
||||
$croper = phpThumbFactory::create($rawImage);
|
||||
if($resizeWidth > 0) $croper->resize($resizeWidth, $resizeHeight);
|
||||
$croper->crop($x, $y, $width, $height);
|
||||
$croper->save($target);
|
||||
}
|
||||
|
||||
/**
|
||||
* Paste image in kindeditor at firefox and chrome.
|
||||
*
|
||||
|
||||
@@ -861,6 +861,21 @@ class my extends control
|
||||
$this->display();
|
||||
}
|
||||
|
||||
/**
|
||||
* Upload avatar.
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function uploadAvatar()
|
||||
{
|
||||
if($_SERVER['REQUEST_METHOD'] == 'POST')
|
||||
{
|
||||
$result = $this->loadModel('user')->uploadAvatar();
|
||||
$this->send($result);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Unbind ranzhi
|
||||
*
|
||||
|
||||
@@ -1,6 +1,12 @@
|
||||
.body-modal .main-header{padding: 13px 0px 0px 0;}
|
||||
.cell{height:440px;}
|
||||
.row table{width: 100%;}
|
||||
.row th{width: 20%; line-height: 30px; padding-right: 20px; text-align: right; font-weight: 500;}
|
||||
.row td{width: 30%; text-align: left; font-weight: 700;}
|
||||
.main-actions{margin: 20px 0 20px 0; text-align: center;}
|
||||
.user-title{margin: 5px 10px; font-size: 14px; font-weight: bold; padding-left: 10px;}
|
||||
.user-title{margin: 20px 10px -10px 10px; font-size: 14px; font-weight: bold; padding-left: 10px;}
|
||||
.avatar { display: inline-block; width: 50px; height: 50px; line-height: 50px;}
|
||||
.user-name{margin-left: 15px}
|
||||
.user-name, .user-role{font-size: 16px; vertical-align: top;}
|
||||
#avatarUploadBtn{padding: 4px 12px; position: relative; left: 32px; bottom: 30px;}
|
||||
#avatarForm{height: 10px}
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
$(document).ready(function()
|
||||
{
|
||||
$('#files').change(function(){$('#avatarForm').submit();});
|
||||
|
||||
$.setAjaxForm('#avatarForm', function(response)
|
||||
{
|
||||
if(response.result == 'success')
|
||||
{
|
||||
setTimeout(function()
|
||||
{
|
||||
$('#avatarUploadBtn').popover('destroy');
|
||||
$('#ajaxModal').load(response.locate);
|
||||
}, 800);
|
||||
}
|
||||
});
|
||||
|
||||
$('#avatarUploadBtn').on('click', function()
|
||||
{
|
||||
$('#files').click();
|
||||
});
|
||||
});
|
||||
@@ -35,6 +35,7 @@ $lang->my->noTodo = 'Keine toDos. ';
|
||||
$lang->my->noData = 'No %s yet. ';
|
||||
$lang->my->storyChanged = "Story Changed";
|
||||
$lang->my->hours = 'Stunde/Tag';
|
||||
$lang->my->uploadAvatar = 'Upload Avatar';
|
||||
|
||||
$lang->my->myExecutions = 'My Stage/Sprint/Iteration';
|
||||
$lang->my->name = 'Name';
|
||||
|
||||
@@ -35,6 +35,7 @@ $lang->my->noTodo = 'No todos yet. ';
|
||||
$lang->my->noData = 'No %s yet. ';
|
||||
$lang->my->storyChanged = "Story Changed";
|
||||
$lang->my->hours = "Hours/day";
|
||||
$lang->my->uploadAvatar = 'Upload Avatar';
|
||||
|
||||
$lang->my->myExecutions = "My Stage/Sprint/Iteration";
|
||||
$lang->my->name = 'Name';
|
||||
|
||||
@@ -35,6 +35,7 @@ $lang->my->noTodo = "Je n'ai rien à faire pour l'instant.";
|
||||
$lang->my->noData = 'No %s yet. ';
|
||||
$lang->my->storyChanged = "Story Changed";
|
||||
$lang->my->hours = 'Heure/jour';
|
||||
$lang->my->uploadAvatar = 'Upload Avatar';
|
||||
|
||||
$lang->my->myExecutions = 'My Stage/Sprint/Iteration';
|
||||
$lang->my->name = 'Name';
|
||||
|
||||
@@ -35,6 +35,7 @@ $lang->my->noTodo = 'Chưa có việc nào.';
|
||||
$lang->my->noData = 'No %s yet. ';
|
||||
$lang->my->storyChanged = "Story Changed";
|
||||
$lang->my->hours = "Giờ/ngày";
|
||||
$lang->my->uploadAvatar = 'Upload Avatar';
|
||||
|
||||
$lang->my->myExecutions = "My Stage/Sprint/Iteration";
|
||||
$lang->my->name = 'Name';
|
||||
|
||||
@@ -35,6 +35,7 @@ $lang->my->noTodo = '暂时没有待办。';
|
||||
$lang->my->noData = "暂时没有%s。";
|
||||
$lang->my->storyChanged = "需求变更";
|
||||
$lang->my->hours = '工时/天';
|
||||
$lang->my->uploadAvatar = '更换头像';
|
||||
|
||||
$lang->my->myExecutions = "我参与的阶段/冲刺/迭代";
|
||||
$lang->my->name = '名称';
|
||||
|
||||
@@ -14,8 +14,13 @@
|
||||
<div id='mainContent'>
|
||||
<div class='cell'>
|
||||
<div class='main-header text-center'>
|
||||
<span class='user-name'><?php echo $user->realname;?></span>
|
||||
<span class="avatar avatar bg-secondary avatar-circle">A</span>
|
||||
<span class='user-name'><strong><?php echo $user->realname;?></strong></span>
|
||||
<span class='user-role'><?php echo zget($lang->user->roleList, $user->role);?></span>
|
||||
<form method='post' action=<?php echo inlink('uploadAvatar');?> id='avatarForm' enctype='multipart/form-data'>
|
||||
<input type="file" name="files" id="files" class="form-control hidden">
|
||||
<?php echo html::a('javascript:void(0);', $lang->my->uploadAvatar, '', "class='btn btn-avatar' id='avatarUploadBtn' data-placement='right'");?>
|
||||
</form>
|
||||
</div>
|
||||
<div class='row'>
|
||||
<div class='user-title'><?php echo $lang->user->basicInfo;?></div>
|
||||
|
||||
@@ -151,7 +151,7 @@ $lang->program->noPRJ = '暂时没有项目';
|
||||
$lang->program->accessDenied = '您无权访问该项目!';
|
||||
$lang->program->chooseProgramType = '选中项目管理模型';
|
||||
$lang->program->nextStep = '下一步';
|
||||
$lang->program->hoursUnit = '%s工时';
|
||||
$lang->program->hoursUnit = "%s $lang->hourCommon";
|
||||
$lang->program->membersUnit = '%s人';
|
||||
$lang->program->lastIteration = '近期迭代';
|
||||
$lang->program->ongoingStage = '进行中的阶段';
|
||||
|
||||
@@ -1162,6 +1162,32 @@ class user extends control
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* crop avatar
|
||||
*
|
||||
* @param int $image
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function cropAvatar($image)
|
||||
{
|
||||
$image = $this->loadModel('file')->getByID($image);
|
||||
|
||||
if(!empty($_POST))
|
||||
{
|
||||
$size = fixer::input('post')->get();
|
||||
$this->file->cropImage($image->realPath, $image->realPath, $size->left, $size->top, $size->right - $size->left, $size->bottom - $size->top, $size->scaled ? $size->scaleWidth : 0, $size->scaled ? $size->scaleHeight : 0);
|
||||
$user = $this->user->getById($this->app->user->account);
|
||||
$this->app->user->avatar = $user->avatar;
|
||||
exit('success');
|
||||
}
|
||||
|
||||
$this->view->user = $this->user->getById($this->app->user->account);
|
||||
$this->view->title = $this->lang->user->cropAvatar;
|
||||
$this->view->image = $image;
|
||||
$this->display();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get user for ajax
|
||||
*
|
||||
|
||||
@@ -52,6 +52,9 @@ $lang->user->verifyPassword = '您的密码';
|
||||
$lang->user->resetPassword = '忘记密码';
|
||||
$lang->user->score = '积分';
|
||||
$lang->user->name = '名称';
|
||||
$lang->user->cropAvatar = '裁剪头像';
|
||||
$lang->user->cropAvatarTip = '拖拽选框来选择头像裁剪范围';
|
||||
$lang->user->cropImageTip = '所使用的头像图片过小,建议图片大小至少为 48x48,当前图片大小为 %s';
|
||||
|
||||
$lang->user->legendBasic = '基本资料';
|
||||
$lang->user->legendContribution = '个人贡献';
|
||||
|
||||
@@ -1146,6 +1146,23 @@ class userModel extends model
|
||||
$this->dao->update(TABLE_USER)->set('ranzhi')->eq('')->where('account')->eq($account)->exec();
|
||||
}
|
||||
|
||||
/**
|
||||
* Upload avatar.
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function uploadAvatar()
|
||||
{
|
||||
$uploadResult = $this->loadModel('file')->saveUpload('avatar');
|
||||
if(!$uploadResult) return array('result' => 'fail', 'message' => $this->lang->fail);
|
||||
|
||||
$fileIdList = array_keys($uploadResult);
|
||||
$file = $this->file->getByID($fileIdList[0]);
|
||||
$this->dao->update(TABLE_USER)->set('avatar')->eq($file->webPath)->where('account')->eq($this->app->user->account)->exec();
|
||||
return array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => helper::createLink('user', 'cropavatar', "image={$file->id}"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get contact list of a user.
|
||||
*
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
<?php
|
||||
/**
|
||||
* The crop avatar view file of user module of ZentaoPms.
|
||||
*
|
||||
* @copyright Copyright 2009-2018 青岛易软天创网络科技有限公司(QingDao Nature Easy Soft Network Technology Co,LTD, www.cnezsoft.com)
|
||||
* @license ZPL (http://zpl.pub/page/zplv12.html)
|
||||
* @author Chunsheng Wang <chunsheng@cnezsoft.com>
|
||||
* @package user
|
||||
* @version $Id: cropavatar.html.php 8669 2021-01-18 16:58:48Z sunguangming$
|
||||
* @link http://www.zdoo.com
|
||||
*/
|
||||
?>
|
||||
<?php include '../../common/view/header.html.php';?>
|
||||
<table class='table table-form'>
|
||||
<tr>
|
||||
<td>
|
||||
<div class="img-cutter fixed-ratio" id="imgCutter" style="max-width: 100%">
|
||||
<div class="canvas">
|
||||
<?php
|
||||
if(empty($user->avatar))
|
||||
{
|
||||
echo html::image($image->webPath);
|
||||
}
|
||||
else
|
||||
{
|
||||
echo html::image($user->avatar);
|
||||
}
|
||||
?>
|
||||
</div>
|
||||
<div class="form-actions">
|
||||
<h5 id='avatarCropTip'><?php echo $lang->user->cropAvatarTip;?></h5>
|
||||
<div class="img-cutter-preview"></div>
|
||||
<button type="button" class="btn btn-primary img-cutter-submit"><?php echo $lang->save;?></button> <?php echo html::a(inlink('profile'), $lang->goback, "class='btn loadInModal'");?>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<script>
|
||||
var $imgCutter = $("#imgCutter");
|
||||
$imgCutter.imgCutter(
|
||||
{
|
||||
fixedRatio: true,
|
||||
minWidth: 48,
|
||||
minHeight: 48,
|
||||
post: '<?php echo inlink('cropavatar', "image={$image->id}")?>',
|
||||
ready: function() {$.zui.ajustModalPosition(); $imgCutter.css('width', $imgCutter.closest('.modal-dialog').width() - 50);},
|
||||
done: function(response)
|
||||
{
|
||||
$('#start .avatar, #startMenu .avatar').html('<img src="<?php echo $user->avatar?>?v=' + $.zui.uuid() + '" />');
|
||||
if($('#start .avatar, #startMenu .avatar').hasClass('with-text')) $('#start .avatar, #startMenu .avatar').toggleClass('with-text').css('background', 'none');
|
||||
$('#ajaxModal').load(createLink('user', 'profile'), function(){$.zui.ajustModalPosition()});
|
||||
},
|
||||
onSizeError: function(size)
|
||||
{
|
||||
$('#avatarCropTip').text('<?php echo $lang->user->cropImageTip ?>'.replace('%s', size.width + 'x' + size.height)).addClass('text-danger');
|
||||
}
|
||||
});
|
||||
</script>
|
||||
<?php include '../../common/view/footer.html.php';?>
|
||||
Reference in New Issue
Block a user