Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
51 / 51
100.00% covered (success)
100.00%
5 / 5
CRAP
100.00% covered (success)
100.00%
1 / 1
MSPDI
100.00% covered (success)
100.00%
51 / 51
100.00% covered (success)
100.00%
5 / 5
16
100.00% covered (success)
100.00%
1 / 1
 __construct
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 save
100.00% covered (success)
100.00%
23 / 23
100.00% covered (success)
100.00%
1 / 1
7
 writeResource
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
1
 writeTask
100.00% covered (success)
100.00%
17 / 17
100.00% covered (success)
100.00%
1 / 1
6
 writeAssignment
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
1
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\Writer;
22
23use PhpOffice\PhpProject\PhpProject;
24use PhpOffice\PhpProject\Resource;
25use PhpOffice\PhpProject\Shared\XMLWriter;
26use PhpOffice\PhpProject\Task;
27
28/**
29 * MSPDI (Microsoft Project Data Interchange) writer
30 */
31class MSPDI implements WriterInterface
32{
33    /**
34     * PHPProject object
35     *
36     * @var PhpProject
37     */
38    protected $phpProject;
39
40    /**
41     *
42     * @var array<array{id_res: int, id_task: int}>
43     */
44    protected $arrAllocations;
45
46    /**
47     * Create a new MSPDI writer
48     *
49     * @param PhpProject $phpProject
50     */
51    public function __construct(PhpProject $phpProject)
52    {
53        $this->phpProject = $phpProject;
54        $this->arrAllocations = array();
55    }
56
57    /**
58     * @param string $pFilename
59     * @throws \Exception
60     */
61    public function save(string $pFilename): void
62    {
63        // Create XML Object
64        $xml = new XMLWriter(XMLWriter::STORAGE_DISK);
65        $xml->startDocument('1.0', 'UTF-8');
66
67        // Project
68        $xml->startElement('Project');
69        $xml->writeAttribute('xmlns', 'http://schemas.microsoft.com/project');
70
71        // Tasks
72        $xml->startElement('Tasks');
73        foreach ($this->phpProject->getAllTasks() as $task) {
74            $this->writeTask($xml, $task);
75        }
76        $xml->endElement();
77
78        // Resources
79        $xml->startElement('Resources');
80        foreach ($this->phpProject->getAllResources() as $resource) {
81            $this->writeResource($xml, $resource);
82        }
83        $xml->endElement();
84
85        // Assignments
86        $xml->startElement('Assignments');
87        if (count($this->arrAllocations) > 0) {
88            foreach ($this->arrAllocations as $allocation) {
89                $this->writeAssignment($xml, $allocation['id_task'], $allocation['id_res']);
90            }
91        }
92        $xml->endElement();
93
94        // >Project
95        $xml->endElement();
96
97        // Writing XML Object in file
98        if (file_exists($pFilename) && !is_writable($pFilename)) {
99            throw new \Exception("Could not open file $pFilename for writing.");
100        }
101        $fileHandle = fopen($pFilename, 'wb+');
102        fwrite($fileHandle, $xml->getData());
103        fclose($fileHandle);
104    }
105
106    /**
107     * @param XMLWriter $xml
108     * @param Resource $resource
109     */
110    protected function writeResource(XMLWriter $xml, Resource $resource): void
111    {
112        $xml->startElement('Resource');
113        $xml->writeElement('UID', (string) $resource->getIndex());
114        $xml->writeElement('Name', $resource->getTitle());
115        $xml->endElement();
116    }
117
118    /**
119     * @param XMLWriter $xml
120     * @param Task $task
121     */
122    protected function writeTask(XMLWriter $xml, Task $task): void
123    {
124        $xml->startElement('Task');
125        $xml->writeElement('UID', (string) $task->getIndex());
126        $xml->writeElement('Name', $task->getName());
127        if ($task->getStartDate() !== null) {
128            $xml->writeElement('Start', date('Y-m-d\TH:i:s', $task->getStartDate()));
129        }
130        if ($task->getEndDate() !== null) {
131            $xml->writeElement('Finish', date('Y-m-d\TH:i:s', $task->getEndDate()));
132        }
133        if ($task->getDuration() !== null) {
134            $xml->writeElement('Work', (string) $task->getDuration());
135        }
136        $xml->writeElement('PercentComplete', (string) (int) (($task->getProgress() ?? 0) * 100));
137
138        // Resources allocations
139        if ($task->getResourceCount() > 0) {
140            foreach ($task->getResources() as $resource) {
141                $allocation = array();
142                $allocation['id_res'] = $resource->getIndex();
143                $allocation['id_task'] = $task->getIndex();
144                $this->arrAllocations[] = $allocation;
145            }
146        }
147
148        $xml->endElement();
149    }
150
151    /**
152     * Write an assignment of a resource to a task
153     * @param XMLWriter $xml
154     * @param int $idTask
155     * @param int $idResource
156     */
157    protected function writeAssignment(XMLWriter $xml, int $idTask, int $idResource): void
158    {
159        $xml->startElement('Assignment');
160        $xml->writeElement('TaskUID', (string) $idTask);
161        $xml->writeElement('ResourceUID', (string) $idResource);
162        $xml->writeElement('Units', '1');
163        $xml->endElement();
164    }
165}