Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
88 / 88
100.00% covered (success)
100.00%
9 / 9
CRAP
100.00% covered (success)
100.00%
1 / 1
MSPDI
100.00% covered (success)
100.00%
88 / 88
100.00% covered (success)
100.00%
9 / 9
44
100.00% covered (success)
100.00%
1 / 1
 __construct
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 canRead
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
3
 load
100.00% covered (success)
100.00%
19 / 19
100.00% covered (success)
100.00%
1 / 1
7
 readNodeResources
100.00% covered (success)
100.00%
6 / 6
100.00% covered (success)
100.00%
1 / 1
4
 readNodeResource
100.00% covered (success)
100.00%
10 / 10
100.00% covered (success)
100.00%
1 / 1
5
 readNodeTasks
100.00% covered (success)
100.00%
6 / 6
100.00% covered (success)
100.00%
1 / 1
4
 readNodeTask
100.00% covered (success)
100.00%
22 / 22
100.00% covered (success)
100.00%
1 / 1
9
 readNodeAssignments
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
4
 readNodeAssignment
100.00% covered (success)
100.00%
16 / 16
100.00% covered (success)
100.00%
1 / 1
7
1<?php
2
3/**
4 * This file is part of PHPProject - A pure PHP library for reading and writing
5 * project management files.
6 *
7 * PHPProject is free software distributed under the terms of the GNU Lesser
8 * General Public License version 3 as published by the Free Software Foundation.
9 *
10 * For the full copyright and license information, please read the LICENSE
11 * file that was distributed with this source code. For the full list of
12 * contributors, visit https://github.com/PHPOffice/PHPProject/contributors.
13 *
14 * @link        https://github.com/PHPOffice/PHPProject
15 * @copyright   2009-2014 PHPProject contributors
16 * @license     http://www.gnu.org/licenses/lgpl.txt LGPL version 3
17 */
18
19declare(strict_types=1);
20
21namespace PhpOffice\PhpProject\Reader;
22
23use PhpOffice\PhpProject\PhpProject;
24use PhpOffice\PhpProject\Resource;
25use PhpOffice\PhpProject\Shared\XMLReader;
26use PhpOffice\PhpProject\Task;
27
28/**
29 * MSPDI (Microsoft Project Data Interchange) reader
30 */
31class MSPDI implements ReaderInterface
32{
33    /**
34     * PHPProject object
35     *
36     * @var PhpProject
37     */
38    protected $phpProject;
39
40    /**
41     * Create a new MSPDI reader
42     */
43    public function __construct()
44    {
45        $this->phpProject = new PhpProject();
46    }
47
48    /**
49     *
50     * @param string $pFilename
51     * @return bool
52     */
53    public function canRead(string $pFilename): bool
54    {
55        if (file_exists($pFilename) && is_readable($pFilename)) {
56            return true;
57        }
58        return false;
59    }
60
61    /**
62     *
63     * @param string $pFilename
64     * @throws \Exception
65     * @return PhpProject
66     */
67    public function load(string $pFilename): PhpProject
68    {
69        if (!$this->canRead($pFilename)) {
70            throw new \Exception('The file is not accessible.');
71        }
72        $content = file_get_contents($pFilename);
73        $xml = new XMLReader();
74        $xml->getDomFromString($content);
75
76        $nodes = $xml->getElements('*');
77        if ($nodes->length > 0) {
78            foreach ($nodes as $node) {
79                switch ($node->nodeName) {
80                    case 'Resources':
81                        $this->readNodeResources($xml, $node);
82                        break;
83                    case 'Tasks':
84                        $this->readNodeTasks($xml, $node);
85                        break;
86                    case 'Assignments':
87                        $this->readNodeAssignments($xml, $node);
88                        break;
89                }
90            }
91        }
92
93        return $this->phpProject;
94    }
95
96    /**
97     * Node "Resources"
98     * @param XMLReader $xml
99     * @param \DOMElement $domNode
100     */
101    protected function readNodeResources(XMLReader $xml, \DOMElement $domNode): void
102    {
103        $nodes = $xml->getElements('*', $domNode);
104        if ($nodes->length > 0) {
105            foreach ($nodes as $node) {
106                if ($node->nodeName == 'Resource') {
107                    $resource = $this->phpProject->createResource();
108                    $this->readNodeResource($xml, $node, $resource);
109                }
110            }
111        }
112    }
113
114    /**
115     * Node "Resource"
116     * @param XMLReader $xml
117     * @param \DOMElement $domNode
118     * @param Resource $resource
119     */
120    protected function readNodeResource(XMLReader $xml, \DOMElement $domNode, Resource $resource): void
121    {
122        $nodes = $xml->getElements('*', $domNode);
123        if ($nodes->length > 0) {
124            foreach ($nodes as $node) {
125                switch ($node->nodeName) {
126                    case 'UID':
127                        $resource->setIndex((int) $node->nodeValue);
128                        break;
129                    case 'Name':
130                        $resource->setTitle($node->nodeValue);
131                        break;
132                }
133            }
134        }
135    }
136
137    /**
138     * Node "Tasks"
139     * @param XMLReader $xml
140     * @param \DOMElement $domNode
141     */
142    protected function readNodeTasks(XMLReader $xml, \DOMElement $domNode): void
143    {
144        $nodes = $xml->getElements('*', $domNode);
145        if ($nodes->length > 0) {
146            foreach ($nodes as $node) {
147                if ($node->nodeName == 'Task') {
148                    $task = $this->phpProject->createTask();
149                    $this->readNodeTask($xml, $node, $task);
150                }
151            }
152        }
153    }
154
155    /**
156     * Node "Task"
157     * @param XMLReader $xml
158     * @param \DOMElement $domNode
159     * @param Task $task
160     */
161    protected function readNodeTask(XMLReader $xml, \DOMElement $domNode, Task $task): void
162    {
163        $nodes = $xml->getElements('*', $domNode);
164        if ($nodes->length > 0) {
165            foreach ($nodes as $node) {
166                switch ($node->nodeName) {
167                    case 'UID':
168                        $task->setIndex((int) $node->nodeValue);
169                        break;
170                    case 'Name':
171                        $task->setName($node->nodeValue);
172                        break;
173                    case 'Start':
174                        $task->setStartDate($node->nodeValue);
175                        break;
176                    case 'Finish':
177                        $task->setEndDate($node->nodeValue);
178                        break;
179                    case 'Work':
180                        $task->setDuration($node->nodeValue);
181                        break;
182                    case 'PercentComplete':
183                        $task->setProgress((float) $node->nodeValue / 100);
184                        break;
185                }
186            }
187        }
188    }
189
190    /**
191     * Node "Assignments"
192     * @param XMLReader $xml
193     * @param \DOMElement $domNode
194     */
195    protected function readNodeAssignments(XMLReader $xml, \DOMElement $domNode): void
196    {
197        $nodes = $xml->getElements('*', $domNode);
198        if ($nodes->length > 0) {
199            foreach ($nodes as $node) {
200                if ($node->nodeName == 'Assignment') {
201                    $this->readNodeAssignment($xml, $node);
202                }
203            }
204        }
205    }
206
207    /**
208     * Node "Assignment"
209     * @param XMLReader $xml
210     * @param \DOMElement $domNode
211     */
212    protected function readNodeAssignment(XMLReader $xml, \DOMElement $domNode): void
213    {
214        $idTask = null;
215        $idResource = null;
216        $nodes = $xml->getElements('*', $domNode);
217        if ($nodes->length > 0) {
218            foreach ($nodes as $node) {
219                switch ($node->nodeName) {
220                    case 'TaskUID':
221                        $idTask = $node->nodeValue;
222                        break;
223                    case 'ResourceUID':
224                        $idResource = $node->nodeValue;
225                        break;
226                }
227            }
228        }
229
230        $resource = $this->phpProject->getResourceFromIndex($idResource);
231        $task = $this->phpProject->getTaskFromIndex($idTask);
232
233        if ($resource instanceof Resource && $task instanceof Task) {
234            $task->addResource($resource);
235        }
236    }
237}