Passed
Push — 1.11.x ( 69d982...5f02d6 )
by Yannick
10:37
created

CcBase::getforumns()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 1
dl 0
loc 3
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 0
1
<?php
2
/* For licensing terms, see /license.txt */
3
4
class CcBase
5
{
6
    public const CC_TYPE_FORUM = 'imsdt_xmlv1p3';
7
    public const CC_TYPE_QUIZ = 'imsqti_xmlv1p3/imscc_xmlv1p3/assessment';
8
    public const CC_TYPE_QUESTION_BANK = 'imsqti_xmlv1p3/imscc_xmlv1p3/question-bank';
9
    public const CC_TYPE_WEBLINK = 'imswl_xmlv1p3';
10
    public const CC_TYPE_WEBCONTENT = 'webcontent';
11
    public const CC_TYPE_ASSOCIATED_CONTENT = 'associatedcontent/imscc_xmlv1p3/learning-application-resource';
12
    public const CC_TYPE_EMPTY = '';
13
14
    public static $restypes = ['associatedcontent/imscc_xmlv1p0/learning-application-resource', 'webcontent'];
15
    public static $forumns = ['dt' => 'http://www.imsglobal.org/xsd/imsdt_v1p0'];
16
    public static $quizns = ['xmlns' => 'http://www.imsglobal.org/xsd/ims_qtiasiv1p2'];
17
    public static $resourcens = ['wl' => 'http://www.imsglobal.org/xsd/imswl_v1p0'];
18
19
    public static $instances = [];
20
    public static $manifest;
21
    public static $pathToManifestFolder;
22
23
    public static $namespaces = ['imscc' => 'http://www.imsglobal.org/xsd/imscc/imscp_v1p1',
24
                                      'lomimscc' => 'http://ltsc.ieee.org/xsd/imscc/LOM',
25
                                      'lom' => 'http://ltsc.ieee.org/xsd/LOM',
26
                                      'voc' => 'http://ltsc.ieee.org/xsd/LOM/vocab',
27
                                      'xsi' => 'http://www.w3.org/2001/XMLSchema-instance',
28
                                      'cc' => 'http://www.imsglobal.org/xsd/imsccauth_v1p0', ];
29
30
    public function __construct($path_to_manifest)
31
    {
32
        static::$manifest = new DOMDocument();
33
        static::$manifest->validateOnParse = false;
34
35
        static::$pathToManifestFolder = dirname($path_to_manifest);
36
37
        static::logAction('Proccess start');
38
        static::logAction('Load the manifest file: '.$path_to_manifest);
39
40
        if (!static::$manifest->load($path_to_manifest, LIBXML_NONET)) {
41
            static::logAction('Cannot load the manifest file: '.$path_to_manifest, true);
42
        }
43
    }
44
45
    /**
46
     * @return array
47
     */
48
    public static function getquizns()
49
    {
50
        return static::$quizns;
51
    }
52
53
    /**
54
     * @return array
55
     */
56
    public static function getforumns()
57
    {
58
        return static::$forumns;
59
    }
60
61
    /**
62
     * @return array
63
     */
64
    public static function getresourcens()
65
    {
66
        return static::$resourcens;
67
    }
68
69
    /**
70
     * Find the imsmanifest.xml file inside the given folder and return its path
71
     * @param string $folder Full path name of the folder in which we expect to find imsmanifest.xml
72
     * @return false|string
73
     */
74
    public static function getManifest(string $folder)
75
    {
76
        if (!is_dir($folder)) {
77
            return false;
78
        }
79
80
        // Before iterate over directories, try to find one manifest at top level
81
        if (file_exists($folder.'/imsmanifest.xml')) {
82
            return $folder.'/imsmanifest.xml';
83
        }
84
85
        $result = false;
86
        try {
87
            $dirIter = new RecursiveDirectoryIterator($folder, RecursiveDirectoryIterator::KEY_AS_PATHNAME);
88
            $recIter = new RecursiveIteratorIterator($dirIter, RecursiveIteratorIterator::CHILD_FIRST);
89
            foreach ($recIter as $info) {
90
                if ($info->isFile() && ($info->getFilename() == 'imsmanifest.xml')) {
91
                    $result = $info->getPathname();
92
                    break;
93
                }
94
            }
95
        } catch (Exception $e) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
96
        }
97
98
        return $result;
99
    }
100
101
    public function isAuth()
102
    {
103
        $xpath = static::newxPath(static::$manifest, static::$namespaces);
104
105
        $count_auth = $xpath->evaluate('count(/imscc:manifest/cc:authorizations)');
106
107
        if ($count_auth > 0) {
108
            $response = true;
109
        } else {
110
            $response = false;
111
        }
112
113
        return $response;
114
    }
