AbstractWikiTemplate::setParamOrderByUser()   A
last analyzed

Complexity

Conditions 4
Paths 5

Size

Total Lines 13
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 10
CRAP Score 4

Importance

Changes 0
Metric Value
cc 4
eloc 9
nc 5
nop 1
dl 0
loc 13
ccs 10
cts 10
cp 1
crap 4
rs 9.9666
c 0
b 0
f 0
1
<?php
2
/*
3
 * This file is part of dispositif/wikibot application (@github)
4
 * 2019-2023 © Philippe M./Irønie  <[email protected]>
5
 * For the full copyright and MIT license information, view the license file.
6
 */
7
8
declare(strict_types=1);
9
10
namespace App\Domain\Models\Wiki;
11
12
use App\Domain\Utils\ArrayProcessTrait;
13
use App\Domain\Utils\TemplateParser;
14
use App\Domain\Utils\WikiArrayTrait;
15
use App\Domain\Utils\WikiTextUtil;
16
use DomainException;
17
use Exception;
18
19
/**
20
 * todo correct text bellow
21
 * The mother of all the wiki-template classes.
22
 * Methods for the wiki-parameters data, hydratation, personnal wiki-style conservation, required params,
23
 * handling error/alias of wiki-parameters, complex serialization into wikicode (minimum params), etc.
24
 * No abstract method.
25
 * Minimum setup for child class : set 'const MODEL_NAME' and it's done !
26
 * Class AbstractWikiTemplate.
27
 */
