GanttProject::save()   C
last analyzed

Complexity

Conditions 9
Paths 32

Size

Total Lines 247

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 178
CRAP Score 9

Importance

Changes 0
Metric Value
dl 0
loc 247
ccs 178
cts 178
cp 1
rs 6.4444
c 0
b 0
f 0
cc 9
nc 32
nop 1
crap 9

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
/**
3
 * This file is part of PHPProject - A pure PHP library for reading and writing
4
 * presentations documents.
5
 *
6
 * PHPProject is free software distributed under the terms of the GNU Lesser
7
 * General Public License version 3 as published by the Free Software Foundation.
8
 *
9
 * For the full copyright and license information, please read the LICENSE
10
 * file that was distributed with this source code. For the full list of
11
 * contributors, visit https://github.com/PHPOffice/PHPWord/contributors.
12
 *
13
 * @link        https://github.com/PHPOffice/PHPProject
14
 * @copyright   2009-2014 PHPProject contributors
15
 * @license     http://www.gnu.org/licenses/lgpl.txt LGPL version 3
16
 */
17
18
namespace PhpOffice\PhpProject\Writer;
19
20
use PhpOffice\PhpProject\PhpProject;
21
use PhpOffice\PhpProject\Shared\XMLWriter;
22
use PhpOffice\PhpProject\Task;
23
24
/**
25
 * PHPProject_Writer_GanttProject
26
 *
27
 * @category    PHPProject
28
 * @package        PHPProject
29
 * @copyright    Copyright (c) 2012 - 2012 PHPProject (https://github.com/PHPOffice/PHPProject)
30
 */
