|
1
|
|
|
<?php |
|
2
|
|
|
|
|
3
|
|
|
namespace SilverStripe\Forms\HTMLEditor; |
|
4
|
|
|
|
|
5
|
|
|
use SilverStripe\Admin\Forms\EditorExternalLinkFormFactory; |
|
6
|
|
|
use SilverStripe\Admin\Forms\EditorEmailLinkFormFactory; |
|
7
|
|
|
use SilverStripe\Assets\File; |
|
8
|
|
|
use SilverStripe\CMS\Model\SiteTree; |
|
9
|
|
|
use SilverStripe\Control\Controller; |
|
10
|
|
|
use SilverStripe\Control\Director; |
|
11
|
|
|
use SilverStripe\Control\RequestHandler; |
|
12
|
|
|
use SilverStripe\Control\HTTPRequest; |
|
13
|
|
|
use SilverStripe\Control\HTTPResponse_Exception; |
|
14
|
|
|
use SilverStripe\Core\Injector\Injector; |
|
15
|
|
|
use SilverStripe\Forms\CheckboxField; |
|
16
|
|
|
use SilverStripe\Forms\CompositeField; |
|
17
|
|
|
use SilverStripe\Forms\EmailField; |
|
18
|
|
|
use SilverStripe\Forms\FieldList; |
|
19
|
|
|
use SilverStripe\Forms\Form; |
|
20
|
|
|
use SilverStripe\Forms\HiddenField; |
|
21
|
|
|
use SilverStripe\Forms\LiteralField; |
|
22
|
|
|
use SilverStripe\Forms\OptionsetField; |
|
23
|
|
|
use SilverStripe\Forms\TextField; |
|
24
|
|
|
use SilverStripe\Forms\TreeDropdownField; |
|
25
|
|
|
use SilverStripe\ORM\DataList; |
|
26
|
|
|
use SilverStripe\ORM\DataObject; |
|
27
|
|
|
use SilverStripe\ORM\FieldType\DBField; |
|
28
|
|
|
use SilverStripe\View\SSViewer; |
|
29
|
|
|
|
|
30
|
|
|
/** |
|
31
|
|
|
* Toolbar shared by all instances of {@link HTMLEditorField}, to avoid too much markup duplication. |
|
32
|
|
|
* Needs to be inserted manually into the template in order to function - see {@link LeftAndMain->EditorToolbar()}. |
|
33
|
|
|
*/ |
|
34
|
|
|
class HTMLEditorField_Toolbar extends RequestHandler |
|
35
|
|
|
{ |
|
36
|
|
|
|
|
37
|
|
|
private static $allowed_actions = array( |
|
38
|
|
|
'LinkForm', |
|
39
|
|
|
'EditorExternalLink', |
|
40
|
|
|
'EditorEmailLink', |
|
41
|
|
|
'viewfile', |
|
42
|
|
|
'getanchors' |
|
43
|
|
|
); |
|
44
|
|
|
|
|
45
|
|
|
/** |
|
46
|
|
|
* @return string |
|
47
|
|
|
*/ |
|
48
|
|
|
public function getTemplateViewFile() |
|
49
|
|
|
{ |
|
50
|
|
|
return SSViewer::get_templates_by_class(get_class($this), '_viewfile', __CLASS__); |
|
51
|
|
|
} |
|
52
|
|
|
|
|
53
|
|
|
/** |
|
54
|
|
|
* @var Controller |
|
55
|
|
|
*/ |
|
56
|
|
|
protected $controller; |
|
57
|
|
|
|
|
58
|
|
|
/** |
|
59
|
|
|
* @var string |
|
60
|
|
|
*/ |
|
61
|
|
|
protected $name; |
|
62
|
|
|
|
|
63
|
|
|
public function __construct($controller, $name) |
|
64
|
|
|
{ |
|
65
|
|
|
parent::__construct(); |
|
66
|
|
|
|
|
67
|
|
|
$this->controller = $controller; |
|
68
|
|
|
$this->name = $name; |
|
69
|
|
|
} |
|
70
|
|
|
|
|
71
|
|
|
public function forTemplate() |
|
72
|
|
|
{ |
|
73
|
|
|
return sprintf( |
|
74
|
|
|
'<div id="cms-editor-dialogs" data-url-linkform="%s"></div>', |
|
75
|
|
|
Controller::join_links($this->controller->Link(), $this->name, 'LinkForm', 'forTemplate') |
|
76
|
|
|
); |
|
77
|
|
|
} |
|
78
|
|
|
|
|
79
|
|
|
/** |
|
80
|
|
|
* Searches the SiteTree for display in the dropdown |
|
81
|
|
|
* |
|
82
|
|
|
* @param string $sourceObject |
|
83
|
|
|
* @param string $labelField |
|
84
|
|
|
* @param string $search |
|
85
|
|
|
* @return DataList |
|
86
|
|
|
*/ |
|
87
|
|
|
public function siteTreeSearchCallback($sourceObject, $labelField, $search) |
|
88
|
|
|
{ |
|
89
|
|
|
return DataObject::get($sourceObject)->filterAny(array( |
|
90
|
|
|
'MenuTitle:PartialMatch' => $search, |
|
91
|
|
|
'Title:PartialMatch' => $search |
|
92
|
|
|
)); |
|
93
|
|
|
} |
|
94
|
|
|
|
|
95
|
|
|
/** |
|
96
|
|
|
* Return a {@link Form} instance allowing a user to |
|
97
|
|
|
* add links in the TinyMCE content editor. |
|
98
|
|
|
* |
|
99
|
|
|
* @skipUpgrade |
|
100
|
|
|
* @return Form |
|
101
|
|
|
*/ |
|
102
|
|
|
public function LinkForm() |
|
103
|
|
|
{ |
|
104
|
|
|
$siteTree = TreeDropdownField::create( |
|
105
|
|
|
'internal', |
|
106
|
|
|
_t(__CLASS__.'.PAGE', "Page"), |
|
107
|
|
|
SiteTree::class, |
|
108
|
|
|
'ID', |
|
109
|
|
|
'MenuTitle', |
|
110
|
|
|
true |
|
111
|
|
|
); |
|
112
|
|
|
// mimic the SiteTree::getMenuTitle(), which is bypassed when the search is performed |
|
113
|
|
|
$siteTree->setSearchFunction(array($this, 'siteTreeSearchCallback')); |
|
114
|
|
|
|
|
115
|
|
|
$numericLabelTmpl = '<span class="step-label"><span class="flyout">Step %d.</span>' |
|
116
|
|
|
. '<span class="title">%s</span></span>'; |
|
117
|
|
|
|
|
118
|
|
|
$form = new Form( |
|
119
|
|
|
$this->controller, |
|
120
|
|
|
"{$this->name}/LinkForm", |
|
121
|
|
|
new FieldList( |
|
122
|
|
|
$headerWrap = new CompositeField( |
|
123
|
|
|
new LiteralField( |
|
124
|
|
|
'Heading', |
|
125
|
|
|
sprintf( |
|
126
|
|
|
'<h3 class="htmleditorfield-linkform-heading insert">%s</h3>', |
|
127
|
|
|
_t(__CLASS__.'.LINK', 'Insert Link') |
|
128
|
|
|
) |
|
129
|
|
|
) |
|
130
|
|
|
), |
|
131
|
|
|
$contentComposite = new CompositeField( |
|
132
|
|
|
OptionsetField::create( |
|
133
|
|
|
'LinkType', |
|
134
|
|
|
DBField::create_field( |
|
135
|
|
|
'HTMLFragment', |
|
136
|
|
|
sprintf($numericLabelTmpl, '1', _t(__CLASS__.'.LINKTO', 'Link type')) |
|
137
|
|
|
), |
|
138
|
|
|
array( |
|
139
|
|
|
'internal' => _t(__CLASS__.'.LINKINTERNAL', 'Link to a page on this site'), |
|
140
|
|
|
'external' => _t(__CLASS__.'.LINKEXTERNAL', 'Link to another website'), |
|
141
|
|
|
'anchor' => _t(__CLASS__.'.LINKANCHOR', 'Link to an anchor on this page'), |
|
142
|
|
|
'email' => _t(__CLASS__.'.LINKEMAIL', 'Link to an email address'), |
|
143
|
|
|
'file' => _t(__CLASS__.'.LINKFILE', 'Link to download a file'), |
|
144
|
|
|
), |
|
145
|
|
|
'internal' |
|
146
|
|
|
), |
|
147
|
|
|
LiteralField::create( |
|
148
|
|
|
'Step2', |
|
149
|
|
|
'<div class="step2">' |
|
150
|
|
|
. sprintf($numericLabelTmpl, '2', _t(__CLASS__.'.LINKDETAILS', 'Link details')) . '</div>' |
|
151
|
|
|
), |
|
152
|
|
|
$siteTree, |
|
153
|
|
|
TextField::create('external', _t(__CLASS__.'.URL', 'URL'), 'http://'), |
|
154
|
|
|
EmailField::create('email', _t(__CLASS__.'.EMAIL', 'Email address')), |
|
155
|
|
|
$fileField = TreeDropdownField::create( |
|
156
|
|
|
'file', |
|
157
|
|
|
_t(__CLASS__.'.FILE', 'File'), |
|
158
|
|
|
File::class, |
|
159
|
|
|
'ID', |
|
160
|
|
|
'Name' |
|
161
|
|
|
), |
|
162
|
|
|
TextField::create('Anchor', _t(__CLASS__.'.ANCHORVALUE', 'Anchor')), |
|
163
|
|
|
TextField::create('Subject', _t(__CLASS__.'.SUBJECT', 'Email subject')), |
|
164
|
|
|
TextField::create('Description', _t(__CLASS__.'.LINKDESCR', 'Link description')), |
|
165
|
|
|
CheckboxField::create( |
|
166
|
|
|
'TargetBlank', |
|
167
|
|
|
_t(__CLASS__.'.LINKOPENNEWWIN', 'Open link in a new window?') |
|
168
|
|
|
), |
|
169
|
|
|
HiddenField::create('Locale', null, $this->controller->Locale) |
|
170
|
|
|
) |
|
171
|
|
|
), |
|
172
|
|
|
new FieldList() |
|
173
|
|
|
); |
|
174
|
|
|
|
|
175
|
|
|
$headerWrap->setName('HeaderWrap'); |
|
176
|
|
|
$headerWrap->addExtraClass('CompositeField composite cms-content-header form-group--no-label '); |
|
177
|
|
|
$contentComposite->setName('ContentBody'); |
|
178
|
|
|
$contentComposite->addExtraClass('ss-insert-link content'); |
|
179
|
|
|
|
|
180
|
|
|
$form->unsetValidator(); |
|
181
|
|
|
$form->loadDataFrom($this); |
|
182
|
|
|
$form->addExtraClass('htmleditorfield-form htmleditorfield-linkform cms-linkform-content'); |
|
183
|
|
|
|
|
184
|
|
|
$this->extend('updateLinkForm', $form); |
|
185
|
|
|
|
|
186
|
|
|
return $form; |
|
187
|
|
|
} |
|
188
|
|
|
|
|
189
|
|
|
/** |
|
190
|
|
|
* Builds and returns the external link form |
|
191
|
|
|
* |
|
192
|
|
|
* @return null|Form |
|
193
|
|
|
*/ |
|
194
|
|
|
public function EditorExternalLink($id = null) |
|
|
|
|
|
|
195
|
|
|
{ |
|
196
|
|
|
/** @var EditorExternalLinkFormFactory $factory */ |
|
197
|
|
|
$factory = Injector::inst()->get(EditorExternalLinkFormFactory::class); |
|
198
|
|
|
if ($factory) { |
|
199
|
|
|
return $factory->getForm($this->controller, "{$this->name}/EditorExternalLink"); |
|
200
|
|
|
} |
|
201
|
|
|
return null; |
|
202
|
|
|
} |
|
203
|
|
|
|
|
204
|
|
|
/** |
|
205
|
|
|
* Builds and returns the external link form |
|
206
|
|
|
* |
|
207
|
|
|
* @return null|Form |
|
208
|
|
|
*/ |
|
209
|
|
|
public function EditorEmailLink($id = null) |
|
|
|
|
|
|
210
|
|
|
{ |
|
211
|
|
|
/** @var EditorEmailLinkFormFactory $factory */ |
|
212
|
|
|
$factory = Injector::inst()->get(EditorEmailLinkFormFactory::class); |
|
213
|
|
|
|
|
214
|
|
|
if ($factory) { |
|
215
|
|
|
return $factory->getForm($this->controller, "{$this->name}/EditorEmailLink"); |
|
216
|
|
|
} |
|
217
|
|
|
return null; |
|
218
|
|
|
} |
|
219
|
|
|
|
|
220
|
|
|
/** |
|
221
|
|
|
* Get the folder ID to filter files by for the "from cms" tab |
|
222
|
|
|
* |
|
223
|
|
|
* @return int |
|
224
|
|
|
*/ |
|
225
|
|
|
protected function getAttachParentID() |
|
226
|
|
|
{ |
|
227
|
|
|
$parentID = $this->controller->getRequest()->requestVar('ParentID'); |
|
228
|
|
|
$this->extend('updateAttachParentID', $parentID); |
|
229
|
|
|
return $parentID; |
|
230
|
|
|
} |
|
231
|
|
|
|
|
232
|
|
|
/** |
|
233
|
|
|
* List of allowed schemes (no wildcard, all lower case) or empty to allow all schemes |
|
234
|
|
|
* |
|
235
|
|
|
* @config |
|
236
|
|
|
* @var array |
|
237
|
|
|
*/ |
|
238
|
|
|
private static $fileurl_scheme_whitelist = array('http', 'https'); |
|
239
|
|
|
|
|
240
|
|
|
/** |
|
241
|
|
|
* List of allowed domains (no wildcard, all lower case) or empty to allow all domains |
|
242
|
|
|
* |
|
243
|
|
|
* @config |
|
244
|
|
|
* @var array |
|
245
|
|
|
*/ |
|
246
|
|
|
private static $fileurl_domain_whitelist = array(); |
|
247
|
|
|
|
|
248
|
|
|
/** |
|
249
|
|
|
* Find local File dataobject given ID |
|
250
|
|
|
* |
|
251
|
|
|
* @param int $id |
|
252
|
|
|
* @return array |
|
253
|
|
|
*/ |
|
254
|
|
|
protected function viewfile_getLocalFileByID($id) |
|
255
|
|
|
{ |
|
256
|
|
|
/** @var File $file */ |
|
257
|
|
|
$file = DataObject::get_by_id(File::class, $id); |
|
258
|
|
|
if ($file && $file->canView()) { |
|
259
|
|
|
return array($file, $file->getURL()); |
|
260
|
|
|
} |
|
261
|
|
|
return [null, null]; |
|
262
|
|
|
} |
|
263
|
|
|
|
|
264
|
|
|
/** |
|
265
|
|
|
* Get remote File given url |
|
266
|
|
|
* |
|
267
|
|
|
* @param string $fileUrl Absolute URL |
|
268
|
|
|
* @return array |
|
269
|
|
|
* @throws HTTPResponse_Exception |
|
270
|
|
|
*/ |
|
271
|
|
|
protected function viewfile_getRemoteFileByURL($fileUrl) |
|
272
|
|
|
{ |
|
273
|
|
|
if (!Director::is_absolute_url($fileUrl)) { |
|
274
|
|
|
throw $this->getErrorFor(_t( |
|
275
|
|
|
"SilverStripe\\Forms\\HTMLEditor\\HTMLEditorField_Toolbar.ERROR_ABSOLUTE", |
|
276
|
|
|
"Only absolute urls can be embedded" |
|
277
|
|
|
)); |
|
278
|
|
|
} |
|
279
|
|
|
$scheme = strtolower(parse_url($fileUrl, PHP_URL_SCHEME)); |
|
280
|
|
|
$allowed_schemes = self::config()->get('fileurl_scheme_whitelist'); |
|
281
|
|
|
if (!$scheme || ($allowed_schemes && !in_array($scheme, $allowed_schemes))) { |
|
282
|
|
|
throw $this->getErrorFor(_t( |
|
283
|
|
|
"SilverStripe\\Forms\\HTMLEditor\\HTMLEditorField_Toolbar.ERROR_SCHEME", |
|
284
|
|
|
"This file scheme is not included in the whitelist" |
|
285
|
|
|
)); |
|
286
|
|
|
} |
|
287
|
|
|
$domain = strtolower(parse_url($fileUrl, PHP_URL_HOST)); |
|
288
|
|
|
$allowed_domains = self::config()->get('fileurl_domain_whitelist'); |
|
289
|
|
|
if (!$domain || ($allowed_domains && !in_array($domain, $allowed_domains))) { |
|
290
|
|
|
throw $this->getErrorFor(_t( |
|
291
|
|
|
"SilverStripe\\Forms\\HTMLEditor\\HTMLEditorField_Toolbar.ERROR_HOSTNAME", |
|
292
|
|
|
"This file hostname is not included in the whitelist" |
|
293
|
|
|
)); |
|
294
|
|
|
} |
|
295
|
|
|
return [null, $fileUrl]; |
|
296
|
|
|
} |
|
297
|
|
|
|
|
298
|
|
|
/** |
|
299
|
|
|
* Prepare error for the front end |
|
300
|
|
|
* |
|
301
|
|
|
* @param string $message |
|
302
|
|
|
* @param int $code |
|
303
|
|
|
* @return HTTPResponse_Exception |
|
304
|
|
|
*/ |
|
305
|
|
|
protected function getErrorFor($message, $code = 400) |
|
306
|
|
|
{ |
|
307
|
|
|
$exception = new HTTPResponse_Exception($message, $code); |
|
308
|
|
|
$exception->getResponse()->addHeader('X-Status', $message); |
|
309
|
|
|
return $exception; |
|
310
|
|
|
} |
|
311
|
|
|
|
|
312
|
|
|
/** |
|
313
|
|
|
* View of a single file, either on the filesystem or on the web. |
|
314
|
|
|
* |
|
315
|
|
|
* @throws HTTPResponse_Exception |
|
316
|
|
|
* @param HTTPRequest $request |
|
317
|
|
|
* @return string |
|
318
|
|
|
*/ |
|
319
|
|
|
public function viewfile($request) |
|
320
|
|
|
{ |
|
321
|
|
|
$file = null; |
|
322
|
|
|
$url = null; |
|
323
|
|
|
// Get file and url by request method |
|
324
|
|
|
if ($fileUrl = $request->getVar('FileURL')) { |
|
325
|
|
|
// Get remote url |
|
326
|
|
|
list($file, $url) = $this->viewfile_getRemoteFileByURL($fileUrl); |
|
327
|
|
|
} elseif ($id = $request->getVar('ID')) { |
|
328
|
|
|
// Or we could have been passed an ID directly |
|
329
|
|
|
list($file, $url) = $this->viewfile_getLocalFileByID($id); |
|
330
|
|
|
} else { |
|
331
|
|
|
// Or we could have been passed nothing, in which case panic |
|
332
|
|
|
throw $this->getErrorFor(_t( |
|
333
|
|
|
"SilverStripe\\Forms\\HTMLEditor\\HTMLEditorField_Toolbar.ERROR_ID", |
|
334
|
|
|
'Need either "ID" or "FileURL" parameter to identify the file' |
|
335
|
|
|
)); |
|
336
|
|
|
} |
|
337
|
|
|
|
|
338
|
|
|
// Validate file exists |
|
339
|
|
|
if (!$url) { |
|
340
|
|
|
throw $this->getErrorFor(_t( |
|
341
|
|
|
"SilverStripe\\Forms\\HTMLEditor\\HTMLEditorField_Toolbar.ERROR_NOTFOUND", |
|
342
|
|
|
'Unable to find file to view' |
|
343
|
|
|
)); |
|
344
|
|
|
} |
|
345
|
|
|
|
|
346
|
|
|
// Instantiate file wrapper and get fields based on its type |
|
347
|
|
|
// Check if appCategory is an image and exists on the local system, otherwise use Embed to reference a |
|
348
|
|
|
// remote image |
|
349
|
|
|
$fileCategory = $this->getFileCategory($url, $file); |
|
350
|
|
|
switch ($fileCategory) { |
|
351
|
|
|
case 'image': |
|
352
|
|
|
case 'image/supported': |
|
353
|
|
|
$fileWrapper = new HTMLEditorField_Image($url, $file); |
|
354
|
|
|
break; |
|
355
|
|
|
case 'flash': |
|
356
|
|
|
$fileWrapper = new HTMLEditorField_Flash($url, $file); |
|
357
|
|
|
break; |
|
358
|
|
|
default: |
|
359
|
|
|
// Only remote files can be linked via o-embed |
|
360
|
|
|
// {@see HTMLEditorField_Toolbar::getAllowedExtensions()) |
|
|
|
|
|
|
361
|
|
|
if ($file) { |
|
362
|
|
|
throw $this->getErrorFor(_t( |
|
363
|
|
|
"SilverStripe\\Forms\\HTMLEditor\\HTMLEditorField_Toolbar.ERROR_OEMBED_REMOTE", |
|
364
|
|
|
"Embed is only compatible with remote files" |
|
365
|
|
|
)); |
|
366
|
|
|
} |
|
367
|
|
|
|
|
368
|
|
|
// Other files should fallback to embed |
|
369
|
|
|
$fileWrapper = new HTMLEditorField_Embed($url, $file); |
|
370
|
|
|
break; |
|
371
|
|
|
} |
|
372
|
|
|
|
|
373
|
|
|
// Render fields and return |
|
374
|
|
|
$fields = $this->getFieldsForFile($url, $fileWrapper); |
|
375
|
|
|
return $fileWrapper->customise(array( |
|
376
|
|
|
'Fields' => $fields, |
|
377
|
|
|
))->renderWith($this->getTemplateViewFile()); |
|
378
|
|
|
} |
|
379
|
|
|
|
|
380
|
|
|
/** |
|
381
|
|
|
* Guess file category from either a file or url |
|
382
|
|
|
* |
|
383
|
|
|
* @param string $url |
|
384
|
|
|
* @param File $file |
|
385
|
|
|
* @return string |
|
386
|
|
|
*/ |
|
387
|
|
|
protected function getFileCategory($url, $file) |
|
388
|
|
|
{ |
|
389
|
|
|
if ($file) { |
|
390
|
|
|
return $file->appCategory(); |
|
391
|
|
|
} |
|
392
|
|
|
if ($url) { |
|
393
|
|
|
return File::get_app_category(File::get_file_extension($url)); |
|
394
|
|
|
} |
|
395
|
|
|
return null; |
|
396
|
|
|
} |
|
397
|
|
|
|
|
398
|
|
|
/** |
|
399
|
|
|
* Find all anchors available on the given page. |
|
400
|
|
|
* |
|
401
|
|
|
* @return array |
|
402
|
|
|
* @throws HTTPResponse_Exception |
|
403
|
|
|
*/ |
|
404
|
|
|
public function getanchors() |
|
405
|
|
|
{ |
|
406
|
|
|
$id = (int)$this->getRequest()->getVar('PageID'); |
|
407
|
|
|
$anchors = array(); |
|
408
|
|
|
|
|
409
|
|
|
if (($page = SiteTree::get()->byID($id)) && !empty($page)) { |
|
410
|
|
|
if (!$page->canView()) { |
|
411
|
|
|
throw new HTTPResponse_Exception( |
|
412
|
|
|
_t( |
|
413
|
|
|
'SilverStripe\\Forms\\HTMLEditor\\HTMLEditorField.ANCHORSCANNOTACCESSPAGE', |
|
414
|
|
|
'You are not permitted to access the content of the target page.' |
|
415
|
|
|
), |
|
416
|
|
|
403 |
|
417
|
|
|
); |
|
418
|
|
|
} |
|
419
|
|
|
|
|
420
|
|
|
// Parse the shortcodes so [img id=x] doesn't end up as anchor x |
|
421
|
|
|
$htmlValue = $page->obj('Content')->forTemplate(); |
|
422
|
|
|
|
|
423
|
|
|
// Similar to the regex found in HTMLEditorField.js / getAnchors method. |
|
424
|
|
|
if (preg_match_all( |
|
425
|
|
|
"/\\s+(name|id)\\s*=\\s*([\"'])([^\\2\\s>]*?)\\2|\\s+(name|id)\\s*=\\s*([^\"']+)[\\s +>]/im", |
|
426
|
|
|
$htmlValue, |
|
427
|
|
|
$matches |
|
428
|
|
|
)) { |
|
429
|
|
|
$anchors = array_values(array_unique(array_filter( |
|
430
|
|
|
array_merge($matches[3], $matches[5]) |
|
431
|
|
|
))); |
|
432
|
|
|
} |
|
433
|
|
|
} else { |
|
434
|
|
|
throw new HTTPResponse_Exception( |
|
435
|
|
|
_t('SilverStripe\\Forms\\HTMLEditor\\HTMLEditorField.ANCHORSPAGENOTFOUND', 'Target page not found.'), |
|
436
|
|
|
404 |
|
437
|
|
|
); |
|
438
|
|
|
} |
|
439
|
|
|
|
|
440
|
|
|
return json_encode($anchors); |
|
441
|
|
|
} |
|
442
|
|
|
|
|
443
|
|
|
/** |
|
444
|
|
|
* Similar to {@link File->getCMSFields()}, but only returns fields |
|
445
|
|
|
* for manipulating the instance of the file as inserted into the HTML content, |
|
446
|
|
|
* not the "master record" in the database - hence there's no form or saving logic. |
|
447
|
|
|
* |
|
448
|
|
|
* @param string $url Abolute URL to asset |
|
449
|
|
|
* @param HTMLEditorField_File $file Asset wrapper |
|
450
|
|
|
* @return FieldList |
|
451
|
|
|
*/ |
|
452
|
|
|
protected function getFieldsForFile($url, HTMLEditorField_File $file) |
|
453
|
|
|
{ |
|
454
|
|
|
$fields = $this->extend('getFieldsForFile', $url, $file); |
|
455
|
|
|
if (!$fields) { |
|
|
|
|
|
|
456
|
|
|
$fields = $file->getFields(); |
|
457
|
|
|
$file->extend('updateFields', $fields); |
|
458
|
|
|
} |
|
459
|
|
|
$this->extend('updateFieldsForFile', $fields, $url, $file); |
|
460
|
|
|
return $fields; |
|
461
|
|
|
} |
|
462
|
|
|
|
|
463
|
|
|
|
|
464
|
|
|
/** |
|
465
|
|
|
* Gets files filtered by a given parent with the allowed extensions |
|
466
|
|
|
* |
|
467
|
|
|
* @param int $parentID |
|
468
|
|
|
* @return DataList |
|
469
|
|
|
*/ |
|
470
|
|
|
protected function getFiles($parentID = null) |
|
471
|
|
|
{ |
|
472
|
|
|
$exts = $this->getAllowedExtensions(); |
|
473
|
|
|
$dotExts = array_map(function ($ext) { |
|
474
|
|
|
return ".{$ext}"; |
|
475
|
|
|
}, $exts); |
|
476
|
|
|
$files = File::get()->filter('Name:EndsWith', $dotExts); |
|
477
|
|
|
|
|
478
|
|
|
// Limit by folder (if required) |
|
479
|
|
|
if ($parentID) { |
|
|
|
|
|
|
480
|
|
|
$files = $files->filter('ParentID', $parentID); |
|
481
|
|
|
} |
|
482
|
|
|
|
|
483
|
|
|
return $files; |
|
484
|
|
|
} |
|
485
|
|
|
|
|
486
|
|
|
/** |
|
487
|
|
|
* @return array All extensions which can be handled by the different views. |
|
488
|
|
|
*/ |
|
489
|
|
|
protected function getAllowedExtensions() |
|
490
|
|
|
{ |
|
491
|
|
|
$exts = array('jpg', 'gif', 'png', 'swf', 'jpeg'); |
|
492
|
|
|
$this->extend('updateAllowedExtensions', $exts); |
|
493
|
|
|
return $exts; |
|
494
|
|
|
} |
|
495
|
|
|
} |
|
496
|
|
|
|
This check looks from parameters that have been defined for a function or method, but which are not used in the method body.