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