Completed
Push — master ( 0820f1...730af2 )
by Daniel
21s queued 10s
created

SiteTreePublishingEngine::reset()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 0
dl 0
loc 3
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace SilverStripe\StaticPublishQueue\Extension\Engine;
4
5
use SilverStripe\CMS\Model\SiteTreeExtension;
6
use SilverStripe\Core\Environment;
7
use SilverStripe\Core\Injector\Injector;
8
use SilverStripe\Core\Resettable;
9
use SilverStripe\StaticPublishQueue\Contract\StaticPublishingTrigger;
10
use SilverStripe\StaticPublishQueue\Extension\Publishable\PublishableSiteTree;
11
use SilverStripe\StaticPublishQueue\Job\DeleteStaticCacheJob;
12
use SilverStripe\StaticPublishQueue\Job\GenerateStaticCacheJob;
13
use Symbiote\QueuedJobs\Services\QueuedJobService;
14
15
/**
16
 * This extension couples to the StaticallyPublishable and StaticPublishingTrigger implementations
17
 * on the SiteTree objects and makes sure the actual change to SiteTree is triggered/enqueued.
18
 *
19
 * Provides the following information as a context to StaticPublishingTrigger:
20
 * * action - name of the executed action: publish or unpublish
21
 *
22
 * @see PublishableSiteTree
23
 */
24
class SiteTreePublishingEngine extends SiteTreeExtension implements Resettable
25
{
26
    /**
27
     * Queued job service injection property
28
     * Used for unit tests only to cover edge cases where Injector doesn't cover
29
     *
30
     * @var QueuedJobService|null
31
     */
32
    protected static $queueService = null;
33
34
    /**
35
     * Queues the urls to be flushed into the queue.
36
     *
37
     * @var array
38
     */
39
    private $toUpdate = [];
40
41
    /**
42
     * Queues the urls to be deleted as part of a next flush operation.
43
     *
44
     * @var array
45
     */
46
    private $toDelete = [];
47
48
    public static function reset(): void
49
    {
50
        static::$queueService = null;
51
    }
52
53
    /**
54
     * Force inject queue service
55
     * Used for unit tests only to cover edge cases where Injector doesn't cover
56
     *
57
     *
58
     * @param QueuedJobService $service
59
     */
60
    public static function setQueueService(QueuedJobService $service): void
61
    {
62
        static::$queueService = $service;
63
    }
64
65
    /**
66
     * @return array
67
     */
68
    public function getToUpdate()
69
    {
70
        return $this->toUpdate;
71
    }
72
73
    /**
74
     * @return array
75
     */
76
    public function getToDelete()
77
    {
78
        return $this->toDelete;
79
    }
80
81
    /**
82
     * @param array $toUpdate
83
     * @return $this
84
     */
85
    public function setToUpdate($toUpdate)
86
    {
87
        $this->toUpdate = $toUpdate;
88
        return $this;
89
    }
90
91
    /**
92
     * @param array $toDelete
93
     * @return $this
94
     */
95
    public function setToDelete($toDelete)
96
    {
97
        $this->toDelete = $toDelete;
98
        return $this;
99
    }
100
101
    /**
102
     * @param \SilverStripe\CMS\Model\SiteTree|null $original
103
     */
104
    public function onAfterPublishRecursive(&$original)
105
    {
106
        // if the site tree has been "reorganised" (ie: the parentID has changed)
107
        // then this is eht equivalent of an unpublish and publish as far as the
108
        // static publisher is concerned
109
        if ($original && (
110
                $original->ParentID !== $this->getOwner()->ParentID
111
                || $original->URLSegment !== $this->getOwner()->URLSegment
112
            )
113
        ) {
114
            $context = [
115
                'action' => 'unpublish',
116
            ];
117
            $original->collectChanges($context);
118
            $original->flushChanges();
119
        }
120
        $context = [
121
            'action' => 'publish',
122
        ];
123
        $this->collectChanges($context);
124
        $this->flushChanges();
125
    }
126
127
    public function onBeforeUnpublish()
128
    {
129
        $context = [
130
            'action' => 'unpublish',
131
        ];
132
        $this->collectChanges($context);
133
    }
134
135
    public function onAfterUnpublish()
136
    {
137
        $this->flushChanges();
138
    }
139
140
    /**
141
     * Collect all changes for the given context.
142
     *
143
     * @param array $context
144
     */
145
    public function collectChanges($context)
146
    {
147
        Environment::increaseMemoryLimitTo();
148
        Environment::increaseTimeLimitTo();
149
150
        if ($this->getOwner()->hasExtension(PublishableSiteTree::class)
151
            || $this->getOwner() instanceof StaticPublishingTrigger
152
        ) {
153
            $toUpdate = $this->getOwner()->objectsToUpdate($context);
154
            $this->setToUpdate($toUpdate);
155
156
            $toDelete = $this->getOwner()->objectsToDelete($context);
157
            $this->setToDelete($toDelete);
158
        }
159
    }
160
161
    /**
162
     * Execute URL deletions, enqueue URL updates.
163
     */
164
    public function flushChanges()
165
    {
166
        $queue = static::$queueService ?? QueuedJobService::singleton();
167
168
        if (!empty($this->toUpdate)) {
169
            foreach ($this->toUpdate as $queueItem) {
170
                $job = Injector::inst()->create(GenerateStaticCacheJob::class);
171
172
                $jobData = new \stdClass();
173
                $urls = $queueItem->urlsToCache();
174
                ksort($urls);
175
                $jobData->URLsToProcess = $urls;
176
177
                $job->setJobData(0, 0, false, $jobData, [
178
                    'Building URLs: ' . var_export(array_keys($jobData->URLsToProcess), true),
179
                ]);
180
181
                $queue->queueJob($job);
182
            }
183
            $this->toUpdate = [];
184
        }
185
186
        if (!empty($this->toDelete)) {
187
            foreach ($this->toDelete as $queueItem) {
188
                $job = Injector::inst()->create(DeleteStaticCacheJob::class);
189
190
                $jobData = new \stdClass();
191
                $urls = $queueItem->urlsToCache();
192
                ksort($urls);
193
                $jobData->URLsToProcess = $urls;
194
195
                $job->setJobData(0, 0, false, $jobData, [
196
                    'Purging URLs: ' . var_export(array_keys($jobData->URLsToProcess), true),
197
                ]);
198
199
                $queue->queueJob($job);
200
            }
201
            $this->toDelete = [];
202
        }
203
    }
204
}
205