115
116
    public function getNodesByCriteria($key, $value)
117
    {
118
        $response = [];
119
120
        if (array_key_exists('index', static::$instances)) {
121
            foreach (static::$instances['index'] as $item) {
122
                if ($item[$key] == $value) {
123
                    $response[] = $item;
124
                }
125
            }
126
        }
127
128
        return $response;
129
    }
130
131
    public function countInstances($type)
132
    {
133
        $quantity = 0;
134
135
        if (array_key_exists('index', static::$instances)) {
136
            if (static::$instances['index'] && $type) {
137
                foreach (static::$instances['index'] as $instance) {
138
                    if (!empty($instance['tool_type'])) {
139
                        $types[] = $instance['tool_type'];
140
                    }
141
                }
142
143
                $quantityInstances = array_count_values($types);
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $types does not seem to be defined for all execution paths leading up to this point.
Loading history...
144
                $quantity = array_key_exists($type, $quantityInstances) ? $quantityInstances[$type] : 0;
145
            }
146
        }
147
148
        return $quantity;
149
    }
150
151
    public function getItemCcType($identifier)
152
    {
153
        $xpath = static::newxPath(static::$manifest, static::$namespaces);
154
155
        $nodes = $xpath->query('/imscc:manifest/imscc:resources/imscc:resource[@identifier="'.$identifier.'"]/@type');
156
157
        if ($nodes && !empty($nodes->item(0)->nodeValue)) {
158
            return $nodes->item(0)->nodeValue;
159
        } else {
160
            return '';
161
        }
162
    }
163
164
    public function getItemHref($identifier)
165
    {
166
        $xpath = static::newxPath(static::$manifest, static::$namespaces);
167
168
        $nodes = $xpath->query('/imscc:manifest/imscc:resources/imscc:resource[@identifier="'.$identifier.'"]/imscc:file/@href');
169
170
        if ($nodes && !empty($nodes->item(0)->nodeValue)) {
171
            return $nodes->item(0)->nodeValue;
172
        } else {
173
            return '';
174
        }
175
    }
176
177
    public static function newxPath(DOMDocument $manifest, $namespaces = '')
178
    {
179
        $xpath = new DOMXPath($manifest);
180
181
        if (!empty($namespaces)) {
182
            foreach ($namespaces as $prefix => $ns) {
183
                if (!$xpath->registerNamespace($prefix, $ns)) {
184
                    static::logAction('Cannot register the namespace: '.$prefix.':'.$ns, true);
185
                }
186
            }
187
        }
188
189
        return $xpath;
190
    }
191
192
    public static function logFile()
193
    {
194
        return static::$pathToManifestFolder.DIRECTORY_SEPARATOR.'cc_import.log';
195
    }
196
197
    public static function logAction($text, $criticalError = false)
198
    {
199
        $full_message = strtoupper(date("j/n/Y g:i:s a"))." - ".$text."\r";
200
201
        file_put_contents(static::logFile(), $full_message, FILE_APPEND);
202
203
        if ($criticalError) {
204
            static::criticalError($text);
205
        }
206
    }
207
208
    public function convertToToolType($ccType)
209
    {
210
        $type = TYPE_UNKNOWN;
211
212
        if ($ccType == static::CC_TYPE_FORUM) {
213
            $type = TOOL_TYPE_FORUM;
214
        }
215
216
        if ($ccType == static::CC_TYPE_QUIZ) {
217
            $type = TOOL_TYPE_QUIZ;
218
        }
219
220
        if ($ccType == static::CC_TYPE_WEBLINK) {
221
            $type = TOOL_TYPE_WEBLINK;
222
        }
223
224
        if ($ccType == static::CC_TYPE_WEBCONTENT) {
225
            $type = TOOL_TYPE_DOCUMENT;
226
        }
227
228
        return $type;
229
    }
230
231
    protected function getMetadata($section, $key)
232
    {
233
        $xpath = static::newxPath(static::$manifest, static::$namespaces);
234
235
        $metadata = $xpath->query('/imscc:manifest/imscc:metadata/lomimscc:lom/lomimscc:'.$section.'/lomimscc:'.$key.'/lomimscc:string');
236
        $value = !empty($metadata->item(0)->nodeValue) ? $metadata->item(0)->nodeValue : '';
237
238
        return $value;
239
    }
240
241
    /**
242
     * Is activity visible or not.
243
     *
244
     * @param string $identifier
245
     *
246
     * @return number
247
     */
248
    protected function getModuleVisible($identifier)
