1 <?php
2 
3 
4 namespace ComboStrap;
5 
6 
7 use ComboStrap\Meta\Api\Metadata;
8 use ComboStrap\Meta\Api\MetadataStore;
9 use ComboStrap\Meta\Api\MetadataText;
10 use ComboStrap\Meta\Store\MetadataDokuWikiStore;
11 use syntax_plugin_combo_frontmatter;
12 
13 class PageDescription extends MetadataText
14 {
15 
16     /**
17      * The description sub key in the dokuwiki meta
18      * that has the description text
19      */
20     const ABSTRACT_KEY = "abstract";
21     public const PROPERTY_NAME = "description";
22     const DESCRIPTION_ORIGIN = "origin";
23     const PLUGIN_DESCRIPTION_META = "plugin_description";
24 
25 
26     /**
27      * @var string - the origin of the description
28      */
29     private $descriptionOrigin;
30 
31 
32     public const DESCRIPTION_PROPERTY = "description";
33     /**
34      * To indicate from where the description comes
35      * This is when it's the original dokuwiki description
36      */
37     public const DESCRIPTION_DOKUWIKI_ORIGIN = "dokuwiki";
38     /**
39      * The origin of the description was set to frontmatter
40      * due to historic reason to say to it comes from combo
41      * (You may set it via the metadata manager and get this origin)
42      */
43     public const DESCRIPTION_COMBO_ORIGIN = syntax_plugin_combo_frontmatter::CANONICAL;
44     private ?string $defaultValue = null;
45 
46     public static function createForPage($page): PageDescription
47     {
48         return (new PageDescription())
49             ->setResource($page);
50     }
51 
52     public static function getTab(): string
53     {
54         return MetaManagerForm::TAB_PAGE_VALUE;
55     }
56 
57     public static function getDescription(): string
58     {
59         return "The description is a paragraph that describe your page. It's advertised to external application and used in templating.";
60     }
61 
62     public static function getLabel(): string
63     {
64         return "Description";
65     }
66 
67     static public function getName(): string
68     {
69         return self::DESCRIPTION_PROPERTY;
70     }
71 
72     public static function getPersistenceType(): string
73     {
74         return MetadataDokuWikiStore::PERSISTENT_DOKUWIKI_KEY;
75     }
76 
77     public static function getDataType(): string
78     {
79         return DataType::PARAGRAPH_TYPE_VALUE;
80     }
81 
82 
83     public static function isMutable(): bool
84     {
85         return true;
86     }
87 
88 
89     /**
90      * @return string
91      */
92     public function getValueOrDefault(): string
93     {
94 
95         try {
96             $value = $this->getValue();
97             if (empty($value)) {
98                 return $this->getDefaultValue();
99             }
100             return $value;
101         } catch (ExceptionNotFound $e) {
102             return $this->getDefaultValue();
103         }
104 
105 
106     }
107 
108 
109     /**
110      * @return string - the dokuwiki calculated description
111      * or the resource name if none (case when there is no text at all for instance with only a icon)
112      */
113     public function getDefaultValue(): string
114     {
115 
116         $this->buildCheck();
117         if ($this->defaultValue === "" || $this->defaultValue === null) {
118             return PageTitle::createForMarkup($this->getResource())
119                 ->getValueOrDefault();
120         }
121         return $this->defaultValue;
122 
123     }
124 
125 
126     public function setFromStoreValueWithoutException($value): Metadata
127     {
128 
129         $metaDataStore = $this->getReadStore();
130         if (!$metaDataStore->isDokuWikiStore()) {
131             parent::setFromStoreValueWithoutException($value);
132             return $this;
133         }
134 
135         if (is_array($value)) {
136             $description = $value[self::ABSTRACT_KEY];
137             if ($description !== null) {
138                 $descriptionOrigin = $value[self::DESCRIPTION_ORIGIN] ?? null;
139                 if ($descriptionOrigin !== null) {
140                     $this->descriptionOrigin = $descriptionOrigin;
141                     parent::setFromStoreValueWithoutException($description);
142                     return $this;
143                 }
144             }
145         }
146         /**
147          * Plugin Plugin Description Integration
148          */
149         $value = $metaDataStore->getFromName(self::PLUGIN_DESCRIPTION_META);
150         if ($value !== null) {
151             $keywords = $value["keywords"];
152             if ($keywords !== null) {
153                 parent::setFromStoreValueWithoutException($keywords);
154                 $this->descriptionOrigin = self::PLUGIN_DESCRIPTION_META;
155                 return $this;
156             }
157         }
158 
159         /**
160          * No description set, null
161          */
162         parent::setFromStoreValueWithoutException(null);
163 
164         /**
165          * Default value is derived from the meta store
166          * We need to set it at build time because the store may change
167          * after the build
168          */
169         $this->defaultValue = $this->getGeneratedValueFromDokuWikiStore($metaDataStore);
170 
171         return $this;
172     }
173 
174 
175     public function setValue($value): Metadata
176     {
177 
178         if ($value === "" || $value === null) {
179 
180             if ($this->getReadStore() instanceof MetadataDokuWikiStore) {
181                 // we need to know the origin of the actual description
182                 if ($this->descriptionOrigin === null) {
183                     /**
184                      * we don't do {@link Metadata::buildCheck() build check} otherwise we get a loop
185                      * because it will use back this method {@link Metadata::setValue()}
186                      */
187                     $this->buildFromReadStore();
188                 }
189                 if ($this->descriptionOrigin === PageDescription::DESCRIPTION_COMBO_ORIGIN) {
190                     throw new ExceptionCompile("The description cannot be empty", PageDescription::DESCRIPTION_PROPERTY);
191                 } else {
192                     // The original description is from Dokuwiki, we don't send an error
193                     // otherwise all page without a first description would get an error
194                     // (What fucked up is fucked up)
195                     return $this;
196                 }
197             }
198 
199         }
200 
201         parent::setValue($value);
202         return $this;
203     }
204 
205     /**
206      * @return ?string|array
207      */
208     public function toStoreValue()
209     {
210         $metaDataStore = $this->getWriteStore();
211         if (!($metaDataStore instanceof MetadataDokuWikiStore)) {
212             // A string
213             return parent::toStoreValue();
214         }
215         /**
216          * For dokuwiki, this is an array
217          */
218         try {
219             return array(
220                 self::ABSTRACT_KEY => $this->getValue(),
221                 self::DESCRIPTION_ORIGIN => PageDescription::DESCRIPTION_COMBO_ORIGIN
222             );
223         } catch (ExceptionNotFound $e) {
224             return null;
225         }
226     }
227 
228 
229     public function getDescriptionOrigin(): string
230     {
231         return $this->descriptionOrigin;
232     }
233 
234     private function getGeneratedValueFromDokuWikiStore(MetadataStore $metaDataStore): ?string
235     {
236 
237         /**
238          * The generated is in the current metadata
239          */
240         $descriptionArray = $metaDataStore->getFromName(self::PROPERTY_NAME);
241         if (empty($descriptionArray)) {
242             return null;
243         }
244         if (!array_key_exists(self::ABSTRACT_KEY, $descriptionArray)) {
245             return null;
246         }
247         $value = $descriptionArray[self::ABSTRACT_KEY];
248 
249 
250         /**
251          * Dokuwiki description
252          * With some trick
253          * TODO: Generate our own description ?
254          */
255         // suppress the carriage return
256         $description = str_replace("\n", " ", $value);
257         // suppress the h1
258         $resourceCombo = $this->getResource();
259         if ($resourceCombo instanceof MarkupPath) {
260             $description = str_replace($resourceCombo->getH1OrDefault(), "", $description);
261         }
262         // Suppress the star, the tab, About
263         $description = preg_replace('/(\*|\t|About)/im', "", $description);
264         // Suppress all double space and trim
265         return trim(preg_replace('/ /m', " ", $description));
266     }
267 
268 
269     public static function isOnForm(): bool
270     {
271         return true;
272     }
273 }
274