Issues (21)

src/VersionFeed.php (7 issues)

1
<?php
2
3
namespace SilverStripe\VersionFeed;
4
5
use SilverStripe\CMS\Model\SiteTreeExtension;
6
use SilverStripe\Core\Config\Config;
7
use SilverStripe\Forms\CheckboxField;
8
use SilverStripe\Forms\FieldGroup;
9
use SilverStripe\Forms\FieldList;
10
use SilverStripe\ORM\ArrayList;
11
use SilverStripe\ORM\DataObject;
12
use SilverStripe\ORM\FieldType\DBField;
13
use SilverStripe\SiteConfig\SiteConfig;
14
use SilverStripe\View\Parsers\Diff;
15
use SilverStripe\CMS\Model\SiteTree;
16
17
class VersionFeed extends SiteTreeExtension
18
{
19
    
20
    private static $db = array(
0 ignored issues
show
The private property $db is not used, and could be removed.
Loading history...
21
        'PublicHistory' => 'Boolean(true)'
22
    );
23
24
    private static $defaults = array(
0 ignored issues
show
The private property $defaults is not used, and could be removed.
Loading history...
25
        'PublicHistory' => true
26
    );
27
28
    public function updateFieldLabels(&$labels)
29
    {
30
        $labels['PublicHistory'] = _t(__CLASS__ . '.LABEL', 'Make history public');
31
    }
32
33
    /**
34
     * Enable the allchanges feed
35
     *
36
     * @config
37
     * @var bool
38
     */
39
    private static $allchanges_enabled = true;
0 ignored issues
show
The private property $allchanges_enabled is not used, and could be removed.
Loading history...
40
41
    /**
42
     * Allchanges feed limit of items.
43
     *
44
     * @config
45
     * @var int
46
     */
47
    private static $allchanges_limit = 20;
0 ignored issues
show
The private property $allchanges_limit is not used, and could be removed.
Loading history...
48
49
    /**
50
     * Enables RSS feed for page-specific changes
51
     *
52
     * @config
53
     * @var bool
54
     */
55
    private static $changes_enabled = true;
0 ignored issues
show
The private property $changes_enabled is not used, and could be removed.
Loading history...
56
57
    /**
58
     * Changes feed limit of items.
59
     *
60
     * @config
61
     * @var int
62
     */
63
    private static $changes_limit = 100;
0 ignored issues
show
The private property $changes_limit is not used, and could be removed.
Loading history...
64
65
    /**
66
     * Compile a list of changes to the current page, excluding non-published and explicitly secured versions.
67
     *
68
     * @param int $highestVersion Top version number to consider.
69
     * @param int $limit Limit to the amount of items returned.
70
     *
71
     * @returns ArrayList List of cleaned records.
72
     */
73
    public function getDiffList($highestVersion = null, $limit = 100)
74
    {
75
        // This can leak secured content if it was protected via inherited setting.
76
        // For now the users will need to be aware about this shortcoming.
77
        $offset = $highestVersion ? "AND \"SiteTree_Versions\".\"Version\"<='".(int)$highestVersion."'" : '';
78
        // Get just enough elements for diffing. We need one more than desired to have something to compare to.
79
        $qLimit = (int)$limit + 1;
80
        $versions = $this->owner->allVersions(
81
            "\"WasPublished\"='1' AND \"CanViewType\" IN ('Anyone', 'Inherit') $offset",
82
            "\"SiteTree\".\"LastEdited\" DESC, \"SiteTree\".\"ID\" DESC",
83
            $qLimit
84
        );
85
86
        // Process the list to add the comparisons.
87
        $changeList = new ArrayList();
88
        $previous = null;
89
        $count = 0;
90
        foreach ($versions as $version) {
91
            $changed = false;
92
93
            // Check if we have something to compare with.
94
            if (isset($previous)) {
95
                // Produce the diff fields for use in the template.
96
                if ($version->Title != $previous->Title) {
97
                    $diffTitle = Diff::compareHTML($version->Title, $previous->Title);
98
99
                    $version->DiffTitle = DBField::create_field('HTMLText', null);
100
                    $version->DiffTitle->setValue(
101
                        sprintf(
102
                            '<div><em>%s</em> ' . $diffTitle . '</div>',
103
                            _t(__CLASS__ . '.TITLECHANGED', 'Title has changed:')
104
                        )
105
                    );
106
                    $changed = true;
107
                }
108
109
                if ($version->Content != $previous->Content) {
110
                    $diffContent = Diff::compareHTML($version->Content, $previous->Content);
111
112
                    $version->DiffContent = DBField::create_field('HTMLText', null);
113
                    $version->DiffContent->setValue('<div>'.$diffContent.'</div>');
114
                    $changed = true;
115
                }
116
117
                // Copy the link so it can be cached.
118
                $oldPage = $version->getField('object');
119
                if (!$oldPage instanceof SiteTree) {
120
                    // We only need enough info to generate the link...
121
                    $oldPage = SiteTree::create([
122
                        'ID' => $oldPage->ID,
123
                        'URLSegment' => $oldPage->URLSegment,
124
                        'ParentID' => $oldPage->ParentID
125
                    ]);
126
                }
127
                $version->GeneratedLink = $oldPage->AbsoluteLink();
128
            }
129
130
            // Omit the versions that haven't been visibly changed (only takes the above fields into consideration).
131
            if ($changed) {
132
                $changeList->push($version);
133
                $count++;
134
            }
135
136
            // Store the last version for comparison.
137
            $previous = $version;
138
        }
139
140
        // Make sure enough diff items have been generated to satisfy the $limit. If we ran out, add the final,
141
        // non-diffed item (the initial version). This will also work for a single-diff request: if we are requesting
142
        // a diff on the initial version we will just get that version, verbatim.
143
        if ($previous && $versions->count()<$qLimit) {
144
            $first = clone($previous);
145
            $first->DiffContent = DBField::create_field('HTMLText', null);
146
            $first->DiffContent->setValue('<div>' . $first->Content . '</div>');
147
            // Copy the link so it can be cached.
148
            $first->GeneratedLink = $first->AbsoluteLink();
149
            $changeList->push($first);
150
        }
151
152
        return $changeList;
153
    }
154
155
    /**
156
     * Return a single diff representing this version.
157
     * Returns the initial version if there is nothing to compare to.
158
     *
159
     * @return DataObject|null Object with relevant fields diffed.
160
     */
161
    public function getDiff()
162
    {
163
        $changes = $this->getDiffList($this->owner->Version, 1);
164
        if ($changes && $changes->Count()) {
165
            return $changes->First();
166
        }
167
168
        return null;
169
    }
170
171
    /**
172
     * Compile a list of changes to the current page, excluding non-published and explicitly secured versions.
173
     *
174
     * @deprecated 2.0.0 Use VersionFeed::getDiffList instead
175
     *
176
     * @param int $highestVersion Top version number to consider.
177
     * @param boolean $fullHistory Set to true to get the full change history, set to false for a single diff.
178
     * @param int $limit Limit to the amount of items returned.
179
     *
180
     * @returns ArrayList List of cleaned records.
181
     */
182
    public function getDiffedChanges($highestVersion = null, $fullHistory = true, $limit = 100)
183
    {
184
        return $this->getDiffList(
185
            $highestVersion,
186
            $fullHistory ? $limit : 1
187
        );
188
    }
189
190
    public function updateSettingsFields(FieldList $fields)
191
    {
192
        if (!$this->owner->config()->get('changes_enabled')) {
193
            return;
194
        }
195
        
196
        // Add public history field.
197
        $fields->addFieldToTab(
198
            'Root.Settings',
199
            $publicHistory = FieldGroup::create(
200
                CheckboxField::create('PublicHistory', $this->owner->fieldLabel('PublicHistory'))
201
            )
202
                ->setDescription(_t(
203
                    __CLASS__ . '.Warning',
204
                    "Publicising the history will also disclose the changes that have at the "
205
                    . "time been protected from the public view."
206
                ))
207
        );
208
209
        if ($this->owner->CanViewType != 'Anyone') {
210
            $canViewType = $fields->fieldByName('Root.Settings.CanViewType');
211
            if ($canViewType) {
0 ignored issues
show
$canViewType is of type SilverStripe\Forms\FormField, thus it always evaluated to true.
Loading history...
212
                $canViewType->setDescription(_t(
213
                    __CLASS__ . '.Warning2',
214
                    "Changing access settings in such a way that this page or pages under it become publicly<br>"
215
                    . "accessible may result in publicising all historical changes on these pages too. Please review"
216
                    . "<br> this section's \"Public history\" settings to ascertain only intended information is "
217
                    . "disclosed."
218
                ));
219
            }
220
        }
221
    }
222
223
    public function getSiteRSSLink()
224
    {
225
        // TODO: This link should be from the homepage, not this page.
226
        if (Config::inst()->get(get_class(), 'allchanges_enabled')
227
            && SiteConfig::current_site_config()->AllChangesEnabled
228
        ) {
229
            return $this->owner->Link('allchanges');
230
        }
231
    }
232
233
    public function getDefaultRSSLink()
234
    {
235
        if (Config::inst()->get(get_class(), 'changes_enabled') && $this->owner->PublicHistory) {
236
            return $this->owner->Link('changes');
237
        }
238
    }
239
}
240