Subversion Repositories PHPX

Compare Revisions

Last modification

Ignore whitespace Rev 38 → Rev 39

/trunk/ZendFramework-2.1.2/library/Zend/I18n/Translator/Translator.php
0,0 → 1,586
<?php
/**
* Zend Framework (http://framework.zend.com/)
*
* @link http://github.com/zendframework/zf2 for the canonical source repository
* @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
 
namespace Zend\I18n\Translator;
 
use Locale;
use Traversable;
use Zend\Cache;
use Zend\Cache\Storage\StorageInterface as CacheStorage;
use Zend\I18n\Exception;
use Zend\I18n\Translator\Loader\FileLoaderInterface;
use Zend\I18n\Translator\Loader\RemoteLoaderInterface;
use Zend\Stdlib\ArrayUtils;
 
/**
* Translator.
*/
class Translator
{
/**
* Messages loaded by the translator.
*
* @var array
*/
protected $messages = array();
 
/**
* Files used for loading messages.
*
* @var array
*/
protected $files = array();
 
/**
* Patterns used for loading messages.
*
* @var array
*/
protected $patterns = array();
 
/**
* Remote locations for loading messages.
*
* @var array
*/
protected $remote = array();
 
/**
* Default locale.
*
* @var string
*/
protected $locale;
 
/**
* Locale to use as fallback if there is no translation.
*
* @var string
*/
protected $fallbackLocale;
 
/**
* Translation cache.
*
* @var CacheStorage
*/
protected $cache;
 
/**
* Plugin manager for translation loaders.
*
* @var LoaderPluginManager
*/
protected $pluginManager;
 
/**
* Instantiate a translator
*
* @param array|Traversable $options
* @return Translator
* @throws Exception\InvalidArgumentException
*/
public static function factory($options)
{
if ($options instanceof Traversable) {
$options = ArrayUtils::iteratorToArray($options);
} elseif (!is_array($options)) {
throw new Exception\InvalidArgumentException(sprintf(
'%s expects an array or Traversable object; received "%s"',
__METHOD__,
(is_object($options) ? get_class($options) : gettype($options))
));
}
 
$translator = new static();
 
// locales
if (isset($options['locale'])) {
$locales = (array) $options['locale'];
$translator->setLocale(array_shift($locales));
if (count($locales) > 0) {
$translator->setFallbackLocale(array_shift($locales));
}
}
 
// file patterns
if (isset($options['translation_file_patterns'])) {
if (!is_array($options['translation_file_patterns'])) {
throw new Exception\InvalidArgumentException(
'"translation_file_patterns" should be an array'
);
}
 
$requiredKeys = array('type', 'base_dir', 'pattern');
foreach ($options['translation_file_patterns'] as $pattern) {
foreach ($requiredKeys as $key) {
if (!isset($pattern[$key])) {
throw new Exception\InvalidArgumentException(
"'{$key}' is missing for translation pattern options"
);
}
}
 
$translator->addTranslationFilePattern(
$pattern['type'],
$pattern['base_dir'],
$pattern['pattern'],
isset($pattern['text_domain']) ? $pattern['text_domain'] : 'default'
);
}
}
 
// files
if (isset($options['translation_files'])) {
if (!is_array($options['translation_files'])) {
throw new Exception\InvalidArgumentException(
'"translation_files" should be an array'
);
}
 
$requiredKeys = array('type', 'filename');
foreach ($options['translation_files'] as $file) {
foreach ($requiredKeys as $key) {
if (!isset($file[$key])) {
throw new Exception\InvalidArgumentException(
"'{$key}' is missing for translation file options"
);
}
}
 
$translator->addTranslationFile(
$file['type'],
$file['filename'],
isset($file['text_domain']) ? $file['text_domain'] : 'default',
isset($file['locale']) ? $file['locale'] : null
);
}
}
 
// remote
if (isset($options['remote_translation'])) {
if (!is_array($options['remote_translation'])) {
throw new Exception\InvalidArgumentException(
'"remote_translation" should be an array'
);
}
 
$requiredKeys = array('type');
foreach ($options['remote_translation'] as $remote) {
foreach ($requiredKeys as $key) {
if (!isset($remote[$key])) {
throw new Exception\InvalidArgumentException(
"'{$key}' is missing for remote translation options"
);
}
}
 
$translator->addRemoteTranslations(
$remote['type'],
isset($remote['text_domain']) ? $remote['text_domain'] : 'default'
);
}
}
 
// cache
if (isset($options['cache'])) {
if ($options['cache'] instanceof CacheStorage) {
$translator->setCache($options['cache']);
} else {
$translator->setCache(Cache\StorageFactory::factory($options['cache']));
}
}
 
return $translator;
}
 
/**
* Set the default locale.
*
* @param string $locale
* @return Translator
*/
public function setLocale($locale)
{
$this->locale = $locale;
 
return $this;
}
 
/**
* Get the default locale.
*
* @return string
*/
public function getLocale()
{
if ($this->locale === null) {
$this->locale = Locale::getDefault();
}
 
return $this->locale;
}
 
/**
* Set the fallback locale.
*
* @param string $locale
* @return Translator
*/
public function setFallbackLocale($locale)
{
$this->fallbackLocale = $locale;
 
return $this;
}
 
/**
* Get the fallback locale.
*
* @return string
*/
public function getFallbackLocale()
{
return $this->fallbackLocale;
}
 
/**
* Sets a cache
*
* @param CacheStorage $cache
* @return Translator
*/
public function setCache(CacheStorage $cache = null)
{
$this->cache = $cache;
 
return $this;
}
 
/**
* Returns the set cache
*
* @return CacheStorage The set cache
*/
public function getCache()
{
return $this->cache;
}
 
/**
* Set the plugin manager for translation loaders
*
* @param LoaderPluginManager $pluginManager
* @return Translator
*/
public function setPluginManager(LoaderPluginManager $pluginManager)
{
$this->pluginManager = $pluginManager;
 
return $this;
}
 
/**
* Retrieve the plugin manager for translation loaders.
*
* Lazy loads an instance if none currently set.
*
* @return LoaderPluginManager
*/
public function getPluginManager()
{
if (!$this->pluginManager instanceof LoaderPluginManager) {
$this->setPluginManager(new LoaderPluginManager());
}
 
return $this->pluginManager;
}
 
/**
* Translate a message.
*
* @param string $message
* @param string $textDomain
* @param string $locale
* @return string
*/
public function translate($message, $textDomain = 'default', $locale = null)
{
$locale = ($locale ?: $this->getLocale());
$translation = $this->getTranslatedMessage($message, $locale, $textDomain);
 
if ($translation !== null && $translation !== '') {
return $translation;
}
 
if (null !== ($fallbackLocale = $this->getFallbackLocale())
&& $locale !== $fallbackLocale
) {
return $this->translate($message, $textDomain, $fallbackLocale);
}
 
return $message;
}
 
/**
* Translate a plural message.
*
* @param string $singular
* @param string $plural
* @param int $number
* @param string $textDomain
* @param string|null $locale
* @return string
* @throws Exception\OutOfBoundsException
*/
public function translatePlural(
$singular,
$plural,
$number,
$textDomain = 'default',
$locale = null
) {
$locale = $locale ?: $this->getLocale();
$translation = $this->getTranslatedMessage($singular, $locale, $textDomain);
 
if ($translation === null || $translation === '') {
if (null !== ($fallbackLocale = $this->getFallbackLocale())
&& $locale !== $fallbackLocale
) {
return $this->translatePlural(
$singular,
$plural,
$number,
$textDomain,
$fallbackLocale
);
}
 
return ($number == 1 ? $singular : $plural);
}
 
$index = $this->messages[$textDomain][$locale]
->getPluralRule()
->evaluate($number);
 
if (!isset($translation[$index])) {
throw new Exception\OutOfBoundsException(sprintf(
'Provided index %d does not exist in plural array', $index
));
}
 
return $translation[$index];
}
 
/**
* Get a translated message.
*
* @param string $message
* @param string $locale
* @param string $textDomain
* @return string|null
*/
protected function getTranslatedMessage(
$message,
$locale = null,
$textDomain = 'default'
) {
if ($message === '') {
return '';
}
 
if (!isset($this->messages[$textDomain][$locale])) {
$this->loadMessages($textDomain, $locale);
}
 
if (!isset($this->messages[$textDomain][$locale][$message])) {
return null;
}
 
return $this->messages[$textDomain][$locale][$message];
}
 
/**
* Add a translation file.
*
* @param string $type
* @param string $filename
* @param string $textDomain
* @param string $locale
* @return Translator
*/
public function addTranslationFile(
$type,
$filename,
$textDomain = 'default',
$locale = null
) {
$locale = $locale ?: '*';
 
if (!isset($this->files[$textDomain])) {
$this->files[$textDomain] = array();
}
 
$this->files[$textDomain][$locale][] = array(
'type' => $type,
'filename' => $filename,
);
 
return $this;
}
 
/**
* Add multiple translations with a file pattern.
*
* @param string $type
* @param string $baseDir
* @param string $pattern
* @param string $textDomain
* @return Translator
*/
public function addTranslationFilePattern(
$type,
$baseDir,
$pattern,
$textDomain = 'default'
) {
if (!isset($this->patterns[$textDomain])) {
$this->patterns[$textDomain] = array();
}
 
$this->patterns[$textDomain][] = array(
'type' => $type,
'baseDir' => rtrim($baseDir, '/'),
'pattern' => $pattern,
);
 
return $this;
}
 
/**
* Add remote translations.
*
* @param string $type
* @param string $textDomain
* @return Translator
*/
public function addRemoteTranslations($type, $textDomain = 'default')
{
if (!isset($this->remote[$textDomain])) {
$this->remote[$textDomain] = array();
}
 
$this->remote[$textDomain][] = $type;
 
return $this;
}
 
/**
* Load messages for a given language and domain.
*
* @param string $textDomain
* @param string $locale
* @throws Exception\RuntimeException
* @return void
*/
protected function loadMessages($textDomain, $locale)
{
if (!isset($this->messages[$textDomain])) {
$this->messages[$textDomain] = array();
}
 
if (null !== ($cache = $this->getCache())) {
$cacheId = 'Zend_I18n_Translator_Messages_' . md5($textDomain . $locale);
 
if (null !== ($result = $cache->getItem($cacheId))) {
$this->messages[$textDomain][$locale] = $result;
 
return;
}
}
 
$hasToCache = false;
 
// Try to load from remote sources
if (isset($this->remote[$textDomain])) {
foreach ($this->remote[$textDomain] as $loaderType) {
$loader = $this->getPluginManager()->get($loaderType);
 
if (!$loader instanceof RemoteLoaderInterface) {
throw new Exception\RuntimeException('Specified loader is not a remote loader');
}
 
if (isset($this->messages[$textDomain][$locale])) {
$this->messages[$textDomain][$locale]->exchangeArray(array_merge(
(array) $this->messages[$textDomain][$locale],
(array) $loader->load($locale, $textDomain)
));
} else {
$this->messages[$textDomain][$locale] = $loader->load($locale, $textDomain);
}
$hasToCache = true;
}
}
 
// Try to load from pattern
if (isset($this->patterns[$textDomain])) {
foreach ($this->patterns[$textDomain] as $pattern) {
$filename = $pattern['baseDir'] . '/' . sprintf($pattern['pattern'], $locale);
 
if (is_file($filename)) {
$loader = $this->getPluginManager()->get($pattern['type']);
 
if (!$loader instanceof FileLoaderInterface) {
throw new Exception\RuntimeException('Specified loader is not a file loader');
}
 
if (isset($this->messages[$textDomain][$locale])) {
$this->messages[$textDomain][$locale]->exchangeArray(array_merge(
(array) $this->messages[$textDomain][$locale],
(array) $loader->load($locale, $filename)
));
} else {
$this->messages[$textDomain][$locale] = $loader->load($locale, $filename);
}
$hasToCache = true;
}
}
}
 
// Try to load from concrete files
foreach (array($locale, '*') as $currentLocale) {
if (!isset($this->files[$textDomain][$currentLocale])) {
continue;
}
foreach ($this->files[$textDomain][$currentLocale] as $file) {
$loader = $this->getPluginManager()->get($file['type']);
 
if (!$loader instanceof FileLoaderInterface) {
throw new Exception\RuntimeException('Specified loader is not a file loader');
}
 
if (isset($this->messages[$textDomain][$locale])) {
$this->messages[$textDomain][$locale]->exchangeArray(array_merge(
(array) $this->messages[$textDomain][$locale],
(array) $loader->load($locale, $file['filename'])
));
} else {
$this->messages[$textDomain][$locale] = $loader->load($locale, $file['filename']);
}
$hasToCache = true;
}
unset($this->files[$textDomain][$currentLocale]);
}
 
// Cache the loaded text domain
if ($hasToCache && $cache !== null) {
$cache->setItem($cacheId, $this->messages[$textDomain][$locale]);
}
}
}
/trunk/ZendFramework-2.1.2/library/Zend/I18n/Translator/TextDomain.php
0,0 → 1,54
<?php
/**
* Zend Framework (http://framework.zend.com/)
*
* @link http://github.com/zendframework/zf2 for the canonical source repository
* @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
 
namespace Zend\I18n\Translator;
 
use ArrayObject;
use Zend\I18n\Translator\Plural\Rule as PluralRule;
 
/**
* Text domain.
*/
class TextDomain extends ArrayObject
{
/**
* Plural rule.
*
* @var PluralRule
*/
protected $pluralRule;
 
/**
* Set the plural rule
*
* @param PluralRule $rule
* @return TextDomain
*/
public function setPluralRule(PluralRule $rule)
{
$this->pluralRule = $rule;
return $this;
}
 
/**
* Get the plural rule.
*
* Lazy loads a default rule if none already registered
*
* @return PluralRule
*/
public function getPluralRule()
{
if ($this->pluralRule === null) {
$this->setPluralRule(PluralRule::fromString('nplurals=2; plural=n==1'));
}
 
return $this->pluralRule;
}
}
/trunk/ZendFramework-2.1.2/library/Zend/I18n/Translator/Loader/Gettext.php
0,0 → 1,188
<?php
/**
* Zend Framework (http://framework.zend.com/)
*
* @link http://github.com/zendframework/zf2 for the canonical source repository
* @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
 
namespace Zend\I18n\Translator\Loader;
 
use Zend\I18n\Exception;
use Zend\I18n\Translator\Plural\Rule as PluralRule;
use Zend\I18n\Translator\TextDomain;
use Zend\Stdlib\ErrorHandler;
 
/**
* Gettext loader.
*/
class Gettext implements FileLoaderInterface
{
/**
* Current file pointer.
*
* @var resource
*/
protected $file;
 
/**
* Whether the current file is little endian.
*
* @var bool
*/
protected $littleEndian;
 
/**
* load(): defined by FileLoaderInterface.
*
* @see FileLoaderInterface::load()
* @param string $locale
* @param string $filename
* @return TextDomain
* @throws Exception\InvalidArgumentException
*/
public function load($locale, $filename)
{
if (!is_file($filename) || !is_readable($filename)) {
throw new Exception\InvalidArgumentException(sprintf(
'Could not open file %s for reading',
$filename
));
}
 
$textDomain = new TextDomain();
 
ErrorHandler::start();
$this->file = fopen($filename, 'rb');
$error = ErrorHandler::stop();
if (false === $this->file) {
throw new Exception\InvalidArgumentException(sprintf(
'Could not open file %s for reading',
$filename
), 0, $error);
}
 
// Verify magic number
$magic = fread($this->file, 4);
 
if ($magic == "\x95\x04\x12\xde") {
$this->littleEndian = false;
} elseif ($magic == "\xde\x12\x04\x95") {
$this->littleEndian = true;
} else {
fclose($this->file);
throw new Exception\InvalidArgumentException(sprintf(
'%s is not a valid gettext file',
$filename
));
}
 
// Verify major revision (only 0 and 1 supported)
$majorRevision = ($this->readInteger() >> 16);
 
if ($majorRevision !== 0 && $majorRevision !== 1) {
fclose($this->file);
throw new Exception\InvalidArgumentException(sprintf(
'%s has an unknown major revision',
$filename
));
}
 
// Gather main information
$numStrings = $this->readInteger();
$originalStringTableOffset = $this->readInteger();
$translationStringTableOffset = $this->readInteger();
 
// Usually there follow size and offset of the hash table, but we have
// no need for it, so we skip them.
fseek($this->file, $originalStringTableOffset);
$originalStringTable = $this->readIntegerList(2 * $numStrings);
 
fseek($this->file, $translationStringTableOffset);
$translationStringTable = $this->readIntegerList(2 * $numStrings);
 
// Read in all translations
for ($current = 0; $current < $numStrings; $current++) {
$sizeKey = $current * 2 + 1;
$offsetKey = $current * 2 + 2;
$originalStringSize = $originalStringTable[$sizeKey];
$originalStringOffset = $originalStringTable[$offsetKey];
$translationStringSize = $translationStringTable[$sizeKey];
$translationStringOffset = $translationStringTable[$offsetKey];
 
$originalString = array('');
if ($originalStringSize > 0) {
fseek($this->file, $originalStringOffset);
$originalString = explode("\0", fread($this->file, $originalStringSize));
}
 
if ($translationStringSize > 0) {
fseek($this->file, $translationStringOffset);
$translationString = explode("\0", fread($this->file, $translationStringSize));
 
if (count($originalString) > 1 && count($translationString) > 1) {
$textDomain[$originalString[0]] = $translationString;
 
array_shift($originalString);
 
foreach ($originalString as $string) {
$textDomain[$string] = '';
}
} else {
$textDomain[$originalString[0]] = $translationString[0];
}
}
}
 
// Read header entries
if (array_key_exists('', $textDomain)) {
$rawHeaders = explode("\n", trim($textDomain['']));
 
foreach ($rawHeaders as $rawHeader) {
list($header, $content) = explode(':', $rawHeader, 2);
 
if (trim(strtolower($header)) === 'plural-forms') {
$textDomain->setPluralRule(PluralRule::fromString($content));
}
}
 
unset($textDomain['']);
}
 
fclose($this->file);
 
return $textDomain;
}
 
/**
* Read a single integer from the current file.
*
* @return integer
*/
protected function readInteger()
{
if ($this->littleEndian) {
$result = unpack('Vint', fread($this->file, 4));
} else {
$result = unpack('Nint', fread($this->file, 4));
}
 
return $result['int'];
}
 
/**
* Read an integer from the current file.
*
* @param integer $num
* @return integer
*/
protected function readIntegerList($num)
{
if ($this->littleEndian) {
return unpack('V' . $num, fread($this->file, 4 * $num));
}
 
return unpack('N' . $num, fread($this->file, 4 * $num));
}
}
/trunk/ZendFramework-2.1.2/library/Zend/I18n/Translator/Loader/FileLoaderInterface.php
0,0 → 1,25
<?php
/**
* Zend Framework (http://framework.zend.com/)
*
* @link http://github.com/zendframework/zf2 for the canonical source repository
* @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
 
namespace Zend\I18n\Translator\Loader;
 
/**
* File loader interface.
*/
interface FileLoaderInterface
{
/**
* Load translations from a file.
*
* @param string $locale
* @param string $filename
* @return \Zend\I18n\Translator\TextDomain|null
*/
public function load($locale, $filename);
}
/trunk/ZendFramework-2.1.2/library/Zend/I18n/Translator/LoaderPluginManager.php
0,0 → 1,58
<?php
/**
* Zend Framework (http://framework.zend.com/)
*
* @link http://github.com/zendframework/zf2 for the canonical source repository
* @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
 
namespace Zend\I18n\Translator;
 
use Zend\I18n\Exception;
use Zend\ServiceManager\AbstractPluginManager;
 
/**
* Plugin manager implementation for translation loaders.
*
* Enforces that loaders retrieved are either instances of
* Loader\FileLoaderInterface or Loader\RemoteLoaderInterface. Additionally,
* it registers a number of default loaders.
*/
class LoaderPluginManager extends AbstractPluginManager
{
/**
* Default set of loaders.
*
* @var array
*/
protected $invokableClasses = array(
'gettext' => 'Zend\I18n\Translator\Loader\Gettext',
'ini' => 'Zend\I18n\Translator\Loader\Ini',
'phparray' => 'Zend\I18n\Translator\Loader\PhpArray',
);
 
/**
* Validate the plugin.
*
* Checks that the filter loaded is an instance of
* Loader\FileLoaderInterface or Loader\RemoteLoaderInterface.
*
* @param mixed $plugin
* @return void
* @throws Exception\RuntimeException if invalid
*/
public function validatePlugin($plugin)
{
if ($plugin instanceof Loader\FileLoaderInterface || $plugin instanceof Loader\RemoteLoaderInterface) {
// we're okay
return;
}
 
throw new Exception\RuntimeException(sprintf(
'Plugin of type %s is invalid; must implement %s\Loader\FileLoaderInterface or %s\Loader\RemoteLoaderInterface',
(is_object($plugin) ? get_class($plugin) : gettype($plugin)),
__NAMESPACE__
));
}
}
/trunk/ZendFramework-2.1.2/library/Zend/Stdlib/ErrorHandler.php
0,0 → 1,115
<?php
/**
* Zend Framework (http://framework.zend.com/)
*
* @link http://github.com/zendframework/zf2 for the canonical source repository
* @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
 
namespace Zend\Stdlib;
 
use ErrorException;
 
/**
* ErrorHandler that can be used to catch internal PHP errors
* and convert to a ErrorException instance.
*/
abstract class ErrorHandler
{
/**
* Active stack
*
* @var array
*/
protected static $stack = array();
 
/**
* Check if this error handler is active
*
* @return boolean
*/
public static function started()
{
return (bool) static::getNestedLevel();
}
 
/**
* Get the current nested level
*
* @return int
*/
public static function getNestedLevel()
{
return count(static::$stack);
}
 
/**
* Starting the error handler
*
* @param int $errorLevel
*/
public static function start($errorLevel = \E_WARNING)
{
if (!static::$stack) {
set_error_handler(array(get_called_class(), 'addError'), $errorLevel);
}
 
static::$stack[] = null;
}
 
/**
* Stopping the error handler
*
* @param bool $throw Throw the ErrorException if any
* @return null|ErrorException
* @throws ErrorException If an error has been catched and $throw is true
*/
public static function stop($throw = false)
{
$errorException = null;
 
if (static::$stack) {
$errorException = array_pop(static::$stack);
 
if (!static::$stack) {
restore_error_handler();
}
 
if ($errorException && $throw) {
throw $errorException;
}
}
 
return $errorException;
}
 
/**
* Stop all active handler
*
* @return void
*/
public static function clean()
{
if (static::$stack) {
restore_error_handler();
}
 
static::$stack = array();
}
 
/**
* Add an error to the stack
*
* @param int $errno
* @param string $errstr
* @param string $errfile
* @param int $errline
* @return void
*/
public static function addError($errno, $errstr = '', $errfile = '', $errline = 0)
{
$stack = & static::$stack[ count(static::$stack) - 1 ];
$stack = new ErrorException($errstr, 0, $errno, $errfile, $errline, $stack);
}
}
/trunk/ZendFramework-2.1.2/library/Zend/ServiceManager/ServiceManager.php
0,0 → 1,986
<?php
/**
* Zend Framework (http://framework.zend.com/)
*
* @link http://github.com/zendframework/zf2 for the canonical source repository
* @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
 
namespace Zend\ServiceManager;
 
use ReflectionClass;
 
class ServiceManager implements ServiceLocatorInterface
{
 
/**@#+
* Constants
*/
const SCOPE_PARENT = 'parent';
const SCOPE_CHILD = 'child';
/**@#-*/
 
