<?php
/**
* EXHIBIT A. Common Public Attribution License Version 1.0
* The contents of this file are subject to the Common Public Attribution License Version 1.0 (the “License”);
* you may not use this file except in compliance with the License. You may obtain a copy of the License at
* http://www.oxwall.org/license. The License is based on the Mozilla Public License Version 1.1
* but Sections 14 and 15 have been added to cover use of software over a computer network and provide for
* limited attribution for the Original Developer. In addition, Exhibit A has been modified to be consistent
* with Exhibit B. Software distributed under the License is distributed on an “AS IS” basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for the specific language
* governing rights and limitations under the License. The Original Code is Oxwall software.
* The Initial Developer of the Original Code is Oxwall Foundation (http://www.oxwall.org/foundation).
* All portions of the code written by Oxwall Foundation are Copyright (c) 2011. All Rights Reserved.
* EXHIBIT B. Attribution Information
* Attribution Copyright Notice: Copyright 2011 Oxwall Foundation. All rights reserved.
* Attribution Phrase (not exceeding 10 words): Powered by Oxwall community software
* Attribution URL: http://www.oxwall.org/
* Graphic Image as provided in the Covered Code.
* Display of Attribution Information is required in Larger Works which are defined in the CPAL as a work
* which combines Covered Code or portions thereof with code not governed by the terms of the CPAL.
*/
/**
* @author Sardar Madumarov <madumarov@gmail.com>
* @package ow_core
* @method static OW_DeveloperTools getInstance()
* @since 1.8.3
*/
class OW_DeveloperTools
{
const CACHE_ENTITY_TEMPLATE = 2;
const CACHE_ENTITY_THEME = 4;
const CACHE_ENTITY_LANGUAGE = 8;
const CACHE_ENTITY_PLUGIN_STRUCTURE = 32;
const EVENT_UPDATE_CACHE_ENTITIES = "base.update_cache_entities";
const CONFIG_NAME = "dev_mode";
use OW_Singleton;
/**
* @var BOL_PluginService
*/
private $pluginService;
/**
* @var BOL_ThemeService
*/
private $themeService;
/**
* @var BOL_LanguageService
*/
private $languageService;
/**
* Constructor.
*/
private function __construct()
{
$this->pluginService = BOL_PluginService::getInstance();
$this->themeService = BOL_ThemeService::getInstance();
$this->languageService = BOL_LanguageService::getInstance();
}
public function init()
{
$configDev = (int) OW::getConfig()->getValue("base", self::CONFIG_NAME);
if ( $configDev > 0 )
{
$this->refreshEntitiesCache($configDev);
OW::getConfig()->saveConfig("base", self::CONFIG_NAME, 0);
OW::getApplication()->redirect();
}
if ( defined("OW_DEV_MODE") && OW_DEV_MODE )
{
$this->refreshEntitiesCache(OW_DEV_MODE);
}
// show profiler only for desktop and if it's enabled
if ( !OW::getApplication()->isDesktop() || OW::getRequest()->isAjax() || !OW_PROFILER_ENABLE )
{
return;
}
OW_View::setCollectDevInfo(true);
OW::getEventManager()->setDevMode(true);
OW::getEventManager()->bind("base.append_markup", array($this, "onAppendMarkup"));
}
/* ---------------------------------------- Developer handlers -------------------------------------------------- */
/**
* Updates all entity types cache
*
* @param int $options
*/
public function refreshEntitiesCache( $options = 1 )
{
$options = (intval($options) == 1 ? PHP_INT_MAX : intval($options));
if ( $options & self::CACHE_ENTITY_TEMPLATE )
{
$this->clearTemplatesCache();
}
if ( $options & self::CACHE_ENTITY_THEME )
{
$this->clearThemeCache();
}
if ( $options & self::CACHE_ENTITY_LANGUAGE )
{
$this->clearLanguagesCache();
}
if ( $options & self::CACHE_ENTITY_PLUGIN_STRUCTURE )
{
$this->updateStructureforAllPlugins();
}
OW::getEventManager()->trigger(new OW_Event(self::EVENT_UPDATE_CACHE_ENTITIES, array("options" => $options)));
}
/**
* Updates all templates cache
*/
public function clearTemplatesCache()
{
OW_ViewRenderer::getInstance()->clearCompiledTpl();
}
/**
* Updates themes list and regenerates cache of each theme
*/
public function clearThemeCache()
{
$this->themeService->updateThemeList();
$this->themeService->processAllThemes();
if ( OW::getConfig()->configExists("base", "cachedEntitiesPostfix") )
{
OW::getConfig()->saveConfig("base", "cachedEntitiesPostfix", UTIL_String::getRandomString());
}
}
/**
* Updates cache for all languages
*/
public function clearLanguagesCache()
{
$this->languageService->generateCacheForAllActiveLanguages();
}
/**
* Updates dir structure for all plugins
*/
public function updateStructureforAllPlugins()
{
$plugins = $this->pluginService->findAllPlugins();
/* @var $pluginDto BOL_Plugin */
foreach ( $plugins as $pluginDto )
{
$this->pluginService->addPluginDirs($pluginDto);
}
}
/* ----------------------- Event handlers ----------------------------------------------------------------------- */
/**
* The method collects all the developer info during the page handling.
*
* @param BASE_CLASS_EventCollector $event
*/
public function onAppendMarkup( BASE_CLASS_EventCollector $event )
{
$viewRenderer = OW_ViewRenderer::getInstance();
$viewRenderer->assignVar("oxwall", BOL_StorageService::getInstance()->getPlatformXmlInfo());
$view = new OW_View();
$view->setTemplate(OW::getPluginManager()->getPlugin("base")->getCmpViewDir() . "dev_tools_tpl.html");
// get current request attributes
$requestHandlerData = OW::getRequestHandler()->getDispatchAttributes();
try
{
$ctrlPath = OW::getAutoloader()->getClassPath($requestHandlerData["controller"]);
}
catch ( Exception $e )
{
$ctrlPath = "not_found";
}
$requestHandlerData["ctrlPath"] = $ctrlPath;
$requestHandlerData["paramsExp"] = var_export(( empty($requestHandlerData["params"]) ? array() : $requestHandlerData["params"]),
true);
$view->assign("requestHandler", $requestHandlerData);
// get current request memory usage
$memoryUsage = "No info";
if ( function_exists("memory_get_peak_usage") )
{
$memoryUsage = UTIL_File::convertBytesToHumanReadable(memory_get_peak_usage(true));
}
$view->assign("memoryUsage", $memoryUsage);
// get default profiler data
$view->assign("profiler", UTIL_Profiler::getInstance()->getResult());
// rendered view data
$view->assign("renderedItems", $this->getViewInfo(OW_View::getDevInfo()));
// sql queries data
$filter = !empty($_GET["pr_query_log_filter"]) ? trim($_GET["pr_query_log_filter"]) : null;
$view->assign("database",
$this->getSqlInfo(OW::getDbo()->getQueryLog(), OW::getDbo()->getTotalQueryExecTime(), $filter));
// events data
$view->assign("events", $this->getEventInfo(OW::getEventManager()->getLog()));
$view->assign("clrBtnUrl", OW::getRequest()->buildUrlQueryString(OW::getRouter()->urlFor("BASE_CTRL_Base", "turnDevModeOn"),
array("back-uri" => urlencode(OW::getRouter()->getUri()))));
$event->add($view->render());
}
protected function getSqlInfo( array $sqlData, $totalTime, $queryFilter = null )
{
foreach ( $sqlData as $key => $query )
{
if ( $queryFilter )
{
if ( !mb_strstr($query["query"], $queryFilter) )
{
unset($sqlData[$key]);
continue;
}
}
if ( isset($query["params"]) && is_array($query["params"]) )
{
$sqlData[$key]["params"] = var_export($query["params"], true);
}
}
return array("qet" => $totalTime, "ql" => $sqlData, "qc" => count($sqlData));
}
protected function getEventInfo( array $eventsData )
{
$eventsDataArray = array("bind" => array(), "calls" => array());
foreach ( $eventsData["bind"] as $eventName => $listeners )
{
$eventsDataArray["bind"][] = array(
"name" => $eventName,
"listeners" => $this->getEventListeners($listeners)
);
}
foreach ( $eventsData["call"] as $eventItem )
{
$paramsData = var_export($eventItem["event"]->getParams(), true);
$eventsDataArray["call"][] = array(
"type" => $eventItem["type"],
"name" => $eventItem["event"]->getName(),
"listeners" => $this->getEventListeners($eventItem["listeners"]),
"params" => $paramsData,
"start" => sprintf("%.3f", $eventItem["start"]),
"exec" => sprintf("%.3f", $eventItem["exec"])
);
}
$eventsDataArray["bindsCount"] = count($eventsDataArray["bind"]);
$eventsDataArray["callsCount"] = count($eventsDataArray["call"]);
return $eventsDataArray;
}
protected function getEventListeners( array $eventData )
{
$listenersList = array();
foreach ( $eventData as $priority )
{
foreach ( $priority as $listener )
{
if ( is_array($listener) )
{
if ( is_object($listener[0]) )
{
$listener = get_class($listener[0]) . " -> {$listener[1]}";
}
else
{
$listener = "{$listener[0]} :: {$listener[1]}";
}
}
else if ( is_string($listener) )
{
// nothing to do
}
else
{
$listener = "ClosureObject";
}
$listenersList[] = $listener;
}
}
return $listenersList;
}
protected function getViewInfo( array $viewData )
{
$viewDataArray = array("mp" => array(), "cmp" => array(), "ctrl" => array());
foreach ( $viewData as $class => $item )
{
try
{
$src = OW::getAutoloader()->getClassPath($class);
}
catch ( Exception $e )
{
$src = "not_found";
}
$addItem = array("class" => $class, "src" => $src, "tpl" => $item);
if ( is_subclass_of($class, OW_MasterPage::class) )
{
$viewDataArray["mp"] = $addItem;
}
else if ( is_subclass_of($class, OW_ActionController::class) )
{
$viewDataArray["ctrl"] = $addItem;
}
else if ( is_subclass_of($class, OW_Component::class) )
{
$viewDataArray["cmp"][] = $addItem;
}
else
{
$viewDataArray["view"][] = $addItem;
}
}
return array("items" => $viewDataArray, "count" => ( count($viewData) - 2 ));
}
}