104fd306cSNickeau<?php 204fd306cSNickeau 304fd306cSNickeaunamespace ComboStrap; 404fd306cSNickeau 504fd306cSNickeau 604fd306cSNickeauuse ComboStrap\Meta\Store\MetadataDbStore; 704fd306cSNickeauuse ComboStrap\Meta\Store\MetadataDokuWikiStore; 804fd306cSNickeauuse ComboStrap\Tag\WebCodeTag; 904fd306cSNickeauuse ComboStrap\Web\Url; 1004fd306cSNickeauuse dokuwiki\ActionRouter; 1104fd306cSNickeauuse dokuwiki\Extension\EventHandler; 1204fd306cSNickeauuse TestRequest; 1304fd306cSNickeau 1404fd306cSNickeau 1504fd306cSNickeau/** 1604fd306cSNickeau * An execution object permits to manage the variable state for 1704fd306cSNickeau * an execution (ie one HTTP request) 1804fd306cSNickeau * 1904fd306cSNickeau * 2004fd306cSNickeau * Note that normally every page has a page context 2104fd306cSNickeau * meaning that you can go from an admin page to show the page. 2204fd306cSNickeau * 2304fd306cSNickeau * 2404fd306cSNickeau * When an execution context has finished, it should be {@link ExecutionContext::close() closed} 2504fd306cSNickeau * or destroyed 2604fd306cSNickeau * 2704fd306cSNickeau * You can get the actual execution context with {@link ExecutionContext::getActualOrCreateFromEnv()} 2804fd306cSNickeau * 2904fd306cSNickeau * 3004fd306cSNickeau * Same concept than [routing context](https://vertx.io/docs/apidocs/index.html?io/vertx/ext/web/RoutingContext.html) 3104fd306cSNickeau * (Not yet fully implemented) 3204fd306cSNickeau * ```java 3304fd306cSNickeau * if (pet.isPresent()) 3404fd306cSNickeau * routingContext 3504fd306cSNickeau * .response() 3604fd306cSNickeau * .setStatusCode(200) 3704fd306cSNickeau * .putHeader(HttpHeaders.CONTENT_TYPE, "application/json") 3804fd306cSNickeau * .end(pet.get().encode()); // (4) 3904fd306cSNickeau * else 4004fd306cSNickeau * routingContext.fail(404, new Exception("Pet not found")); 4104fd306cSNickeau * } 4204fd306cSNickeau * ``` 4304fd306cSNickeau */ 4404fd306cSNickeauclass ExecutionContext 4504fd306cSNickeau{ 4604fd306cSNickeau 4704fd306cSNickeau /** 4804fd306cSNickeau * Dokuwiki do attribute 4904fd306cSNickeau */ 5004fd306cSNickeau const DO_ATTRIBUTE = "do"; 5104fd306cSNickeau 5204fd306cSNickeau 5304fd306cSNickeau const CANONICAL = "execution-context"; 5404fd306cSNickeau 5504fd306cSNickeau /** 5604fd306cSNickeau * All action (handler) 5704fd306cSNickeau * That's what you will found in the `do` parameters 5804fd306cSNickeau */ 5904fd306cSNickeau const SHOW_ACTION = "show"; 6004fd306cSNickeau const EDIT_ACTION = "edit"; 6104fd306cSNickeau /** 6204fd306cSNickeau * Preview is also used to 6304fd306cSNickeau * set the {@link FetcherMarkup::isFragment()} 6404fd306cSNickeau * processing to fragment 6504fd306cSNickeau */ 6604fd306cSNickeau const PREVIEW_ACTION = "preview"; 6704fd306cSNickeau const ADMIN_ACTION = "admin"; 6804fd306cSNickeau const DRAFT_ACTION = "draft"; 6904fd306cSNickeau const SEARCH_ACTION = "search"; 7004fd306cSNickeau const LOGIN_ACTION = "login"; 7104fd306cSNickeau const SAVE_ACTION = "save"; 7204fd306cSNickeau const DRAFT_DEL_ACTION = "draftdel"; 7304fd306cSNickeau const REDIRECT_ACTION = "redirect"; 7404fd306cSNickeau 7504fd306cSNickeau /** 7604fd306cSNickeau * private actions does not render a page to be indexed 7704fd306cSNickeau * by a search engine (ie no redirect) 7804fd306cSNickeau * May be easier, if not `show`, not public 7904fd306cSNickeau */ 8004fd306cSNickeau const PRIVATES_ACTION_NO_REDIRECT = [ 8104fd306cSNickeau self::EDIT_ACTION, 8204fd306cSNickeau self::PREVIEW_ACTION, 8304fd306cSNickeau self::ADMIN_ACTION, 8404fd306cSNickeau self::DRAFT_ACTION, 8504fd306cSNickeau self::DRAFT_DEL_ACTION, 8604fd306cSNickeau self::SEARCH_ACTION, 8704fd306cSNickeau self::LOGIN_ACTION, 8804fd306cSNickeau self::SAVE_ACTION, 8904fd306cSNickeau self::REDIRECT_ACTION, 9004fd306cSNickeau self::REGISTER_ACTION, 9104fd306cSNickeau self::RESEND_PWD_ACTION, 9204fd306cSNickeau self::PROFILE_ACTION, 9304fd306cSNickeau ]; 9404fd306cSNickeau const REGISTER_ACTION = "register"; 9504fd306cSNickeau const RESEND_PWD_ACTION = "resendpwd"; 9604fd306cSNickeau const PROFILE_ACTION = "profile"; 9704fd306cSNickeau const REVISIONS_ACTION = "revisions"; 9804fd306cSNickeau const DIFF_ACTION = "diff"; 9904fd306cSNickeau const INDEX_ACTION = "index"; 10004fd306cSNickeau 10104fd306cSNickeau 10204fd306cSNickeau /** 10304fd306cSNickeau * @var array of objects that are scoped to this request 10404fd306cSNickeau */ 10504fd306cSNickeau private array $executionScopedVariables = []; 10604fd306cSNickeau 10704fd306cSNickeau private CacheManager $cacheManager; 10804fd306cSNickeau 10904fd306cSNickeau private Site $app; 11004fd306cSNickeau 11104fd306cSNickeau /** 11204fd306cSNickeau * A root execution context if any 11304fd306cSNickeau * Null because you can not unset a static variable 11404fd306cSNickeau */ 11504fd306cSNickeau private static ?ExecutionContext $actualExecutionContext = null; 11604fd306cSNickeau 11704fd306cSNickeau private ?string $capturedGlobalId; 11804fd306cSNickeau /** 11904fd306cSNickeau * It may be an array when preview/save/cancel 12004fd306cSNickeau * @var array|string|null 12104fd306cSNickeau */ 12204fd306cSNickeau private $capturedAct; 12304fd306cSNickeau 12404fd306cSNickeau 12504fd306cSNickeau private Url $url; 12604fd306cSNickeau 12704fd306cSNickeau 12804fd306cSNickeau public HttpResponse $response; 12904fd306cSNickeau 13004fd306cSNickeau /** 13104fd306cSNickeau * @var IFetcher - the fetcher that takes into account the HTTP request 13204fd306cSNickeau */ 13304fd306cSNickeau private IFetcher $executingMainFetcher; 13404fd306cSNickeau 13504fd306cSNickeau /** 13604fd306cSNickeau * @var array - a stack of: 13704fd306cSNickeau * * markup handler executing (ie handler that is taking a markup (file, string) and making it a HTML, pdf, ...) 13804fd306cSNickeau * * and old global environement, $executingId, $contextExecutingId, $act 13904fd306cSNickeau * 14004fd306cSNickeau * This fetcher is called by the main fetcher or by the {@link self::setExecutingMarkupHandler()} 14104fd306cSNickeau */ 14204fd306cSNickeau private array $executingMarkupHandlerStack = []; 14304fd306cSNickeau 14404fd306cSNickeau /** 14504fd306cSNickeau * @var TemplateForWebPage - the page template fetcher running (when a fetcher creates a page, it would uses this fetcher) 14604fd306cSNickeau * This class is called by the main fetcher to create a page 14704fd306cSNickeau */ 14804fd306cSNickeau private TemplateForWebPage $executingPageTemplate; 14904fd306cSNickeau private string $creationTime; 15004fd306cSNickeau 15104fd306cSNickeau 15204fd306cSNickeau public function __construct() 15304fd306cSNickeau { 15404fd306cSNickeau 15504fd306cSNickeau $this->creationTime = Iso8601Date::createFromNow()->toIsoStringMs(); 15604fd306cSNickeau 15704fd306cSNickeau $this->url = Url::createFromGetOrPostGlobalVariable(); 15804fd306cSNickeau 15904fd306cSNickeau $this->response = HttpResponse::createFromExecutionContext($this); 16004fd306cSNickeau 16104fd306cSNickeau /** 16204fd306cSNickeau * The requested action 16304fd306cSNickeau */ 16404fd306cSNickeau global $ACT; 16504fd306cSNickeau $this->capturedAct = $ACT; 16604fd306cSNickeau try { 16704fd306cSNickeau $urlAct = $this->url->getQueryPropertyValue(self::DO_ATTRIBUTE); 16804fd306cSNickeau } catch (ExceptionNotFound $e) { 16904fd306cSNickeau /** 17004fd306cSNickeau * The value is unknown 17104fd306cSNickeau * (in doku.php, the default is `show`, 17204fd306cSNickeau * we take the dokuwiki value because the execution context may be 17304fd306cSNickeau * created after the dokuwiki init) 17404fd306cSNickeau */ 17504fd306cSNickeau $urlAct = $ACT; 17604fd306cSNickeau } 17704fd306cSNickeau $ACT = $urlAct; 17804fd306cSNickeau 17904fd306cSNickeau /** 18004fd306cSNickeau * The requested id 18104fd306cSNickeau */ 18204fd306cSNickeau global $ID; 18304fd306cSNickeau $this->capturedGlobalId = $ID; 18404fd306cSNickeau try { 18504fd306cSNickeau 18604fd306cSNickeau $urlId = $this->url->getQueryPropertyValue(DokuwikiId::DOKUWIKI_ID_ATTRIBUTE); 18704fd306cSNickeau if (is_array($urlId)) { 18804fd306cSNickeau /** 18904fd306cSNickeau * hack because the dokuwiki request global object as `ID` and `id` as array 19004fd306cSNickeau * but our own {@link Url object} don't allow that and makes an array instead 19104fd306cSNickeau * We don't use this data anyway, anymore ... 19204fd306cSNickeau */ 19304fd306cSNickeau $urlId = $urlId[0]; 19404fd306cSNickeau } 19504fd306cSNickeau $ID = $urlId; 19604fd306cSNickeau 19704fd306cSNickeau } catch (ExceptionNotFound $e) { 19804fd306cSNickeau // none 19904fd306cSNickeau $ID = null; 20004fd306cSNickeau } 20104fd306cSNickeau 20204fd306cSNickeau 20304fd306cSNickeau } 20404fd306cSNickeau 20504fd306cSNickeau 20604fd306cSNickeau /** 20704fd306cSNickeau * @throws ExceptionNotFound 20804fd306cSNickeau */ 20904fd306cSNickeau public static function getExecutionContext(): ExecutionContext 21004fd306cSNickeau { 21104fd306cSNickeau if (!isset(self::$actualExecutionContext)) { 21204fd306cSNickeau throw new ExceptionNotFound("No root context"); 21304fd306cSNickeau } 21404fd306cSNickeau return self::$actualExecutionContext; 21504fd306cSNickeau } 21604fd306cSNickeau 21704fd306cSNickeau /** 21804fd306cSNickeau * Utility class to set the requested id (used only in test, 21904fd306cSNickeau * normally the environment is set from global PHP environment variable 22004fd306cSNickeau * that get the HTTP request 22104fd306cSNickeau * @param string $requestedId 22204fd306cSNickeau * @return ExecutionContext 22304fd306cSNickeau * @deprecated use {@link self::setDefaultContextPath()} if you want to set a context path 22404fd306cSNickeau * without using a {@link TemplateForWebPage} or {@link FetcherMarkup} 22504fd306cSNickeau */ 22604fd306cSNickeau public static function getOrCreateFromRequestedWikiId(string $requestedId): ExecutionContext 22704fd306cSNickeau { 22804fd306cSNickeau 22904fd306cSNickeau return self::getActualOrCreateFromEnv() 23004fd306cSNickeau ->setDefaultContextPath(WikiPath::createMarkupPathFromId($requestedId)); 23104fd306cSNickeau 23204fd306cSNickeau } 23304fd306cSNickeau 23404fd306cSNickeau 23504fd306cSNickeau /** 23604fd306cSNickeau * @return ExecutionContext 23704fd306cSNickeau * @deprecated uses {@link self::createBlank()} instead 23804fd306cSNickeau */ 23904fd306cSNickeau public static function createFromEnvironmentVariable(): ExecutionContext 24004fd306cSNickeau { 24104fd306cSNickeau return self::createBlank(); 24204fd306cSNickeau } 24304fd306cSNickeau 24404fd306cSNickeau 24504fd306cSNickeau public static function createBlank(): ExecutionContext 24604fd306cSNickeau { 24704fd306cSNickeau 24804fd306cSNickeau if (self::$actualExecutionContext !== null) { 24904fd306cSNickeau throw new ExceptionRuntimeInternal("The previous root context should be closed first"); 25004fd306cSNickeau } 25104fd306cSNickeau $rootExecutionContext = (new ExecutionContext()); 25204fd306cSNickeau self::$actualExecutionContext = $rootExecutionContext; 25304fd306cSNickeau return $rootExecutionContext; 25404fd306cSNickeau 25504fd306cSNickeau } 25604fd306cSNickeau 25704fd306cSNickeau /** 25804fd306cSNickeau * @return ExecutionContext - return the actual context or create a new one from the environment 25904fd306cSNickeau */ 26004fd306cSNickeau public static function getActualOrCreateFromEnv(): ExecutionContext 26104fd306cSNickeau { 26204fd306cSNickeau try { 26304fd306cSNickeau return self::getExecutionContext(); 26404fd306cSNickeau } catch (ExceptionNotFound $e) { 26504fd306cSNickeau return self::createBlank(); 26604fd306cSNickeau } 26704fd306cSNickeau } 26804fd306cSNickeau 26904fd306cSNickeau /** 27004fd306cSNickeau * We create the id manager in the execution 27104fd306cSNickeau * context 27204fd306cSNickeau * (because in case a user choose to not use templating, the {@link FetcherMarkup} 27304fd306cSNickeau * is not available) 27404fd306cSNickeau * And all dynamic component such as {@link \syntax_plugin_combo_dropdown} would not 27504fd306cSNickeau * work anymore. 27604fd306cSNickeau * 27704fd306cSNickeau * @return IdManager 27804fd306cSNickeau */ 27904fd306cSNickeau public function getIdManager(): IdManager 28004fd306cSNickeau { 28104fd306cSNickeau if (!isset($this->idManager)) { 28204fd306cSNickeau $this->idManager = new IdManager($this); 28304fd306cSNickeau } 28404fd306cSNickeau return $this->idManager; 28504fd306cSNickeau } 28604fd306cSNickeau 28704fd306cSNickeau /** 28804fd306cSNickeau * Return the actual context path 28904fd306cSNickeau */ 29004fd306cSNickeau public function getContextNamespacePath(): WikiPath 29104fd306cSNickeau { 29204fd306cSNickeau $requestedPath = $this->getContextPath(); 29304fd306cSNickeau try { 29404fd306cSNickeau return $requestedPath->getParent(); 29504fd306cSNickeau } catch (ExceptionNotFound $e) { 29604fd306cSNickeau // root 29704fd306cSNickeau return $requestedPath; 29804fd306cSNickeau } 29904fd306cSNickeau 30004fd306cSNickeau } 30104fd306cSNickeau 30204fd306cSNickeau 30304fd306cSNickeau /** 30404fd306cSNickeau * @throws ExceptionNotFound 30504fd306cSNickeau */ 30604fd306cSNickeau public function getExecutingWikiId(): string 30704fd306cSNickeau { 30804fd306cSNickeau global $ID; 30904fd306cSNickeau if (empty($ID)) { 31004fd306cSNickeau throw new ExceptionNotFound("No executing id was found"); 31104fd306cSNickeau } 31204fd306cSNickeau return $ID; 31304fd306cSNickeau } 31404fd306cSNickeau 31504fd306cSNickeau 31604fd306cSNickeau /** 31704fd306cSNickeau * @return void close the execution context 31804fd306cSNickeau */ 31904fd306cSNickeau public function close() 32004fd306cSNickeau { 32104fd306cSNickeau 32204fd306cSNickeau /** 32304fd306cSNickeau * Check that this execution context was not closed 32404fd306cSNickeau */ 32504fd306cSNickeau if (self::$actualExecutionContext->creationTime !== $this->creationTime) { 32604fd306cSNickeau throw new ExceptionRuntimeInternal("This execution context was already closed"); 32704fd306cSNickeau } 32804fd306cSNickeau 32904fd306cSNickeau /** 33004fd306cSNickeau * Restore the global $conf of dokuwiki 33104fd306cSNickeau */ 33204fd306cSNickeau $this->getApp()->getConfig()->restoreConfigState(); 33304fd306cSNickeau 33404fd306cSNickeau /** global dokuwiki messages variable */ 33504fd306cSNickeau global $MSG; 33604fd306cSNickeau unset($MSG); 33704fd306cSNickeau 33804fd306cSNickeau /** 33904fd306cSNickeau * Environment restoration 34004fd306cSNickeau * Execution context, change for now only this 34104fd306cSNickeau * global variables 34204fd306cSNickeau */ 34304fd306cSNickeau global $ACT; 34404fd306cSNickeau $ACT = $this->getCapturedAct(); 34504fd306cSNickeau global $ID; 34604fd306cSNickeau $ID = $this->getCapturedRunningId(); 34704fd306cSNickeau global $TOC; 34804fd306cSNickeau unset($TOC); 34904fd306cSNickeau 35004fd306cSNickeau // global scope store 35104fd306cSNickeau MetadataDbStore::resetAll(); 35204fd306cSNickeau MetadataDokuWikiStore::unsetGlobalVariables(); 35304fd306cSNickeau 35404fd306cSNickeau // Router: dokuwiki global 35504fd306cSNickeau // reset event handler 35604fd306cSNickeau global $EVENT_HANDLER; 35704fd306cSNickeau $EVENT_HANDLER = new EventHandler(); 35804fd306cSNickeau /** 35904fd306cSNickeau * We can't give the getInstance, a true value 36004fd306cSNickeau * because it will otherwise start the routing process 36104fd306cSNickeau * {@link ActionRouter::getInstance()} 36204fd306cSNickeau */ 36304fd306cSNickeau 36404fd306cSNickeau 36504fd306cSNickeau /** 36604fd306cSNickeau * Close execution variables 36704fd306cSNickeau * (and therefore also {@link Sqlite} 36804fd306cSNickeau */ 36904fd306cSNickeau $this->closeExecutionVariables(); 37004fd306cSNickeau 37104fd306cSNickeau /** 37204fd306cSNickeau * Is this really needed ? 37304fd306cSNickeau * as we unset the execution context below 37404fd306cSNickeau */ 37504fd306cSNickeau unset($this->executingMainFetcher); 37604fd306cSNickeau unset($this->executingMarkupHandlerStack); 37704fd306cSNickeau unset($this->cacheManager); 37804fd306cSNickeau unset($this->idManager); 37904fd306cSNickeau 38004fd306cSNickeau /** 38104fd306cSNickeau * Deleting 38204fd306cSNickeau */ 38304fd306cSNickeau self::$actualExecutionContext = null; 38404fd306cSNickeau 38504fd306cSNickeau 38604fd306cSNickeau } 38704fd306cSNickeau 38804fd306cSNickeau 38904fd306cSNickeau public function getCapturedRunningId(): ?string 39004fd306cSNickeau { 39104fd306cSNickeau return $this->capturedGlobalId; 39204fd306cSNickeau } 39304fd306cSNickeau 39404fd306cSNickeau public function getCapturedAct() 39504fd306cSNickeau { 39604fd306cSNickeau return $this->capturedAct; 39704fd306cSNickeau } 39804fd306cSNickeau 39904fd306cSNickeau public function getCacheManager(): CacheManager 40004fd306cSNickeau { 40104fd306cSNickeau $root = self::$actualExecutionContext; 40204fd306cSNickeau if (!isset($root->cacheManager)) { 40304fd306cSNickeau $root->cacheManager = new CacheManager($this); 40404fd306cSNickeau } 40504fd306cSNickeau return $root->cacheManager; 40604fd306cSNickeau 40704fd306cSNickeau } 40804fd306cSNickeau 40904fd306cSNickeau /** 41004fd306cSNickeau * Return the root path if nothing is found 41104fd306cSNickeau */ 41204fd306cSNickeau public function getRequestedPath(): WikiPath 41304fd306cSNickeau { 41404fd306cSNickeau /** 41504fd306cSNickeau * Do we have a template page executing ? 41604fd306cSNickeau */ 41704fd306cSNickeau try { 41804fd306cSNickeau return $this->getExecutingPageTemplate() 41904fd306cSNickeau ->getRequestedContextPath(); 42004fd306cSNickeau } catch (ExceptionNotFound $e) { 42104fd306cSNickeau try { 42204fd306cSNickeau /** 42304fd306cSNickeau * Case when the main handler 42404fd306cSNickeau * run the main content before 42504fd306cSNickeau * to inject it in the template page 42604fd306cSNickeau * {@link TemplateForWebPage::render()} 42704fd306cSNickeau */ 42804fd306cSNickeau return $this->getExecutingMarkupHandler() 42904fd306cSNickeau ->getRequestedContextPath(); 43004fd306cSNickeau } catch (ExceptionNotFound $e) { 43104fd306cSNickeau 43204fd306cSNickeau 43304fd306cSNickeau /** 43404fd306cSNickeau * not a template engine running 43504fd306cSNickeau * The id notion is a little bit everywhere 43604fd306cSNickeau * That's why we just don't check the action ($ACT) 43704fd306cSNickeau * 43804fd306cSNickeau * Example: 43904fd306cSNickeau * * `id` may be asked by acl to determine the right 44004fd306cSNickeau * * ... 44104fd306cSNickeau */ 44204fd306cSNickeau global $INPUT; 44304fd306cSNickeau $inputId = $INPUT->str("id"); 44404fd306cSNickeau if (!empty($inputId)) { 44504fd306cSNickeau return WikiPath::createMarkupPathFromId($inputId); 44604fd306cSNickeau } 44704fd306cSNickeau 44804fd306cSNickeau global $ID; 44904fd306cSNickeau if (!empty($ID)) { 45004fd306cSNickeau return WikiPath::createMarkupPathFromId($ID); 45104fd306cSNickeau } 45204fd306cSNickeau 45304fd306cSNickeau /** 45404fd306cSNickeau * This should be less used 45504fd306cSNickeau * but shows where the requested id is spilled in dokuwiki 45604fd306cSNickeau * 45704fd306cSNickeau * If the component is in a sidebar, we don't want the ID of the sidebar 45804fd306cSNickeau * but the ID of the page. 45904fd306cSNickeau */ 46004fd306cSNickeau global $INFO; 46104fd306cSNickeau if ($INFO !== null) { 46204fd306cSNickeau $callingId = $INFO['id']; 46304fd306cSNickeau if (!empty($callingId)) { 46404fd306cSNickeau return WikiPath::createMarkupPathFromId($callingId); 46504fd306cSNickeau } 46604fd306cSNickeau } 46704fd306cSNickeau 46804fd306cSNickeau /** 46904fd306cSNickeau * This is the case with event triggered 47004fd306cSNickeau * before DokuWiki such as 47104fd306cSNickeau * https://www.dokuwiki.org/devel:event:init_lang_load 47204fd306cSNickeau * REQUEST is a mixed of post and get parameters 47304fd306cSNickeau */ 47404fd306cSNickeau global $_REQUEST; 47504fd306cSNickeau if (isset($_REQUEST[DokuwikiId::DOKUWIKI_ID_ATTRIBUTE])) { 47604fd306cSNickeau $requestId = $_REQUEST[DokuwikiId::DOKUWIKI_ID_ATTRIBUTE]; 47704fd306cSNickeau if (!empty($requestId)) { 47804fd306cSNickeau return WikiPath::createMarkupPathFromId($requestId); 47904fd306cSNickeau } 48004fd306cSNickeau } 48104fd306cSNickeau 48204fd306cSNickeau // not that show action is the default even if it's not set 48304fd306cSNickeau // we can't then control if the id should exists or not 48404fd306cSNickeau // markup based on string (test) or snippet of code 48504fd306cSNickeau // return the default context path (ie the root page) 48604fd306cSNickeau return $this->getConfig()->getDefaultContextPath(); 48704fd306cSNickeau } 48804fd306cSNickeau 48904fd306cSNickeau } 49004fd306cSNickeau 49104fd306cSNickeau } 49204fd306cSNickeau 49304fd306cSNickeau /** 49404fd306cSNickeau * @throws ExceptionNotFound 49504fd306cSNickeau */ 49604fd306cSNickeau public function &getRuntimeObject(string $objectIdentifier) 49704fd306cSNickeau { 49804fd306cSNickeau if (isset($this->executionScopedVariables[$objectIdentifier])) { 49904fd306cSNickeau return $this->executionScopedVariables[$objectIdentifier]; 50004fd306cSNickeau } 50104fd306cSNickeau throw new ExceptionNotFound("No object $objectIdentifier found"); 50204fd306cSNickeau } 50304fd306cSNickeau 50404fd306cSNickeau public function setRuntimeObject($objectIdentifier, &$object): ExecutionContext 50504fd306cSNickeau { 50604fd306cSNickeau $this->executionScopedVariables[$objectIdentifier] = &$object; 50704fd306cSNickeau return $this; 50804fd306cSNickeau } 50904fd306cSNickeau 51004fd306cSNickeau public function getUrl(): Url 51104fd306cSNickeau { 51204fd306cSNickeau return $this->url; 51304fd306cSNickeau } 51404fd306cSNickeau 51504fd306cSNickeau 51604fd306cSNickeau /** 51704fd306cSNickeau * @param string $key 51804fd306cSNickeau * @param $value 51904fd306cSNickeau * @param string|null $pluginNamespace - if null, stored in the global conf namespace 52004fd306cSNickeau * @return $this 52104fd306cSNickeau * @deprecated use {@link SiteConfig::setConf()} instead 52204fd306cSNickeau */ 52304fd306cSNickeau public function setConf(string $key, $value, ?string $pluginNamespace = PluginUtility::PLUGIN_BASE_NAME): ExecutionContext 52404fd306cSNickeau { 52504fd306cSNickeau $this->getApp()->getConfig()->setConf($key, $value, $pluginNamespace); 52604fd306cSNickeau return $this; 52704fd306cSNickeau } 52804fd306cSNickeau 52904fd306cSNickeau /** 53004fd306cSNickeau * @param string $key 53104fd306cSNickeau * @param string|null $default 53204fd306cSNickeau * @return mixed|null 53304fd306cSNickeau * @deprecated use 53404fd306cSNickeau */ 53504fd306cSNickeau public function getConfValue(string $key, string $default = null) 53604fd306cSNickeau { 53704fd306cSNickeau return $this->getApp()->getConfig()->getValue($key, $default); 53804fd306cSNickeau } 53904fd306cSNickeau 54004fd306cSNickeau public function setRuntimeBoolean(string $key, bool $b): ExecutionContext 54104fd306cSNickeau { 54204fd306cSNickeau $this->executionScopedVariables[$key] = $b; 54304fd306cSNickeau return $this; 54404fd306cSNickeau } 54504fd306cSNickeau 54604fd306cSNickeau /** 54704fd306cSNickeau * @throws ExceptionNotFound 54804fd306cSNickeau */ 54904fd306cSNickeau public function getRuntimeBoolean(string $name): bool 55004fd306cSNickeau { 55104fd306cSNickeau $var = $this->executionScopedVariables[$name]; 55204fd306cSNickeau if (!isset($var)) { 55304fd306cSNickeau throw new ExceptionNotFound("No $name runtime env was found"); 55404fd306cSNickeau } 55504fd306cSNickeau return DataType::toBoolean($var); 55604fd306cSNickeau } 55704fd306cSNickeau 55804fd306cSNickeau /** 55904fd306cSNickeau * @return $this 56004fd306cSNickeau * @deprecated uses {@link SiteConfig::setCacheXhtmlOn()} 56104fd306cSNickeau */ 56204fd306cSNickeau public function setCacheXhtmlOn(): ExecutionContext 56304fd306cSNickeau { 56404fd306cSNickeau $this->getApp()->getConfig()->setCacheXhtmlOn(); 56504fd306cSNickeau return $this; 56604fd306cSNickeau } 56704fd306cSNickeau 56804fd306cSNickeau /** 56904fd306cSNickeau * 57004fd306cSNickeau * @return $this 57104fd306cSNickeau * @deprecated use the {@link SiteConfig::setConsoleOn} instead 57204fd306cSNickeau */ 57304fd306cSNickeau public function setConsoleOn(): ExecutionContext 57404fd306cSNickeau { 57504fd306cSNickeau $this->getApp()->getConfig()->setCacheXhtmlOn(); 57604fd306cSNickeau return $this; 57704fd306cSNickeau } 57804fd306cSNickeau 57904fd306cSNickeau public function setConsoleOff(): ExecutionContext 58004fd306cSNickeau { 58104fd306cSNickeau $this->getConfig()->setConsoleOff(); 58204fd306cSNickeau return $this; 58304fd306cSNickeau } 58404fd306cSNickeau 58504fd306cSNickeau /** 58604fd306cSNickeau * @return $this 58704fd306cSNickeau * @deprecated use {@link SiteConfig::setDisableThemeSystem()} 58804fd306cSNickeau */ 58904fd306cSNickeau public function setDisableTemplating(): ExecutionContext 59004fd306cSNickeau { 59104fd306cSNickeau $this->getApp()->getConfig()->setDisableThemeSystem(); 59204fd306cSNickeau return $this; 59304fd306cSNickeau } 59404fd306cSNickeau 59504fd306cSNickeau 59604fd306cSNickeau /** 59704fd306cSNickeau * @return bool 59804fd306cSNickeau * @deprecated use the {@link SiteConfig::isConsoleOn()} instead 59904fd306cSNickeau */ 60004fd306cSNickeau public function isConsoleOn(): bool 60104fd306cSNickeau { 60204fd306cSNickeau return $this->getApp()->getConfig()->isConsoleOn(); 60304fd306cSNickeau } 60404fd306cSNickeau 60504fd306cSNickeau 60604fd306cSNickeau /** 60704fd306cSNickeau * Dokuwiki handler name 60804fd306cSNickeau * @return array|mixed|string 60904fd306cSNickeau */ 61004fd306cSNickeau public function getExecutingAction() 61104fd306cSNickeau { 61204fd306cSNickeau global $ACT; 61304fd306cSNickeau return $ACT; 61404fd306cSNickeau } 61504fd306cSNickeau 61604fd306cSNickeau public function setLogExceptionToError(): ExecutionContext 61704fd306cSNickeau { 61804fd306cSNickeau $this->getConfig()->setLogExceptionToError(); 61904fd306cSNickeau return $this; 62004fd306cSNickeau } 62104fd306cSNickeau 62204fd306cSNickeau /** 62304fd306cSNickeau * @return SnippetSystem 62404fd306cSNickeau * It's not attached to the {@link FetcherMarkup} 62504fd306cSNickeau * because the user may choose to not use it (ie {@link SiteConfig::isThemeSystemEnabled()} 62604fd306cSNickeau */ 62704fd306cSNickeau public function getSnippetSystem(): SnippetSystem 62804fd306cSNickeau { 62904fd306cSNickeau return SnippetSystem::getFromContext(); 63004fd306cSNickeau } 63104fd306cSNickeau 63204fd306cSNickeau /** 63304fd306cSNickeau * @return bool - does the action create a publication (render a page) 63404fd306cSNickeau */ 63504fd306cSNickeau public function isPublicationAction(): bool 63604fd306cSNickeau { 63704fd306cSNickeau 63804fd306cSNickeau $act = $this->getExecutingAction(); 63904fd306cSNickeau if (in_array($act, self::PRIVATES_ACTION_NO_REDIRECT)) { 64004fd306cSNickeau return false; 64104fd306cSNickeau } 64204fd306cSNickeau 64304fd306cSNickeau return true; 64404fd306cSNickeau 64504fd306cSNickeau } 64604fd306cSNickeau 64704fd306cSNickeau public function setEnableSectionEditing(): ExecutionContext 64804fd306cSNickeau { 64904fd306cSNickeau $this->setConf('maxseclevel', 999, null); 65004fd306cSNickeau return $this; 65104fd306cSNickeau } 65204fd306cSNickeau 65304fd306cSNickeau /** 65404fd306cSNickeau * @param string $value 65504fd306cSNickeau * @return $this 65604fd306cSNickeau * @deprecated use the {@link SiteConfig::setCanonicalUrlType()} instead 65704fd306cSNickeau */ 65804fd306cSNickeau public function setCanonicalUrlType(string $value): ExecutionContext 65904fd306cSNickeau { 66004fd306cSNickeau $this->getConfig()->setCanonicalUrlType($value); 66104fd306cSNickeau return $this; 66204fd306cSNickeau } 66304fd306cSNickeau 66404fd306cSNickeau public function setUseHeadingAsTitle(): ExecutionContext 66504fd306cSNickeau { 66604fd306cSNickeau // https://www.dokuwiki.org/config:useheading 66704fd306cSNickeau $this->setConf('useheading', 1, null); 66804fd306cSNickeau return $this; 66904fd306cSNickeau } 67004fd306cSNickeau 67104fd306cSNickeau public function response(): HttpResponse 67204fd306cSNickeau { 67304fd306cSNickeau return $this->response; 67404fd306cSNickeau } 67504fd306cSNickeau 67604fd306cSNickeau /** 67704fd306cSNickeau * @param string|null $executingId 67804fd306cSNickeau * @return void 67904fd306cSNickeau */ 68004fd306cSNickeau private function setExecutingId(?string $executingId): void 68104fd306cSNickeau { 68204fd306cSNickeau global $ID; 68304fd306cSNickeau if ($executingId == null) { 68404fd306cSNickeau // ID should not be null 68504fd306cSNickeau // to be able to check the ACL 68604fd306cSNickeau return; 68704fd306cSNickeau } 68804fd306cSNickeau $executingId = WikiPath::removeRootSepIfPresent($executingId); 68904fd306cSNickeau $ID = $executingId; 69004fd306cSNickeau } 69104fd306cSNickeau 69204fd306cSNickeau public function setConfGlobal(string $key, string $value): ExecutionContext 69304fd306cSNickeau { 69404fd306cSNickeau $this->setConf($key, $value, null); 69504fd306cSNickeau return $this; 69604fd306cSNickeau } 69704fd306cSNickeau 69804fd306cSNickeau /** 69904fd306cSNickeau * @return bool - if this execution is a test running 70004fd306cSNickeau */ 70104fd306cSNickeau public function isTestRun(): bool 70204fd306cSNickeau { 70304fd306cSNickeau /** 70404fd306cSNickeau * Test Requested is loaded only in a test run 70504fd306cSNickeau * Does not exist in a normal installation 70604fd306cSNickeau * and is not found, triggering an exception 70704fd306cSNickeau */ 70804fd306cSNickeau if (class_exists('TestRequest')) { 70904fd306cSNickeau $testRequest = TestRequest::getRunning(); 71004fd306cSNickeau return $testRequest !== null; 71104fd306cSNickeau } 71204fd306cSNickeau return false; 71304fd306cSNickeau 71404fd306cSNickeau } 71504fd306cSNickeau 71604fd306cSNickeau private function setExecutingAction(?string $runningAct): ExecutionContext 71704fd306cSNickeau { 71804fd306cSNickeau global $ACT; 71904fd306cSNickeau $ACT = $runningAct; 72004fd306cSNickeau return $this; 72104fd306cSNickeau } 72204fd306cSNickeau 72304fd306cSNickeau 72404fd306cSNickeau /** 72504fd306cSNickeau * Set the main fetcher, the entry point of the request (ie the url of the browser) 72604fd306cSNickeau * that will return a string 72704fd306cSNickeau * @throws ExceptionBadArgument 72804fd306cSNickeau * @throws ExceptionInternal 72904fd306cSNickeau * @throws ExceptionNotFound 73004fd306cSNickeau */ 73104fd306cSNickeau public function createStringMainFetcherFromRequestedUrl(Url $fetchUrl): IFetcherString 73204fd306cSNickeau { 73304fd306cSNickeau $this->executingMainFetcher = FetcherSystem::createFetcherStringFromUrl($fetchUrl); 73404fd306cSNickeau return $this->executingMainFetcher; 73504fd306cSNickeau } 73604fd306cSNickeau 73704fd306cSNickeau 73804fd306cSNickeau /** 73904fd306cSNickeau * Set the main fetcher (with the url of the browser) 74004fd306cSNickeau * that will return a path (image, ...) 74104fd306cSNickeau * @throws ExceptionBadArgument 74204fd306cSNickeau * @throws ExceptionInternal 74304fd306cSNickeau * @throws ExceptionNotFound 74404fd306cSNickeau */ 74504fd306cSNickeau public function createPathMainFetcherFromUrl(Url $fetchUrl): IFetcherPath 74604fd306cSNickeau { 74704fd306cSNickeau $this->executingMainFetcher = FetcherSystem::createPathFetcherFromUrl($fetchUrl); 74804fd306cSNickeau return $this->executingMainFetcher; 74904fd306cSNickeau } 75004fd306cSNickeau 75104fd306cSNickeau public function closeMainExecutingFetcher(): ExecutionContext 75204fd306cSNickeau { 75304fd306cSNickeau unset($this->executingMainFetcher); 75404fd306cSNickeau /** 75504fd306cSNickeau * Snippet are not yet fully coupled to the {@link FetcherMarkup} 75604fd306cSNickeau */ 75704fd306cSNickeau $this->closeAndRemoveRuntimeVariableIfExists(Snippet::CANONICAL); 75804fd306cSNickeau return $this; 75904fd306cSNickeau } 76004fd306cSNickeau 76104fd306cSNickeau /** 76204fd306cSNickeau * This function sets the markup running context object globally, 76304fd306cSNickeau * so that code may access it via this global variable 76404fd306cSNickeau * (Fighting dokuwiki global scope) 76504fd306cSNickeau * @param FetcherMarkup $markupHandler 76604fd306cSNickeau * @return $this 76704fd306cSNickeau */ 76804fd306cSNickeau public function setExecutingMarkupHandler(FetcherMarkup $markupHandler): ExecutionContext 76904fd306cSNickeau { 77004fd306cSNickeau 77104fd306cSNickeau 77204fd306cSNickeau /** 77304fd306cSNickeau * Act 77404fd306cSNickeau */ 77504fd306cSNickeau $oldAct = $this->getExecutingAction(); 77604fd306cSNickeau if (!$markupHandler->isPathExecution() && $oldAct !== ExecutionContext::PREVIEW_ACTION) { 77704fd306cSNickeau /** 77804fd306cSNickeau * Not sure that is is still needed 77904fd306cSNickeau * as we have now the notion of document/fragment 78004fd306cSNickeau * {@link FetcherMarkup::isDocument()} 78104fd306cSNickeau */ 78204fd306cSNickeau $runningAct = FetcherMarkup::MARKUP_DYNAMIC_EXECUTION_NAME; 78304fd306cSNickeau $this->setExecutingAction($runningAct); 78404fd306cSNickeau } 78504fd306cSNickeau 78604fd306cSNickeau /** 78704fd306cSNickeau * Id 78804fd306cSNickeau */ 78904fd306cSNickeau try { 79004fd306cSNickeau $oldExecutingId = $this->getExecutingWikiId(); 79104fd306cSNickeau } catch (ExceptionNotFound $e) { 79204fd306cSNickeau $oldExecutingId = null; 79304fd306cSNickeau } 79404fd306cSNickeau try { 79504fd306cSNickeau 79604fd306cSNickeau $executingPath = $markupHandler->getRequestedExecutingPath(); 79704fd306cSNickeau $executingId = $executingPath->toAbsoluteId(); 79804fd306cSNickeau $this->setExecutingId($executingId); 79904fd306cSNickeau } catch (ExceptionNotFound $e) { 80004fd306cSNickeau // no executing path dynamic markup execution 80104fd306cSNickeau } 80204fd306cSNickeau 80304fd306cSNickeau /** 80404fd306cSNickeau * $INFO (Fragment run, ...) 80504fd306cSNickeau * We don't use {@link pageinfo()} for now 80604fd306cSNickeau * We just advertise if this is a fragment run 80704fd306cSNickeau * via the `id` 80804fd306cSNickeau */ 80904fd306cSNickeau global $INFO; 810*94bd6462Sgerardnico $oldContextId = $INFO['id'] ?? null; 81104fd306cSNickeau if ($markupHandler->isFragment()) { 81204fd306cSNickeau $contextPath = $markupHandler->getRequestedContextPath(); 81304fd306cSNickeau $INFO['id'] = $contextPath->getWikiId(); 81404fd306cSNickeau } 81504fd306cSNickeau 81604fd306cSNickeau /** 81704fd306cSNickeau * Call to Fetcher Markup can be recursive, 81804fd306cSNickeau * we try to break a loop 81904fd306cSNickeau * 82004fd306cSNickeau * Note that the same object may call recursively: 82104fd306cSNickeau * * the {@link FetcherMarkup::processMetaEventually()} metadata may call the {@link FetcherMarkup::getInstructions() instructions}, 82204fd306cSNickeau */ 82304fd306cSNickeau $id = $markupHandler->getId(); 82404fd306cSNickeau if (array_key_exists($id, $this->executingMarkupHandlerStack)) { 82504fd306cSNickeau LogUtility::internalError("The markup ($id) is already executing"); 82604fd306cSNickeau $id = "$id-already-in-stack"; 82704fd306cSNickeau } 82804fd306cSNickeau $this->executingMarkupHandlerStack[$id] = [$markupHandler, $oldExecutingId, $oldContextId, $oldAct]; 82904fd306cSNickeau return $this; 83004fd306cSNickeau } 83104fd306cSNickeau 83204fd306cSNickeau public 83304fd306cSNickeau function closeExecutingMarkupHandler(): ExecutionContext 83404fd306cSNickeau { 83504fd306cSNickeau /** @noinspection PhpUnusedLocalVariableInspection */ 83604fd306cSNickeau [$markupHandler, $oldExecutingId, $oldContextId, $oldAct] = array_pop($this->executingMarkupHandlerStack); 83704fd306cSNickeau 83804fd306cSNickeau $this 83904fd306cSNickeau ->setExecutingAction($oldAct) 84004fd306cSNickeau ->setExecutingId($oldExecutingId); 84104fd306cSNickeau 84204fd306cSNickeau global $INFO; 84304fd306cSNickeau if ($oldExecutingId === null) { 84404fd306cSNickeau unset($INFO['id']); 84504fd306cSNickeau } else { 84604fd306cSNickeau $INFO['id'] = $oldContextId; 84704fd306cSNickeau } 84804fd306cSNickeau return $this; 84904fd306cSNickeau } 85004fd306cSNickeau 85104fd306cSNickeau 85204fd306cSNickeau /** 85304fd306cSNickeau * @throws ExceptionNotFound - if there is no markup handler execution running 85404fd306cSNickeau */ 85504fd306cSNickeau public 85604fd306cSNickeau function getExecutingMarkupHandler(): FetcherMarkup 85704fd306cSNickeau { 85804fd306cSNickeau $count = count($this->executingMarkupHandlerStack); 85904fd306cSNickeau if ($count >= 1) { 86004fd306cSNickeau return $this->executingMarkupHandlerStack[array_key_last($this->executingMarkupHandlerStack)][0]; 86104fd306cSNickeau } 86204fd306cSNickeau throw new ExceptionNotFound("No markup handler running"); 86304fd306cSNickeau } 86404fd306cSNickeau 86504fd306cSNickeau /** 86604fd306cSNickeau * @throws ExceptionNotFound - if there is no parent markup handler execution found 86704fd306cSNickeau */ 86804fd306cSNickeau public 86904fd306cSNickeau function getExecutingParentMarkupHandler(): FetcherMarkup 87004fd306cSNickeau { 87104fd306cSNickeau return $this->getExecutingMarkupHandler()->getParent(); 87204fd306cSNickeau } 87304fd306cSNickeau 87404fd306cSNickeau /** 87504fd306cSNickeau * This function sets the default context path. 87604fd306cSNickeau * 87704fd306cSNickeau * Mostly used in test, to determine relative path 87804fd306cSNickeau * when testing {@link LinkMarkup} and {@link WikiPath} 87904fd306cSNickeau * and not use a {@link FetcherMarkup} 88004fd306cSNickeau * 88104fd306cSNickeau * @param WikiPath $contextPath - a markup file context path used (not a namespace) 88204fd306cSNickeau * @return $this 88304fd306cSNickeau * @deprecated 88404fd306cSNickeau */ 88504fd306cSNickeau public 88604fd306cSNickeau function setDefaultContextPath(WikiPath $contextPath): ExecutionContext 88704fd306cSNickeau { 88804fd306cSNickeau $this->getConfig()->setDefaultContextPath($contextPath); 88904fd306cSNickeau return $this; 89004fd306cSNickeau } 89104fd306cSNickeau 89204fd306cSNickeau 89304fd306cSNickeau /** 89404fd306cSNickeau * @return WikiPath - the context path is a markup file that gives context. 89504fd306cSNickeau * Ie this is the equivalent of the current directory. 89604fd306cSNickeau * When a link/path is empty or relative, the program will check for the context path 89704fd306cSNickeau * to calculate the absolute path 89804fd306cSNickeau */ 89904fd306cSNickeau public 90004fd306cSNickeau function getContextPath(): WikiPath 90104fd306cSNickeau { 90204fd306cSNickeau 90304fd306cSNickeau try { 90404fd306cSNickeau 90504fd306cSNickeau /** 90604fd306cSNickeau * Do we a fetcher markup running ? 90704fd306cSNickeau * (It's first as we may change it 90804fd306cSNickeau * for a slot for instance) 90904fd306cSNickeau */ 91004fd306cSNickeau return $this 91104fd306cSNickeau ->getExecutingMarkupHandler() 91204fd306cSNickeau ->getRequestedContextPath(); 91304fd306cSNickeau 91404fd306cSNickeau } catch (ExceptionNotFound $e) { 91504fd306cSNickeau try { 91604fd306cSNickeau 91704fd306cSNickeau /** 91804fd306cSNickeau * Do we have a template page executing ? 91904fd306cSNickeau */ 92004fd306cSNickeau return $this->getExecutingPageTemplate() 92104fd306cSNickeau ->getRequestedContextPath(); 92204fd306cSNickeau 92304fd306cSNickeau } catch (ExceptionNotFound $e) { 92404fd306cSNickeau 92504fd306cSNickeau /** 92604fd306cSNickeau * Hack, hack, hack 92704fd306cSNickeau * In preview mode, the context path is the last visited page 92804fd306cSNickeau * for a slot 92904fd306cSNickeau */ 93004fd306cSNickeau global $ACT; 93104fd306cSNickeau if ($ACT === ExecutionContext::PREVIEW_ACTION) { 93204fd306cSNickeau global $ID; 93304fd306cSNickeau if (!empty($ID)) { 93404fd306cSNickeau try { 93504fd306cSNickeau $markupPath = MarkupPath::createMarkupFromId($ID); 93604fd306cSNickeau if ($markupPath->isSlot()) { 93704fd306cSNickeau return SlotSystem::getContextPath()->toWikiPath(); 93804fd306cSNickeau } 93904fd306cSNickeau } catch (ExceptionCast|ExceptionNotFound $e) { 94004fd306cSNickeau // ok 94104fd306cSNickeau } 94204fd306cSNickeau } 94304fd306cSNickeau } 94404fd306cSNickeau 94504fd306cSNickeau /** 94604fd306cSNickeau * Nope ? This is a dokuwiki run (admin page, ...) 94704fd306cSNickeau */ 94804fd306cSNickeau return $this->getConfig()->getDefaultContextPath(); 94904fd306cSNickeau 95004fd306cSNickeau } 95104fd306cSNickeau 95204fd306cSNickeau } 95304fd306cSNickeau 95404fd306cSNickeau 95504fd306cSNickeau } 95604fd306cSNickeau 95704fd306cSNickeau 95804fd306cSNickeau /** 95904fd306cSNickeau * @return WikiPath 96004fd306cSNickeau * @deprecated uses {@link SiteConfig::getDefaultContextPath()} 96104fd306cSNickeau */ 96204fd306cSNickeau public 96304fd306cSNickeau function getDefaultContextPath(): WikiPath 96404fd306cSNickeau { 96504fd306cSNickeau return $this->getConfig()->getDefaultContextPath(); 96604fd306cSNickeau } 96704fd306cSNickeau 96804fd306cSNickeau /** 96904fd306cSNickeau * The page global context object 97004fd306cSNickeau * @throws ExceptionNotFound 97104fd306cSNickeau */ 97204fd306cSNickeau public 97304fd306cSNickeau function getExecutingPageTemplate(): TemplateForWebPage 97404fd306cSNickeau { 97504fd306cSNickeau if (isset($this->executingPageTemplate)) { 97604fd306cSNickeau return $this->executingPageTemplate; 97704fd306cSNickeau } 97804fd306cSNickeau throw new ExceptionNotFound("No page template execution running"); 97904fd306cSNickeau } 98004fd306cSNickeau 98104fd306cSNickeau /** 98204fd306cSNickeau * Set the page template that is executing. 98304fd306cSNickeau * It's the context object for all page related 98404fd306cSNickeau * (mostly header event) 98504fd306cSNickeau * @param TemplateForWebPage $pageTemplate 98604fd306cSNickeau * @return $this 98704fd306cSNickeau */ 98804fd306cSNickeau public 98904fd306cSNickeau function setExecutingPageTemplate(TemplateForWebPage $pageTemplate): ExecutionContext 99004fd306cSNickeau { 99104fd306cSNickeau $this->executingPageTemplate = $pageTemplate; 99204fd306cSNickeau return $this; 99304fd306cSNickeau } 99404fd306cSNickeau 99504fd306cSNickeau public 99604fd306cSNickeau function closeExecutingPageTemplate(): ExecutionContext 99704fd306cSNickeau { 99804fd306cSNickeau unset($this->executingPageTemplate); 99904fd306cSNickeau return $this; 100004fd306cSNickeau } 100104fd306cSNickeau 100204fd306cSNickeau public 100304fd306cSNickeau function getApp(): Site 100404fd306cSNickeau { 100504fd306cSNickeau if (isset($this->app)) { 100604fd306cSNickeau return $this->app; 100704fd306cSNickeau } 100804fd306cSNickeau $this->app = new Site($this); 100904fd306cSNickeau return $this->app; 101004fd306cSNickeau } 101104fd306cSNickeau 101204fd306cSNickeau /** 101304fd306cSNickeau * @return SiteConfig short utility function to get access to the global app config 101404fd306cSNickeau */ 101504fd306cSNickeau public 101604fd306cSNickeau function getConfig(): SiteConfig 101704fd306cSNickeau { 101804fd306cSNickeau return $this->getApp()->getConfig(); 101904fd306cSNickeau } 102004fd306cSNickeau 102104fd306cSNickeau /** 102204fd306cSNickeau * @throws ExceptionNotFound - when there is no executing id (markup execution) 102304fd306cSNickeau */ 102404fd306cSNickeau public 102504fd306cSNickeau function getExecutingWikiPath(): WikiPath 102604fd306cSNickeau { 102704fd306cSNickeau try { 102804fd306cSNickeau return $this->getExecutingMarkupHandler() 102904fd306cSNickeau ->getRequestedExecutingPath() 103004fd306cSNickeau ->toWikiPath(); 103104fd306cSNickeau } catch (ExceptionCast|ExceptionNotFound $e) { 103204fd306cSNickeau // Execution without templating (ie without fetcher markup) 103304fd306cSNickeau return WikiPath::createMarkupPathFromId($this->getExecutingWikiId()); 103404fd306cSNickeau } 103504fd306cSNickeau 103604fd306cSNickeau } 103704fd306cSNickeau 103804fd306cSNickeau /** 103904fd306cSNickeau * @return array - data in context 104004fd306cSNickeau * This is the central point to get data in context as there is no 104104fd306cSNickeau * content object in dokuwiki 104204fd306cSNickeau * 104304fd306cSNickeau * It takes care of returning the context path 104404fd306cSNickeau * (in case of slot via the {@link self::getContextPath()} 104504fd306cSNickeau */ 104604fd306cSNickeau public 104704fd306cSNickeau function getContextData(): array 104804fd306cSNickeau { 104904fd306cSNickeau 105004fd306cSNickeau try { 105104fd306cSNickeau 105204fd306cSNickeau /** 105304fd306cSNickeau * Context data may be dynamically given 105404fd306cSNickeau * by the {@link \syntax_plugin_combo_iterator} 105504fd306cSNickeau */ 105604fd306cSNickeau return $this 105704fd306cSNickeau ->getExecutingMarkupHandler() 105804fd306cSNickeau ->getContextData(); 105904fd306cSNickeau 106004fd306cSNickeau } catch (ExceptionNotFound $e) { 106104fd306cSNickeau 106204fd306cSNickeau /** 106304fd306cSNickeau * Preview / slot 106404fd306cSNickeau */ 106504fd306cSNickeau return MarkupPath::createPageFromPathObject($this->getContextPath())->getMetadataForRendering(); 106604fd306cSNickeau 106704fd306cSNickeau } 106804fd306cSNickeau 106904fd306cSNickeau } 107004fd306cSNickeau 107104fd306cSNickeau /** 107204fd306cSNickeau * This method will delete the global identifier 107304fd306cSNickeau * and call the 'close' method if the method exists. 107404fd306cSNickeau * @param string $globalObjectIdentifier 107504fd306cSNickeau * @return void 107604fd306cSNickeau */ 107704fd306cSNickeau public 107804fd306cSNickeau function closeAndRemoveRuntimeVariableIfExists(string $globalObjectIdentifier) 107904fd306cSNickeau { 108004fd306cSNickeau 108104fd306cSNickeau if (!isset($this->executionScopedVariables[$globalObjectIdentifier])) { 108204fd306cSNickeau return; 108304fd306cSNickeau } 108404fd306cSNickeau 108504fd306cSNickeau /** 108604fd306cSNickeau * Get the object references 108704fd306cSNickeau */ 108804fd306cSNickeau $object = &$this->executionScopedVariables[$globalObjectIdentifier]; 108904fd306cSNickeau 109004fd306cSNickeau 109104fd306cSNickeau /** 109204fd306cSNickeau * Call the close method 109304fd306cSNickeau */ 109404fd306cSNickeau if (is_object($object)) { 109504fd306cSNickeau if (method_exists($object, 'close')) { 109604fd306cSNickeau $object->close(); 109704fd306cSNickeau } 109804fd306cSNickeau } 109904fd306cSNickeau 110004fd306cSNickeau /** 110104fd306cSNickeau * Close it really by setting null 110204fd306cSNickeau * 110304fd306cSNickeau * (Forwhatever reason, sqlite closing in php 110404fd306cSNickeau * is putting the variable to null) 110504fd306cSNickeau */ 110604fd306cSNickeau $object = null; 110704fd306cSNickeau 110804fd306cSNickeau /** 110904fd306cSNickeau * Delete it from the array 111004fd306cSNickeau */ 111104fd306cSNickeau unset($this->executionScopedVariables[$globalObjectIdentifier]); 111204fd306cSNickeau 111304fd306cSNickeau } 111404fd306cSNickeau 111504fd306cSNickeau /** 111604fd306cSNickeau * Close all execution variables 111704fd306cSNickeau */ 111804fd306cSNickeau public 111904fd306cSNickeau function closeExecutionVariables(): ExecutionContext 112004fd306cSNickeau { 112104fd306cSNickeau $scopedVariables = array_keys($this->executionScopedVariables); 112204fd306cSNickeau foreach ($scopedVariables as $executionScopedVariableKey) { 112304fd306cSNickeau $this->closeAndRemoveRuntimeVariableIfExists($executionScopedVariableKey); 112404fd306cSNickeau } 112504fd306cSNickeau return $this; 112604fd306cSNickeau } 112704fd306cSNickeau 112804fd306cSNickeau public 112904fd306cSNickeau function __toString() 113004fd306cSNickeau { 113104fd306cSNickeau return $this->creationTime; 113204fd306cSNickeau } 113304fd306cSNickeau 113404fd306cSNickeau public 113504fd306cSNickeau function isExecutingPageTemplate(): bool 113604fd306cSNickeau { 113704fd306cSNickeau try { 113804fd306cSNickeau $this->getExecutingPageTemplate(); 113904fd306cSNickeau return true; 114004fd306cSNickeau } catch (ExceptionNotFound $e) { 114104fd306cSNickeau return false; 114204fd306cSNickeau } 114304fd306cSNickeau } 114404fd306cSNickeau 114504fd306cSNickeau public 114604fd306cSNickeau function hasExecutingMarkupHandler(): bool 114704fd306cSNickeau { 114804fd306cSNickeau try { 114904fd306cSNickeau $this->getExecutingMarkupHandler(); 115004fd306cSNickeau return true; 115104fd306cSNickeau } catch (ExceptionNotFound $e) { 115204fd306cSNickeau return false; 115304fd306cSNickeau } 115404fd306cSNickeau } 115504fd306cSNickeau 115604fd306cSNickeau 115704fd306cSNickeau} 1158