/**
* Lookup for canonicalized names.
*
* @var array
*/
protected $canonicalNames = array();
 
/**
* @var bool
*/
protected $allowOverride = false;
 
/**
* @var array
*/
protected $invokableClasses = array();
 
/**
* @var string|callable|\Closure|FactoryInterface[]
*/
protected $factories = array();
 
/**
* @var AbstractFactoryInterface[]
*/
protected $abstractFactories = array();
 
/**
* @var array
*/
protected $pendingAbstractFactoryRequests = array();
 
/**
* @var array
*/
protected $shared = array();
 
/**
* Registered services and cached values
*
* @var array
*/
protected $instances = array();
 
/**
* @var array
*/
protected $aliases = array();
 
/**
* @var array
*/
protected $initializers = array();
 
/**
* @var ServiceManager[]
*/
protected $peeringServiceManagers = array();
 
/**
* Whether or not to share by default
*
* @var bool
*/
protected $shareByDefault = true;
 
/**
* @var bool
*/
protected $retrieveFromPeeringManagerFirst = false;
 
/**
* @var bool Track whether not to throw exceptions during create()
*/
protected $throwExceptionInCreate = true;
 
/**
* @var array map of characters to be replaced through strtr
*/
protected $canonicalNamesReplacements = array('-' => '', '_' => '', ' ' => '', '\\' => '', '/' => '');
 
