Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 51
0.00% covered (danger)
0.00%
0 / 3
CRAP
0.00% covered (danger)
0.00%
0 / 1
PortableElementAssetValidator
0.00% covered (danger)
0.00%
0 / 51
0.00% covered (danger)
0.00%
0 / 3
756
0.00% covered (danger)
0.00%
0 / 1
 validateAssets
0.00% covered (danger)
0.00%
0 / 17
0.00% covered (danger)
0.00%
0 / 1
56
 getAssets
0.00% covered (danger)
0.00%
0 / 24
0.00% covered (danger)
0.00%
0 / 1
240
 validFile
0.00% covered (danger)
0.00%
0 / 10
0.00% covered (danger)
0.00%
0 / 1
30
1<?php
2
3/**
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; under version 2
7 * of the License (non-upgradable).
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 *
18 * Copyright (c) 2016 (original work) Open Assessment Technologies SA;
19 *
20 */
21
22namespace oat\taoQtiItem\model\portableElement\validator;
23
24use oat\tao\model\ClientLibRegistry;
25use oat\taoQtiItem\model\portableElement\exception\PortableElementInvalidAssetException;
26use oat\taoQtiItem\model\portableElement\exception\PortableElementInvalidModelException;
27use oat\taoQtiItem\model\portableElement\exception\PortableElementParserException;
28use oat\taoQtiItem\model\portableElement\element\PortableElementObject;
29
30abstract class PortableElementAssetValidator implements Validatable
31{
32    /**
33     * Validate files by checking:
34     *  - Model requirement
35     *  - Existing as file or alias
36     *
37     * @param PortableElementObject $object
38     * @param string $source Temporary directory source
39     * @param array $files Array of file relative path
40     * @return bool
41     * @throws PortableElementInvalidAssetException
42     * @throws PortableElementInvalidModelException
43     * @throws PortableElementParserException
44     * @throws \common_exception_Error
45     */
46    public function validateAssets(PortableElementObject $object, $source, array $files = [])
47    {
48        $errorReport = \common_report_Report::createFailure('Portable element validation has failed.');
49
50        if (empty($files)) {
51            //if no files requested, get all all assets
52            try {
53                $files = $this->getAssets($object);
54            } catch (PortableElementInvalidAssetException $e) {
55                $subReport = \common_report_Report::createFailure($e->getMessage());
56                $errorReport->add($subReport);
57            }
58        }
59
60        if (!empty($files)) {
61            foreach ($files as $key => $file) {
62                try {
63                    $this->validFile($source, $file);
64                } catch (PortableElementInvalidAssetException $e) {
65                    $subReport = \common_report_Report::createFailure(__('Cannot locate the file "%s"', $file));
66                    $errorReport->add($subReport);
67                }
68            }
69        }
70
71        if ($errorReport->containsError()) {
72            $exception = new PortableElementInvalidModelException();
73            $exception->setReport($errorReport);
74            throw $exception;
75        }
76        return true;
77    }
78
79    /**
80     * Return all assets of a portable element in a array of string
81     * Path is relative to Portable Element location
82     *
83     * @param PortableElementObject $object
84     * @param null $type Object key to focus
85     * @return array List of file relative path
86     * @throws PortableElementInvalidAssetException
87     */
88    public function getAssets(PortableElementObject $object, $type = null)
89    {
90        $assets = [];
91        if (is_null($type) || ($type == 'runtime')) {
92            $assets = ['runtime' => $object->getRuntimePath()];
93        }
94
95        if (is_null($type) || ($type == 'creator')) {
96            if (! empty($object->getCreator())) {
97                $assets['creator'] = $object->getCreatorPath();
98            }
99        }
100
101        $files = [];
102        foreach ($assets as $key => $asset) {
103            $constraints = $this->getAssetConstraints($key);
104            foreach ($constraints as $constraint) {
105                if (! isset($asset[$constraint])) {
106                    if ($this->isOptionalConstraint($key, $constraint)) {
107                        continue;
108                    }
109                    throw new PortableElementInvalidAssetException(
110                        'Missing asset file for ' . $key . ':' . $constraint
111                    );
112                }
113                if (is_array($asset[$constraint])) {
114                    //get a flat list out of the structure of file data
115                    $it = new \RecursiveIteratorIterator(new \RecursiveArrayIterator($asset[$constraint]));
116                    foreach ($it as $k => $v) {
117                        if (!in_array(strval($k), $object->getRegistrationExcludedKey()) && !empty($v)) {
118                            $files[] = $v;
119                        }
120                    }
121                } else {
122                    if (!empty($asset[$constraint])) {
123                        $files[] = $asset[$constraint];
124                    }
125                }
126            }
127        }
128        return $files;
129    }
130
131    /**
132     * Valid a file if exists or alias
133     *
134     * @param string $source Temporary directory source
135     * @param string $file Path to the file
136     * @return bool
137     * @throws PortableElementInvalidAssetException
138     * @throws PortableElementParserException
139     */
140    public function validFile($source, $file)
141    {
142        if (! file_exists($source)) {
143            throw new PortableElementParserException('Unable to locate extracted zip file.');
144        }
145
146        $filePath = rtrim($source, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR . preg_replace('/^\.\//', '', $file);
147
148        if (file_exists($filePath) || file_exists($filePath . '.js')) {
149            return true;
150        }
151
152        if (array_key_exists($file, ClientLibRegistry::getRegistry()->getLibAliasMap())) {
153            return true;
154        }
155
156        throw new PortableElementInvalidAssetException(
157            'Asset "' . $file . '" is not found in the source "' . $source . '"" neither through alias'
158        );
159    }
160}