protected function doBuild(\PageContext $ctxt, \PageBuilderContext $builderCtxt, \RequestArrayAdapter $requestParams, \ArrayAdapter $buildParams) { //1. ЗАГОЛОВОК $builderCtxt->setTitle($this->authed ? 'Админка | ' . $this->adminPage->title() : 'xxx'); //2. JAVASCRIPT $builderCtxt->setJsParams($this->authed ? $this->adminPage->getJsParams() : null); //3. SMARTY RESOURCES if ($this->authed) { $builderCtxt->setSmartyParams4Resources($this->adminPage->getSmartyParams4Resources()); $builderCtxt->setSmartyParam4Resources('IDENT', $this->adminPage->getPageIdent()); $builderCtxt->setSmartyParam4Resources('TIMELINE_ENABE', true); } $smartyParams['authed'] = $this->authed; $smartyParams['isBasic'] = PsSecurity::isBasic(); if (!$this->authed) { return $smartyParams; } //Запустим неограниченный по времени режим - мало ли, что мы там будем делать:) PsUtil::startUnlimitedMode(); //Отменим нормализацию страницы PsDefines::setNormalizePage(false); //Получаем содержимое админской страницы $content = ContentHelper::getContent($this->adminPage); //Добавляем к ней ресурсы $content = APagesResources::inst()->getResourcesLinks($this->adminPage->getPageIdent(), $content); $smartyParams['page'] = $this->adminPage; $smartyParams['content'] = $content; $smartyParams['pagesLayout'] = AdminPagesManager::getInstance()->getLayout(); return $smartyParams; }
public function buildContent() { //Можно и не устанавливать, т.к. к popup окнам мы не подключаем спрайты PsDefines::setReplaceFormulesWithSprites(false); $params = array('prinvView' => $this->postCP->getPostPrintVariant()); return $this->getFoldedEntity()->fetchTpl($params); }
/** @return ToDoFile */ public static function inst() { if (!isset(self::$todo)) { PsDefines::assertProductionOff(__CLASS__); self::$todo = new ToDoFile(); } return self::$todo; }
/** * Управление постом */ function smarty_modifier_post_header_controls($post) { $post = $post instanceof PostContentProvider ? $post->getPost() : $post; $pp = Handlers::getInstance()->getPostsProcessorByPostType($post->getPostType()); /* * Собираем кнопки управления */ $buttons = array(); $hintClasses = 'hint--top hint--info hint--rounded'; //Печать поста $attrs = array(); $title = 'Версия для печати'; $attrs['href'] = '#print'; $attrs['title'] = $title; $attrs['data'] = array('hint' => $title); $attrs['class'] = $hintClasses; $content = CssSpritesManager::getDirSprite(CssSpritesManager::DIR_ICO, 'print', true); $buttons[] = PsHtml::a($attrs, $content); //Оригинальный вид поста if (PsDefines::isReplaceFormulesWithImages()) { $attrs = array(); $title = 'Просмотр ' . ps_strtolower($pp->postTitle(null, 2)) . ' без замены формул на картинки'; $attrs['href'] = '#originalView'; $attrs['title'] = $title; $attrs['data'] = array('hint' => $title); $attrs['class'] = $hintClasses; $content = CssSpritesManager::getDirSprite(CssSpritesManager::DIR_ICO, 'formula', true); $buttons[] = PsHtml::a($attrs, $content); } //Быстрый просмотр постов (перелистывание) $attrs = array(); $title = 'Предыдущий/следующий ' . ps_strtolower($pp->postTitle(null, 1)); $attrs['href'] = '#prevNextView'; $attrs['title'] = $title; $attrs['data'] = array('hint' => $title); $attrs['class'] = $hintClasses; $content = CssSpritesManager::getDirSprite(CssSpritesManager::DIR_ICO, 'prev_next', true); $buttons[] = PsHtml::a($attrs, $content); //Предыдущий пост $prevPost = $pp->getPrevPost($post->getId(), false); if ($prevPost) { $attrs = array(); $attrs['data']['hint'] = $pp->postTitle($prevPost); $attrs['class'] = $hintClasses; $content = CssSpritesManager::getDirSprite(CssSpritesManager::DIR_ICO, 'prev_s', true); $buttons[] = $pp->postHref($prevPost, $content, null, $attrs); } //Следующий пост $nextPost = $pp->getNextPost($post->getId(), false); if ($nextPost) { $attrs = array(); $attrs['data']['hint'] = $pp->postTitle($nextPost); $attrs['class'] = $hintClasses; $content = CssSpritesManager::getDirSprite(CssSpritesManager::DIR_ICO, 'next_s', true); $buttons[] = $pp->postHref($nextPost, $content, null, $attrs); } return PsHtml::div(array('class' => PsConstJs::POST_HEAD_CONTROLS), implode(' ', $buttons)); }
private function __construct() { $this->CAHCE = new SimpleDataCache(); $this->enabled = PsDefines::isProfilingEnabled(); $this->dirManager = DirManager::autogen('profilers'); if ($this->enabled) { PsShotdownSdk::registerDestructable($this, PsShotdownSdk::PsProfiler); } }
protected function processImpl(PostArrayAdapter $adapter, $button) { PsDefines::assertProductionOff(__CLASS__); $text = $adapter->str('text'); if (!$text) { return array('text', 'required'); } $mtime = $adapter->int('mtime'); ToDoFile::inst()->save($text, $mtime); return new AjaxSuccess(); }
public function buildContent() { $user = PsUser::inst(); FORM_RegEditForm::getInstance()->setParam(FORM_PARAM_REG_NAME, $user->getName()); FORM_RegEditForm::getInstance()->setParam(FORM_PARAM_REG_SEX, $user->getSex()); FORM_RegEditForm::getInstance()->setParam(FORM_PARAM_REG_ABOUT, $user->getAboutSrc()); FORM_RegEditForm::getInstance()->setParam(FORM_PARAM_REG_CONTACTS, $user->getContactsSrc()); FORM_RegEditForm::getInstance()->setParam(FORM_PARAM_REG_MSG, $user->getMsgSrc()); PsDefines::setReplaceFormulesWithImages(false); echo $this->getFoldedEntity()->fetchTpl(array('user' => $user, 'avatars' => $user->getAvatarsList(true))); }
public static function testProductivity($callback, $count = 1000) { PsDefines::assertProductionOff(__CLASS__); check_condition(is_callable($callback), 'Передан некорректный callback для тестирования'); $s = Secundomer::inst(); for ($index = 0; $index < $count; $index++) { $s->start(); call_user_func($callback); $s->stop(); } return $s; }
/** * Метод регистрации страницы * * WebPages::register('xxx.php', 'Консоль администратора', PAGE_ADMIN, self::getIdent(), AuthManager::AUTH_TYPE_NO_MATTER, PAGE_ADMIN); * * @param string $path - путь к скрипту, например 'xxx.php' * @param string $name - название страницы, например 'Консоль администратора' * @param int $code - код страницы PAGE_ADMIN * @param int $builderIdent - идентификатор построителя страниц, например 'PB_admin::getIdent()' * @param int $authType - тип авторизации, необходимый для доступа к странице, например 'AuthManager::AUTH_TYPE_NO_MATTER' * @param int $pageCodeNoAccess - страница, на которую нужно перейти при отсутствии доступа, например 'BASE_PAGE_INDEX' * @param bool $allovedInProduction - признак, доступна ли страница в ProductionMode */ protected final function register($path, $name, $code, $builderIdent = null, $authType = AuthManager::AUTH_TYPE_NO_MATTER, $pageCodeNoAccess = null, $allovedInProduction = true) { if (!$allovedInProduction && PsDefines::isProduction()) { return; //---- } $path = PsCheck::notEmptyString($path); $name = PsCheck::notEmptyString($name); $code = PsCheck::int($code); if (array_key_exists($code, $this->PAGES)) { PsUtil::raise('\'{}\' is already registered. Cannot register WebPage with same code \'{}\'.', $this->PAGES[$code], $code); } else { $this->PAGES[$code] = new WebPage($path, $name, $code, $authType, $pageCodeNoAccess, $builderIdent); $this->LOGGER->info('+{}. {}', pad_left(count($this->PAGES), 2, ' '), $this->PAGES[$code]); } }
/** * Список методов, доступных для вызова */ public static function getMethodsList() { if (!AuthManager::isAuthorizedAsAdmin() || PsDefines::isProduction()) { return array(); } if (!is_array(self::$METHODS)) { self::$METHODS = array(); $methodNames = PsUtil::getClassMethods(TestManager::inst(), true, false, true, true); foreach ($methodNames as $name) { $method = new ReflectionMethod(TestManager::inst(), $name); $params['name'] = $name; $params['descr'] = implode("\n", StringUtils::parseMultiLineComments($method->getDocComment())); $params['params'] = array(); /* @var $param ReflectionParameter */ foreach ($method->getParameters() as $param) { $params['params'][] = array('name' => $param->getName(), 'dflt' => $param->isDefaultValueAvailable() ? var_export($param->getDefaultValue(), true) : null); } self::$METHODS[$name] = $params; } } return self::$METHODS; }
/** * Метод выполняет фактическую замену TEX тега на его представление в виде картинки или спрайта. * * @param str $original \[v_{\text{cp}}=\frac{\Delta S}{\Delta t}\] * @param str $formula v_{\text{cp}}=\frac{\Delta S}{\Delta t} * @param str $type block or inline */ public function _replaceInTextImpl($original, $formula, $isBlock) { $type = $isBlock ? 'block' : 'inline'; $replace = ''; if ($formula) { /* * Проверяем, разрешена ли замена формул на спрайты и есть ли сейчас контекст. * Если всё выполнено, то это вовсе не означает, что необходимый спрайт подключен и есть * спрайт для данной формулы. */ if (PsDefines::isReplaceFormulesWithSprites() && FoldedContextWatcher::getInstance()->getSpritableContext()) { $replace = CssSpritesManager::getFormulaSprite(FoldedContextWatcher::getInstance()->getSpritableContext()->getSpritable(), $formula, array('TeX', $type)); } /* * Если спрайта не нашлось, то заменяем на картинку. */ if (!$replace) { $imgDi = $this->getImgDi($formula); $imgPath = $imgDi ? $imgDi->getRelPath() : null; if ($imgPath) { $replace = PsHtml::img(array('src' => $imgPath, 'class' => "TeX {$type}", 'alt' => '')); } else { $replace = $original; } } } /* * Логирование */ if ($this->LOGGER->isEnabled()) { $this->LOGGER->info(++$this->replaced . ". Replacing {$type} TeX"); $this->LOGGER->info("FULL: {$original}"); $this->LOGGER->info("CONTENT: {$formula}"); $this->LOGGER->info("SAVED: {$formula}"); $this->LOGGER->info("REPLACED: {$replace}"); $this->LOGGER->info("\n"); } return $replace; }
public function buildContent() { PsDefines::setReplaceFormulesWithImages(false); return $this->getFoldedEntity()->fetchTpl($this->params); }
private function validateGroup($group) { /** * Если зависимости от сущностей БД ещё не были проверены, * то запустим эту проверку и больше о валидности кешей, * зависящих от сущностей БД, можно не заботиться. * * Эту проверку нужно выполнять в любом случае, так как её запуск может * показать изменение сущностей фолдинга или самих фолдингов, работающих * с изменёнными таблицами/представлениями. */ DbChangeListener::check(); $this->TREE->setTypeValidated(self::CHILD_DBENTITY, 'Выполнена проверка изменений в БД'); /** * Если группа не валидируема - пропускаем. * Она могла стать валидируемой после проверки по базе. */ if (!$this->TREE->isGroupValidatable($group)) { return; //--- } $this->LOGGER->info(" > Валидируем группу кешей [{$group}]"); /* * Проверим, можно ли выполнить процесс и, если можно, выполним. * После выполнения о свежести логов можно будет не заботиться. */ $this->LOGGER->info(" ! Пытаемся выполнить внейший процесс"); if (ExternalProcess::inst()->executeFromClient()) { $this->TREE->setTypeValidated(self::CHILD_FOLDING, 'Выполнен внешний процесс от имени клиента'); return; //--- } /* * Если мы в продакшене - прекращаем дальнейшие проверки. * * Вообще говоря без полной проверки всех фолдингов, от которых зависит данная группа кеша, * считать группу провалидированной нельзя. Но если где-либо будет обнаружен изменённый * фолдинг, то это приведёт к вызову метода {@link #onFoldingChanged} и кеш всёже будет сброшен. */ $this->LOGGER->info(" ! Проверяем режим продакшн"); if (PsDefines::isProduction()) { $this->TREE->setTypeValidated(self::CHILD_FOLDING, 'Включён режим продакшн'); return; //--- } $foldings = $this->TREE->getChildsForValidate(self::CHILD_FOLDING, $group); $this->LOGGER->info(" ! Валидируем фолдинги"); foreach ($foldings as $fUnique) { $this->LOGGER->info(" ! Проверяем на изменение фолдинг [{$fUnique}]"); if (Handlers::getInstance()->getFoldingByUnique($fUnique)->checkFirstEntityChanged()) { //Выполним действия по оповещению об изменении $this->onFoldingChanged($fUnique); //Не будем проверять вообще все фолдинги, от которых мы зависим - это задача {@see ExternalProcess}. return; //--- } else { $this->TREE->onChildValidated(self::CHILD_FOLDING, $fUnique); } } $this->LOGGER->info(" < Группа кешей [{$group}] прошла валидацию и не была изменена"); }
public function get($default = null) { return PsDefines::get($this->name(), $this->type, $default); }
public final function buildPage(array $buildParams = array()) { header('Content-Type: text/html; charset=utf-8'); ExceptionHandler::registerPretty(); //Запросим адаптер, чтобы сбросить параметры в сессии UnloadArrayAdapter::inst(); // Подготовим необходимые классы $CTXT = PageContext::inst(); $PAGE = $CTXT->getPage(); $BUILDER = $this->getPageBuilder($CTXT->getPageType()); $PROFILER = $BUILDER->getProfiler(); $RESOURCES = null; $TITLE = null; $CONTENT = null; if ($PROFILER) { // Начинаем профилирование $PROFILER->start($CTXT->getRequestUrl()); } try { //Подготовим объекты, которые будем передавать построителю страницы $RQ_PARAMS = RequestArrayAdapter::inst(); $BUILD_PARAMS = ArrayAdapter::inst($buildParams); $BUILDER_CTXT = PageBuilderContext::getInstance(); //Стартуем контекст $BUILDER_CTXT->setContextWithFoldedEntity($BUILDER->getFoldedEntity()); //Вызываем предварительную обработку страницы $BUILDER->preProcessPage($CTXT, $RQ_PARAMS, $BUILD_PARAMS); // Оповещаем слушателей /* @var $listener PagePreloadListener */ foreach (Handlers::getInstance()->getPagePreloadListeners() as $listener) { $listener->onPagePreload($PAGE); } //Билдер строит страницу, наполняя контекст. Нам от него нужны будут только данные из контекста $PARAMS = $BUILDER->buildPage($CTXT, $BUILDER_CTXT, $RQ_PARAMS, $BUILD_PARAMS); //Остановим контекст $BUILDER_CTXT->dropContext(); //Загрузим параметры $TITLE = $PARAMS->getTitle(); $CONTENT = $PARAMS->getContent(); // Подключаем все необходимые ресурсы $RESOURCES = $this->buildResources($PARAMS, $CTXT); //Проведём финализацию страницы, чтобы различные менеджеры могли добавить к ней свои данные $CONTENT = PageFinaliserFoldings::finalize($this->LOGGER, $CONTENT); } catch (Exception $ex) { $TITLE = trim($TITLE) . ' (произошла ошибка)'; $CONTENT = ExceptionHandler::getHtml($ex); } //Непосредственное построение страницы. $PAGE_PARAMS['RESOURCES'] = $RESOURCES; $PAGE_PARAMS['TITLE'] = $TITLE; $PAGE_PARAMS['CONTENT'] = $CONTENT; //ПОДСТАВЛЯЕМ ВСЕ ПАРАМЕТРЫ СТРАНИЦЫ В БАЗОВЫЙ ШАБЛОН $PAGE_CONTENT = PSSmarty::template('page/page_pattern.tpl', $PAGE_PARAMS)->fetch(); $this->LOGGER->infoBox('HTML PAGE', $PAGE_CONTENT); //ФИНАЛИЗАЦИЯ СТРАНИЦЫ - ВЫЧИСЛИМ РЕСУРСЫ, КОТОРЫЕ НУЖНО ОТКЛЮЧИТЬ $PAGE_CONTENT = PageFinaliserRegExp::finalize($this->LOGGER, $PAGE_CONTENT); //НОРМАЛИЗАЦИЯ СТРАНИЦЫ - УДАЛИМ ДВОЙНЫЕ ПРОБЕЛЫ И ПЕРЕНОСЫ if (PsDefines::isNormalizePage()) { $PAGE_CONTENT = PageNormalizer::finalize($this->LOGGER, $PAGE_CONTENT); } //ВСТАВИМ ASIS ПАРАМЕТРЫ, ТАК КАК БОЛЕЕ SMARTY ФИЛЬТРЫ ВЫЗЫВАТЬСЯ НЕ БУДУТ $PAGE_CONTENT = $this->replaceAsIsValues($PAGE_CONTENT); $this->LOGGER->infoBox('PAGE WITH ASIS REPLACED', $PAGE_CONTENT); //BOOOM :) echo $PAGE_CONTENT; if ($PROFILER) { // Заканчиваем профилирование $PROFILER->stop(); PageOpenWatcher::updateUserPageWatch($CTXT->getRequestUrl()); } }
/** * Признак - авторизованы мы под админом или же работаем в девелопменте. * Часто в этом сочитании можно дать возможность выполнять дополнительные действия. */ public static function DEVMODE_OR_ADMIN() { return !PsDefines::isProduction() || AuthManager::isAuthorizedAsAdmin(); }
public function doProcess(ArrayAdapter $params) { PsDefines::assertProductionOff(__CLASS__); //Отключим нормализацию страниц, так как мы редактируем HTML PsDefines::setNormalizePage(false); }
/** * Метод выполняет дамп таблицы */ public static function dumpTable($idColumn, $table, array $where = array(), $order = null) { //Стартуем секундомер $secundomer = Secundomer::startedInst("Снятие дампа {$table}"); //Отключим ограничение по времени PsUtil::startUnlimitedMode(); //Получим экземпляр логгера $LOGGER = PsLogger::inst(__CLASS__); //Текущий пользователь $userId = AuthManager::getUserIdOrNull(); //Для логов, запросов и все остального $table = strtoupper(PsCheck::tableName($table)); //Макс кол-во записей $limit = PsDefines::getTableDumpPortion(); //Проверим наличие id $idColumn = PsCheck::tableColName($idColumn); $LOGGER->info('Dumping table {}. Id column: {}, limit: {}. User id: {}.', $table, $idColumn, $limit, $userId); //Получаем лок (без ожидания) $lockName = "DUMP table {$table}"; $locked = PsLock::lock($lockName, false); $LOGGER->info('Lock name: {}, locked ? {}.', $lockName, var_export($locked, true)); if (!$locked) { return false; //Не удалось получить лок } $zipDi = false; try { //ЗПРОСЫ: //1. Запрос на извлечение колва записей, подлежащих дампированию $queryCnt = Query::select("count({$idColumn}) as cnt", $table, $where); //2. Запрос на извлечение данных, подлежащих дампированию $queryDump = Query::select('*', $table, $where, null, $order, $limit); //3. Запрос на извлечение кодов дампируемых записей $selectIds = Query::select($idColumn, $table, $where, null, $order, $limit); //4. Запрос на удаление дампированных данных $queryDel = Query::delete($table, Query::plainParam("{$idColumn} in (select {$idColumn} from (" . $selectIds->build($delParams) . ') t )', $delParams)); //Выполним запрос для получения кол-ва записей, подлежащих дампу $cnt = PsCheck::int(array_get_value('cnt', PSDB::getRec($queryCnt, null, true))); $LOGGER->info('Dump recs count allowed: {}.', $cnt); if ($cnt < $limit) { $LOGGER->info('SKIP dumping table, count allowed ({}) < limit ({})...', $cnt, $limit); $LOGGER->info("Query for extract dump records count: {$queryCnt}"); PsLock::unlock($lockName); return false; } //Время дампа $date = PsUtil::fileUniqueTime(false); $time = time(); //Название файлов $zipName = $date . ' ' . $table; //Элемент, указывающий на zip архив $zipDi = DirManager::stuff(null, array(self::DUMPS_TABLE, $table))->getDirItem(null, $zipName, PsConst::EXT_ZIP); $LOGGER->info('Dump to: [{}].', $zipDi->getAbsPath()); if ($zipDi->isFile()) { $LOGGER->info('Dump file exists, skip dumping table...'); PsLock::unlock($lockName); return false; } //Комментарий к таблице $commentToken[] = "Date: {$date}"; $commentToken[] = "Time: {$time}"; $commentToken[] = "Table: {$table}"; $commentToken[] = "Manager: {$userId}"; $commentToken[] = "Recs dumped: {$limit}"; $commentToken[] = "Total allowed: {$cnt}"; $commentToken[] = "Query dump cnt: {$queryCnt}"; $commentToken[] = "Query dump data: {$queryDump}"; $commentToken[] = "Query dump ids: {$selectIds}"; $commentToken[] = "Query del dumped: {$queryDel}"; $comment = implode("\n", $commentToken); //Начинаем zip и сохраняем в него данные $zip = $zipDi->startZip(); $zip->addFromString($zipName, serialize(PSDB::getArray($queryDump))); $zip->setArchiveComment($comment); $zip->close(); $LOGGER->info('Data successfully dumped, zip comment:'); $LOGGER->info("[\n{$comment}\n]"); //Удалим те записи, дамп которых был снят $LOGGER->info('Clearing dumped table records...'); $affected = PSDB::update($queryDel); $LOGGER->info('Rows deleted: {}.', $affected); $LOGGER->info('Dumping is SUCCESSFULLY finished. Total time: {} sec.', $secundomer->stop()->getAverage()); } catch (Exception $ex) { PsLock::unlock($lockName); ExceptionHandler::dumpError($ex); $LOGGER->info('Error occured: {}', $ex->getMessage()); throw $ex; } return $zipDi; }
public function buildContent() { PsDefines::setReplaceFormulesWithImages(false); $navigation = AdminPageNavigation::inst(); /* * Инициализируем необходимые менеджеры */ $TE = TableExporter::inst(); $RQ = GetArrayAdapter::inst(); $FORM = FORM_RecEditForm::getInstance(); $TABLES = PsTable::configured(); /* * Инициализируем параметры, которые нужно будет передать smarty */ $PARAMS['mode'] = null; $PARAMS['table'] = null; $PARAMS['error'] = null; $PARAMS['errors'] = PsDbIniHelper::validateAll(); /* * Обработаем форму */ try { if ($FORM->isValid4Process()) { $this->processForm($FORM->getData()); } else { if ($FORM->isErrorOccurred()) { $PARAMS['error'] = PsHtml::divErr($FORM->getError()); } } } catch (Exception $e) { $PARAMS['error'] = ExceptionHandler::getHtml($e); } /* * Обработаем параметры и определим режим работы */ $MODE = $RQ->str('mode', self::MODE_TABLES_LIST); /** @var PsTable */ $TABLE = null; // Таблица $ROW = null; // Редактируемая строка switch ($MODE) { case self::MODE_ROW_ADD: //Если передан фолдинг, то подставим в форму создания его параметры $folding = Handlers::getInstance()->getFolding($RQ->str('ftype'), $RQ->str('fsubtype'), false); $fident = $RQ->str('fident'); if ($folding && $folding->getTableName() && $fident) { $TABLE = $TE->getTable($folding); $ROW = $folding->getDbRec4Entity($fident); break; } $TABLE = PsTable::inst($RQ->str('table')); /* * Нам не удалось определить внешний вид создаваемой строки, * но если у данной таблицы один фолдинг - возмём вид строки у него. */ $folding = $TABLE->getSingleFolding(); $ROW = $folding ? $folding->getDbRec4Entity($folding->getNextEntityIdent()) : null; break; case self::MODE_TABLE_ROWS: case self::MODE_TABLE_SQL: case self::MODE_TABLE_ARR: case self::MODE_ROW_EDIT: case self::MODE_ROW_DELETE: $TABLE = PsTable::inst($RQ->str('table')); switch ($MODE) { case self::MODE_ROW_EDIT: case self::MODE_ROW_DELETE: $ROW = $TABLE->getRow($RQ->int($TABLE->getPk()->getName())); break; } break; case self::MODE_INSERTS: //Nothing to do break; default: //Защитимся от некорректного значения параметра 'mode' $MODE = self::MODE_TABLES_LIST; break; } $PARAMS['mode'] = $MODE; $PARAMS['table'] = $TABLE; /* * ВЫПОЛНЯЕМ ОБРАБОТКУ */ switch ($MODE) { case self::MODE_TABLES_LIST: $PARAMS['tables'] = $TABLES; $navigation->setCurrent('Список таблиц'); break; case self::MODE_INSERTS: $PARAMS['tables'] = $TABLES; $navigation->addPath(self::urlTables(), 'Список таблиц'); $navigation->setCurrent('Вставка данных'); break; case self::MODE_TABLE_ROWS: $PARAMS['rows'] = $TABLE->getRows(); $PARAMS['addurl'] = self::urlRecAdd($TABLE); $PARAMS['modified'] = $TABLE->getModifiedRows(); case self::MODE_TABLE_SQL: case self::MODE_TABLE_ARR: $navigation->addPath(self::urlTables(), 'Список таблиц'); $navigation->setCurrent($TABLE->getName()); break; default: switch ($MODE) { /* * Помимо действий над записью, мы ещё раздиляем действия над фолдингами * (если они есть для таблицы). Поэтому мы установм: * FormAction - для типа редактирования записи * FormButton - для типа работы с фолдингом */ case self::MODE_ROW_ADD: $FORM->setFormAction(PS_ACTION_CREATE); $FORM->setButtons(FORM_RecEditForm::BUTTON_CREATE); if ($TABLE->hasFoldings()) { $FORM->addButton(FORM_RecEditForm::BUTTON_CREATEF); } $navigation->setCurrent('Создание записи'); break; case self::MODE_ROW_EDIT: $FORM->setFormAction(PS_ACTION_EDIT); $FORM->setButtons(FORM_RecEditForm::BUTTON_EDIT); if ($TABLE->hasFoldings() && !$TABLE->hasFoldingEntity4DbRec($ROW, true)) { $FORM->addButton(FORM_RecEditForm::BUTTON_EDITF); } $navigation->setCurrent('Редактирование записи'); break; case self::MODE_ROW_DELETE: $FORM->setFormAction(PS_ACTION_DELETE); $FORM->setButtons(FORM_RecEditForm::BUTTON_DELETE); if ($TABLE->hasFoldingEntity4DbRec($ROW, true)) { $FORM->addButton(FORM_RecEditForm::BUTTON_DELETEF); } $navigation->setCurrent('Удаление записи'); break; default: raise_error("Неизвестный режим: [{$MODE}]"); } $FORM->setHidden('table', $TABLE->getName()); $FORM->setSmartyParam('table', $TABLE); $FORM->setSmartyParam('rec', $ROW); $navigation->addPath(self::urlTables(), 'Список таблиц'); $navigation->addPath(self::urlTableRows($TABLE), $TABLE->getName()); break; } echo $this->getFoldedEntity()->fetchTpl($PARAMS); }
/** * Метод получает на вход url ресурса и пытается его обфусцировать, если это возможно. * * @return: путь к ресурсу, который должнет быть подключен, или null, если ресурс подключать не нужно */ private function tryReplaceResource($url) { if (!starts_with($url, DIR_SEPARATOR)) { //Это внешний ресурс: http:// и т.д. - подключаем. return $url; } $di = DirItem::inst($url); if (!$di->isFile() || $di->getSize() <= 0) { return null; } if (!PsDefines::isProduction()) { //Не будем пытаться обфусцировать в девелопменте //return $url; } if (!ends_with($url, '.js')) { //Мы не можем обфусцировать .css файлы, так как они используют относительные пути к ресурсам. return $url; } return $url; $url = $di->getRelPath(); if (!starts_with($url, $this->OBFUSCATABLE)) { //Не стоит обфусцировать не наши .js файлы, так как они могут внутри использовать ссылки на рядом лежащие ресурсы return $url; } $type = 'js'; $obfuscatedDi = DirManager::autogen("resources/{$type}")->getDirItem(null, md5($url), $type); $mtyme = $obfuscatedDi->getModificationTime(); if (!$mtyme || $mtyme < $di->getModificationTime()) { $obfuscatedDi->writeToFile(StringUtils::normalizeResourceFile($type, $di->getFileContents()), true); } return $obfuscatedDi->getRelPath(); }
protected function __construct() { //Разрешаем работать с классом только администратору AuthManager::checkAdminAccess(); //Мы должны находиться не в продакшене PsDefines::assertProductionOff(__CLASS__); $this->LOGGER = PsLogger::inst(__CLASS__); $this->BEAN = TESTBean::inst(); }
/** * В процессе закрытия данного класса мы напишем полный список изменённых сущностей */ public function onDestruct() { foreach (array('ACTION_FOLDING_' => 'Фолдинги', 'ACTION_ENTITY_' => 'Сущности') as $CONST_PREFIX => $name) { $this->LOGGER->infoBox($name); foreach (PsUtil::getClassConsts($this, $CONST_PREFIX) as $action) { $idents = array_get_value($action, $this->ACTIONS, array()); $count = count($idents); $this->LOGGER->info(); $this->LOGGER->info($action . ':'); if ($count > 0) { for ($i = 0; $i < $count; $i++) { $this->LOGGER->info("\t" . (1 + $i) . '. ' . $idents[$i][0] . ($idents[$i][1] ? ' [' . $idents[$i][1] . ']' : '')); } } else { $this->LOGGER->info("\t -- Нет --"); } } } /** * Распечатаем карту зависимости сущностей фолдинга. * Операция настолько тяжёлая, что в режиме ajax также будем избегать её выполнение. */ if (PsDefines::isDevmode() && !PageContext::inst()->isAjax()) { $this->LOGGER->infoBox('Карта зависимости сущностей фолдингов:'); foreach ($this->getDependsOnMap() as $who => $fromWhoArr) { $this->LOGGER->info("\t{$who}:"); foreach ($fromWhoArr as $fromWho) { $this->LOGGER->info("\t\t{$fromWho}"); } } } }
/** * Вызывается после компиляции макета (построения php-файла). * Может быть переопределён в наследнике. * * @param string $source - "сырой" код шаблона * @param Smarty_Internal_Template $template */ protected function outputImpl($source, Smarty_Internal_Template $template) { if (PsDefines::isReplaceFormulesWithImages()) { return TexImager::inst()->replaceInText($source); } return $source; }
public function buildContent() { $navigation = AdminPageNavigation::inst(); $RQ = RequestArrayAdapter::inst(); /** @var FoldedEntity */ $entity = FoldedStorageInsts::getFoldedEntityByUnique($RQ->str('entity'), false); /** @var FoldedResources */ $folding = $entity ? $entity->getFolding() : FoldedStorageInsts::byUnique($RQ->str('folding'), false); $mode = $RQ->str('mode', self::MODE_FOLDINGS_LIST); $PARAMS['mode'] = $mode; $PARAMS['error'] = null; $PARAMS['entity'] = $entity; $PARAMS['folding'] = $folding; $PARAMS['foldings'] = FoldedStorageInsts::listFoldings(); $ftype = $folding ? $folding->getFoldingType() : ''; $fsubtype = $folding ? $folding->getFoldingSubType() : ''; $fident = $entity ? $entity->getIdent() : ''; $flist = $RQ->str('list'); $ftplpath = $RQ->str('tplpath'); //РЕДИРЕКТ if ($mode != self::MODE_FOLDINGS_LIST && !$folding) { PsUtil::redirectTo(self::urlFoldingsList()); } //ВЫПОЛНЕНИЕ switch ($mode) { //СПИСОК ВСЕХ ФОЛДИНГОВ case self::MODE_FOLDINGS_LIST: $navigation->setCurrent('Список фолдингов'); break; //СПИСОК СУЩНОСТЕЙ ДАННОГО ФОЛДИНГА //СПИСОК СУЩНОСТЕЙ ДАННОГО ФОЛДИНГА case self::MODE_FOLDING_CONTENT: $newIdent = $folding->getNextEntityIdent(); //Форма создания $FORM = FORM_AdminFoldingCreateForm::getInstance(); $FORM->setHidden('folding', $folding->getUnique()); $FORM->setParam(FORM_AdminFoldingCreateForm::PARAM_NEW_FOLDING_IDENT, $newIdent); $FORM->setSmartyParam('folding', $folding); /* @var $TABLE PsTable */ $FORM->setSmartyParam('rec', $folding->getDbRec4Entity($newIdent)); //Форма загрузки $FORM = FORM_AdminFoldingUploadForm::getInstance(); $FORM->setHidden('folding', $folding->getUnique()); $navigation->addPath(self::urlFoldingsList(), 'Список фолдингов'); $navigation->setCurrent($folding->getEntityName()); break; case self::MODE_FOLDING_LIST_EDIT: $PARAMS['list'] = $flist; //TODO - выкинуто //$PARAMS['listIdents'] = $folding->getPossibleListIdents($flist); $navigation->addPath(self::urlFoldingsList(), 'Список фолдингов'); $navigation->addPath(self::urlFoldingEntitys($folding), $folding->getEntityName()); $navigation->setCurrent('Редактирование списка ' . $flist); break; case self::MODE_FOLDING_TPLS_LIST: $PARAMS['tplsList'] = $folding->getAllInfoTpls($fident); $navigation->addPath(self::urlFoldingsList(), 'Список фолдингов'); $navigation->addPath(self::urlFoldingEntitys($folding), $folding->getEntityName()); $navigation->addPath(self::urlFoldingEdit($entity), $fident); $navigation->setCurrent('Информационные шаблоны'); break; case self::MODE_FOLDING_TPL_EDIT: $PARAMS['tplsList'] = $folding->getAllInfoTpls($fident); $tpl = $folding->getInfoTpl($entity->getIdent(), $ftplpath); $PARAMS['tpl'] = $tpl; //Отфетчим содержимое, извлеча из запроса те параметры, которые начинаются на sm_ $PARAMS['content'] = $tpl->fetchNoCache($RQ->getByKeyPrefix('sm_', true)); $FORM = FORM_AdminFoldingInfoTplEditForm::getInstance(); $FORM->setHidden('fentity', $entity->getUnique()); $FORM->setHidden('ftpl', $tpl->getInfoRelPath()); $FORM->setSmartyParam('tpl', $tpl->getDirItem()->getFileContents()); $navigation->addPath(self::urlFoldingsList(), 'Список фолдингов'); $navigation->addPath(self::urlFoldingEntitys($folding), $folding->getEntityName()); $navigation->addPath(self::urlFoldingEdit($entity), $fident); $navigation->addPath(self::urlFoldingInfoTplsList($entity), 'Информационные шаблоны'); $navigation->setCurrent($tpl->getInfoRelPath()); break; case self::MODE_FOLDING_EDIT: //Ссылка для скачивания спрайтов $download['class'] = 'download'; $download['data'] = array('ftype' => $ftype, 'fsubtype' => $fsubtype, 'fident' => $fident); $PARAMS['download'] = PsHtml::a($download, '[Скачать]'); $spriteImg = $folding->getSprite($fident); $spriteImg = $spriteImg && $spriteImg->getImgDi()->isImg() ? $spriteImg->getImgDi() : null; $PARAMS['sprite'] = $spriteImg ? PsHtml::a(array('href' => $spriteImg->getRelPath()), '[Спрайт]', true) : null; //Информационные шаблоны $PARAMS['patterns'] = ''; if (count($folding->getInfoDiList($fident))) { $patterns['href'] = self::urlFoldingInfoTplsList($entity); $PARAMS['patterns'] = PsHtml::a($patterns, '[Инфо шаблоны]'); } $PARAMS['info'] = ''; try { $prew = $folding->getFoldedEntityPreview($fident); if (is_array($prew)) { $PARAMS['info'] = array_get_value('info', $prew); $PARAMS['content'] = array_get_value('content', $prew); } else { $PARAMS['content'] = $prew; } } catch (Exception $e) { $PARAMS['content'] = ExceptionHandler::getHtml($e); } /* * Подготовим форму редактирования фолдинга */ $FORM = FORM_AdminFoldingEditForm::getInstance(); /* hiddens */ $FORM->setHidden('ftype', $ftype); $FORM->setHidden('fsubtype', $fsubtype); $FORM->setHidden('fident', $fident); $rtypes = $folding->getAllowedResourceTypes(); /* fields */ foreach ($rtypes as $rtype) { $FORM->setParam($rtype, $folding->getResourceDi($fident, $rtype)->getFileContents(false)); } /* smarty */ $FORM->setSmartyParam('types', $rtypes); $FORM->setSmartyParam('covers', $folding->isImagesFactoryEnabled()); /* table */ $TABLE = null; $DBROW = null; if ($folding->getTableName()) { $TABLE = TableExporter::inst()->getTable($folding->getTableName()); //TODO - выкинуто //$DBROW = $TABLE->getFoldingDbRec($folding, $fident); } $FORM->setSmartyParam('table', $TABLE); $FORM->setSmartyParam('row', $DBROW); if (!$DBROW) { $FORM->removeButton(FORM_AdminFoldingEditForm::BUTTON_DELETE_ALL); } /* * Навигация */ $navigation->addPath(self::urlFoldingsList(), 'Список фолдингов'); $navigation->addPath(self::urlFoldingEntitys($folding), $folding->getEntityName()); $navigation->setCurrent($fident); break; } PsDefines::setReplaceFormulesWithImages(false); echo $this->getFoldedEntity()->fetchTpl($PARAMS); }
/** * Функция для регистрации страниц * * @param type $path * @param type $name * @param type $code * @param AbstractPageBuilder $builderIdent * @param type $authType * @param type $basePageCode * @param type $pageCodeNoAccess * @param type $allovedInProduction * @return type */ public static final function register($path, $name, $code, $builderIdent, $authType, $basePageCode = null, $pageCodeNoAccess = null, $allovedInProduction = true) { self::$allowedScripts[] = $path; if (!$allovedInProduction && PsDefines::isProduction()) { return; //---- } check_condition(self::$storeState === 1, 'Страница не может быть заретистирована, хранилище находится в состоянии [' . self::$storeState . ']'); check_condition(is_string($path) && !isEmpty($path), "Некорректный путь для страницы [{$path}]"); check_condition(is_integer($code), "Некорректный код для страницы [{$code}]"); $pathBase = get_file_name($path); check_condition(!array_key_exists($pathBase, self::$page2pathBase) && !array_key_exists($code, self::$page2code), "Страница [{$name} ({$code})] не может быть зарегистрирована дважды"); $page = new WebPage($path, $name, $code, $authType, $basePageCode, $pageCodeNoAccess, $builderIdent); self::$page2code[$code] = $page; self::$page2pathBase[$pathBase] = $page; }
public function buildContent() { PsDefines::setReplaceFormulesWithImages(false); echo $this->postCP->getPostPopupVariant(); }
protected function doProcess(PageContext $ctxt, RequestArrayAdapter $requestParams, ArrayAdapter $buildParams) { PsDefines::assertProductionOff(__CLASS__); PsUtil::startUnlimitedMode(); }
public function get() { return PsDefines::get($this->name(), $this->ctxt, $this->phpType, $this->default); }
protected function __construct() { PsDefines::assertProductionOff(__CLASS__); parent::__construct(); }
public function fetchTplImpl($ident, $smParams = null, $returnType = self::FETCH_RETURN_CONTENT, $addResources = false, $cacheId = null) { $this->assertHasAccess($ident); $logMsg = null; if ($this->LOGGER->isEnabled()) { $rqNum = ++self::$FETCH_REQUEST_CNT; $logMsg = "#{$rqNum} Smarty params count: " . count(to_array($smParams)) . ", type: {$returnType}, resources: " . var_export($addResources, true) . ", " . ($cacheId ? "cache id: [{$cacheId}]" : 'nocache'); $this->LOGGER->info("Tpl fetching requested for entity [{$ident}]. {$logMsg}"); FoldedResourcesManager::onEntityAction(FoldedResourcesManager::ACTION_ENTITY_FETCH_REQUESTD, $this, $ident, $logMsg); } $entity = $this->getFoldedEntity($ident); //Сразу установим зависимость от текущей сущности FoldedContextWatcher::getInstance()->setDependsOnEntity($entity); $CTXT = $this->getFoldedContext(); $PCLASS = $CTXT->tplFetchParamsClass(); $PCLASS_BASE = FoldedTplFetchPrams::getClassName(); check_condition(PsUtil::isInstanceOf($PCLASS, $PCLASS_BASE), "Класс [{$PCLASS}] для хранения данных контекста {$CTXT} должен быть подклассом {$PCLASS_BASE}"); //Если мы не возвращаем содержимое, то в любом случае ресурсы добавлять не к чему $addResources = $addResources && !in_array($returnType, array(self::FETCH_RETURN_PARAMS, self::FETCH_RETURN_PARAMS_OB)); $keysRequired = PsUtil::getClassConsts($PCLASS, 'PARAM_'); $keysRequiredParams = array_diff($keysRequired, array(FoldedTplFetchPrams::PARAM_CONTENT)); $PARAMS = null; $PARAMS_KEY = null; $CONTENT = null; $CONTENT_KEY = null; $RETURN_KEY = null; if ($cacheId) { $cacheId = ensure_wrapped_with($cacheId, '[', ']') . '[' . PsDefines::getReplaceFormulesType() . ']'; $RETURN_KEY = $cacheId . '-' . $returnType; if (array_key_exists($ident, $this->FETCH_RETURNS)) { if (array_key_exists($RETURN_KEY, $this->FETCH_RETURNS[$ident])) { return $this->FETCH_RETURNS[$ident][$RETURN_KEY]; } } else { $this->FETCH_RETURNS[$ident] = array(); } $PARAMS_KEY = empty($keysRequiredParams) ? null : $cacheId . '-params'; $CONTENT_KEY = $cacheId . '-content'; switch ($returnType) { case self::FETCH_RETURN_FULL: case self::FETCH_RETURN_FULL_OB: $CONTENT = $this->getFromFoldedCache($ident, $CONTENT_KEY); $PARAMS = $PARAMS_KEY ? $this->getFromFoldedCache($ident, $PARAMS_KEY, $keysRequiredParams) : array(); if ($CONTENT && is_array($PARAMS)) { $CONTENT = $addResources ? $this->getResourcesLinks($ident, $CONTENT) : $CONTENT; $PARAMS[FoldedTplFetchPrams::PARAM_CONTENT] = $CONTENT; switch ($returnType) { case self::FETCH_RETURN_FULL: return $this->FETCH_RETURNS[$ident][$RETURN_KEY] = $PARAMS; case self::FETCH_RETURN_FULL_OB: return $this->FETCH_RETURNS[$ident][$RETURN_KEY] = new $PCLASS($PARAMS); default: raise_error("Unprocessed fetch return type [{$returnType}]."); } } break; case self::FETCH_RETURN_CONTENT: $CONTENT = $this->getFromFoldedCache($ident, $CONTENT_KEY); if ($CONTENT) { $CONTENT = $addResources ? $this->getResourcesLinks($ident, $CONTENT) : $CONTENT; return $this->FETCH_RETURNS[$ident][$RETURN_KEY] = $CONTENT; } break; case self::FETCH_RETURN_PARAMS: case self::FETCH_RETURN_PARAMS_OB: $PARAMS = $PARAMS_KEY ? $this->getFromFoldedCache($ident, $PARAMS_KEY, $keysRequiredParams) : array(); if (is_array($PARAMS)) { switch ($returnType) { case self::FETCH_RETURN_PARAMS: return $this->FETCH_RETURNS[$ident][$RETURN_KEY] = $PARAMS; case self::FETCH_RETURN_PARAMS_OB: return $this->FETCH_RETURNS[$ident][$RETURN_KEY] = new $PCLASS($PARAMS); default: raise_error("Unprocessed fetch return type [{$returnType}]."); } } break; } } $settedNow = false; if (!$entity->equalTo(FoldedContextWatcher::getInstance()->getFoldedEntity())) { $CTXT->setContextWithFoldedEntity($entity); $settedNow = true; } try { $CONTENT = $this->getTpl($ident, $smParams)->fetch(); $entityNow = FoldedContextWatcher::getInstance()->getFoldedEntity(); check_condition($entity->equalTo($entityNow), "After tpl fetching folded entity [{$entity}] chenged to [{$entityNow}]"); $PARAMS_FULL = $CTXT->finalizeTplContent($CONTENT); check_condition(is_array($PARAMS_FULL), "After [{$entity}] tpl finalisation not array is returned"); $keysReturned = array_keys($PARAMS_FULL); if (count(array_diff($keysReturned, $keysRequired)) || count(array_diff($keysRequired, $keysReturned))) { raise_error("After [{$entity}] tpl finalisation required keys: " . array_to_string($keysRequired) . '], returned keys: [' . array_to_string($keysReturned) . ']'); } if ($this->LOGGER->isEnabled()) { $this->LOGGER->info("Tpl fetching actually done for entity [{$ident}]. {$logMsg}"); FoldedResourcesManager::onEntityAction(FoldedResourcesManager::ACTION_ENTITY_FETCH_DONE, $this, $ident, $logMsg); } } catch (Exception $e) { /* * Произошла ошибка! * * Если мы устанавливали контенст и он не поменялся после завершения фетчинга (если поменялся, это ошибка), то нужно его обязательно завершить. * Если контекст был установлен во внешнем блоке, то этот блок должен позаботиться о сбросе контекста. * * Далее от нас требуется только пробросить ошибку наверх. */ if ($settedNow && $entity->equalTo(FoldedContextWatcher::getInstance()->getFoldedEntity())) { $CTXT->dropContext(); } throw $e; } $CONTENT = $PARAMS_FULL[FoldedTplFetchPrams::PARAM_CONTENT]; $PARAMS = $PARAMS_FULL; unset($PARAMS[FoldedTplFetchPrams::PARAM_CONTENT]); if ($PARAMS_KEY) { $this->saveToFoldedCache($PARAMS, $ident, $PARAMS_KEY); } if ($CONTENT_KEY) { $this->saveToFoldedCache($CONTENT, $ident, $CONTENT_KEY); } if ($settedNow) { $CTXT->dropContext(); } if ($addResources) { $CONTENT = $this->getResourcesLinks($ident, $CONTENT); $PARAMS_FULL[FoldedTplFetchPrams::PARAM_CONTENT] = $CONTENT; } switch ($returnType) { case self::FETCH_RETURN_FULL: return $RETURN_KEY ? $this->FETCH_RETURNS[$ident][$RETURN_KEY] = $PARAMS_FULL : $PARAMS_FULL; case self::FETCH_RETURN_FULL_OB: return $RETURN_KEY ? $this->FETCH_RETURNS[$ident][$RETURN_KEY] = new $PCLASS($PARAMS_FULL) : new $PCLASS($PARAMS_FULL); case self::FETCH_RETURN_CONTENT: return $RETURN_KEY ? $this->FETCH_RETURNS[$ident][$RETURN_KEY] = $CONTENT : $CONTENT; case self::FETCH_RETURN_PARAMS: return $RETURN_KEY ? $this->FETCH_RETURNS[$ident][$RETURN_KEY] = $PARAMS : $PARAMS; case self::FETCH_RETURN_PARAMS_OB: return $RETURN_KEY ? $this->FETCH_RETURNS[$ident][$RETURN_KEY] = new $PCLASS($PARAMS) : new $PCLASS($PARAMS); } raise_error("Unknown fetch return type [{$returnType}]."); }