/**
* Constructor
*
* @param ConfigInterface $config
*/
public function __construct(ConfigInterface $config = null)
{
if ($config) {
$config->configureServiceManager($this);
}
}
 
/**
* Set allow override
*
* @param $allowOverride
* @return ServiceManager
*/
public function setAllowOverride($allowOverride)
{
$this->allowOverride = (bool) $allowOverride;
return $this;
}
 
/**
* Get allow override
*
* @return bool
*/
public function getAllowOverride()
{
return $this->allowOverride;
}
 
/**
* Set flag indicating whether services are shared by default
*
* @param bool $shareByDefault
* @return ServiceManager
* @throws Exception\RuntimeException if allowOverride is false
*/
public function setShareByDefault($shareByDefault)
{
if ($this->allowOverride === false) {
throw new Exception\RuntimeException(sprintf(
'%s: cannot alter default shared service setting; container is marked immutable (allow_override is false)',
__METHOD__
));
}
$this->shareByDefault = (bool) $shareByDefault;
return $this;
}
 
/**
* Are services shared by default?
*
* @return bool
*/
public function shareByDefault()
{
return $this->shareByDefault;
}
 
/**
* Set throw exceptions in create
*
* @param bool $throwExceptionInCreate
* @return ServiceManager
*/
public function setThrowExceptionInCreate($throwExceptionInCreate)
{
$this->throwExceptionInCreate = $throwExceptionInCreate;
return $this;
}
 