31
class GanttProject
32
{
33
    /**
34
     * PHPProject object
35
     *
36
     * @var \PhpOffice\PhpProject\PhpProject
37
     */
38
    private $phpProject;
39
    
40
    /**
41
     * 
42
     * @var array
43
     */
44
    private $arrAllocations;
45
    
46
    
47
    /**
48
     * Create a new PHPProject_Writer_GanttProject
49
     *
50
     * @param    PHPProject    $phpProject
51
     */
52 3
    public function __construct(PhpProject $phpProject)
53
    {
54 3
        $this->phpProject = $phpProject;
55 3
        $this->arrAllocations = array();
56 3
    }
57
    
58
    /**
59
     * 
60
     * @param string $pFilename
61
     * @throws Exception
62
     */
63 2
    public function save($pFilename)
64
    {
65 2
        $arrProjectInfo = $this->sanitizeProject();
66
        
67
        // Create XML Object
68 2
        $oXML = new XMLWriter(XMLWriter::STORAGE_DISK);
69 2
        $oXML->startDocument('1.0', 'UTF-8');
70
        // project
71 2
        $oXML->startElement('project');
72 2
        if (isset($arrProjectInfo['date_start']) && $arrProjectInfo['date_start'] != 0) {
73 1
            $oXML->writeAttribute('view-date', date('Y-m-d', $arrProjectInfo['date_start']));
74 1
        }
75 2
        $oXML->writeAttribute('version', '2.0');
76
        
77
        // view
78 2
        $oXML->startElement('view');
79 2
        $oXML->writeAttribute('id', 'resource-table');
80
        
81
        // field
82 2
        $oXML->startElement('field');
83 2
        $oXML->writeAttribute('id', '0');
84 2
        $oXML->writeAttribute('name', 'Nom');
85 2
        $oXML->writeAttribute('width', '56');
86 2
        $oXML->writeAttribute('valuetype', '0');
87 2
        $oXML->endElement();
88
        
89 2
        $oXML->startElement('field');
90 2
        $oXML->writeAttribute('id', '1');
91 2
        $oXML->writeAttribute('name', 'Rôle par défaut');
92 2
        $oXML->writeAttribute('width', '43');
93 2
        $oXML->writeAttribute('valuetype', '1');
94 2
        $oXML->endElement();
95
        
96
        // >view
97 2
        $oXML->endElement();
98
        
99
        // tasks
100 2
        $oXML->startElement('tasks');
101
        
102
        // tasksproperties
103 2
        $oXML->startElement('tasksproperties');
104
        
105
        // taskproperty
106 2
        $oXML->startElement('taskproperty');
107 2
        $oXML->writeAttribute('id', 'tpd0');
108 2
        $oXML->writeAttribute('name', 'type');
109 2
        $oXML->writeAttribute('type', 'default');
110 2
        $oXML->writeAttribute('valuetype', 'icon');
111 2
        $oXML->endElement();
112
        
113 2
        $oXML->startElement('taskproperty');
114 2
        $oXML->writeAttribute('id', 'tpd1');
115 2
        $oXML->writeAttribute('name', 'priority');
116 2
        $oXML->writeAttribute('type', 'default');
117 2
        $oXML->writeAttribute('valuetype', 'icon');
118 2
        $oXML->endElement();
119
        
120 2
        $oXML->startElement('taskproperty');
121 2
        $oXML->writeAttribute('id', 'tpd2');
122 2
        $oXML->writeAttribute('name', 'info');
123 2
        $oXML->writeAttribute('type', 'default');
124 2
        $oXML->writeAttribute('valuetype', 'icon');
125 2
        $oXML->endElement();
126
        
127 2
        $oXML->startElement('taskproperty');
128 2
        $oXML->writeAttribute('id', 'tpd3');
129 2
        $oXML->writeAttribute('name', 'name');
130 2
        $oXML->writeAttribute('type', 'default');
131 2
        $oXML->writeAttribute('valuetype', 'text');
132 2
        $oXML->endElement();
133
        
134 2
        $oXML->startElement('taskproperty');
135 2
        $oXML->writeAttribute('id', 'tpd4');
136 2
        $oXML->writeAttribute('name', 'begindate');
137 2
        $oXML->writeAttribute('type', 'default');
138 2
        $oXML->writeAttribute('valuetype', 'date');
139 2
        $oXML->endElement();
140
        
141 2
        $oXML->startElement('taskproperty');
142 2
        $oXML->writeAttribute('id', 'tpd5');
143 2
        $oXML->writeAttribute('name', 'enddate');
144 2
        $oXML->writeAttribute('type', 'default');
145 2
        $oXML->writeAttribute('valuetype', 'date');
146 2
        $oXML->endElement();
147
        
148 2
        $oXML->startElement('taskproperty');
149 2
        $oXML->writeAttribute('id', 'tpd6');
150 2
        $oXML->writeAttribute('name', 'duration');
151 2
        $oXML->writeAttribute('type', 'default');
152 2
        $oXML->writeAttribute('valuetype', 'int');
153 2
        $oXML->endElement();
154
        
155 2
        $oXML->startElement('taskproperty');
156 2
        $oXML->writeAttribute('id', 'tpd7');
157 2
        $oXML->writeAttribute('name', 'completion');
158 2
        $oXML->writeAttribute('type', 'default');
159 2
        $oXML->writeAttribute('valuetype', 'int');
160 2
        $oXML->endElement();
161
        
162 2
        $oXML->startElement('taskproperty');
163 2
        $oXML->writeAttribute('id', 'tpd8');
164 2
        $oXML->writeAttribute('name', 'coordinator');
165 2
        $oXML->writeAttribute('type', 'default');
166 2
        $oXML->writeAttribute('valuetype', 'text');
167 2
        $oXML->endElement();
168
        
169 2
        $oXML->startElement('taskproperty');
170 2
        $oXML->writeAttribute('id', 'tpd9');
171 2
        $oXML->writeAttribute('name', 'predecessorsr');
172 2
        $oXML->writeAttribute('type', 'default');
173 2
        $oXML->writeAttribute('valuetype', 'text');
174 2
        $oXML->endElement();
175
        // >taskproperty
176
        
177
        // >tasksproperties
178 2
        $oXML->endElement();
179
        
180
        // task
181 2
        foreach ($this->phpProject->getAllTasks() as $oTask) {
182 2
            $this->writeTask($oXML, $oTask);
183 2
        }
184
        
185
        // >tasks
186 2
        $oXML->endElement();
187
        
188
        // resources
189 2
        $oXML->startElement('resources');
190
        
191
        // resource
192 2
        foreach ($this->phpProject->getAllResources() as $oResource) {
193 1
            $this->writeResource($oXML, $oResource);
0 ignored issues
show
Documentation introduced by
$oResource is of type resource, but the function expects a object<PhpOffice\PhpProject\Resource>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
194 2
        }
195
        
196
        // >resources
197 2
        $oXML->endElement();
198
        
199
        // allocations
200 2
        $oXML->startElement('allocations');
201
        
202 2
        if (count($this->arrAllocations) > 0) {
203 1
            foreach ($this->arrAllocations as $itmAllocation) {
204 1
                $this->writeAllocation($oXML, $itmAllocation['id_task'], $itmAllocation['id_res']);
205 1
            }
206 1
        }
207
        
208
        // >allocations
209 2
        $oXML->endElement();
210
        
211
        // taskdisplaycolumns
212 2
        $oXML->startElement('tasksproperties');
213
        
214
        // displaycolumn
215 2
        $oXML->startElement('displaycolumn');
216 2
        $oXML->writeAttribute('property-id', 'tpd2');
217 2
        $oXML->writeAttribute('order', '-1');
218 2
        $oXML->writeAttribute('width', '75');
219 2
        $oXML->writeAttribute('visible', 'false');
220 2
        $oXML->endElement();
221
        
222 2
        $oXML->startElement('displaycolumn');
223 2
        $oXML->writeAttribute('property-id', 'tpd7');
224 2
        $oXML->writeAttribute('order', '-1');
225 2
        $oXML->writeAttribute('width', '75');
226 2
        $oXML->writeAttribute('visible', 'false');
227 2
        $oXML->endElement();
228
        
229 2
        $oXML->startElement('displaycolumn');
230 2
        $oXML->writeAttribute('property-id', 'tpd6');
231 2
        $oXML->writeAttribute('order', '-1');
232 2
        $oXML->writeAttribute('width', '75');
233 2
        $oXML->writeAttribute('visible', 'false');
234 2
        $oXML->endElement();
235
        
236 2
        $oXML->startElement('displaycolumn');
237 2
        $oXML->writeAttribute('property-id', 'tpd10');
238 2
        $oXML->writeAttribute('order', '-1');
239 2
        $oXML->writeAttribute('width', '75');
240 2
        $oXML->writeAttribute('visible', 'false');
241 2
        $oXML->endElement();
242
        
243 2
        $oXML->startElement('displaycolumn');
244 2
        $oXML->writeAttribute('property-id', 'tpd1');
245 2
        $oXML->writeAttribute('order', '-1');
246 2
        $oXML->writeAttribute('width', '75');
247 2
        $oXML->writeAttribute('visible', 'false');
248 2
        $oXML->endElement();
249
        
250 2
        $oXML->startElement('displaycolumn');
251 2
        $oXML->writeAttribute('property-id', 'tpd9');
252 2
        $oXML->writeAttribute('order', '-1');
253 2
        $oXML->writeAttribute('width', '75');
254 2
        $oXML->writeAttribute('visible', 'false');
255 2
        $oXML->endElement();
256
        
257 2
        $oXML->startElement('displaycolumn');
258 2
        $oXML->writeAttribute('property-id', 'tpd8');
259 2
        $oXML->writeAttribute('order', '-1');
260 2
        $oXML->writeAttribute('width', '75');
261 2
        $oXML->writeAttribute('visible', 'false');
262 2
        $oXML->endElement();
263
        
264 2
        $oXML->startElement('displaycolumn');
265 2
        $oXML->writeAttribute('property-id', 'tpd0');
266 2
        $oXML->writeAttribute('order', '-1');
267 2
        $oXML->writeAttribute('width', '75');
268 2
        $oXML->writeAttribute('visible', 'false');
269 2
        $oXML->endElement();
270
        
271 2
        $oXML->startElement('displaycolumn');
272 2
        $oXML->writeAttribute('property-id', 'tpd3');
273 2
        $oXML->writeAttribute('order', '0');
274 2
        $oXML->writeAttribute('width', '199');
275 2
        $oXML->writeAttribute('visible', 'true');
276 2
        $oXML->endElement();
277
        
278 2
        $oXML->startElement('displaycolumn');
279 2
        $oXML->writeAttribute('property-id', 'tpd4');
280 2
        $oXML->writeAttribute('order', '1');
281 2
        $oXML->writeAttribute('width', '75');
282 2
        $oXML->writeAttribute('visible', 'true');
283 2
        $oXML->endElement();
284
        
285 2
        $oXML->startElement('displaycolumn');
286 2
        $oXML->writeAttribute('property-id', 'tpd5');
287 2
        $oXML->writeAttribute('order', '2');
288 2
        $oXML->writeAttribute('width', '75');
289 2
        $oXML->writeAttribute('visible', 'true');
290 2
        $oXML->endElement();
291
        // >displaycolumn
292
        
293
        // >taskdisplaycolumns
294 2
        $oXML->endElement();
295
        
296
        // >project
297 2
        $oXML->endElement();
298
        
299
        // Writing XML Object in file
300
        // Open file
301 2
        if (file_exists($pFilename) && !is_writable($pFilename)) {
302 1
            throw new \Exception("Could not open file $pFilename for writing.");
303
        }
304 1
        $fileHandle = fopen($pFilename, 'wb+');
305
        // Write XML Content
306 1
        fwrite($fileHandle, $oXML->getData());
307
        // Close file
308 1
        fclose($fileHandle);
309 1
    }
310
    
311 2
    private function writeTask(XMLWriter $oXML, Task $oTask)
312
    {
313 2
        $oXML->startElement('task');
314 2
        $oXML->writeAttribute('id', $oTask->getIndex());
315 2
        $oXML->writeAttribute('name', $oTask->getName());
316 2
        $oXML->writeAttribute('start', date('Y-m-d', $oTask->getStartDate()));
317 2
        $oXML->writeAttribute('duration', $oTask->getDuration());
318 2
        $oXML->writeAttribute('complete', $oTask->getProgress() * 100);
319 2
        $oXML->writeAttribute('meeting', 'false');
320 2
        $oXML->writeAttribute('expand', 'true');
321
        
322
        // Resources Allocations
323 2
        if ($oTask->getResourceCount() > 0) {
324 1
            foreach ($oTask->getResources() as $oResource) {
325 1
                $itmAllocation = array();
326 1
                $itmAllocation['id_res'] = $oResource->getIndex();
0 ignored issues
show
Bug introduced by
The method getIndex cannot be called on $oResource (of type integer).

Methods can only be called on objects. This check looks for methods being called on variables that have been inferred to never be objects.

Loading history...
327 1
                $itmAllocation['id_task'] = $oTask->getIndex();
328 1
                $this->arrAllocations[] = $itmAllocation;
329 1
            }
330 1
        }
331
        
332
        // Children
333 2
        if ($oTask->getTaskCount() > 0) {
334 1
            $arrTasksChilds = $oTask->getTasks();
335 1
            foreach ($arrTasksChilds as $oTaskChild) {
336 1
                $this->writeTask($oXML, $oTaskChild);
337 1
            }
338 1
        } else {
339
            // Nothing
340
        }
341 2
        $oXML->endElement();
342 2
    }
343
    
344
    /**
345
     * 
346
     * @param XMLWriter $oXML
347
     * @param \PhpOffice\PhpProject\Resource $oResource
348
     */
349 1
    private function writeResource(XMLWriter $oXML, \PhpOffice\PhpProject\Resource $oResource)
350
    {
351 1
        $oXML->startElement('resource');
352 1
        $oXML->writeAttribute('id', $oResource->getIndex());
353 1
        $oXML->writeAttribute('name', $oResource->getTitle());
354 1
        $oXML->writeAttribute('function', 'Default:0');
355 1
        $oXML->writeAttribute('contacts', '');
356 1
        $oXML->writeAttribute('phone', '');
357 1
        $oXML->endElement();
358 1
    }
359
    
360
    /**
361
     * Write allocation of a resource for a task
362
     * @param XMLWriter $oXML
363
     * @param integer $piIdTask
364
     * @param integer $piIdResource
365
     */
366 1
    private function writeAllocation(XMLWriter $oXML, $piIdTask, $piIdResource)
367
    {
368 1
        $oXML->startElement('allocation');
369 1
        $oXML->writeAttribute('task-id', $piIdTask);
370 1
        $oXML->writeAttribute('resource-id', $piIdResource);
371 1
        $oXML->writeAttribute('function', 'Default:0');
372 1
        $oXML->writeAttribute('responsible', 'true');
373 1
        $oXML->writeAttribute('load', '100.0');
374 1
        $oXML->endElement();
375 1
    }
376
    
377
    /**
378
     * @return multitype:Ambigous <number, unknown>
0 ignored issues
show
Documentation introduced by
The doc-type multitype:Ambigous could not be parsed: Unknown type name "multitype:Ambigous" at position 0. (view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
379
     */
380 2
    private function sanitizeProject()
381
    {
382
        // Info Project
383 2
        $minDate = 0;
384
        // Browse all tasks
385 2
        $arrTasks = $this->phpProject->getAllTasks();
386 2
        foreach ($arrTasks as $oTask) {
387 2
            if ($oTask->getTaskCount() == 0) {
388 2
                $this->sanitizeTask($oTask);
389 2
            } else {
390 1
                $this->sanitizeTaskParent($oTask);
391
            }
392 2
            $tStartDate = $oTask->getStartDate();
393 2
            if ($minDate == 0 || $tStartDate < $minDate) {
394 2
                $minDate = $tStartDate;
395 2
            }
396 2
        }
397
        
398
        return array(
399
            'date_start' => (int)$minDate
400 2
        );
401
    }
402
    
403
    /**
404
     * Permits to clean a task
405
     * - If the duration is not filled, but the end date is, we calculate it.
406
     * - If the end date is not filled, but the duration is, we calculate it.
407
     * @param PHPProject_Task $oTask
408
     */
409 2
    private function sanitizeTask(Task $oTask)
410
    {
411 2
        $pDuration = $oTask->getDuration();
412 2
        $pEndDate = $oTask->getEndDate();
413 2
        $pStartDate = $oTask->getStartDate();
414
        
415 2
        if (is_null($pDuration) && !is_null($pEndDate)) {
416 1
            $iTimeDiff = $pEndDate - $pStartDate;
417 1
            $iNumDays = $iTimeDiff / 60 / 60 / 24;
418 1
            $oTask->setDuration($iNumDays + 1);
419 2
        } elseif (!is_null($pDuration) && is_null($pEndDate)) {
420 1
            $oTask->setEndDate($pStartDate + ($pDuration * 24 * 60 * 60));
421 1
        }
422 2
    }
423
    
424
    /**
425
     * Permits to clean parent task and calculate parent data like total duration,
426
     *   date start and complete average.
427
     * @param PHPProject_Task $oParentTask
428
     */
429 1
    private function sanitizeTaskParent(Task $oParentTask)
430
    {
431 1
        $arrTasksChilds = $oParentTask->getTasks();
432
        
433 1
        $iProgress = 0;
434 1
        $tStartDate = null;
435 1
        $tEndDate = null;
436 1
        foreach ($arrTasksChilds as $oTaskChild) {
437 1
            if ($oTaskChild->getTaskCount() == 0) {
438 1
                $this->sanitizeTask($oTaskChild);
439 1
            } else {
440 1
                $this->sanitizeTaskParent($oTaskChild);
441
            }
442
            
443 1
            $iProgress += $oTaskChild->getProgress();
444 1
            if (is_null($tStartDate)) {
445 1
                $tStartDate = $oTaskChild->getStartDate();
446 1
            } elseif ($tStartDate > $oTaskChild->getStartDate()) {
447 1
                $tStartDate = $oTaskChild->getStartDate();
448 1
            }
449
            
450 1
            if (is_null($tEndDate)) {
451 1
                $tEndDate = $oTaskChild->getEndDate();
452 1
            } elseif ($tEndDate < $oTaskChild->getEndDate()) {
453 1
                $tEndDate = $oTaskChild->getEndDate();
454 1
            }
455 1
        }
456 1
        $oParentTask->setProgress($iProgress / $oParentTask->getTaskCount());
457 1
        $oParentTask->setStartDate($tStartDate);
458 1
        $oParentTask->setEndDate($tEndDate);
459 1
        $oParentTask->setDuration((($tEndDate - $tStartDate) / 60 / 60 / 24) + 1);
460 1
    }
461
}
462