Completed
Push — master ( 17cf3d...d536df )
by Robbie
13s
created

VersionFeedController::changes()   B

Complexity

Conditions 4
Paths 2

Size

Total Lines 22
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 22
rs 8.9197
c 0
b 0
f 0
cc 4
eloc 12
nc 2
nop 0
1
<?php
2
3
namespace SilverStripe\VersionFeed;
4
5
use SilverStripe\Core\Config\Config;
6
use SilverStripe\VersionFeed\VersionFeed;
7
use SilverStripe\Control\RSS\RSSFeed;
8
use SilverStripe\SiteConfig\SiteConfig;
9
use SilverStripe\ORM\DB;
10
use SilverStripe\Security\Member;
11
use SilverStripe\ORM\ArrayList;
12
use SilverStripe\CMS\Model\SiteTree;
13
use SilverStripe\Versioned\Versioned_Version;
14
use SilverStripe\Core\Convert;
15
use SilverStripe\View\Requirements;
16
use SilverStripe\Core\Extension;
17
use SilverStripe\VersionFeed\Filters\ContentFilter;
18
19
class VersionFeedController extends Extension
20
{
21
22
    private static $allowed_actions = array(
0 ignored issues
show
introduced by
The private property $allowed_actions is not used, and could be removed.
Loading history...
23
        'changes',
24
        'allchanges'
25
    );
26
    
27
    /**
28
     * Content handler
29
     *
30
     * @var ContentFilter
31
     */
32
    protected $contentFilter;
33
    
34
    /**
35
     * Sets the content filter
36
     *
37
     * @param ContentFilter $contentFilter
38
     */
39
    public function setContentFilter(ContentFilter $contentFilter)
40
    {
41
        $this->contentFilter = $contentFilter;
42
    }
43
    
44
    /**
45
     * Evaluates the result of the given callback
46
     *
47
     * @param string $key Unique key for this
48
     * @param callable $callback Callback for evaluating the content
49
     * @return mixed Result of $callback()
50
     */
51
    protected function filterContent($key, $callback)
52
    {
53
        if ($this->contentFilter) {
54
            return $this->contentFilter->getContent($key, $callback);
55
        } else {
56
            return call_user_func($callback);
57
        }
58
    }
59
60
    public function onAfterInit()
61
    {
62
        $this->linkToPageRSSFeed();
63
        $this->linkToAllSiteRSSFeed();
64
    }
65
66
    /**
67
     * Get page-specific changes in a RSS feed.
68
     */
69
    public function changes()
70
    {
71
        // Check viewability of changes
72
        if (!Config::inst()->get(VersionFeed::class, 'changes_enabled')
73
            || !$this->owner->PublicHistory
74
            || $this->owner->Version == ''
75
        ) {
76
            return $this->owner->httpError(404, 'Page history not viewable');
77
        }
78
79
        // Cache the diffs to remove DOS possibility.
80
        $target = $this->owner;
81
        $key = implode('_', array('changes', $this->owner->ID, $this->owner->Version));
82
        $entries = $this->filterContent($key, function () use ($target) {
83
            return $target->getDiffList(null, Config::inst()->get(VersionFeed::class, 'changes_limit'));
84
        });
85
86
        // Generate the output.
87
        $title = sprintf(_t('RSSHistory.SINGLEPAGEFEEDTITLE', 'Updates to %s page'), $this->owner->Title);
88
        $rss = new RSSFeed($entries, $this->owner->request->getURL(), $title, '', 'Title', '', null);
89
        $rss->setTemplate('Page_changes_rss');
90
        return $rss->outputToBrowser();
91
    }
92
93
    /**
94
     * Get all changes from the site in a RSS feed.
95
     */
96
    public function allchanges()
97
    {
98
        // Check viewability of allchanges
99
        if (!Config::inst()->get(VersionFeed::class, 'allchanges_enabled')
100
            || !SiteConfig::current_site_config()->AllChangesEnabled
101
        ) {
102
            return $this->owner->httpError(404, 'Global history not viewable');
103
        }
104
105
        $limit = (int)Config::inst()->get(VersionFeed::class, 'allchanges_limit');
106
        $latestChanges = DB::query('
107
			SELECT * FROM "SiteTree_Versions"
108
			WHERE "WasPublished" = \'1\'
109
			AND "CanViewType" IN (\'Anyone\', \'Inherit\')
110
			AND "ShowInSearch" = 1
111
			AND ("PublicHistory" IS NULL OR "PublicHistory" = \'1\')
112
			ORDER BY "LastEdited" DESC LIMIT ' . $limit);
113
        $lastChange = $latestChanges->record();
114
        $latestChanges->rewind();
115
116
        if ($lastChange) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $lastChange of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
117
            // Cache the diffs to remove DOS possibility.
118
            $key = 'allchanges'
119
                . preg_replace('#[^a-zA-Z0-9_]#', '', $lastChange['LastEdited'])
120
                . (Member::currentUserID() ?: 'public');
121
            $changeList = $this->filterContent($key, function () use ($latestChanges) {
122
                $changeList = new ArrayList();
123
                $canView = array();
124
                foreach ($latestChanges as $record) {
125
                    // Check if the page should be visible.
126
                    // WARNING: although we are providing historical details, we check the current configuration.
127
                    $id = $record['RecordID'];
128
                    if (!isset($canView[$id])) {
129
                        $page = SiteTree::get()->byID($id);
130
                        $canView[$id] = $page && $page->canView(new Member());
131
                    }
132
                    if (!$canView[$id]) {
133
                        continue;
134
                    }
135
136
                    // Get the diff to the previous version.
137
                    $version = SiteTree::create($record);
138
                    if ($diff = $version->getDiff()) {
139
                        $changeList->push($diff);
140
                    }
141
                }
142
143
                return $changeList;
144
            });
145
        } else {
146
            $changeList = new ArrayList();
147
        }
148
149
        // Produce output
150
        $url = $this->owner->getRequest()->getURL();
151
        $rss = new RSSFeed($changeList, $url, $this->linkToAllSitesRSSFeedTitle(), '', 'Title', '', null);
152
        $rss->setTemplate('Page_allchanges_rss');
153
        return $rss->outputToBrowser();
154
    }
155
    
156
    /**
157
     * Generates and embeds the RSS header link for the page-specific version rss feed
158
     */
159
    public function linkToPageRSSFeed()
160
    {
161
        if (!Config::inst()->get(VersionFeed::class, 'changes_enabled') || !$this->owner->PublicHistory) {
162
            return;
163
        }
164
        
165
        RSSFeed::linkToFeed(
166
            $this->owner->Link('changes'),
167
            sprintf(
168
                _t('RSSHistory.SINGLEPAGEFEEDTITLE', 'Updates to %s page'),
169
                $this->owner->Title
170
            )
171
        );
172
    }
173
174
    /**
175
     * Generates and embeds the RSS header link for the global version rss feed
176
     */
177
    public function linkToAllSiteRSSFeed()
178
    {
179
        if (!Config::inst()->get(VersionFeed::class, 'allchanges_enabled')
180
            || !SiteConfig::current_site_config()->AllChangesEnabled
181
        ) {
182
            return;
183
        }
184
        
185
        // RSS feed to all-site changes.
186
        $title = Convert::raw2xml($this->linkToAllSitesRSSFeedTitle());
187
        $url = $this->owner->getSiteRSSLink();
188
189
        Requirements::insertHeadTags(
190
            '<link rel="alternate" type="application/rss+xml" title="' . $title .
191
            '" href="' . $url . '" />'
192
        );
193
    }
194
195
    public function linkToAllSitesRSSFeedTitle()
196
    {
197
        return sprintf(_t('RSSHistory.SITEFEEDTITLE', 'Updates to %s'), SiteConfig::current_site_config()->Title);
198
    }
199
}
200