This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include
, or for example
via PHP's auto-loading mechanism.
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | /** |
||
3 | * An extension that adds the ability to replace files with new uploads, and |
||
4 | * view and roll back to existing versions. |
||
5 | * |
||
6 | * @package silverstripe-versionedfiles |
||
7 | */ |
||
8 | class VersionedFileExtension extends DataExtension |
||
9 | { |
||
10 | private static $has_one = array('CurrentVersion' => 'FileVersion'); |
||
11 | private static $has_many = array('Versions' => 'FileVersion'); |
||
12 | |||
13 | /** |
||
14 | * @param FieldSet $fields |
||
15 | */ |
||
16 | public function updateCMSFields(FieldList $fields) |
||
17 | { |
||
18 | if ($this->owner instanceof Folder || !$this->owner->ID) { |
||
0 ignored issues
–
show
|
|||
19 | return; |
||
20 | } |
||
21 | |||
22 | $fields->addFieldToTab('Root.Main', new ReadonlyField( |
||
23 | 'VersionNumber', |
||
24 | _t('VersionedFiles.CURRENTVERSION', 'Current Version') |
||
25 | ), 'Created'); |
||
26 | |||
27 | |||
28 | // History |
||
29 | |||
30 | $gridFieldConfig = GridFieldConfig::create()->addComponents( |
||
31 | new GridFieldToolbarHeader(), |
||
32 | //new GridFieldFilterHeader(), |
||
33 | new GridFieldSortableHeader(), |
||
34 | new GridFieldDataColumns(), |
||
35 | new GridFieldPaginator(15), |
||
36 | new GridFieldViewButton(), |
||
37 | //new GridFieldDeleteAction(), |
||
38 | new GridFieldDetailForm() |
||
39 | ); |
||
40 | |||
41 | $gridField = new GridField('Versions', 'Versions', $this->owner->Versions(), $gridFieldConfig); |
||
42 | $columns = $gridField->getConfig()->getComponentByType('GridFieldDataColumns'); |
||
43 | $columns->setDisplayFields(array( |
||
44 | 'VersionNumber' => _t('VersionedFiles.VERSIONNUMBER', 'Version Number'), |
||
45 | 'Creator.Name' => _t('VersionedFiles.CREATOR', 'Creator'), |
||
46 | 'Created' => _t('VersionedFiles.DATE', 'Date'), |
||
47 | 'Link' => _t('VersionedFiles.LINK', 'Link'), |
||
48 | 'IsCurrent' => _t('VersionedFiles.ISCURRENT', 'Is Current') |
||
49 | )); |
||
50 | |||
51 | $columns->setFieldCasting(array( |
||
52 | 'Created' => 'Date->Nice' |
||
53 | )); |
||
54 | |||
55 | $columns->setFieldFormatting(array( |
||
56 | 'Link' => '<a href=\"$URL\" target=\"_blank\">$Name</a>', |
||
57 | 'IsCurrent' => '{$IsCurrent()->Nice()}', |
||
58 | 'Created' => '{$obj(\'Created\')->Nice()}' |
||
59 | )); |
||
60 | |||
61 | // history |
||
62 | |||
63 | $versions = $this->owner->Versions( |
||
64 | sprintf('"VersionNumber" <> %d', $this->getVersionNumber()) |
||
65 | ); |
||
66 | |||
67 | if ($versions && $versions->Count() && $this->owner->canEdit()) { |
||
68 | $fields->addFieldToTab('Root.History', new HeaderField('RollbackHeader', _t('VersionedFiles.ROLLBACKPREVVERSION', 'Rollback to a Previous Version'))); |
||
69 | $fields->addFieldToTab('Root.History', $versionDropdown = new DropdownField('PreviousVersion', '', $versions->map('VersionNumber'))); |
||
70 | $versionDropdown->setEmptyString(_t('VersionedFiles.SELECTAVERSION', '(Select a Version)')); |
||
71 | } |
||
72 | |||
73 | $fields->addFieldToTab('Root.History', $gridField); |
||
74 | |||
75 | // Replace |
||
76 | if (!$this->owner->config()->get('disableReplaceTab')) { |
||
77 | if (!$this->owner->canEdit()) { |
||
78 | return; |
||
79 | } |
||
80 | |||
81 | $folder = $this->owner->Parent(); |
||
0 ignored issues
–
show
|
|||
82 | $uploadField = new VersionedFileUploadField('ReplacementFile', ''); |
||
83 | $uploadField->setConfig('previewMaxWidth', 40); |
||
84 | $uploadField->setConfig('previewMaxHeight', 30); |
||
85 | $uploadField->setConfig('allowedMaxFileNumber', 1); |
||
86 | $uploadField->addExtraClass('ss-assetuploadfield'); |
||
87 | $uploadField->removeExtraClass('ss-uploadfield'); |
||
88 | $uploadField->setTemplate('VersionedFileUploadField'); |
||
89 | $uploadField->currentVersionFile = $this->owner; |
||
0 ignored issues
–
show
$this->owner is of type object<SS_Object> , but the property $currentVersionFile was declared to be of type object<File> . Are you sure that you always receive this specific sub-class here, or does it make sense to add an instanceof check?
Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a given class or a super-class is assigned to a property that is type hinted more strictly. Either this assignment is in error or an instanceof check should be added for that assignment. class Alien {}
class Dalek extends Alien {}
class Plot
{
/** @var Dalek */
public $villain;
}
$alien = new Alien();
$plot = new Plot();
if ($alien instanceof Dalek) {
$plot->villain = $alien;
}
![]() |
|||
90 | $uploadField->relationAutoSetting = false; |
||
91 | $uploadField->setOverwriteWarning(false); |
||
92 | |||
93 | if ($folder->exists() && $folder->getFilename()) { |
||
94 | $path = preg_replace('/^' . ASSETS_DIR . '\//', '', $folder->getFilename()); |
||
95 | $uploadField->setFolderName($path); |
||
96 | } else { |
||
97 | $uploadField->setFolderName(ASSETS_DIR); |
||
98 | } |
||
99 | |||
100 | // set the valid extensions to only that of the original file |
||
101 | $ext = strtolower($this->owner->Extension); |
||
0 ignored issues
–
show
The property
Extension does not seem to exist. Did you mean extension_instances ?
An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name. If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading. ![]() |
|||
102 | $uploadField->getValidator()->setAllowedExtensions(array($ext)); |
||
103 | |||
104 | // css / js requirements for asset admin style file uploader |
||
105 | Requirements::javascript(FRAMEWORK_DIR . '/javascript/AssetUploadField.js'); |
||
106 | Requirements::css(FRAMEWORK_DIR . '/css/AssetUploadField.css'); |
||
107 | |||
108 | $fields->addFieldToTab('Root.Replace', $uploadField); |
||
109 | |||
110 | |||
111 | $sameTypeMessage = sprintf(_t( |
||
112 | 'VersionedFiles.SAMETYPEMESSAGE', |
||
113 | 'You may only replace this file with another of the same type: .%s' |
||
114 | ), $this->owner->getExtension()); |
||
0 ignored issues
–
show
The method
getExtension() does not exist on SS_Object . Did you maybe mean getExtensionInstance() ?
This check marks calls to methods that do not seem to exist on an object. This is most likely the result of a method being renamed without all references to it being renamed likewise. ![]() |
|||
115 | |||
116 | $fields->addFieldToTab('Root.Replace', new LiteralField('SameTypeMessage', "<p>$sameTypeMessage</p>")); |
||
117 | } |
||
118 | |||
119 | return; |
||
120 | } |
||
121 | |||
122 | /** |
||
123 | * Creates the initial version when the file is created, as well as updating |
||
124 | * the version records when the parent file is moved. |
||
125 | */ |
||
126 | public function onAfterWrite() |
||
127 | { |
||
128 | $changed = $this->owner->getChangedFields(true, 2); |
||
129 | |||
130 | if (!$this->owner instanceof Folder && !$this->owner->CurrentVersionID) { |
||
0 ignored issues
–
show
The property
CurrentVersionID does not seem to exist in SS_Object .
An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name. If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading. ![]() |
|||
131 | $this->createVersion(); |
||
132 | } |
||
133 | |||
134 | if (array_key_exists('Filename', $changed)) { |
||
135 | if ($changed['Filename']['before'] == null) { |
||
136 | return; |
||
137 | } |
||
138 | |||
139 | $oldDirname = '/' . trim(dirname($changed['Filename']['before']), '/'); |
||
140 | $newDirname = '/' . trim(dirname($changed['Filename']['after']), '/'); |
||
141 | |||
142 | if ($oldDirname == $newDirname) { |
||
143 | return; |
||
144 | } |
||
145 | |||
146 | // First move the _versions directory across. |
||
147 | $versionsDir = FileVersion::VERSION_FOLDER . '/' . $this->owner->ID; |
||
0 ignored issues
–
show
The property
ID does not seem to exist in SS_Object .
An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name. If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading. ![]() |
|||
148 | $oldVersions = BASE_PATH . $oldDirname . '/' . $versionsDir; |
||
149 | $newVersions = BASE_PATH . $newDirname . '/' . $versionsDir; |
||
150 | |||
151 | if (is_dir($oldVersions)) { |
||
152 | if (!is_dir($newVersions)) { |
||
153 | mkdir($newVersions, Config::inst()->get('Filesystem', 'folder_create_mask'), true); |
||
154 | } |
||
155 | |||
156 | if (!is_dir($newVersions)) { |
||
157 | rename($oldVersions, $newVersions); |
||
158 | } |
||
159 | } |
||
160 | |||
161 | // Then update individual version records to point to the new |
||
162 | // location. |
||
163 | foreach ($this->owner->Versions() as $version) { |
||
164 | if (strpos($version->Filename, $oldDirname) === 0) { |
||
165 | $version->Filename = $newDirname . substr($version->Filename, strlen($oldDirname)); |
||
166 | $version->write(); |
||
167 | } |
||
168 | } |
||
169 | } |
||
170 | } |
||
171 | |||
172 | /** |
||
173 | * Since AssetAdmin does not use {@link onBeforeWrite}, onAfterUpload is |
||
174 | * also needed. |
||
175 | * |
||
176 | * @uses onAfterWrite() |
||
177 | */ |
||
178 | public function onAfterUpload() |
||
179 | { |
||
180 | $this->onAfterWrite(); |
||
181 | } |
||
182 | |||
183 | |||
184 | /** |
||
185 | * Deletes all saved version of the file as well as the file itself. |
||
186 | */ |
||
187 | public function onBeforeDelete() |
||
188 | { |
||
189 | $currentVersion = $this->owner->CurrentVersion(); |
||
190 | |||
191 | // make sure there actually is a current version, otherwise we're going |
||
192 | // to end up deleting a bunch of incorrect stuff! |
||
193 | if ($currentVersion && $currentVersion->ID > 0) { |
||
194 | $folder = dirname($this->owner->CurrentVersion()->getFullPath()); |
||
195 | |||
196 | if ($versions = $this->owner->Versions()) { |
||
197 | foreach ($versions as $version) { |
||
198 | $version->delete(); |
||
199 | } |
||
200 | } |
||
201 | |||
202 | if (is_dir($folder)) { |
||
203 | Filesystem::removeFolder($folder); |
||
204 | } |
||
205 | |||
206 | // If the _versions folder is now empty - because there are no other versions of any assets - then we can |
||
207 | // delete the _versions folder |
||
208 | $folder = dirname($folder); // We want the parent of $folder, as we just deleted $folder |
||
209 | if (is_dir($folder)) { |
||
210 | $dir = opendir($folder); |
||
211 | $foundOtherFile = false; |
||
212 | |||
213 | while ($file = readdir($dir)) { |
||
214 | if (($file == '.' || $file == '..')) { |
||
215 | continue; |
||
216 | } |
||
217 | $foundOtherFile = true; |
||
218 | } |
||
219 | |||
220 | if (!$foundOtherFile) { |
||
221 | // No other files found, so we can delete the _versions folder |
||
222 | rmdir($folder); |
||
223 | } |
||
224 | } |
||
225 | } |
||
226 | } |
||
227 | |||
228 | |||
229 | /** |
||
230 | * @return int |
||
231 | */ |
||
232 | public function getVersionNumber() |
||
233 | { |
||
234 | if ($this->owner->CurrentVersionID) { |
||
0 ignored issues
–
show
The property
CurrentVersionID does not seem to exist in SS_Object .
An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name. If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading. ![]() |
|||
235 | return $this->owner->CurrentVersion()->VersionNumber; |
||
236 | } |
||
237 | } |
||
238 | |||
239 | |||
240 | /** |
||
241 | * @param int $version |
||
242 | */ |
||
243 | public function setVersionNumber($version) |
||
244 | { |
||
245 | $fileVersion = DataObject::get_one('FileVersion', sprintf( |
||
246 | '"FileID" = %d AND "VersionNumber" = %d', $this->owner->ID, $version |
||
0 ignored issues
–
show
The property
ID does not seem to exist in SS_Object .
An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name. If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading. ![]() |
|||
247 | )); |
||
248 | |||
249 | if (!$fileVersion) { |
||
250 | throw new Exception( |
||
251 | "Could not get version #$version of file #{$this->owner->ID}" |
||
252 | ); |
||
253 | } |
||
254 | |||
255 | $versionPath = Controller::join_links( |
||
256 | Director::baseFolder(), $fileVersion->Filename |
||
257 | ); |
||
258 | $currentPath = $this->owner->getFullPath(); |
||
259 | |||
260 | if (!copy($versionPath, $currentPath)) { |
||
261 | throw new Exception( |
||
262 | "Could not replace file #{$this->owner->ID} with version #$version." |
||
263 | ); |
||
264 | } |
||
265 | |||
266 | $this->owner->CurrentVersionID = $fileVersion->ID; |
||
0 ignored issues
–
show
The property
CurrentVersionID does not seem to exist in SS_Object .
An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name. If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading. ![]() |
|||
267 | } |
||
268 | |||
269 | /** |
||
270 | * Handles rolling back to a selected version on save. |
||
271 | * |
||
272 | * @param int $version |
||
273 | */ |
||
274 | public function savePreviousVersion($version) |
||
275 | { |
||
276 | if (!is_numeric($version)) { |
||
277 | return; |
||
278 | } |
||
279 | |||
280 | try { |
||
281 | $this->setVersionNumber($version); |
||
282 | $this->owner->write(); |
||
283 | } catch (Exception $e) { |
||
284 | throw new ValidationException(new ValidationResult( |
||
285 | false, |
||
286 | "Could not replace file #{$this->owner->ID} with version #$version." |
||
0 ignored issues
–
show
The property
ID does not seem to exist in SS_Object .
An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name. If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading. ![]() |
|||
287 | )); |
||
288 | } |
||
289 | } |
||
290 | |||
291 | |||
292 | /** |
||
293 | * Creates a new file version and sets it as the current version. |
||
294 | * |
||
295 | * @return boolean Whether file version is created |
||
296 | */ |
||
297 | public function createVersion() |
||
298 | { |
||
299 | if (!file_exists($this->owner->getFullPath())) { |
||
300 | return false; |
||
301 | } |
||
302 | |||
303 | $version = new FileVersion(); |
||
304 | $version->FileID = $this->owner->ID; |
||
0 ignored issues
–
show
The property
FileID does not exist on object<FileVersion> . Since you implemented __set , maybe consider adding a @property annotation.
Since your code implements the magic setter <?php
/**
* @property int $x
* @property int $y
* @property string $text
*/
class MyLabel
{
private $properties;
private $allowedProperties = array('x', 'y', 'text');
public function __get($name)
{
if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
return $properties[$name];
} else {
return null;
}
}
public function __set($name, $value)
{
if (in_array($name, $this->allowedProperties)) {
$properties[$name] = $value;
} else {
throw new \LogicException("Property $name is not defined.");
}
}
}
Since the property has write access only, you can use the @property-write annotation instead. Of course, you may also just have mistyped another name, in which case you should fix the error. See also the PhpDoc documentation for @property. ![]() The property
ID does not seem to exist in SS_Object .
An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name. If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading. ![]() |
|||
305 | $version->write(); |
||
306 | |||
307 | $this->owner->CurrentVersionID = $version->ID; |
||
0 ignored issues
–
show
The property
CurrentVersionID does not seem to exist in SS_Object .
An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name. If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading. ![]() |
|||
308 | return (bool) $this->owner->write(); |
||
309 | } |
||
310 | } |
||
311 |
An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.
If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.