/**
* Get throw exceptions in create
*
* @return bool
*/
public function getThrowExceptionInCreate()
{
return $this->throwExceptionInCreate;
}
 
/**
* Set flag indicating whether to pull from peering manager before attempting creation
*
* @param bool $retrieveFromPeeringManagerFirst
* @return ServiceManager
*/
public function setRetrieveFromPeeringManagerFirst($retrieveFromPeeringManagerFirst = true)
{
$this->retrieveFromPeeringManagerFirst = (bool) $retrieveFromPeeringManagerFirst;
return $this;
}
 
/**
* Should we retrieve from the peering manager prior to attempting to create a service?
*
* @return bool
*/
public function retrieveFromPeeringManagerFirst()
{
return $this->retrieveFromPeeringManagerFirst;
}
 
/**
* Set invokable class
*
* @param string $name
* @param string $invokableClass
* @param bool $shared
* @return ServiceManager
* @throws Exception\InvalidServiceNameException
*/
public function setInvokableClass($name, $invokableClass, $shared = null)
{
$cName = $this->canonicalizeName($name);
 
if ($this->has(array($cName, $name), false)) {
if ($this->allowOverride === false) {
throw new Exception\InvalidServiceNameException(sprintf(
'A service by the name or alias "%s" already exists and cannot be overridden; please use an alternate name',
$cName
));
}
$this->unregisterService($cName);
}
 
if ($shared === null) {
$shared = $this->shareByDefault();
}
 
$this->invokableClasses[$cName] = $invokableClass;
$this->shared[$cName] = (bool) $shared;
 
return $this;
}
 
