TaskList   A
last analyzed

Complexity

Total Complexity 20

Size/Duplication

Total Lines 202
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 3

Importance

Changes 1
Bugs 0 Features 0
Metric Value
wmc 20
lcom 1
cbo 3
dl 0
loc 202
rs 10
c 1
b 0
f 0

11 Methods

Rating   Name   Duplication   Size   Complexity  
A dequeue() 0 16 4
A getNext() 0 9 2
A remove() 0 11 2
A getIds() 0 4 1
A getTask() 0 9 2
A taskIdToFileName() 0 4 1
A generateId() 0 4 1
A getConfig() 0 4 1
A __construct() 0 5 1
B queue() 0 27 3
A createTaskFromMetaData() 0 9 2
1
<?php
2
3
/**
4
 * This file is part of tenside/core.
5
 *
6
 * (c) Christian Schiffler <[email protected]>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 *
11
 * This project is provided in good faith and hope to be usable by anyone.
12
 *
13
 * @package    tenside/core
14
 * @author     Christian Schiffler <[email protected]>
15
 * @copyright  2015 Christian Schiffler <[email protected]>
16
 * @license    https://github.com/tenside/core/blob/master/LICENSE MIT
17
 * @link       https://github.com/tenside/core
18
 * @filesource
19
 */
20
21
namespace Tenside\Core\Task;
22
23
use Tenside\Core\Util\JsonArray;
24
use Tenside\Core\Util\JsonFile;
25
26
/**
27
 * This class is an implementation of the task list.
28
 */
29
class TaskList
30
{
31
    /**
32
     * The config to read from.
33
     *
34
     * @var string
35
     */
36
    private $dataDir;
37
38
    /**
39
     * The task factory to use.
40
     *
41
     * @var TaskFactoryInterface
42
     */
43
    private $factory;
44
45
    /**
46
     * Create a new instance.
47
     *
48
     * @param string               $dataDir The directory to keep the database in.
49
     *
50
     * @param TaskFactoryInterface $factory The task factory to use.
51
     */
52
    public function __construct($dataDir, TaskFactoryInterface $factory)
53
    {
54
        $this->dataDir = $dataDir;
55
        $this->factory = $factory;
56
    }
57
58
    /**
59
     * Add the task to the list.
60
     *
61
     * @param string         $type     The type name.
62
     *
63
     * @param JsonArray|null $metaData The (optional) meta data.
64
     *
65
     * @return string
66
     *
67
     * @throws \InvalidArgumentException When no task instance can be created from the meta data.
68
     */
69
    public function queue($type, JsonArray $metaData = null)
70
    {
71
        $taskId = $this->generateId();
72
73
        if (null === $metaData) {
74
            $metaData = new JsonArray();
75
        }
76
77
        $metaData
78
            ->set(Task::SETTING_ID, $taskId)
79
            ->set(Task::SETTING_TYPE, $type)
80
            ->set('status', Task::STATE_PENDING)
81
            ->set(Task::SETTING_CREATED_AT, date('c'));
82
83
        $taskFile = new JsonFile($this->taskIdToFileName($taskId), null);
84
        $taskFile->setData($metaData->getData());
85
        $taskFile->save();
86
87
        if (!$this->createTaskFromMetaData($taskFile)) {
88
            unlink($taskFile->getFilename());
89
            throw new \InvalidArgumentException('Could not create task of type "' . $metaData->get('type') . '"');
90
        }
91
92
        $this->getConfig()->set($taskId, $metaData->getData());
93
94
        return $taskId;
95
    }
96
97
    /**
98
     * Remove a task from the queue (or the first one if no id given).
99
     *
100
     * @param null|string $taskId The id of the task to dequeue, if null the first queued task will be returned.
101
     *
102
     * @return Task|null
103
     */
104
    public function dequeue($taskId = null)
105
    {
106
        $idList = $this->getIds();
107
        if ((null === $taskId) && (false === ($taskId = current($idList)))) {
108
            return null;
109
        }
110
111
        if (!in_array($taskId, $idList)) {
112
            // Not in list, get out.
113
            return null;
114
        }
115
116
        $this->getConfig()->remove($taskId);
117
118
        return $this->getTask($taskId);
119
    }
120
121
    /**
122
     * Retrieve the first task from the queue without removing it.
123
     *
124
     * @return Task|null
125
     */
126
    public function getNext()
127
    {
128
        $idList = $this->getIds();
129
        if (false === ($taskId = current($idList))) {
130
            return null;
131
        }
132
133
        return $this->getTask($taskId);
134
    }
135
136
    /**
137
     * Remove a task from the list, including it's task file.
138
     *
139
     * @param string $taskId The task to remove.
140
     *
141
     * @return TaskList
142
     */
143
    public function remove($taskId)
144
    {
145
        $idList = $this->getIds();
146
147
        if (in_array($taskId, $idList)) {
148
            $this->getConfig()->remove($taskId);
149
            unlink($this->taskIdToFileName($taskId));
150
        }
151
152
        return $this;
153
    }
154
155
    /**
156
     * Retrieve the ids of all registered tasks.
157
     *
158
     * @return string[]
159
     */
160
    public function getIds()
161
    {
162
        return  $this->getConfig()->getEntries('/');
163
    }
164
165
    /**
166
     * Retrieve a task.
167
     *
168
     * @param string $taskId The id of the task to retrieve.
169
     *
170
     * @return Task|null
171
     */
172
    public function getTask($taskId)
173
    {
174
        $filename = $this->taskIdToFileName($taskId);
175
        if (!file_exists($filename)) {
176
            return null;
177
        }
178
179
        return $this->createTaskFromMetaData(new JsonFile($filename, null));
180
    }
181
182
    /**
183
     * Retrieve the correct filename for the given task id.
184
     *
185
     * @param string $taskId The task id to generate the file name for.
186
     *
187
     * @return string
188
     */
189
    private function taskIdToFileName($taskId)
190
    {
191
        return $this->dataDir . DIRECTORY_SEPARATOR . 'tenside-task-' . $taskId . '.json';
192
    }
193
194
    /**
195
     * Create a task instance from the given MetaData.
196
     *
197
     * @param JsonArray $config The configuration of the task.
198
     *
199
     * @return Task|null
200
     */
201
    private function createTaskFromMetaData(JsonArray $config)
202
    {
203
        $typeName = $config->get(Task::SETTING_TYPE);
204
        if ($this->factory->isTypeSupported($typeName)) {
205
            return $this->factory->createInstance($typeName, $config);
206
        }
207
208
        return null;
209
    }
210
211
    /**
212
     * Generate a task id.
213
     *
214
     * @return string
215
     */
216
    private function generateId()
217
    {
218
        return md5(uniqid('', true));
219
    }
220
221
    /**
222
     * Get the config file instance.
223
     *
224
     * @return JsonFile
225
     */
226
    private function getConfig()
227
    {
228
        return new JsonFile($this->dataDir . DIRECTORY_SEPARATOR . 'tenside-tasks.json', null);
229
    }
230
}
231