1 <?php
2 
3 namespace ComboStrap;
4 
5 
6 use action_plugin_combo_css;
7 use ComboStrap\Api\ApiRouter;
8 use ComboStrap\Meta\Field\PageTemplateName;
9 use ComboStrap\Web\Url;
10 use ComboStrap\Web\UrlEndpoint;
11 
12 /**
13  *
14  * This code permits to render a markup from a string passed as argument
15  *
16  * Technically, it's the same than {@link FetcherMarkup}
17  * but:
18  *   * it outputs the HTML within a minimal HTML page (no layout as in {@link FetcherPage})
19  *   * it gets the input from the url query properties
20  *
21  * It's used primarily by {@link \syntax_plugin_combo_webcode}
22  * that's why it's called webcode.
23  *
24  */
25 class FetcherMarkupWebcode extends IFetcherAbs implements IFetcherString
26 {
27 
28     const CANONICAL = "webcode";
29     const NAME = "markup";
30 
31     public const MARKUP_PROPERTY = "markup";
32     const TITLE_PROPERTY = "title";
33 
34     private string $requestedMarkup;
35     private string $requestedTitle = "ComboStrap WebCode - Markup Renderer";
36 
37     public static function createFetcherMarkup(string $markup): FetcherMarkupWebcode
38     {
39         return (new FetcherMarkupWebcode())
40             ->setRequestedMarkup($markup);
41     }
42 
43     /**
44      * @throws ExceptionBadState - the markup is mandatory
45      */
46     function getFetchUrl(Url $url = null): Url
47     {
48         $url = UrlEndpoint::createAjaxUrl()
49             ->addQueryParameter(ApiRouter::AJAX_CALL_ATTRIBUTE, ApiRouter::AJAX_CALL_VALUE)
50             ->addQueryParameter(self::MARKUP_PROPERTY, $this->getRequestedMarkup())
51             ->addQueryParameter(self::TITLE_PROPERTY, $this->getRequestedTitle());
52         return parent::getFetchUrl($url);
53     }
54 
55 
56     function getBuster(): string
57     {
58         try {
59             return FileSystems::getCacheBuster(ClassUtility::getClassPath(FetcherMarkupWebcode::class));
60         } catch (ExceptionNotFound|\ReflectionException $e) {
61             LogUtility::internalError("The cache buster should be good. Error:{$e->getMessage()}", self::NAME);
62             return "";
63         }
64     }
65 
66     public function buildFromTagAttributes(TagAttributes $tagAttributes): IFetcher
67     {
68 
69         $markupProperty = self::MARKUP_PROPERTY;
70         $markup = $tagAttributes->getValueAndRemove($markupProperty);
71         if ($markup === null) {
72             throw new ExceptionBadArgument("The markup property ($markupProperty) is mandatory");
73         }
74         $this->setRequestedMarkup($markup);
75         $title = $tagAttributes->getValueAndRemove(self::TITLE_PROPERTY);
76         if ($title !== null) {
77             $this->setRequestedTitle($title);
78         }
79         return parent::buildFromTagAttributes($tagAttributes);
80     }
81 
82 
83     public function getMime(): Mime
84     {
85         return Mime::getHtml();
86     }
87 
88     public function getFetcherName(): string
89     {
90         return self::NAME;
91     }
92 
93     /**
94      * @return string
95      * @throws ExceptionBadState - if the markup was not defined
96      * @throws ExceptionCompile - if any error
97      */
98     public function getFetchString(): string
99     {
100 
101         /**
102          * Conf
103          */
104         ExecutionContext::getActualOrCreateFromEnv()
105             ->getConfig()
106             ->setConf(action_plugin_combo_css::CONF_DISABLE_DOKUWIKI_STYLESHEET, true);
107 
108         $fetcherCache = FetcherCache::createFrom($this);
109         if ($fetcherCache->isCacheUsable()) {
110             try {
111                 return FileSystems::getContent($fetcherCache->getFile());
112             } catch (ExceptionNotFound $e) {
113                 $message = "The cache file should exists";
114                 if (PluginUtility::isDevOrTest()) {
115                     throw new ExceptionRuntimeInternal($message);
116                 }
117                 LogUtility::internalError($message);
118             }
119         }
120 
121         $requestedMarkup = $this->getRequestedMarkup();
122 
123         try {
124             $mainContent = FetcherMarkup::confRoot()
125                 ->setRequestedMarkupString($requestedMarkup)
126                 ->setDeleteRootBlockElement(true)
127                 ->setRequestedMimeToXhtml()
128                 ->setRequestedContextPathWithDefault()
129                 ->setIsStandAloneCodeExecution(true)
130                 ->build()
131                 ->getFetchString();
132         } catch (ExceptionNotExists|ExceptionCompile $e) {
133             throw new ExceptionRuntimeInternal("An error has occurred while transforming the markup fragment to HTML. Error: {$e->getMessage()}", self::CANONICAL, 1, $e);
134         }
135 
136         $title = $this->getRequestedTitle();
137 
138         $html = TemplateForWebPage::create()
139             ->setRequestedTitle($title)
140             ->setRequestedTemplateName(PageTemplateName::BLANK_TEMPLATE_VALUE)
141             ->setRequestedEnableTaskRunner(false)
142             ->setIsIframe(true)
143             ->setMainContent($mainContent)
144             ->render();
145 
146         $fetcherCache->storeCache($html);
147         return $html;
148 
149     }
150 
151     public function setRequestedMarkup(string $markup): FetcherMarkupWebcode
152     {
153         $this->requestedMarkup = $markup;
154         return $this;
155 
156     }
157 
158     public function setRequestedTitle(string $title): FetcherMarkupWebcode
159     {
160         $this->requestedTitle = $title;
161         return $this;
162     }
163 
164     /**
165      * @throws ExceptionBadState
166      */
167     private function getRequestedMarkup(): string
168     {
169         if (!isset($this->requestedMarkup)) {
170             throw new ExceptionBadState("The markup was not defined.", self::CANONICAL);
171         }
172         return $this->requestedMarkup;
173     }
174 
175     private function getRequestedTitle(): string
176     {
177         return $this->requestedTitle;
178     }
179 
180 
181     public function getLabel(): string
182     {
183         return self::CANONICAL;
184     }
185 
186 }
187