/**
* Set factory
*
* @param string $name
* @param string|FactoryInterface|callable $factory
* @param bool $shared
* @return ServiceManager
* @throws Exception\InvalidArgumentException
* @throws Exception\InvalidServiceNameException
*/
public function setFactory($name, $factory, $shared = null)
{
$cName = $this->canonicalizeName($name);
 
if (!is_string($factory) && !$factory instanceof FactoryInterface && !is_callable($factory)) {
throw new Exception\InvalidArgumentException(
'Provided abstract factory must be the class name of an abstract factory or an instance of an AbstractFactoryInterface.'
);
}
 
if ($this->has(array($cName, $name), false)) {
if ($this->allowOverride === false) {
throw new Exception\InvalidServiceNameException(sprintf(
'A service by the name or alias "%s" already exists and cannot be overridden, please use an alternate name',
$cName
));
}
$this->unregisterService($cName);
}
 
if ($shared === null) {
$shared = $this->shareByDefault();
}
 
$this->factories[$cName] = $factory;
$this->shared[$cName] = (bool) $shared;
 
return $this;
}
 
/**
* Add abstract factory
*
* @param AbstractFactoryInterface|string $factory
* @param bool $topOfStack
* @return ServiceManager
* @throws Exception\InvalidArgumentException if the abstract factory is invalid
*/
public function addAbstractFactory($factory, $topOfStack = true)
{
if (!is_string($factory) && !$factory instanceof AbstractFactoryInterface) {
throw new Exception\InvalidArgumentException(
'Provided abstract factory must be the class name of an abstract factory or an instance of an AbstractFactoryInterface.'
);
}
if (is_string($factory)) {
if (!class_exists($factory, true)) {
throw new Exception\InvalidArgumentException(
'Provided abstract factory must be the class name of an abstract factory or an instance of an AbstractFactoryInterface.'
);
}
$refl = new ReflectionClass($factory);
if (!$refl->implementsInterface(__NAMESPACE__ . '\\AbstractFactoryInterface')) {
throw new Exception\InvalidArgumentException(
'Provided abstract factory must be the class name of an abstract factory or an instance of an AbstractFactoryInterface.'
);
}
}
 
if ($topOfStack) {
array_unshift($this->abstractFactories, $factory);
} else {
array_push($this->abstractFactories, $factory);
}
return $this;
}
 
/**
* Add initializer
*
* @param callable|InitializerInterface $initializer
* @param bool $topOfStack
* @return ServiceManager
* @throws Exception\InvalidArgumentException
*/
public function addInitializer($initializer, $topOfStack = true)
{
if (!is_callable($initializer) && !$initializer instanceof InitializerInterface) {
if (!is_string($initializer)
|| !$this->isSubclassOf($initializer, __NAMESPACE__ . '\InitializerInterface')
) {
throw new Exception\InvalidArgumentException('$initializer should be callable.');
}
$initializer = new $initializer;
}
 
if ($topOfStack) {
array_unshift($this->initializers, $initializer);
} else {
array_push($this->initializers, $initializer);
}
return $this;
}
 
/**
* Register a service with the locator
*
* @param string $name
* @param mixed $service
* @return ServiceManager
* @throws Exception\InvalidServiceNameException
*/
public function setService($name, $service)
{
$cName = $this->canonicalizeName($name);
 
if ($this->has($cName, false)) {
if ($this->allowOverride === false) {
throw new Exception\InvalidServiceNameException(sprintf(
'%s: A service by the name "%s" or alias already exists and cannot be overridden, please use an alternate name.',
__METHOD__,
$name
));
}
$this->unregisterService($cName);
}
 
$this->instances[$cName] = $service;
 
return $this;
}
 
/**
* @param string $name
* @param bool $isShared
* @return ServiceManager
* @throws Exception\ServiceNotFoundException
*/
public function setShared($name, $isShared)
{
$cName = $this->canonicalizeName($name);
 
if (
!isset($this->invokableClasses[$cName])
&& !isset($this->factories[$cName])
&& !$this->canCreateFromAbstractFactory($cName, $name)
) {
throw new Exception\ServiceNotFoundException(sprintf(
'%s: A service by the name "%s" was not found and could not be marked as shared',
__METHOD__,
$name
));
}
 
$this->shared[$cName] = (bool) $isShared;
return $this;
}
 
/**
* Retrieve a registered instance
*
* @param string $name
* @param bool $usePeeringServiceManagers
* @throws Exception\ServiceNotFoundException
* @return object|array
*/
public function get($name, $usePeeringServiceManagers = true)
{
$cName = $this->canonicalizeName($name);
$isAlias = false;
 
if ($this->hasAlias($cName)) {
$isAlias = true;
 
do {
$cName = $this->aliases[$cName];
} while ($this->hasAlias($cName));
}
 
$instance = null;
$retrieveFromPeeringManagerFirst = $this->retrieveFromPeeringManagerFirst();
 
if ($usePeeringServiceManagers && $retrieveFromPeeringManagerFirst) {
$instance = $this->retrieveFromPeeringManager($name);
 
if(null !== $instance) {
return $instance;
}
}
 
if (isset($this->instances[$cName])) {
return $this->instances[$cName];
}
 
if (!$instance) {
if ($this->canCreate(array($cName, $name))) {
$instance = $this->create(array($cName, $name));
} elseif ($usePeeringServiceManagers && !$retrieveFromPeeringManagerFirst) {
$instance = $this->retrieveFromPeeringManager($name);
}
}
 
// Still no instance? raise an exception
if ($instance === null && !is_array($instance)) {
if ($isAlias) {
throw new Exception\ServiceNotFoundException(sprintf(
'An alias "%s" was requested but no service could be found.',
$name
));
}
 
throw new Exception\ServiceNotFoundException(sprintf(
'%s was unable to fetch or create an instance for %s',
__METHOD__,
$name
));
}
 
if (
($this->shareByDefault() && !isset($this->shared[$cName]))
|| (isset($this->shared[$cName]) && $this->shared[$cName] === true)
) {
$this->instances[$cName] = $instance;
}
 
return $instance;
}
 
