<?php
/**
* СодеÑÐ¶Ð¸Ñ ÐºÐ»Ð°ÑÑ ComponentConfig
*
* @package energine
* @subpackage core
* @author dr.Pavka
* @copyright ColoCall 2007
* @version $Id: ComponentConfig.class.php,v 1.10 2007/12/17 14:16:03 pavka Exp $
*/
//require_once('core/framework/Object.class.php');
//require_once('core/framework/ConfigElement.class.php');
/**
* ÐлаÑÑ ÑеализÑÑÑий ÑабоÑÑ Ñ ÐºÐ¾Ð½ÑигÑÑаÑионнÑм Ñайлом компоненÑа
*
* @package energine
* @subpackage core
* @final
*/
final class ComponentConfig extends Object {
/**
* ÐÑÑÑ Ðº диÑекÑоÑии, ÑодеÑжаÑей полÑзоваÑелÑÑкие ÑÐ°Ð¹Ð»Ñ ÐºÐ¾Ð½ÑигÑÑаÑии Ð´Ð»Ñ ÐºÐ¾Ð¼Ð¿Ð¾Ð½ÐµÐ½Ñов
*/
const SITE_CONFIG_DIR = 'site/config/';
/**
* ÐÑÑÑ Ðº диÑекÑоÑии, ÑодеÑжаÑей ÑÐ°Ð¹Ð»Ñ ÐºÐ¾Ð½ÑигÑÑаÑии Ð´Ð»Ñ ÑÑандаÑÑнÑÑ
компоненÑов
* (вмеÑÑо %s бÑÐ´ÐµÑ Ð¿Ð¾Ð´ÑÑавлено Ð¸Ð¼Ñ Ð¼Ð¾Ð´ÑлÑ, ÑодеÑжаÑего компоненÑ)
*/
const CORE_CONFIG_DIR = 'core/modules/%s/config/';
/**
* ÐонÑигÑÑаÑионнÑй Ñайл
*
* @var SimpleXMLElement
* @access private
*/
private $config = false;
/**
* ÐÐ¼Ñ ÑекÑÑего меÑода
*
* @var ConfigElement
* @access private
*/
private $currentMethod = false;
/**
* ÐонÑÑÑÑкÑÐ¾Ñ ÐºÐ»Ð°ÑÑа
*
* @param string Ð¸Ð¼Ñ ÐºÐ¾Ð½ÑигÑÑаÑионного Ñайла
* @return void
*/
public function __construct($configFileName, $className, $moduleName) {
parent::__construct();
$configFileName = ($param = $this->getConfigPath($configFileName, $moduleName))?$param:$this->getConfigPath($className.'.component.xml', $moduleName);
if ($configFileName) {
try {
$this->config = simplexml_load_file($configFileName, 'ConfigElement');
}
catch (Exception $e) {
throw new SystemException('ERR_DEV_BAD_CONFIG_FILE', SystemException::ERR_DEVELOPER, $configFileName);
}
}
}
/**
* ÐозвÑаÑÐ°ÐµÑ Ð¿Ð¾Ð»Ð½Ñй пÑÑÑ Ðº конÑигÑÑаÑÐ¸Ð¾Ð½Ð½Ð¾Ð¼Ñ ÑайлÑ, или false еÑли Ñайл не ÑÑÑеÑÑвÑеÑ.
*
* @access private
* @param string $configFilename Ð¸Ð¼Ñ ÐºÐ¾Ð½ÑигÑÑаÑионного Ñайла
* @return mixed
*/
private function getConfigPath($configFilename, $moduleName) {
$file = false;
if ($configFilename && !file_exists($file = $configFilename))
//СмоÑÑим в диÑекÑоÑии Ñ Ð¿Ð¾Ð»ÑзоваÑелÑÑкими конÑигами
if (!file_exists($file = self::SITE_CONFIG_DIR.$configFilename)) {
if(!file_exists($file = sprintf(self::CORE_CONFIG_DIR, $moduleName).$configFilename)){
//еÑли Ñайла Ñ ÑказаннÑм именем Ð½ÐµÑ Ð½Ð¸ в папке Ñ Ð¿Ð¾Ð»ÑзоваÑелÑÑкими конÑигами, ни в папке модÑÐ»Ñ Ñ ÐºÐ¾Ð½Ñигами
//throw new SystemException('ERR_DEV_NO_CONFIG', SystemException::ERR_DEVELOPER, $configFilename);
$file = false;
}
}
return $file;
}
/**
* УÑÑÐ°Ð½Ð°Ð²Ð»Ð¸Ð²Ð°ÐµÑ Ð¸Ð¼Ñ ÑекÑÑего меÑода
*
* @param string Ð¸Ð¼Ñ Ð¼ÐµÑода
* @return void
* @access public
*/
public function setCurrentMethod($methodName) {
if(!($this->currentMethod = $this->getMethodConfig($methodName))){
throw new SystemException('ERR_NO_METHOD', SystemException::ERR_DEVELOPER);
}
}
/**
* ÐозвÑаÑÐ°ÐµÑ ÐºÐ¾Ð½ÑигÑÑаÑÐ¸Ñ ÑекÑÑего меÑода
*
* @return ConfigElement
* @access public
*/
public function getCurrentMethodConfig() {
return $this->currentMethod;
}
/**
* ÐозвÑаÑÐ°ÐµÑ Ñлаг Ñого, ÑÑо конÑиг пÑÑÑой
*
* @return boolean
* @access public
*/
public function isEmpty() {
return ($this->config)?false:true;
}
/**
* ÐозвÑаÑÐ°ÐµÑ Ð¸Ð¼Ñ Ð´ÐµÐ¹ÑÑÐ²Ð¸Ñ Ð¸Ð· конÑигÑÑаÑии, оÑновÑваÑÑÑ Ð½Ð° URI запÑоÑа.
*
* @access public
* @return array
*/
public function getActionByURI($path) {
$actionName = false;
$actionParams = array();
$path = '/'.$path;
$patterns = array();
foreach ($this->config->methods->method as $method) {
if (isset($method->uri_patterns->pattern)) {
foreach ($method->uri_patterns->pattern as $pattern) {
$patterns[$pattern->getValue()] = $method->getAttribute('name');
}
}
}
// ÑоÑÑиÑÑем ÑÐ°Ð±Ð»Ð¾Ð½Ñ URI Ð¾Ñ Ð±Ð¾Ð»ÐµÐµ ÑпеÑиÑиÑнÑÑ
к менее ÑпеÑиÑиÑнÑм
//uksort($patterns,array('ComponentConfig', 'uriPatternsCmp'));
/**
* @todo ÐÑжно замениÑÑ Ð½Ð° uksort когда бÑÐ´ÐµÑ Ð»Ð¸ÐºÐ²Ð¸Ð´Ð¸Ñован глÑк Ñ segfault
*/
$patterns = $this->sortByKeys($patterns, array('ComponentConfig','uriPatternsCmp'));
foreach ($patterns as $pattern => $methodName) {
$regexpr = str_replace(
array('/', '[int]', '[string]', '[any]\/', '[any]'),
array('\/', '(\d+)', '([^\/]+)', '(.*)', '(.*)'),
$pattern
);
if (preg_match("/^$regexpr$/", $path, $matches)) {
array_shift($matches);
if (strpos($pattern, '[any]') !== false) {
array_pop($matches);
}
$actionName = $methodName;
$actionParams = $matches;
//inspect($this->getName());
//$this->request->setPathOffset($this->request->getPathOffset()+sizeof($actionParams));
break;
}
}
if ($actionName == false) {
return false;
}
return array('name' => $actionName, 'params' => $actionParams);
}
/**
* ÐозвÑаÑÐ°ÐµÑ ÐºÐ¾Ð½ÑигÑÑаÑÐ¸Ñ Ð´Ð»Ñ Ñказанного меÑода.
*
* @access public
* @param string $methodName Ð¸Ð¼Ñ Ð¼ÐµÑода
* @return SimpleXMLElement
*/
public function getMethodConfig($methodName) {
$result = false;
if (!$this->isEmpty()) {
$methodConfig = $this->config->xpath(sprintf('/configuration/methods/method[@name=\'%s\']', $methodName));
if (!empty($methodConfig)) {
$result = $methodConfig[0];
}
}
return $result;
}
/**
* ÐозвÑаÑÐ°ÐµÑ Ñлаг, ÑказÑваÑÑий какой из пÑедложеннÑÑ
паÑÑеÑнов более ÑпеÑиÑиÑен
* ÐÑзÑваеÑÑÑ ÐºÐ°Ðº callback Ð´Ð»Ñ uksort
*
* @access private
* @param string $patternA
* @param string $patternB
* @return int
* @static
*/
static private function uriPatternsCmp($patternA, $patternB) {
$placeholders = array('/[int]/', '/[string]/', '/[any]/');
if (in_array($patternA, $placeholders)) {
$result = 1;
}
elseif (in_array($patternB, $placeholders)) {
$result = -1;
}
else {
$result = -(strlen($patternA) - strlen($patternB));
}
return $result;
}
/**
* Ðналог uksort
*
* @return array
* @access public
*/
public function sortByKeys($data, $callback) {
$result = array();
//ÐолÑÑаем иÑÑ
одное колиÑеÑÑво ÑлеменÑов в маÑÑиве
$arrayLength = sizeof($data);
//до ÑеÑ
Ð¿Ð¾Ñ Ð¿Ð¾ÐºÐ° ÑÐ°Ð·Ð¼ÐµÑ ÑезÑлÑÑиÑÑÑÑего маÑÑива менÑÑе ÑазмеÑа иÑÑ
одного маÑива
while (sizeof($result)<$arrayLength){
$currentElement = array(key($data) => current($data));
do {
if (($haveNext = next($data)) && (call_user_func($callback, key($currentElement), key($data))<0)){
$currentElement = array(key($data) => current($data));
}
}
while($haveNext);
$result = array_merge($currentElement, $result);
unset($data[key($currentElement)]);
reset($data);
}
return $result;
}
}