Passed
Push — 1.11.x ( 47915c...7101db )
by Yannick
09:38
created

CcBase   F

Complexity

Total Complexity 62

Size/Duplication

Total Lines 346
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 160
c 1
b 0
f 0
dl 0
loc 346
rs 3.44
wmc 62

18 Methods

Rating   Name   Duplication   Size   Complexity  
A getquizns() 0 3 1
A getforumns() 0 3 1
A getresourcens() 0 3 1
A __construct() 0 12 2
A getItemCcType() 0 10 3
A getNodesByCriteria() 0 13 4
A getMetadata() 0 8 2
A convertToToolType() 0 21 5
A isAuth() 0 13 2
A createCourseCode() 0 7 1
A logAction() 0 8 2
B getManifest() 0 25 7
A criticalError() 0 23 1
A newxPath() 0 13 4
A logFile() 0 3 1
B countInstances() 0 18 7
A getModuleVisible() 0 18 5
C createInstances() 0 64 13

How to fix   Complexity   

Complex Class

Complex classes like CcBase often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use CcBase, and based on these observations, apply Extract Interface, too.

1
<?php
2
/* For licensing terms, see /license.txt */
3
4
class CcBase
5
{
6
    const CC_TYPE_FORUM = 'imsdt_xmlv1p3';
7
    const CC_TYPE_QUIZ = 'imsqti_xmlv1p3/imscc_xmlv1p3/assessment';
8
    const CC_TYPE_QUESTION_BANK = 'imsqti_xmlv1p3/imscc_xmlv1p3/question-bank';
9
    const CC_TYPE_WEBLINK = 'imswl_xmlv1p3';
10
    const CC_TYPE_WEBCONTENT = 'webcontent';
11
    const CC_TYPE_ASSOCIATED_CONTENT = 'associatedcontent/imscc_xmlv1p3/learning-application-resource';
12
    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
    public static function getManifest($folder)
70
    {
71
        if (!is_dir($folder)) {
72
            return false;
73
        }
74
75
        // Before iterate over directories, try to find one manifest at top level
76
        if (file_exists($folder.'/imsmanifest.xml')) {
77
            return $folder.'/imsmanifest.xml';
78
        }
79
80
        $result = false;
81
        try {
82
            $dirIter = new RecursiveDirectoryIterator($folder, RecursiveDirectoryIterator::KEY_AS_PATHNAME);
83
            $recIter = new RecursiveIteratorIterator($dirIter, RecursiveIteratorIterator::CHILD_FIRST);
84
            foreach ($recIter as $info) {
85
                if ($info->isFile() && ($info->getFilename() == 'imsmanifest.xml')) {
86
                    $result = $info->getPathname();
87
                    break;
88
                }
89
            }
90
        } catch (Exception $e) {
0 ignored issues
show
Coding Style Comprehensibility introduced by Christian
Consider adding a comment why this CATCH block is empty.
Loading history...
91
        }
92
93
        return $result;
94
    }
95
96
    public function isAuth()
97
    {
98
        $xpath = static::newxPath(static::$manifest, static::$namespaces);
99
100
        $count_auth = $xpath->evaluate('count(/imscc:manifest/cc:authorizations)');
101
102
        if ($count_auth > 0) {
103
            $response = true;
104
        } else {
105
            $response = false;
106
        }
107
108
        return $response;
109
    }
110
111
    public function getNodesByCriteria($key, $value)
112
    {
113
        $response = [];
114
115
        if (array_key_exists('index', static::$instances)) {
116
            foreach (static::$instances['index'] as $item) {
117
                if ($item[$key] == $value) {
118
                    $response[] = $item;
119
                }
120
            }
121
        }
122
123
        return $response;
124
    }
125
126
    public function countInstances($type)
127
    {
128
        $quantity = 0;
129
130
        if (array_key_exists('index', static::$instances)) {
131
            if (static::$instances['index'] && $type) {
132
                foreach (static::$instances['index'] as $instance) {
133
                    if (!empty($instance['tool_type'])) {
134
                        $types[] = $instance['tool_type'];
135
                    }
136
                }
137
138
                $quantityInstances = array_count_values($types);
0 ignored issues
show
Comprehensibility Best Practice introduced by Christian
The variable $types does not seem to be defined for all execution paths leading up to this point.
Loading history...
139
                $quantity = array_key_exists($type, $quantityInstances) ? $quantityInstances[$type] : 0;
140
            }
141
        }
142
143
        return $quantity;
144
    }
145
146
    public function getItemCcType($identifier)
147
    {
148
        $xpath = static::newxPath(static::$manifest, static::$namespaces);
149
150
        $nodes = $xpath->query('/imscc:manifest/imscc:resources/imscc:resource[@identifier="'.$identifier.'"]/@type');
151
152
        if ($nodes && !empty($nodes->item(0)->nodeValue)) {
153
            return $nodes->item(0)->nodeValue;
154
        } else {
155
            return '';
156
        }
157
    }
158
159
    public static function newxPath(DOMDocument $manifest, $namespaces = '')
160
    {
161
        $xpath = new DOMXPath($manifest);
162
163
        if (!empty($namespaces)) {
164
            foreach ($namespaces as $prefix => $ns) {
165
                if (!$xpath->registerNamespace($prefix, $ns)) {
166
                    static::logAction('Cannot register the namespace: '.$prefix.':'.$ns, true);
167
                }
168
            }
169
        }
170
171
        return $xpath;
172
    }
173
174
    public static function logFile()
175
    {
176
        return static::$pathToManifestFolder.DIRECTORY_SEPARATOR.'cc_import.log';
177
    }
178
179
    public static function logAction($text, $criticalError = false)
180
    {
181
        $full_message = strtoupper(date("j/n/Y g:i:s a"))." - ".$text."\r";
182
183
        file_put_contents(static::logFile(), $full_message, FILE_APPEND);
184
185
        if ($criticalError) {
186
            static::criticalError($text);
187
        }
188
    }
189
190
    public function convertToToolType($ccType)
191
    {
192
        $type = TYPE_UNKNOWN;
193
194
        if ($ccType == static::CC_TYPE_FORUM) {
195
            $type = TOOL_TYPE_FORUM;
196
        }
197
198
        if ($ccType == static::CC_TYPE_QUIZ) {
199
            $type = TOOL_TYPE_QUIZ;
200
        }
201
202
        if ($ccType == static::CC_TYPE_WEBLINK) {
203
            $type = TOOL_TYPE_WEBLINK;
204
        }
205
206
        if ($ccType == static::CC_TYPE_WEBCONTENT) {
207
            $type = TOOL_TYPE_DOCUMENT;
208
        }
209
210
        return $type;
211
    }
212
213
    protected function getMetadata($section, $key)
214
    {
215
        $xpath = static::newxPath(static::$manifest, static::$namespaces);
216
217
        $metadata = $xpath->query('/imscc:manifest/imscc:metadata/lomimscc:lom/lomimscc:'.$section.'/lomimscc:'.$key.'/lomimscc:string');
218
        $value = !empty($metadata->item(0)->nodeValue) ? $metadata->item(0)->nodeValue : '';
219
220
        return $value;
221
    }
222
223
    /**
224
     * Is activity visible or not.
225
     *
226
     * @param string $identifier
227
     *
228
     * @return number
229
     */
230
    protected function getModuleVisible($identifier)
231
    {
232
        //Should item be hidden or not
233
        $mod_visible = 1;
234
        if (!empty($identifier)) {
235
            $xpath = static::newxPath(static::$manifest, static::$namespaces);
236
            $query = '/imscc:manifest/imscc:resources/imscc:resource[@identifier="'.$identifier.'"]';
237
            $query .= '//lom:intendedEndUserRole/voc:vocabulary/lom:value';
238
            $intendeduserrole = $xpath->query($query);
239
            if (!empty($intendeduserrole) && ($intendeduserrole->length > 0)) {
240
                $role = trim($intendeduserrole->item(0)->nodeValue);
241
                if (strcasecmp('Instructor', $role) == 0) {
242
                    $mod_visible = 0;
243
                }
244
            }
245
        }
246
247
        return $mod_visible;
248
    }
249
250
    protected function createInstances($items, $level = 0, &$array_index = 0, $index_root = 0)
251
    {
252
        $level++;
253
        $i = 1;
254
255
        if ($items) {
256
            $xpath = self::newxPath(static::$manifest, static::$namespaces);
257
258
            foreach ($items as $item) {
259
                $array_index++;
260
                if ($item->nodeName == "item") {
261
                    $identifierref = '';
262
                    if ($item->hasAttribute('identifierref')) {
263
                        $identifierref = $item->getAttribute('identifierref');
264
                    }
265
266
                    $title = '';
267
                    $titles = $xpath->query('imscc:title', $item);
268
                    if ($titles->length > 0) {
269
                        $title = $titles->item(0)->nodeValue;
270
                    }
271
272
                    $ccType = $this->getItemCcType($identifierref);
273
                    $tool_type = $this->convertToToolType($ccType);
274
                    //Fix the label issue - MDL-33523
275
                    if (empty($identifierref) && empty($title)) {
276
                        $tool_type = TYPE_UNKNOWN;
277
                    }
278
                } elseif ($item->nodeName == "resource") {
279
                    $identifierref = $xpath->query('@identifier', $item);
280
                    $identifierref = !empty($identifierref->item(0)->nodeValue) ? $identifierref->item(0)->nodeValue : '';
281
282
                    $ccType = $this->getItemCcType($identifierref);
283
                    $tool_type = $this->convertToToolType($ccType);
284
285
                    $title = 'Quiz Bank '.($this->countInstances($tool_type) + 1);
286
                }
287
288
                if ($level == ROOT_DEEP) {
289
                    $index_root = $array_index;
290
                }
291
292
                static::$instances['index'][$array_index]['common_cartriedge_type'] = $ccType;
0 ignored issues
show
Comprehensibility Best Practice introduced by Christian
The variable $ccType does not seem to be defined for all execution paths leading up to this point.
Loading history...
293
                static::$instances['index'][$array_index]['tool_type'] = $tool_type;
0 ignored issues
show
Comprehensibility Best Practice introduced by Christian
The variable $tool_type does not seem to be defined for all execution paths leading up to this point.
Loading history...
294
                static::$instances['index'][$array_index]['title'] = $title ? $title : '';
0 ignored issues
show
Comprehensibility Best Practice introduced by Christian
The variable $title does not seem to be defined for all execution paths leading up to this point.
Loading history...
295
                static::$instances['index'][$array_index]['root_parent'] = $index_root;
296
                static::$instances['index'][$array_index]['index'] = $array_index;
297
                static::$instances['index'][$array_index]['deep'] = $level;
298
                static::$instances['index'][$array_index]['instance'] = $this->countInstances($tool_type);
299
                static::$instances['index'][$array_index]['resource_indentifier'] = $identifierref;
0 ignored issues
show
Comprehensibility Best Practice introduced by Christian
The variable $identifierref does not seem to be defined for all execution paths leading up to this point.
Loading history...
300
301
                static::$instances['instances'][$tool_type][] = ['title' => $title,
302
                                                                        'instance' => static::$instances['index'][$array_index]['instance'],
303
                                                                        'common_cartriedge_type' => $ccType,
304
                                                                        'resource_indentifier' => $identifierref,
305
                                                                        'deep' => $level, ];
306
307
                $more_items = $xpath->query('imscc:item', $item);
308
309
                if ($more_items->length > 0) {
310
                    $this->createInstances($more_items, $level, $array_index, $index_root);
311
                }
312
313
                $i++;
314
            }
315
        }
316
    }
317
318
    protected static function criticalError($text)
319
    {
320
        $path_to_log = static::logFile();
321
322
        echo '
323
324
        <p>
325
        <hr />A critical error has been found!
326
327
        <p>'.$text.'</p>
328
329
330
        <p>
331
        The process has been stopped. Please see the <a href="'.$path_to_log.'">log file</a> for more information.</p>
332
333
        <p>Log: '.$path_to_log.'</p>
334
335
        <hr />
336
337
        </p>
338
        ';
339
340
        exit();
0 ignored issues
show
Best Practice introduced by Christian
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...
341
    }
342
343
    protected function createCourseCode($title)
344
    {
345
        //Making sure that text of the short name does not go over the DB limit.
346
        //and leaving the space to add additional characters by the platform
347
        $code = substr(strtoupper(str_replace(' ', '', trim($title))), 0, 94);
348
349
        return $code;
350
    }
351
}
352