1<?php
2
3/*
4 * This file is part of the TYPO3 CMS project.
5 *
6 * It is free software; you can redistribute it and/or modify it under
7 * the terms of the GNU General Public License, either version 2
8 * of the License, or any later version.
9 *
10 * For the full copyright and license information, please read the
11 * LICENSE.txt file that was distributed with this source code.
12 *
13 * The TYPO3 project - inspiring people to share!
14 */
15
16namespace TYPO3\CMS\Extensionmanager\Domain\Model;
17
18use TYPO3\CMS\Core\Core\Environment;
19use TYPO3\CMS\Core\Utility\MathUtility;
20use TYPO3\CMS\Extbase\DomainObject\AbstractEntity;
21use TYPO3\CMS\Extbase\Object\ObjectManager;
22use TYPO3\CMS\Extensionmanager\Utility\ExtensionModelUtility;
23
24/**
25 * Main extension model
26 * @internal This class is a specific domain model implementation and is not part of the Public TYPO3 API.
27 */
28class Extension extends AbstractEntity
29{
30    /**
31     * Category index for distributions
32     */
33    const DISTRIBUTION_CATEGORY = 10;
34
35    /**
36     * Contains default categories.
37     *
38     * @var array
39     */
40    protected static $defaultCategories = [
41        0 => 'be',
42        1 => 'module',
43        2 => 'fe',
44        3 => 'plugin',
45        4 => 'misc',
46        5 => 'services',
47        6 => 'templates',
48        8 => 'doc',
49        9 => 'example',
50        self::DISTRIBUTION_CATEGORY => 'distribution'
51    ];
52
53    /**
54     * Contains default states.
55     *
56     * @var array
57     */
58    protected static $defaultStates = [
59        0 => 'alpha',
60        1 => 'beta',
61        2 => 'stable',
62        3 => 'experimental',
63        4 => 'test',
64        5 => 'obsolete',
65        6 => 'excludeFromUpdates',
66        7 => 'deprecated',
67        999 => 'n/a'
68    ];
69
70    /**
71     * @var ObjectManager
72     */
73    protected $objectManager;
74
75    /**
76     * @var string
77     */
78    protected $extensionKey = '';
79
80    /**
81     * @var string
82     */
83    protected $version = '';
84
85    /**
86     * @var int
87     */
88    protected $integerVersion = 0;
89
90    /**
91     * @var string
92     */
93    protected $title = '';
94
95    /**
96     * @var string
97     */
98    protected $description = '';
99
100    /**
101     * @var int
102     */
103    protected $state = 0;
104
105    /**
106     * @var int
107     */
108    protected $category = 0;
109
110    /**
111     * @var \DateTime
112     */
113    protected $lastUpdated;
114
115    /**
116     * @var string
117     */
118    protected $updateComment = '';
119
120    /**
121     * @var string
122     */
123    protected $authorName = '';
124
125    /**
126     * @var string
127     */
128    protected $authorEmail = '';
129
130    /**
131     * @var bool
132     */
133    protected $currentVersion = false;
134
135    /**
136     * @var string
137     */
138    protected $md5hash = '';
139
140    /**
141     * @var int
142     */
143    protected $reviewState;
144
145    /**
146     * @var int
147     */
148    protected $alldownloadcounter;
149
150    /**
151     * @var string
152     */
153    protected $serializedDependencies = '';
154
155    /**
156     * @var \SplObjectStorage<\TYPO3\CMS\Extensionmanager\Domain\Model\Dependency>
157     */
158    protected $dependencies;
159
160    /**
161     * @var string
162     */
163    protected $documentationLink = '';
164
165    /**
166     * @internal
167     * @var int
168     */
169    protected $position = 0;
170
171    /**
172     * @param ObjectManager $objectManager
173     */
174    public function injectObjectManager(ObjectManager $objectManager)
175    {
176        $this->objectManager = $objectManager;
177    }
178
179    /**
180     * @param string $authorEmail
181     */
182    public function setAuthorEmail($authorEmail)
183    {
184        $this->authorEmail = $authorEmail;
185    }
186
187    /**
188     * @return string
189     */
190    public function getAuthorEmail()
191    {
192        return $this->authorEmail;
193    }
194
195    /**
196     * @param string $authorName
197     */
198    public function setAuthorName($authorName)
199    {
200        $this->authorName = $authorName;
201    }
202
203    /**
204     * @return string
205     */
206    public function getAuthorName()
207    {
208        return $this->authorName;
209    }
210
211    /**
212     * @param int $category
213     */
214    public function setCategory($category)
215    {
216        $this->category = $category;
217    }
218
219    /**
220     * @return int
221     */
222    public function getCategory()
223    {
224        return $this->category;
225    }
226
227    /**
228     * Get Category String
229     *
230     * @return string
231     */
232    public function getCategoryString()
233    {
234        $categoryString = '';
235        if (isset(self::$defaultCategories[$this->getCategory()])) {
236            $categoryString = self::$defaultCategories[$this->getCategory()];
237        }
238        return $categoryString;
239    }
240
241    /**
242     * Returns category index from a given string or an integer.
243     * Fallback to 4 - 'misc' in case string is not found or integer ist out of range.
244     *
245     * @param string|int $category Category string or integer
246     * @return int Valid category index
247     */
248    public function getCategoryIndexFromStringOrNumber($category)
249    {
250        $categoryIndex = 4;
251        if (MathUtility::canBeInterpretedAsInteger($category)) {
252            $categoryIndex = (int)$category;
253            if ($categoryIndex < 0 || $categoryIndex > 10) {
254                $categoryIndex = 4;
255            }
256        } elseif (is_string($category)) {
257            $categoryIndex = array_search($category, self::$defaultCategories);
258            if ($categoryIndex === false) {
259                $categoryIndex = 4;
260            }
261        }
262        return $categoryIndex;
263    }
264
265    /**
266     * @param string $description
267     */
268    public function setDescription($description)
269    {
270        $this->description = $description;
271    }
272
273    /**
274     * @return string
275     */
276    public function getDescription()
277    {
278        return $this->description;
279    }
280
281    /**
282     * @param string $extensionKey
283     */
284    public function setExtensionKey($extensionKey)
285    {
286        $this->extensionKey = $extensionKey;
287    }
288
289    /**
290     * @return string
291     */
292    public function getExtensionKey()
293    {
294        return $this->extensionKey;
295    }
296
297    /**
298     * @param \DateTime $lastUpdated
299     */
300    public function setLastUpdated(\DateTime $lastUpdated)
301    {
302        $this->lastUpdated = $lastUpdated;
303    }
304
305    /**
306     * @return \DateTime
307     */
308    public function getLastUpdated()
309    {
310        return $this->lastUpdated;
311    }
312
313    /**
314     * @param int $state
315     */
316    public function setState($state)
317    {
318        $this->state = $state;
319    }
320
321    /**
322     * @return int
323     */
324    public function getState()
325    {
326        return $this->state;
327    }
328
329    /**
330     * Get State string
331     *
332     * @return string
333     */
334    public function getStateString()
335    {
336        $stateString = '';
337        if (isset(self::$defaultStates[$this->getState()])) {
338            $stateString = self::$defaultStates[$this->getState()];
339        }
340        return $stateString;
341    }
342
343    /**
344     * Returns either array with all default states or index/title
345     * of a state entry.
346     *
347     * @param mixed $state state title or state index
348     * @return mixed
349     */
350    public function getDefaultState($state = null)
351    {
352        $defaultState = '';
353        if ($state === null) {
354            $defaultState = self::$defaultStates;
355        } else {
356            if (is_string($state)) {
357                $stateIndex = array_search(strtolower($state), self::$defaultStates);
358                if ($stateIndex === false) {
359                    // default state
360                    $stateIndex = 999;
361                }
362                $defaultState = $stateIndex;
363            } else {
364                if (is_int($state) && $state >= 0) {
365                    if (array_key_exists($state, self::$defaultStates)) {
366                        $stateTitle = self::$defaultStates[$state];
367                    } else {
368                        // default state
369                        $stateTitle = 'n/a';
370                    }
371                    $defaultState = $stateTitle;
372                }
373            }
374        }
375        return $defaultState;
376    }
377
378    /**
379     * @param string $title
380     */
381    public function setTitle($title)
382    {
383        $this->title = $title;
384    }
385
386    /**
387     * @return string
388     */
389    public function getTitle()
390    {
391        return $this->title;
392    }
393
394    /**
395     * @param string $updateComment
396     */
397    public function setUpdateComment($updateComment)
398    {
399        $this->updateComment = $updateComment;
400    }
401
402    /**
403     * @return string
404     */
405    public function getUpdateComment()
406    {
407        return $this->updateComment;
408    }
409
410    /**
411     * @param string $version
412     */
413    public function setVersion($version)
414    {
415        $this->version = $version;
416    }
417
418    /**
419     * @return string
420     */
421    public function getVersion()
422    {
423        return $this->version;
424    }
425
426    /**
427     * @param bool $currentVersion
428     */
429    public function setCurrentVersion($currentVersion)
430    {
431        $this->currentVersion = $currentVersion;
432    }
433
434    /**
435     * @return bool
436     */
437    public function getCurrentVersion()
438    {
439        return $this->currentVersion;
440    }
441
442    /**
443     * @param string $md5hash
444     */
445    public function setMd5hash($md5hash)
446    {
447        $this->md5hash = $md5hash;
448    }
449
450    /**
451     * @return string
452     */
453    public function getMd5hash()
454    {
455        return $this->md5hash;
456    }
457
458    /**
459     * Possible install paths
460     *
461     * @static
462     * @return array
463     */
464    public static function returnInstallPaths()
465    {
466        $installPaths = [
467            'System' => Environment::getFrameworkBasePath() . '/',
468            'Global' => Environment::getBackendPath() . '/ext/',
469            'Local' => Environment::getExtensionsPath() . '/'
470        ];
471        return $installPaths;
472    }
473
474    /**
475     * Allowed install paths
476     *
477     * @static
478     * @return array
479     */
480    public static function returnAllowedInstallPaths()
481    {
482        $installPaths = self::returnInstallPaths();
483        if (empty($GLOBALS['TYPO3_CONF_VARS']['EXT']['allowGlobalInstall'])) {
484            unset($installPaths['Global']);
485        }
486        if (empty($GLOBALS['TYPO3_CONF_VARS']['EXT']['allowLocalInstall'])) {
487            unset($installPaths['Local']);
488        }
489        return $installPaths;
490    }
491
492    /**
493     * Allowed install names: System, Global, Local
494     *
495     * @static
496     * @return array
497     */
498    public static function returnAllowedInstallTypes()
499    {
500        $installPaths = self::returnAllowedInstallPaths();
501        return array_keys($installPaths);
502    }
503
504    /**
505     * @param string $dependencies
506     */
507    public function setSerializedDependencies($dependencies)
508    {
509        $this->serializedDependencies = $dependencies;
510    }
511
512    /**
513     * @return string
514     */
515    public function getSerializedDependencies()
516    {
517        return $this->serializedDependencies;
518    }
519
520    /**
521     * @param \SplObjectStorage $dependencies
522     */
523    public function setDependencies($dependencies)
524    {
525        $this->dependencies = $dependencies;
526    }
527
528    /**
529     * @return \SplObjectStorage
530     */
531    public function getDependencies()
532    {
533        if (!is_object($this->dependencies)) {
534            $extensionModelUtility = $this->objectManager->get(ExtensionModelUtility::class);
535            $this->setDependencies($extensionModelUtility->convertDependenciesToObjects($this->getSerializedDependencies()));
536        }
537        return $this->dependencies;
538    }
539
540    /**
541     * @param Dependency $dependency
542     */
543    public function addDependency(Dependency $dependency)
544    {
545        $this->dependencies->attach($dependency);
546    }
547
548    /**
549     * @param int $integerVersion
550     */
551    public function setIntegerVersion($integerVersion)
552    {
553        $this->integerVersion = $integerVersion;
554    }
555
556    /**
557     * @return int
558     */
559    public function getIntegerVersion()
560    {
561        return $this->integerVersion;
562    }
563
564    /**
565     * @param int $reviewState
566     */
567    public function setReviewState($reviewState)
568    {
569        $this->reviewState = $reviewState;
570    }
571
572    /**
573     * @return int
574     */
575    public function getReviewState()
576    {
577        return $this->reviewState;
578    }
579
580    /**
581     * @param int $position
582     */
583    public function setPosition($position)
584    {
585        $this->position = $position;
586    }
587
588    /**
589     * @return int
590     */
591    public function getPosition()
592    {
593        return $this->position;
594    }
595
596    /**
597     * @param int $alldownloadcounter
598     */
599    public function setAlldownloadcounter($alldownloadcounter)
600    {
601        $this->alldownloadcounter = $alldownloadcounter;
602    }
603
604    /**
605     * @return int
606     */
607    public function getAlldownloadcounter()
608    {
609        return $this->alldownloadcounter;
610    }
611
612    /**
613     * @return string
614     */
615    public function getDocumentationLink(): string
616    {
617        return $this->documentationLink;
618    }
619
620    /**
621     * @param string $documentationLink
622     */
623    public function setDocumentationLink(string $documentationLink): void
624    {
625        $this->documentationLink = $documentationLink;
626    }
627}
628