/**
* Create an instance
*
* @param string|array $name
* @return bool|object
* @throws Exception\ServiceNotFoundException
* @throws Exception\ServiceNotCreatedException
*/
public function create($name)
{
$instance = false;
 
if (is_array($name)) {
list($cName, $rName) = $name;
} else {
$rName = $name;
$cName = $this->canonicalizeName($rName);
}
 
 
if (isset($this->factories[$cName])) {
$instance = $this->createFromFactory($cName, $rName);
}
 
if ($instance === false && isset($this->invokableClasses[$cName])) {
$instance = $this->createFromInvokable($cName, $rName);
}
 
if ($instance === false && $this->canCreateFromAbstractFactory($cName, $rName)) {
$instance = $this->createFromAbstractFactory($cName, $rName);
}
 
if ($this->throwExceptionInCreate == true && $instance === false) {
throw new Exception\ServiceNotFoundException(sprintf(
'No valid instance was found for %s%s',
$cName,
($rName ? '(alias: ' . $rName . ')' : '')
));
}
 
foreach ($this->initializers as $initializer) {
if ($initializer instanceof InitializerInterface) {
$initializer->initialize($instance, $this);
} elseif (is_object($initializer) && is_callable($initializer)) {
$initializer($instance, $this);
} else {
call_user_func($initializer, $instance, $this);
}
}
 
return $instance;
}
 
/**
* Determine if we can create an instance.
*
* @param string|array $name
* @param bool $checkAbstractFactories
* @return bool
*/
public function canCreate($name, $checkAbstractFactories = true)
{
if (is_array($name)) {
list($cName, $rName) = $name;
} else {
$rName = $name;
$cName = $this->canonicalizeName($rName);
}
 
if (
isset($this->invokableClasses[$cName])
|| isset($this->factories[$cName])
|| isset($this->aliases[$cName])
|| isset($this->instances[$cName])
) {
return true;
}
 
if ($checkAbstractFactories && $this->canCreateFromAbstractFactory($cName, $rName)) {
return true;
}
 
return false;
}
 
/**
* @param string|array $name
* @param bool $checkAbstractFactories
* @param bool $usePeeringServiceManagers
* @return bool
*/
public function has($name, $checkAbstractFactories = true, $usePeeringServiceManagers = true)
{
if (is_array($name)) {
list($cName, $rName) = $name;
} else {
$rName = $name;
$cName = $this->canonicalizeName($rName);
}
 
if ($this->canCreate(array($cName, $rName), $checkAbstractFactories)) {
return true;
}
 
if ($usePeeringServiceManagers) {
foreach ($this->peeringServiceManagers as $peeringServiceManager) {
if ($peeringServiceManager->has($rName)) {
return true;
}
}
}
 
return false;
}
 
/**
* Determine if we can create an instance from an abstract factory.
*
* @param string $cName
* @param string $rName
* @return bool
*/
public function canCreateFromAbstractFactory($cName, $rName)
{
// check abstract factories
foreach ($this->abstractFactories as $index => $abstractFactory) {
// Support string abstract factory class names
if (is_string($abstractFactory) && class_exists($abstractFactory, true)) {
$this->abstractFactories[$index] = $abstractFactory = new $abstractFactory();
}
 
if (
isset($this->pendingAbstractFactoryRequests[get_class($abstractFactory)])
&& $this->pendingAbstractFactoryRequests[get_class($abstractFactory)] == $rName
) {
return false;
}
 
if ($abstractFactory->canCreateServiceWithName($this, $cName, $rName)) {
return true;
}
}
return false;
}
 
/**
* @param string $alias
* @param string $nameOrAlias
* @return ServiceManager
* @throws Exception\ServiceNotFoundException
* @throws Exception\InvalidServiceNameException
*/
public function setAlias($alias, $nameOrAlias)
{
if (!is_string($alias) || !is_string($nameOrAlias)) {
throw new Exception\InvalidServiceNameException('Service or alias names must be strings.');
}
 
$cAlias = $this->canonicalizeName($alias);
$nameOrAlias = $this->canonicalizeName($nameOrAlias);
 
if ($alias == '' || $nameOrAlias == '') {
throw new Exception\InvalidServiceNameException('Invalid service name alias');
}
 
if ($this->allowOverride === false && $this->has(array($cAlias, $alias), false)) {
throw new Exception\InvalidServiceNameException(sprintf(
'An alias by the name "%s" or "%s" already exists',
$cAlias,
$alias
));
}
 
$this->aliases[$cAlias] = $nameOrAlias;
return $this;
}
 
/**
* Determine if we have an alias
*
* @param string $alias
* @return bool
*/
public function hasAlias($alias)
{
$alias = $this->canonicalizeName($alias);
return (isset($this->aliases[$alias]));
}
 
/**
* Create scoped service manager
*
* @param string $peering
* @return ServiceManager
*/
public function createScopedServiceManager($peering = self::SCOPE_PARENT)
{
$scopedServiceManager = new ServiceManager();
if ($peering == self::SCOPE_PARENT) {
$scopedServiceManager->peeringServiceManagers[] = $this;
}
if ($peering == self::SCOPE_CHILD) {
$this->peeringServiceManagers[] = $scopedServiceManager;
}
return $scopedServiceManager;
}
 
/**
* Add a peering relationship
*
* @param ServiceManager $manager
* @param string $peering
* @return ServiceManager
*/
public function addPeeringServiceManager(ServiceManager $manager, $peering = self::SCOPE_PARENT)
{
if ($peering == self::SCOPE_PARENT) {
$this->peeringServiceManagers[] = $manager;
}
if ($peering == self::SCOPE_CHILD) {
$manager->peeringServiceManagers[] = $this;
}
return $this;
}
 
/**
* Canonicalize name
*
* @param string $name
* @return string
*/
protected function canonicalizeName($name)
{
if (isset($this->canonicalNames[$name])) {
return $this->canonicalNames[$name];
}
 
// this is just for performance instead of using str_replace
return $this->canonicalNames[$name] = strtolower(strtr($name, $this->canonicalNamesReplacements));
}
 