28
abstract class AbstractWikiTemplate extends AbstractStrictWikiTemplate implements WikiTemplateInterface
29
{
30
    use ArrayProcessTrait, WikiArrayTrait, InfoTrait;
31
32
    protected const ALLOW_USER_MULTI_SPACED = true;
33
34
    public $parametersErrorFromHydrate;
35
36
    public $userSeparator;
37
38
    public bool $userMultiSpaced = false;
39
40
    /**
41
     * optional
42
     * Not a constant so it can be modified in constructor.
43
     * Commented so it can be inherit from trait in OuvrageTemplate (bad design)
44
     */
45
    //protected $parametersByOrder = [];
46
47
    /**
48
     * TODO : DONE
49
     * TODO : refac $inlineStyle as $userPreferences[].
50
     *
51
     * @param bool|null $cleanOrder
52
     *
53
     * @return string
54 82
     */
55
    public function serialize(?bool $cleanOrder = false): string
56 82
    {
57 82
        $paramsByRenderOrder = $this->paramsByRenderOrder($cleanOrder);
58
        $paramsByRenderOrder = $this->keepMinimumOrNotEmpty($paramsByRenderOrder);
59
60 82
        // max caractères des paramètres (valides)
61 82
        $maxChars = 0;
62 82
        foreach (array_keys($paramsByRenderOrder) as $paramName) {
63
            $maxChars = max($maxChars, mb_strlen($paramName));
64
        }
65
66
        // TODO old : $option 'strict' to keep/delete the wrong parameters ?
67 82
        // Using the wrong parameters+value from user input ?
68
        $paramsByRenderOrder = $this->mergeWrongParametersFromUser($paramsByRenderOrder);
69 82
70 82
        $string = '{{'.static::WIKITEMPLATE_NAME;
71 82
        foreach ($paramsByRenderOrder as $paramName => $paramValue) {
72
            $string .= ($this->userSeparator) ?? '|';
73 82
74 82
            if (!in_array($paramName, ['0', '1', '2', '3', '4', '5'])) {
75
                $string .= $paramName;
76
77 82
                // MultiSpaced : espacements multiples pour style étendu : "auteur    = Bla"
78 82
                if ($this->userSeparator
79 82
                    && str_contains((string) $this->userSeparator, "\n")
80
                    && self::ALLOW_USER_MULTI_SPACED
81 1
                    && $this->userMultiSpaced
82 1
                ) {
83 1
                    $spaceNb = max(0, $maxChars - mb_strlen($paramName));
84
                    $string .= str_repeat(' ', $spaceNb);
85
                    $string .= ' = ';
86 82
                } else {
87
                    // style condensé "auteur=Bla" ou non multiSpaced
88
                    $string .= '=';
89
                }
90 82
            }
91
            // {{template|1=blabla}} -> {{template|blabla}}
92
            $string .= $paramValue;
93 82
        }
94 1
        // expanded model -> "\n}}"
95
        if ($this->userSeparator && str_contains((string) $this->userSeparator, "\n")) {
96 82
            $string .= "\n";
97
        }
98 82
99
        return $string . '}}';
100
    }
101
102
    /**
103
     *  TODO DONE
104
     *
105
     * @param bool|null $cleanOrder
106
     *
107
     * @return array
108 82
     */
109
    protected function paramsByRenderOrder(?bool $cleanOrder = false): array
110 82
    {
111
        $renderParams = [];
112
113 82
        // By user order
114 12
        if (!empty($this->paramOrderByUser) && !$cleanOrder) {
115 12
            $completeFantasyOrder = $this->completeFantasyOrder(
116 12
                $this->paramOrderByUser,
117
                $this->parametersByOrder /* @phpstan-ignore-line */
118
            );
119 12
120 12
            foreach ($completeFantasyOrder as $paramName) {
121 12
                if (isset($this->parametersValues[$paramName])) {
122
                    $renderParams[$paramName] = $this->parametersValues[$paramName];
123
                }
124
            }
125 12
126
            return $renderParams;
127
        }
128
129 72
        // default order
130
        return parent::paramsByRenderOrder();
131
    }
132
133
    /**
134
     * Merge Render data with wrong parameters+value from user input.
135
     * The wrong ones already corrected are not added.
136
     *
137
     *
138
     * @return array
139
     */
140 82
    protected function mergeWrongParametersFromUser(array $paramsByRenderOrder): array
141
    {
142 82
        if (!empty($this->parametersErrorFromHydrate)) {
143
            // FIXED? : si y'a de l'info dans un paramètre erreur et sans value...
144
            //$errorUserData = $this->deleteEmptyValueArray($this->parametersErrorFromHydrate);
145 2
            $errorUserData = $this->parametersErrorFromHydrate;
146
147
            // Add a note in HTML commentary
148 2
            foreach ($errorUserData as $param => $value) {
149 2
                if ('string' === gettype($param) && empty(trim($param))) {
150
                    continue;
151
                }
152 2
                if (is_int($param)) {
153
                    // erreur "|lire en ligne|"
154 1
                    if (in_array($value, $this->getParamsAndAlias())) {
155 1
                        unset($errorUserData[$param]);
156
157 1
                        continue;
158
                    }
159
160
                    // ou 1= 2= 3=
161
                    $errorUserData[$param] = $value.' <!--VALEUR SANS NOM DE PARAMETRE -->';
162
163
                    continue;
164
                }
165 1
                $errorUserData[$param] = $value." <!--PARAMETRE '$param' N'EXISTE PAS -->";
166
            }
167 2
            $paramsByRenderOrder = array_merge($paramsByRenderOrder, $errorUserData);
168
        }
169
170 82
        return $paramsByRenderOrder;
171
    }
172
173
    /**
174
     * KEEP THERE
175
     * Get data from wiki-template. Also invalid param/values.
176
     *
177
     * @return array
178
     */
179 19
    public function toArray(): array
180
    {
181 19
        $allValue = array_merge($this->parametersValues, $this->parametersErrorFromHydrate ?? []);
182
183 19
        return $this->deleteEmptyValueArray($allValue);
184
    }
185
186
    /**
187
     * TODO move ? trait ? to TemplateFactory ? /refac.
188
     *
189
     *
190
     * @return AbstractWikiTemplate
191
     * @throws Exception
192
     */
193
    public function hydrateFromText(string $tplText): AbstractWikiTemplate
194 23
    {
195
        $tplText = (string) str_ireplace((string) static::COMMENT_STRIPPED, '', $tplText);
196 23
197
        if (WikiTextUtil::isCommented($tplText)) {
198 23
            throw new DomainException('HTML comment tag detected');
199
        }
200
        $data = TemplateParser::parseDataFromTemplate($this::WIKITEMPLATE_NAME, $tplText);
201 23
        $this->hydrate($data);
202 23
203
        $this->detectUserSeparator($tplText);
204 23
205
        return $this;
206 23
    }
207
208
    /**
209
     * keep there
210
     *
211
     * @param $text
212
     */
213
    public function detectUserSeparator($text): void
214 25
    {
215
        // TODO : retirer styles personnels
216 25
        $this->userSeparator = TemplateParser::findUserStyleSeparator($text); // ou ' |'
217 25
        $this->userMultiSpaced = TemplateParser::isMultispacedTemplate($text); // ou false
218 25
    }
219
220
    /**
221
     * @param array $data
222
     *
223
     * @return AbstractStrictWikiTemplate
224
     * @throws Exception
225
     */
226 89
    public function hydrate(array $data): AbstractStrictWikiTemplate
227
    {
228 89
        parent::hydrate($data);
229 89
        $this->setParamOrderByUser($data);
230
231 89
        return $this;
232
    }
233
234
    /**
235
     * TODO : KEEP
236
     * Define the serialize order of parameters (from user initial choice).
237
     * default : $params = ['param1'=>'', 'param2' => '', ...]
238
     * OK with $params = ['a','b','c'].
239
     *
240
     * @param array
241
     *
242
     * @throws Exception
243
     */
244 89
    private function setParamOrderByUser(array $params = []): void
245
    {
246 89
        $validParams = [];
247 89
        foreach ($params as $key => $value) {
248 89
            $name = (is_int($key)) ? $value : $key;
249 89
            if (!$this->isValidParamName($name)) {
250 5
                $this->log[] = "Parameter $name do not exists";
251 5
                continue;
252
            }
253 88
            $name = $this->getAliasParam($name);
254 88
            $validParams[] = $name;
255
        }
256 89
        $this->paramOrderByUser = $validParams; /* @phpstan-ignore-line */
257 89
    }
258
259
    /**
260
     * TODO refac extract
261
     * todo : why not using setParam() ?????
262
     *
263
     * @param           $name    string|int
264
     * @param string    $value
265
     *
266
     * @throws Exception
267
     */
268 89
    protected function hydrateTemplateParameter($name, string $value): void
269
    {
270
        // Gestion alias
271 89
        if (!$this->isValidParamName($name)) {
272
            // hack : 1 => "ouvrage collectif"
273 5
            $name = (string)$name;
274 5
            $this->log[] = "parameter $name not found";
275
276
            // todo keep there
277 5
            $this->parametersErrorFromHydrate[$name] = $value;
278
279 5
            return;
280
        }
281
282 88
        $name = $this->getAliasParam($name); // main parameter name
283
284
        // todo keep that
285
        // Gestion des doublons de paramètres
286 88
        if ($this->hasParamValue($name)) {
287 1
            if (!empty($value)) {
288 1
                $this->log[] = "parameter $name en doublon";
289 1
                $this->parametersErrorFromHydrate[$name.'-doublon'] = $value;
290
            }
291
292 1
            return;
293
        }
294
295 88
        if (empty($value)) {
296
            // optional parameter
297
            if (!isset(static::MINIMUM_PARAMETERS[$name])) {
298
                unset($this->parametersValues[$name]);
299
300
                return;
301
            }
302
            // required parameter
303
            $this->parametersValues[$name] = '';
304
        }
305
306 88
        $method = $this->setterMethodName($name);
307 88
        if (method_exists($this, $method)) {
308 3
            $this->$method($value);
309
310 3
            return;
311
        }
312
313 88
        $this->parametersValues[$name] = $value;
314 88
    }
315
}
316