1<?php 2 3use ComboStrap\DokuwikiId; 4use ComboStrap\ExceptionNotFound; 5use ComboStrap\ExceptionReporter; 6use ComboStrap\ExecutionContext; 7use ComboStrap\FetcherAppPages; 8use ComboStrap\FetcherPage; 9use ComboStrap\FileSystems; 10use ComboStrap\HttpResponseStatus; 11use ComboStrap\IFetcher; 12use ComboStrap\LogUtility; 13use ComboStrap\MarkupPath; 14use ComboStrap\Mime; 15use ComboStrap\PluginUtility; 16use ComboStrap\Site; 17use ComboStrap\SiteConfig; 18use ComboStrap\Web\Url; 19use ComboStrap\Web\UrlRewrite; 20 21/** 22 * Implementation of custom do (ie ACT) to output {@link \ComboStrap\IFetcherString} 23 * 24 * 25 * 26 */ 27class action_plugin_combo_docustom extends DokuWiki_Action_Plugin 28{ 29 30 const DO_PREFIX = "combo_"; 31 32 const TEMPLATE_CANONICAL = "template"; 33 34 /** 35 * @var bool to avoid recursion that may happen using {@link tpl_content()} 36 */ 37 private bool $doCustomActuallyExecuting = false; 38 39 /** 40 * @return bool 41 */ 42 public static function isThemeSystemEnabled(): bool 43 { 44 $confValue = SiteConfig::getConfValue(SiteConfig::CONF_ENABLE_THEME_SYSTEM, SiteConfig::CONF_ENABLE_THEME_SYSTEM_DEFAULT); 45 return $confValue === 1; 46 } 47 48 public static function getDoParameterValue(string $fetcherName): string 49 { 50 return self::DO_PREFIX . $fetcherName; 51 } 52 53 /** 54 * 55 * @param Doku_Event_Handler $controller 56 * @return void 57 */ 58 59 public function register(\Doku_Event_Handler $controller) 60 { 61 /** 62 * Execute the combo action via an ACTION_ACT_PREPROCESS 63 * 64 * Not via the [TPL_ACT_UNKNOWN](https://www.dokuwiki.org/devel:event:tpl_act_unknown) 65 * because it would otherwise put the content in the middle of the page 66 * as an admin page. 67 * 68 * Not really useful if you want your own layout or do an export 69 */ 70 $controller->register_hook('ACTION_ACT_PREPROCESS', 'BEFORE', $this, 'executeComboDoAction'); 71 72 } 73 74 /** 75 * @param Doku_Event $event 76 * @param $param 77 * @return void 78 * 79 */ 80 public function executeComboDoAction(Doku_Event $event, $param) 81 { 82 83 if ($this->doCustomActuallyExecuting) { 84 return; 85 } 86 87 /** 88 * The router may have done a redirection 89 * (The Dokuwiki testRequest does not stop unfortunately) 90 */ 91 $executionContext = ExecutionContext::getActualOrCreateFromEnv(); 92 $hasEnded = $executionContext 93 ->response() 94 ->hasEnded(); 95 if ($hasEnded) { 96 if ($executionContext->isTestRun()) { 97 /** 98 * This info helps the developer to see 99 * why nothing happens when it sends two dokuwiki {@link TestRequest} 100 * 101 * And not two {@link \ComboStrap\HttpResponse} 102 * that reinitialize the global scope 103 */ 104 LogUtility::info("ExecuteDoAction: The response has already be send (ended)."); 105 } 106 return; 107 } 108 109 $urlRewrite = Site::getUrlRewrite(); 110 if ($urlRewrite == UrlRewrite::VALUE_DOKU_REWRITE) { 111 UrlRewrite::sendErrorMessage(); 112 return; 113 } 114 115 $action = $event->data; 116 117 if (self::isThemeSystemEnabled()) { 118 switch ($action) { 119 case "show": 120 try { 121 $id = Url::createFromGetOrPostGlobalVariable()->getPropertyValue(DokuwikiId::DOKUWIKI_ID_ATTRIBUTE); 122 } catch (ExceptionNotFound $e) { 123 // should not happen but yeah 124 return; 125 } 126 $path = MarkupPath::createMarkupFromId($id); 127 if (!FileSystems::exists($path)) { 128 return; 129 } 130 $action = self::getDoParameterValue(FetcherPage::NAME); 131 break; 132 case ExecutionContext::LOGIN_ACTION: 133 case ExecutionContext::REGISTER_ACTION: 134 case ExecutionContext::RESEND_PWD_ACTION: 135 case ExecutionContext::PROFILE_ACTION: 136 case ExecutionContext::EDIT_ACTION: 137 case ExecutionContext::PREVIEW_ACTION: 138 case ExecutionContext::SEARCH_ACTION: 139 case ExecutionContext::INDEX_ACTION: 140 //case ExecutionContext::REVISIONS_ACTION: 141 //case ExecutionContext::DIFF_ACTION: needs styling 142 $action = self::getDoParameterValue(FetcherAppPages::NAME); 143 break; 144 } 145 } 146 147 if (!$this->isComboDoAction($action)) return; 148 149 /** 150 * To avoid recursion 151 */ 152 $this->doCustomActuallyExecuting = true; 153 154 155 try { 156 $fetcherName = $this->getFetcherNameFromAction($action); 157 $url = Url::createFromGetOrPostGlobalVariable() 158 ->addQueryParameter(IFetcher::FETCHER_KEY, $fetcherName); 159 $fetcher = $executionContext->createStringMainFetcherFromRequestedUrl($url); 160 $body = $fetcher->getFetchString(); 161 $mime = $fetcher->getMime(); 162 $executionContext->response() 163 ->setStatus(HttpResponseStatus::ALL_GOOD) 164 ->setBody($body, $mime) 165 ->end(); 166 } catch (\Exception $e) { 167 168 169 $reporterMessage = "An error has occurred during the execution of the action ($action)"; 170 $html = ExceptionReporter::createForException($e) 171 ->getHtmlPage($reporterMessage); 172 if (PluginUtility::isDevOrTest()) { 173 // Permits to throw the error to get the stack trace 174 LogUtility::warning($reporterMessage, self::TEMPLATE_CANONICAL, $e); 175 } 176 $executionContext->response() 177 ->setException($e) 178 ->setBody($html, Mime::getHtml()) 179 ->end(); 180 181 } finally { 182 $this->doCustomActuallyExecuting = false; 183 } 184 185 } 186 187 188 private function isComboDoAction($actionName): bool 189 { 190 return strpos($actionName, self::DO_PREFIX) === 0; 191 } 192 193 private function getFetcherNameFromAction($actionName) 194 { 195 return substr($actionName, strlen(self::DO_PREFIX)); 196 } 197 198 199} 200