/**
* Create service via callback
*
* @param callable $callable
* @param string $cName
* @param string $rName
* @throws Exception\ServiceNotCreatedException
* @throws Exception\ServiceNotFoundException
* @throws Exception\CircularDependencyFoundException
* @return object
*/
protected function createServiceViaCallback($callable, $cName, $rName)
{
static $circularDependencyResolver = array();
$depKey = spl_object_hash($this) . '-' . $cName;
 
if (isset($circularDependencyResolver[$depKey])) {
$circularDependencyResolver = array();
throw new Exception\CircularDependencyFoundException('Circular dependency for LazyServiceLoader was found for instance ' . $rName);
}
 
try {
$circularDependencyResolver[$depKey] = true;
$instance = call_user_func($callable, $this, $cName, $rName);
unset($circularDependencyResolver[$depKey]);
} catch (Exception\ServiceNotFoundException $e) {
unset($circularDependencyResolver[$depKey]);
throw $e;
} catch (\Exception $e) {
unset($circularDependencyResolver[$depKey]);
throw new Exception\ServiceNotCreatedException(
sprintf('An exception was raised while creating "%s"; no instance returned', $rName),
$e->getCode(),
$e
);
}
if ($instance === null) {
throw new Exception\ServiceNotCreatedException('The factory was called but did not return an instance.');
}
 
return $instance;
}
 
/**
* Retrieve a keyed list of all registered services. Handy for debugging!
*
* @return array
*/
public function getRegisteredServices()
{
return array(
'invokableClasses' => array_keys($this->invokableClasses),
'factories' => array_keys($this->factories),
'aliases' => array_keys($this->aliases),
'instances' => array_keys($this->instances),
);
}
 
/**
* Retrieve a keyed list of all canonical names. Handy for debugging!
*
* @return array
*/
public function getCanonicalNames()
{
return $this->canonicalNames;
}
 
/**
* Allows to override the canonical names lookup map with predefined
* values.
*
* @param array $canonicalNames
* @return ServiceManager
*/
public function setCanonicalNames($canonicalNames)
{
$this->canonicalNames = $canonicalNames;
 
return $this;
}
 
/**
* Attempt to retrieve an instance via a peering manager
*
* @param string $name
* @return mixed
*/
protected function retrieveFromPeeringManager($name)
{
foreach ($this->peeringServiceManagers as $peeringServiceManager) {
if ($peeringServiceManager->has($name)) {
return $peeringServiceManager->get($name);
}
}
 
$name = $this->canonicalizeName($name);
 
if ($this->hasAlias($name)) {
do {
$name = $this->aliases[$name];
} while ($this->hasAlias($name));
}
 
foreach ($this->peeringServiceManagers as $peeringServiceManager) {
if ($peeringServiceManager->has($name)) {
return $peeringServiceManager->get($name);
}
}
 
return null;
}
 
/**
* Attempt to create an instance via an invokable class
*
* @param string $canonicalName
* @param string $requestedName
* @return null|\stdClass
* @throws Exception\ServiceNotFoundException If resolved class does not exist
*/
protected function createFromInvokable($canonicalName, $requestedName)
{
$invokable = $this->invokableClasses[$canonicalName];
if (!class_exists($invokable)) {
throw new Exception\ServiceNotFoundException(sprintf(
'%s: failed retrieving "%s%s" via invokable class "%s"; class does not exist',
__METHOD__,
$canonicalName,
($requestedName ? '(alias: ' . $requestedName . ')' : ''),
$invokable
));
}
$instance = new $invokable;
return $instance;
}
 
/**
* Attempt to create an instance via a factory
*
* @param string $canonicalName
* @param string $requestedName
* @return mixed
* @throws Exception\ServiceNotCreatedException If factory is not callable
*/
protected function createFromFactory($canonicalName, $requestedName)
{
$factory = $this->factories[$canonicalName];
if (is_string($factory) && class_exists($factory, true)) {
$factory = new $factory;
$this->factories[$canonicalName] = $factory;
}
if ($factory instanceof FactoryInterface) {
$instance = $this->createServiceViaCallback(array($factory, 'createService'), $canonicalName, $requestedName);
} elseif (is_callable($factory)) {
$instance = $this->createServiceViaCallback($factory, $canonicalName, $requestedName);
} else {
throw new Exception\ServiceNotCreatedException(sprintf(
'While attempting to create %s%s an invalid factory was registered for this instance type.',
$canonicalName,
($requestedName ? '(alias: ' . $requestedName . ')' : '')
));
}
return $instance;
}
 
/**
* Attempt to create an instance via an abstract factory
*
* @param string $canonicalName
* @param string $requestedName
* @return object|null
* @throws Exception\ServiceNotCreatedException If abstract factory is not callable
*/
protected function createFromAbstractFactory($canonicalName, $requestedName)
{
foreach ($this->abstractFactories as $index => $abstractFactory) {
// support factories as strings
if (is_string($abstractFactory) && class_exists($abstractFactory, true)) {
$this->abstractFactories[$index] = $abstractFactory = new $abstractFactory;
} elseif (!$abstractFactory instanceof AbstractFactoryInterface) {
throw new Exception\ServiceNotCreatedException(sprintf(
'While attempting to create %s%s an abstract factory could not produce a valid instance.',
$canonicalName,
($requestedName ? '(alias: ' . $requestedName . ')' : '')
));
}
try {
if ($abstractFactory->canCreateServiceWithName($this, $canonicalName, $requestedName)) {
$this->pendingAbstractFactoryRequests[get_class($abstractFactory)] = $requestedName;
$instance = $this->createServiceViaCallback(
array($abstractFactory, 'createServiceWithName'),
$canonicalName,
$requestedName
);
unset($this->pendingAbstractFactoryRequests[get_class($abstractFactory)]);
} else {
$instance = false;
}
} catch (\Exception $e) {
unset($this->pendingAbstractFactoryRequests[get_class($abstractFactory)]);
throw new Exception\ServiceNotCreatedException(
sprintf(
'An abstract factory could not create an instance of %s%s.',
$canonicalName,
($requestedName ? '(alias: ' . $requestedName . ')' : '')
),
$e->getCode(),
$e
);
}
if (is_object($instance)) {
break;
}
}
 
return $instance;
}
 
/**
* Checks if the object has this class as one of its parents
*
* @see https://bugs.php.net/bug.php?id=53727
* @see https://github.com/zendframework/zf2/pull/1807
*
* @param string $className
* @param string $type
* @return bool
*/
protected static function isSubclassOf($className, $type)
{
if (is_subclass_of($className, $type)) {
return true;
}
if (version_compare(PHP_VERSION, '5.3.7', '>=')) {
return false;
}
if (!interface_exists($type)) {
return false;
}
$r = new ReflectionClass($className);
return $r->implementsInterface($type);
}
 
