silverstripe /
silverstripe-versionfeed
| 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
introduced
by
Loading history...
|
|||
| 21 | 'PublicHistory' => 'Boolean(true)' |
||
| 22 | ); |
||
| 23 | |||
| 24 | private static $defaults = array( |
||
|
0 ignored issues
–
show
|
|||
| 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
|
|||
| 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
|
|||
| 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
|
|||
| 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
|
|||
| 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
|
|||
| 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 |