Passed
Pull Request — master (#132)
by
unknown
02:31
created

onAfterPublishRecursive()   A

Complexity

Conditions 4
Paths 2

Size

Total Lines 21
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Importance

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