249
    {
250
        //Should item be hidden or not
251
        $mod_visible = 1;
252
        if (!empty($identifier)) {
253
            $xpath = static::newxPath(static::$manifest, static::$namespaces);
254
            $query = '/imscc:manifest/imscc:resources/imscc:resource[@identifier="'.$identifier.'"]';
255
            $query .= '//lom:intendedEndUserRole/voc:vocabulary/lom:value';
256
            $intendeduserrole = $xpath->query($query);
257
            if (!empty($intendeduserrole) && ($intendeduserrole->length > 0)) {
258
                $role = trim($intendeduserrole->item(0)->nodeValue);
259
                if (strcasecmp('Instructor', $role) == 0) {
260
                    $mod_visible = 0;
261
                }
262
            }
263
        }
264
265
        return $mod_visible;
266
    }
267
268
    protected function createInstances($items, $level = 0, &$array_index = 0, $index_root = 0)
269
    {
270
        $level++;
271
        $i = 1;
272
273
        if ($items) {
274
            $xpath = self::newxPath(static::$manifest, static::$namespaces);
275
276
            foreach ($items as $item) {
277
                $array_index++;
278
                $title = $path = $tool_type = $identifierref = '';
279
                if ($item->nodeName == 'item') {
280
                    if ($item->hasAttribute('identifierref')) {
281
                        $identifierref = $item->getAttribute('identifierref');
282
                    }
283
284
                    $titles = $xpath->query('imscc:title', $item);
285
                    if ($titles->length > 0) {
286
                        $title = $titles->item(0)->nodeValue;
287
                    }
288
289
                    $ccType = $this->getItemCcType($identifierref);
290
                    $tool_type = $this->convertToToolType($ccType);
291
                    //Fix the label issue - MDL-33523
292
                    if (empty($identifierref) && empty($title)) {
293
                        $tool_type = TYPE_UNKNOWN;
294
                    }
295
                } elseif ($item->nodeName == 'resource') {
296
                    $identifierref = $xpath->query('@identifier', $item);
297
                    $identifierref = !empty($identifierref->item(0)->nodeValue) ? $identifierref->item(0)->nodeValue : '';
298
299
                    $ccType = $this->getItemCcType($identifierref);
300
                    $tool_type = $this->convertToToolType($ccType);
301
                    if (self::CC_TYPE_WEBCONTENT == $ccType) {
302
                        $path = $this->getItemHref($identifierref);
303
                        $title = basename($path);
304
                    } else { // A resource but not a file... we assume it's a quiz bank and its assigned identifier is irrelevant to its name
305
                        $title = 'Quiz Bank '.($this->countInstances($tool_type) + 1);
306
                    }
307
                }
308
309
                if ($level == ROOT_DEEP) {
310
                    $index_root = $array_index;
311
                }
312
313
                static::$instances['index'][$array_index] = [
314
                    'common_cartridge_type' => $ccType,
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $ccType does not seem to be defined for all execution paths leading up to this point.
Loading history...
315
                    'tool_type' => $tool_type,
316
                    'title' => $title ? $title : '',
317
                    'root_parent' => $index_root,
318
                    'index' => $array_index,
319
                    'deep' => $level,
320
                    'instance' => $this->countInstances($tool_type),
321
                    'resource_identifier' => $identifierref,
322
                ];
323
324
                static::$instances['instances'][$tool_type][] = [
325
                    'title' => $title,
326
                    'instance' => static::$instances['index'][$array_index]['instance'],
327
                    'common_cartridge_type' => $ccType,
328
                    'resource_identifier' => $identifierref,
329
                    'deep' => $level,
330
                    'src' => $path,
331
                ];
332
333
                $more_items = $xpath->query('imscc:item', $item);
334
335
                if ($more_items->length > 0) {
336
                    $this->createInstances($more_items, $level, $array_index, $index_root);
337
                }
338
339
                $i++;
340
            }
341
        }
342
    }
343
344
    protected static function criticalError($text)
345
    {
346
        $path_to_log = static::logFile();
347
348
        echo '
349
350
        <p>
351
        <hr />A critical error has been found!
352
353
        <p>'.$text.'</p>
354
355
356
        <p>
357
        The process has been stopped. Please see the <a href="'.$path_to_log.'">log file</a> for more information.</p>
358
359
        <p>Log: '.$path_to_log.'</p>
360
361
        <hr />
362
363
        </p>
364
        ';
365
366
        exit();
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
367
    }
368
369
    protected function createCourseCode($title)
370
    {
371
        //Making sure that text of the short name does not go over the DB limit.
372
        //and leaving the space to add additional characters by the platform
373
        $code = substr(strtoupper(str_replace(' ', '', trim($title))), 0, 94);
374
375
        return $code;
376
    }
377
}
378