Passed
Pull Request — master (#42)
by
unknown
04:10
created

VersionFeedController::linkToPageRSSFeed()   A

Complexity

Conditions 3
Paths 2

Size

Total Lines 10
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 10
rs 9.4285
c 0
b 0
f 0
cc 3
eloc 7
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
	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...
22
		'changes',
23
		'allchanges'
24
	);
25
	
26
	/**
27
	 * Content handler
28
	 *
29
	 * @var ContentFilter
30
	 */
31
	protected $contentFilter;
32
	
33
	/**
34
	 * Sets the content filter
35
	 * 
36
	 * @param ContentFilter $contentFilter
37
	 */
38
	public function setContentFilter(ContentFilter $contentFilter) {
39
		$this->contentFilter = $contentFilter;
40
	}
41
	
42
	/**
43
	 * Evaluates the result of the given callback
44
	 * 
45
	 * @param string $key Unique key for this
46
	 * @param callable $callback Callback for evaluating the content
47
	 * @return mixed Result of $callback()
48
	 */
49
	protected function filterContent($key, $callback) {
50
		if($this->contentFilter) {
51
			return $this->contentFilter->getContent($key, $callback);
52
		} else {
53
			return call_user_func($callback);
54
		}
55
	}
56
57
	public function onAfterInit() {
58
		$this->linkToPageRSSFeed();
59
		$this->linkToAllSiteRSSFeed();
60
	}
61
62
	/**
63
	 * Get page-specific changes in a RSS feed.
64
	 */
65
	public function changes() {
66
		// Check viewability of changes
67
		if(!Config::inst()->get(VersionFeed::class, 'changes_enabled')
68
			|| !$this->owner->PublicHistory
69
			|| $this->owner->Version == ''
70
		) {
71
			return $this->owner->httpError(404, 'Page history not viewable');
72
		}
73
74
		// Cache the diffs to remove DOS possibility.
75
		$target = $this->owner;
76
		$key = implode('_', array('changes', $this->owner->ID, $this->owner->Version));
77
		$entries = $this->filterContent($key, function() use ($target) {
78
			return $target->getDiffList(null, Config::inst()->get(VersionFeed::class, 'changes_limit'));
79
		});
80
81
		// Generate the output.
82
		$title = sprintf(_t('RSSHistory.SINGLEPAGEFEEDTITLE', 'Updates to %s page'), $this->owner->Title);
83
		$rss = new RSSFeed($entries, $this->owner->request->getURL(), $title, '', 'Title', '', null);
84
		$rss->setTemplate('Page_changes_rss');
85
		return $rss->outputToBrowser();
86
	}
87
88
	/**
89
	 * Get all changes from the site in a RSS feed.
90
	 */
91
	public function allchanges() {
92
		// Check viewability of allchanges
93
		if(!Config::inst()->get(VersionFeed::class, 'allchanges_enabled')
94
			|| !SiteConfig::current_site_config()->AllChangesEnabled
95
		) {
96
			return $this->owner->httpError(404, 'Global history not viewable');
97
		}
98
99
		$limit = (int)Config::inst()->get(VersionFeed::class, 'allchanges_limit');
100
		$latestChanges = DB::query('
101
			SELECT * FROM "SiteTree_versions"
102
			WHERE "WasPublished" = \'1\'
103
			AND "CanViewType" IN (\'Anyone\', \'Inherit\')
104
			AND "ShowInSearch" = 1
105
			AND ("PublicHistory" IS NULL OR "PublicHistory" = \'1\')
106
			ORDER BY "LastEdited" DESC LIMIT ' . $limit
107
		);
108
		$lastChange = $latestChanges->record();
109
		$latestChanges->rewind();
110
111
		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...
112
113
			// Cache the diffs to remove DOS possibility.
114
			$key = 'allchanges'
115
				. preg_replace('#[^a-zA-Z0-9_]#', '', $lastChange['LastEdited'])
116
				. (Member::currentUserID() ?: 'public');
117
			$changeList = $this->filterContent($key, function() use ($latestChanges) {
118
				$changeList = new ArrayList();
119
				$canView = array();
120
				foreach ($latestChanges as $record) {
121
					
122
					// Check if the page should be visible.
123
					// WARNING: although we are providing historical details, we check the current configuration.
124
					$id = $record['RecordID'];
125
					if(!isset($canView[$id])) {
126
						$page = SiteTree::get()->byID($id);
127
						$canView[$id] = $page && $page->canView(new Member());
128
					}
129
					if (!$canView[$id]) continue;
130
131
					// Get the diff to the previous version.
132
					$version = new Versioned_Version($record);
133
					if ($diff = $version->getDiff()) {
134
						$changeList->push($diff);
135
					}
136
				}
137
138
				return $changeList;
139
			});
140
		} else {
141
			$changeList = new ArrayList();
142
		}
143
144
		// Produce output
145
		$rss = new RSSFeed($changeList, $this->owner->request->getURL(), $this->linkToAllSitesRSSFeedTitle(), '', 'Title', '', null);
146
		$rss->setTemplate('Page_allchanges_rss');
147
		return $rss->outputToBrowser();
148
	}
149
	
150
	/**
151
	 * Generates and embeds the RSS header link for the page-specific version rss feed
152
	 */
153
	public function linkToPageRSSFeed() {
154
		if (!Config::inst()->get(VersionFeed::class, 'changes_enabled') || !$this->owner->PublicHistory) {
155
			return;
156
		}
157
		
158
		RSSFeed::linkToFeed(
159
			$this->owner->Link('changes'),
160
			sprintf(
161
				_t('RSSHistory.SINGLEPAGEFEEDTITLE', 'Updates to %s page'),
162
				$this->owner->Title
163
			)
164
		);
165
	}
166
167
	/**
168
	 * Generates and embeds the RSS header link for the global version rss feed
169
	 */
170
	public function linkToAllSiteRSSFeed() {
171
		if(!Config::inst()->get(VersionFeed::class, 'allchanges_enabled')
172
			|| !SiteConfig::current_site_config()->AllChangesEnabled
173
		) {
174
			return;
175
		}
176
		
177
		// RSS feed to all-site changes.
178
		$title = Convert::raw2xml($this->linkToAllSitesRSSFeedTitle());
179
		$url = $this->owner->getSiteRSSLink();
180
181
		Requirements::insertHeadTags(
182
			'<link rel="alternate" type="application/rss+xml" title="' . $title .
183
			'" href="' . $url . '" />');
184
	}
185
186
	public function linkToAllSitesRSSFeedTitle() {
187
		return sprintf(_t('RSSHistory.SITEFEEDTITLE', 'Updates to %s'), SiteConfig::current_site_config()->Title);
188
	}
189
}
190