/**
* Unregister a service
*
* Called when $allowOverride is true and we detect that a service being
* added to the instance already exists. This will remove the duplicate
* entry, and also any shared flags previously registered.
*
* @param string $canonical
* @return void
*/
protected function unregisterService($canonical)
{
$types = array('invokableClasses', 'factories', 'aliases');
foreach ($types as $type) {
if (isset($this->{$type}[$canonical])) {
unset($this->{$type}[$canonical]);
break;
}
}
 
if (isset($this->instances[$canonical])) {
unset($this->instances[$canonical]);
}
 
if (isset($this->shared[$canonical])) {
unset($this->shared[$canonical]);
}
}
}
/trunk/ZendFramework-2.1.2/library/Zend/ServiceManager/AbstractPluginManager.php
0,0 → 1,214
<?php
/**
* Zend Framework (http://framework.zend.com/)
*
* @link http://github.com/zendframework/zf2 for the canonical source repository
* @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
 
namespace Zend\ServiceManager;
 
/**
* ServiceManager implementation for managing plugins
*
* Automatically registers an initializer which should be used to verify that
* a plugin instance is of a valid type. Additionally, allows plugins to accept
* an array of options for the constructor, which can be used to configure
* the plugin when retrieved. Finally, enables the allowOverride property by
* default to allow registering factories, aliases, and invokables to take
* the place of those provided by the implementing class.
*/
abstract class AbstractPluginManager extends ServiceManager implements ServiceLocatorAwareInterface
{
/**
* Allow overriding by default
*
* @var bool
*/
protected $allowOverride = true;
 
/**
* Whether or not to auto-add a class as an invokable class if it exists
*
* @var bool
*/
protected $autoAddInvokableClass = true;
 
/**
* Options to use when creating an instance
*
* @var mixed
*/
protected $creationOptions = null;
 
/**
* The main service locator
*
* @var ServiceLocatorInterface
*/
protected $serviceLocator;
 
/**
* Constructor
*
* Add a default initializer to ensure the plugin is valid after instance
* creation.
*
* @param null|ConfigInterface $configuration
*/
public function __construct(ConfigInterface $configuration = null)
{
parent::__construct($configuration);
$self = $this;
$this->addInitializer(function ($instance) use ($self) {
if ($instance instanceof ServiceLocatorAwareInterface) {
$instance->setServiceLocator($self);
}
});
}
 
/**
* Validate the plugin
*
* Checks that the filter loaded is either a valid callback or an instance
* of FilterInterface.
*
* @param mixed $plugin
* @return void
* @throws Exception\RuntimeException if invalid
*/
abstract public function validatePlugin($plugin);
 
/**
* Retrieve a service from the manager by name
*
* Allows passing an array of options to use when creating the instance.
* createFromInvokable() will use these and pass them to the instance
* constructor if not null and a non-empty array.
*
* @param string $name
* @param array $options
* @param bool $usePeeringServiceManagers
* @return object
*/
public function get($name, $options = array(), $usePeeringServiceManagers = true)
{
// Allow specifying a class name directly; registers as an invokable class
if (!$this->has($name) && $this->autoAddInvokableClass && class_exists($name)) {
$this->setInvokableClass($name, $name);
}
 
$this->creationOptions = $options;
$instance = parent::get($name, $usePeeringServiceManagers);
$this->creationOptions = null;
$this->validatePlugin($instance);
return $instance;
}
 
/**
* Register a service with the locator.
*
* Validates that the service object via validatePlugin() prior to
* attempting to register it.
*
* @param string $name
* @param mixed $service
* @param bool $shared
* @return AbstractPluginManager
* @throws Exception\InvalidServiceNameException
*/
public function setService($name, $service, $shared = true)
{
if ($service) {
$this->validatePlugin($service);
}
parent::setService($name, $service, $shared);
return $this;
}
 
/**
* Set the main service locator so factories can have access to it to pull deps
*
* @param ServiceLocatorInterface $serviceLocator
* @return AbstractPluginManager
*/
public function setServiceLocator(ServiceLocatorInterface $serviceLocator)
{
$this->serviceLocator = $serviceLocator;
return $this;
}
 
/**
* Get the main plugin manager. Useful for fetching dependencies from within factories.
*
* @return mixed
*/
public function getServiceLocator()
{
return $this->serviceLocator;
}
 
/**
* Attempt to create an instance via an invokable class
*
* Overrides parent implementation by passing $creationOptions to the
* constructor, if non-null.
*
* @param string $canonicalName
* @param string $requestedName
* @return null|\stdClass
* @throws Exception\ServiceNotCreatedException If resolved class does not exist
*/
protected function createFromInvokable($canonicalName, $requestedName)
{
$invokable = $this->invokableClasses[$canonicalName];
 
if (null === $this->creationOptions
|| (is_array($this->creationOptions) && empty($this->creationOptions))
) {
$instance = new $invokable();
} else {
$instance = new $invokable($this->creationOptions);
}
 
return $instance;
}
 
/**
* Attempt to create an instance via a factory class
*
* Overrides parent implementation by passing $creationOptions to the
* constructor, if non-null.
*
* @param string $canonicalName
* @param string $requestedName
* @return mixed
* @throws Exception\ServiceNotCreatedException If factory is not callable
*/
protected function createFromFactory($canonicalName, $requestedName)
{
$factory = $this->factories[$canonicalName];
if (is_string($factory) && class_exists($factory, true)) {
if (null === $this->creationOptions || (is_array($this->creationOptions) && empty($this->creationOptions))) {
$factory = new $factory();
} else {
$factory = new $factory($this->creationOptions);
}
 
$this->factories[$canonicalName] = $factory;
}
 
if ($factory instanceof FactoryInterface) {
$instance = $this->createServiceViaCallback(array($factory, 'createService'), $canonicalName, $requestedName);
} elseif (is_callable($factory)) {
$instance = $this->createServiceViaCallback($factory, $canonicalName, $requestedName);
} else {
throw new Exception\ServiceNotCreatedException(sprintf(
'While attempting to create %s%s an invalid factory was registered for this instance type.', $canonicalName, ($requestedName ? '(alias: ' . $requestedName . ')' : '')
));
}
 
return $instance;
}
}
/trunk/ZendFramework-2.1.2/library/Zend/ServiceManager/ServiceLocatorAwareInterface.php
0,0 → 1,27
<?php
/**
* Zend Framework (http://framework.zend.com/)
*
* @link http://github.com/zendframework/zf2 for the canonical source repository
* @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
 
namespace Zend\ServiceManager;
 
interface ServiceLocatorAwareInterface
{
/**
* Set service locator
*
* @param ServiceLocatorInterface $serviceLocator
*/
public function setServiceLocator(ServiceLocatorInterface $serviceLocator);
 
/**
* Get service locator
*
* @return ServiceLocatorInterface
*/
public function getServiceLocator();
}
/trunk/ZendFramework-2.1.2/library/Zend/ServiceManager/ServiceLocatorInterface.php
0,0 → 1,33
<?php
/**
* Zend Framework (http://framework.zend.com/)
*
* @link http://github.com/zendframework/zf2 for the canonical source repository
* @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
 
namespace Zend\ServiceManager;
 
/**
* Service locator interface
*/
interface ServiceLocatorInterface
{
/**
* Retrieve a registered instance
*
* @param string $name
* @throws Exception\ServiceNotFoundException
* @return object|array
*/
public function get($name);
 
/**
* Check for a registered instance
*
* @param string|array $name
* @return bool
*/
public function has($name);
}