/** * Метод получает экземпляр класса и, если нужно, кеширует его. */ public static function getClassInstance($__DIR__, $subDir, $className, $parent, $caching = true) { if (!is_valid_file_name($className)) { return null; //--- } $className = get_file_name($className); if ($className == $parent) { //Абстрактный класс/интерфейс лежит рядом с классами реализации - пропустим его return null; } //Абсолютный путь к классу $classPath = file_path(array($__DIR__, $subDir), $className, PsConst::EXT_PHP); //Ключ кеширования $cacheKey = md5($classPath); $CACHE = $caching ? SimpleDataCache::inst(__CLASS__, __FUNCTION__) : null; if ($CACHE && $CACHE->has($cacheKey)) { return $CACHE->get($cacheKey); } $INST = null; if (is_file($classPath)) { //Подключим данный класс require_once $classPath; //Проверим, существует ли класс $rc = PsUtil::newReflectionClass($className, false); $INST = $rc && $rc->isSubclassOf($parent) ? $rc->newInstance() : null; } if ($CACHE && $INST) { $CACHE->set($cacheKey, $INST); } return $INST; }
protected function __construct($class, $idxCol, array $constructorParams = null, $fetchType = self::FETCH_TYPE_ARRAY, callable $fetcher = null) { parent::__construct($idxCol, false); $this->RC = PsUtil::newReflectionClass($class); $this->idxCol = $idxCol; $this->constructorParams = $constructorParams; $this->fetchType = $fetchType; $this->fetcher = $fetcher; $this->useFetcher = is_callable($fetcher); }
/** * Метод создаёт новый фолдинг */ public function makeNewFolding(ArrayAdapter $adapter) { $ifaces = $adapter->arr('ifaces'); $rtypes = $adapter->arr('rtypes'); $type = lowertrim($adapter->str('FoldingType')); $subtype = lowertrim($adapter->str('FoldingSubType')); $group = $adapter->str('FoldingGroup'); $classPrefix = $adapter->str('FoldingClassPrefix'); check_condition($type, 'Не передан тип фолдинга'); check_condition($group, 'Не передана группа для фолдинга'); check_condition($classPrefix, 'Не передан префикс для классов фолдинга'); //TODO - определять директорию для воздания менеджера фолдингов. die('Folding dir is not deffined.'); $classesDi = DirItem::inst(array('sdk/kit', 'folded'), $group); check_condition(!$classesDi->isDir(), "Директория {$classesDi} уже существует"); check_condition(!$classesDi->isFile(), "Элемент {$classesDi} не может быть файлом"); $rtypes = array_intersect(array_keys(PsUtil::getClassConsts('FoldedResources', 'RTYPE_')), $rtypes); $rtypesArr = trim(implode(', self::', $rtypes)); $rtypesArr = $rtypesArr ? "self::{$rtypesArr}" : ''; $hasPhp = in_array('RTYPE_PHP', $rtypes); $classesDm = DirManager::inst($classesDi->getRelPath())->makePath(); $resourcesPatternDmTo = DirManager::resources(array('folded', $group, FoldedResources::PATTERN_NAME)); check_condition(!$resourcesPatternDmTo->isDir(), "Целевая директория {$resourcesPatternDmTo} существует"); $resourcesPatternDmFrom = DirManager::resources(array('folded', FoldedResources::PATTERN_NAME)); check_condition($resourcesPatternDmFrom->isDir(), "Некорректна директория-источник {$resourcesPatternDmFrom}"); $interfaces = array(); foreach ($this->getFoldedInterfaces($ifaces) as $name => $ifaceClass) { $ctt = $ifaceClass->getClassBody(); if ($ctt) { $interfaces[] = "/****************\n\t * {$name}\n\t ****************/\n" . $ctt; } } $smParams = $adapter->getData(); $smParams['rtypes'] = $rtypesArr; $smParams['funique'] = FoldedResources::unique($type, $subtype); $smParams['BaseClass'] = 'Base' . $classPrefix; $smParams['ManagerClass'] = $classPrefix . 'Manager'; $smParams['ResourcesClass'] = $classPrefix . 'Resources'; $smParams['implements'] = $ifaces ? 'implements ' . implode(', ', $ifaces) . ' ' : ''; $smParams['interfaces'] = $interfaces ? implode("\n\n\t", $interfaces) : ''; try { //КЛАССЫ //Resources $tpl = PSSmarty::template(DirItem::inst(array(__DIR__, 'tpls'), 'resources.tpl'), $smParams); $di = $classesDm->getDirItem(null, $smParams['ResourcesClass'], 'php'); $di->writeToFile(trim($tpl->fetch()), true); //Manager $tpl = PSSmarty::template(DirItem::inst(array(__DIR__, 'tpls'), 'manager.tpl'), $smParams); $di = $classesDm->getDirItem(null, $smParams['ManagerClass'], 'php'); $di->writeToFile(trim($tpl->fetch()), true); if ($hasPhp) { //BaseClass $tpl = PSSmarty::template(DirItem::inst(array(__DIR__, 'tpls'), 'baseclass.tpl'), $smParams); $di = $classesDm->getDirItem(null, $smParams['BaseClass'], 'php'); $di->writeToFile(trim($tpl->fetch()), true); } //ШАБЛОН ДЛЯ СУЩНОСТЕЙ $resourcesPatternDmTo->makePath(); foreach ($rtypes as $rtype) { $ext = FoldedResources::resourceTypeToExt(PsUtil::newReflectionClass('FoldedResources')->getConstant($rtype)); $diTo = $resourcesPatternDmTo->getDirItem(null, FoldedResources::PATTERN_NAME, $ext); $diFrom = $resourcesPatternDmFrom->getDirItem(null, FoldedResources::PATTERN_NAME, $ext); if ($ext == PsConst::EXT_PHP) { $diTo->writeToFile(str_replace('eclassnamebase', $smParams['BaseClass'], $diFrom->getFileContents())); continue; } $diFrom->copyTo($diTo); } } catch (Exception $ex) { $classesDm->clearDir(null, true); $resourcesPatternDmTo->clearDir(null, true); throw $ex; } }
/** * @covers PsUtil::newReflectionClass */ public function testNewReflectionClass() { PsUtil::assertInstanceOf(PsUtil::newReflectionClass(ClassA::get__CLASS__()), 'ReflectionClass'); PsUtil::assertInstanceOf(PsUtil::newReflectionClass(new ClassA()), 'ReflectionClass'); try { PsUtil::newReflectionClass(self::NOT_ALLOWED_STR); $this->fail('ReflectionException is expected'); } catch (ReflectionException $ex) { //OK } }
function executeProcess(array $argv) { $CLASS_PATTERN = file_get_contents(file_path(__DIR__, 'class.txt')); $METHOD_PATTERN = file_get_contents(file_path(__DIR__, 'method.txt')); /* * Название тестового файла. * Для проверки мы сначала удалим класс для него, если он был, потом проверим, что за класс был сгенерирован. */ $TEST_MESSAGES_FILE = 'ExampleSdkProcessMessages'; //Убедимся, что тестовый .msgs существует и удалим тестовый .php файл $TEST_PHP_DI = DirItem::inst(__DIR__ . '/classes', $TEST_MESSAGES_FILE, PsConst::EXT_PHP)->remove(); $TEST_MSGS_DI = DirItem::inst(__DIR__ . '/classes', $TEST_MESSAGES_FILE, PsConst::EXT_MSGS); check_condition($TEST_MSGS_DI->isFile(), "File {$TEST_MSGS_DI->getAbsPath()} must exists"); dolog('Loading all files, ended with Messages.msgs'); //TODO - после нужно получать эту информацию из какого-нибудь места $exceptDirs[] = DirManager::autogen()->relDirPath(); $exceptDirs[] = DirManager::resources()->relDirPath(); $exceptDirs[] = DirManager::stuff()->relDirPath(); //$exceptDirs = array(); $items = DirManager::inst()->getDirContentFull(null, function (DirItem $di) { dolog($di->getAbsPath()); return $di->isFile() && ends_with($di->getName(), 'Messages.msgs'); }, $exceptDirs); dolog('Message files for processing: {}', count($items)); //Проверим, что был выбран тестовый файл check_condition(in_array($TEST_MSGS_DI, $items, true), "Test file [{$TEST_MESSAGES_FILE}] is not included"); //Удалим его из массива... array_remove_value($items, $TEST_MSGS_DI, true); //И поместим наверх, чтобы он был обработан первым array_unshift($items, $TEST_MSGS_DI); /* @var $msgsDi DirItem */ foreach ($items as $msgsDi) { dolog('PROCESSING [{}]', $msgsDi->getAbsPath()); //Сбросим методы $METHODS = array(); //Извлечём название класса $CLASS = $msgsDi->getNameNoExt(); //DirItem файла с сообщениями php $classDi = DirItem::inst($msgsDi->getDirname(), $CLASS, PsConst::EXT_PHP); //Получаем сообщения из файла .msgs $messages = $msgsDi->getFileAsProps(); foreach ($messages as $MSG_KEY => $MGG_VALUE) { dolog(' >> {}={}', $MSG_KEY, $MGG_VALUE); //Получим список всех параметров из макросов ({0}, {1}, {2} и т.д.) preg_match_all("/\\{(.+?)\\}/", $MGG_VALUE, $args); $args = array_values(array_unique($args[1])); sort($args, SORT_NUMERIC); $ARGS = array(); for ($index = 0; $index < count($args); $index++) { $arg = $args[$index]; $lineDescr = PsStrings::replaceWithBraced('[{}] in line [{}={}]', $msgsDi->getRelPath(), $MSG_KEY, $MGG_VALUE); check_condition(is_inumeric($arg), "Invalid argument [{$arg}] for {$lineDescr}"); check_condition($index == $args[$index], "Missing index [{$index}] for {$lineDescr}"); $ARGS[] = '$p' . $index; } $ARGS = join(', ', $ARGS); //Добавляем метод dolog(" A: {}::{} ({})", $CLASS, $MSG_KEY, $ARGS); $PARAMS['SUPPORT_CLASS'] = PsMsgs::getClass(); $PARAMS['MESSAGE'] = $MGG_VALUE; $PARAMS['FUNCTION'] = $MSG_KEY; $PARAMS['ARGS'] = $ARGS; $METHODS[] = PsStrings::replaceMapBracedKeys($METHOD_PATTERN, $PARAMS); } dolog('Made methods: ({})', count($METHODS)); if ($METHODS) { $PARAMS['FILE'] = $msgsDi->getAbsPath(); $PARAMS['CLASS'] = $CLASS; $PARAMS['DATE'] = date(DF_PS); $PARAMS['METHODS'] = "\n" . join("\n\n", $METHODS) . "\n"; $CLASS_PHP = PsStrings::replaceMapBracedKeys($CLASS_PATTERN, $PARAMS); $classDi->putToFile($CLASS_PHP); } /* * Если обрабатываем тестовый файл - проверим его */ //TEST CLASS VALIDATION START >>> if ($msgsDi->equals($TEST_MSGS_DI)) { dolog(''); dolog('Validating test class {}', $TEST_MESSAGES_FILE); //Проверим, что .php был сгенерирован check_condition($TEST_PHP_DI->isFile(), "File {$TEST_PHP_DI->getAbsPath()} was not created!"); //Проверим, что для каждого сообщения был создан метод $methods = PsUtil::newReflectionClass($TEST_MESSAGES_FILE)->getMethods(); $messages = $TEST_MSGS_DI->getFileAsProps(); check_condition(count($methods) == count($messages), 'Methods count missmatch, check ' . $TEST_PHP_DI->getAbsPath()); /* @var $method ReflectionMethod */ foreach ($methods as $method) { check_condition(array_key_exists($method->getName(), $messages), "No method {$TEST_MESSAGES_FILE}::" . $method->getName()); } //Проверим, что возвращают методы тестового сгенерированного класса function doTest($className, $methodName, array $params, $expected) { $method = "{$className}::{$methodName}"; $actual = call_user_func_array($method, $params); dolog("{}({})='{}', Expected='{}'", $method, join(', ', $params), $actual, $expected); check_condition($actual == $expected, "{$actual} != {$expected}"); } doTest($TEST_MESSAGES_FILE, 'message1', array(), 'Message 1'); doTest($TEST_MESSAGES_FILE, 'message2', array('a', 'b', 'c'), 'Parametred a,c,b'); dolog('Test class is valid!'); } //TEST CLASS VALIDATION END <<< } //# DirItems validation end }
public function __construct($class) { $this->rc = PsUtil::newReflectionClass($class); $this->di = DirItem::inst(Autoload::inst()->getClassPath($this->rc->name)); }