2007-07-19 12:40:28 +02:00
|
|
|
<?php
|
|
|
|
/**
|
2009-10-11 02:07:13 +02:00
|
|
|
* A TinyMCE-powered WYSIWYG HTML editor field with image and link insertion and tracking capabilities. Editor fields
|
|
|
|
* are created from <textarea> tags, which are then converted with JavaScript.
|
|
|
|
*
|
2008-01-09 05:18:36 +01:00
|
|
|
* @package forms
|
|
|
|
* @subpackage fields-formattedinput
|
2007-07-19 12:40:28 +02:00
|
|
|
*/
|
|
|
|
class HtmlEditorField extends TextareaField {
|
2012-01-06 12:01:33 +01:00
|
|
|
|
|
|
|
/**
|
2013-03-21 19:48:54 +01:00
|
|
|
* @config
|
2012-01-06 12:01:33 +01:00
|
|
|
* @var Boolean Use TinyMCE's GZIP compressor
|
|
|
|
*/
|
2013-03-21 19:48:54 +01:00
|
|
|
private static $use_gzip = true;
|
2012-02-10 12:15:21 +01:00
|
|
|
|
2013-06-24 22:25:16 +02:00
|
|
|
/**
|
|
|
|
* @config
|
|
|
|
* @var Integer Default insertion width for Images and Media
|
|
|
|
*/
|
|
|
|
private static $insert_width = 600;
|
|
|
|
|
2013-07-03 10:06:49 +02:00
|
|
|
/**
|
|
|
|
* @config
|
|
|
|
* @var bool Should we check the valid_elements (& extended_valid_elements) rules from HtmlEditorConfig server side?
|
|
|
|
*/
|
|
|
|
private static $sanitise_server_side = false;
|
|
|
|
|
2012-03-12 16:03:13 +01:00
|
|
|
protected $rows = 30;
|
2015-08-14 02:39:33 +02:00
|
|
|
|
2009-05-18 02:19:47 +02:00
|
|
|
/**
|
2015-06-19 01:59:27 +02:00
|
|
|
* @deprecated since version 4.0
|
2009-05-18 02:19:47 +02:00
|
|
|
*/
|
2009-10-11 02:07:13 +02:00
|
|
|
public static function include_js() {
|
2015-06-09 02:01:21 +02:00
|
|
|
Deprecation::notice('4.0', 'Use HtmlEditorConfig::require_js() instead');
|
|
|
|
HtmlEditorConfig::require_js();
|
2009-05-18 02:19:47 +02:00
|
|
|
}
|
2013-06-21 00:32:08 +02:00
|
|
|
|
2015-06-09 02:01:21 +02:00
|
|
|
|
|
|
|
protected $editorConfig = null;
|
|
|
|
|
2007-07-19 12:40:28 +02:00
|
|
|
/**
|
2015-06-09 02:01:21 +02:00
|
|
|
* Creates a new HTMLEditorField.
|
2009-10-11 02:07:13 +02:00
|
|
|
* @see TextareaField::__construct()
|
2015-06-09 02:01:21 +02:00
|
|
|
*
|
|
|
|
* @param string $name The internal field name, passed to forms.
|
|
|
|
* @param string $title The human-readable field label.
|
|
|
|
* @param mixed $value The value of the field.
|
|
|
|
* @param string $config HTMLEditorConfig identifier to be used. Default to the active one.
|
2015-08-14 02:39:33 +02:00
|
|
|
*/
|
2015-06-09 02:01:21 +02:00
|
|
|
public function __construct($name, $title = null, $value = '', $config = null) {
|
2012-01-02 17:44:23 +01:00
|
|
|
parent::__construct($name, $title, $value);
|
2013-06-21 00:32:08 +02:00
|
|
|
|
2015-06-09 02:01:21 +02:00
|
|
|
$this->editorConfig = $config ? $config : HtmlEditorConfig::get_active_identifier();
|
2007-07-19 12:40:28 +02:00
|
|
|
}
|
2013-06-21 00:32:08 +02:00
|
|
|
|
2012-09-19 12:07:39 +02:00
|
|
|
public function getAttributes() {
|
2011-12-22 13:10:57 +01:00
|
|
|
return array_merge(
|
|
|
|
parent::getAttributes(),
|
|
|
|
array(
|
|
|
|
'tinymce' => 'true',
|
2012-03-12 16:03:13 +01:00
|
|
|
'style' => 'width: 97%; height: ' . ($this->rows * 16) . 'px', // prevents horizontal scrollbars
|
2011-12-22 13:10:57 +01:00
|
|
|
'value' => null,
|
2015-06-09 02:01:21 +02:00
|
|
|
'data-config' => $this->editorConfig
|
2011-12-22 13:10:57 +01:00
|
|
|
)
|
|
|
|
);
|
|
|
|
}
|
2013-06-21 00:32:08 +02:00
|
|
|
|
2012-04-11 07:00:57 +02:00
|
|
|
public function saveInto(DataObjectInterface $record) {
|
2013-04-29 09:32:05 +02:00
|
|
|
if($record->hasField($this->name) && $record->escapeTypeForField($this->name) != 'xml') {
|
2009-10-11 02:07:13 +02:00
|
|
|
throw new Exception (
|
|
|
|
'HtmlEditorField->saveInto(): This field should save into a HTMLText or HTMLVarchar field.'
|
2008-01-17 05:22:13 +01:00
|
|
|
);
|
|
|
|
}
|
2013-06-21 00:32:08 +02:00
|
|
|
|
2013-03-11 21:06:20 +01:00
|
|
|
$htmlValue = Injector::inst()->create('HTMLValue', $this->value);
|
2013-07-03 10:06:49 +02:00
|
|
|
|
2013-08-07 01:02:11 +02:00
|
|
|
// Sanitise if requested
|
2013-07-03 10:06:49 +02:00
|
|
|
if($this->config()->sanitise_server_side) {
|
|
|
|
$santiser = Injector::inst()->create('HtmlEditorSanitiser', HtmlEditorConfig::get_active());
|
|
|
|
$santiser->sanitise($htmlValue);
|
|
|
|
}
|
|
|
|
|
2013-08-07 01:02:11 +02:00
|
|
|
// Resample images and add default attributes
|
2009-10-11 02:07:27 +02:00
|
|
|
if($images = $htmlValue->getElementsByTagName('img')) foreach($images as $img) {
|
|
|
|
// strip any ?r=n data from the src attribute
|
|
|
|
$img->setAttribute('src', preg_replace('/([^\?]*)\?r=[0-9]+$/i', '$1', $img->getAttribute('src')));
|
2013-08-07 01:02:11 +02:00
|
|
|
|
2009-10-11 02:07:13 +02:00
|
|
|
// Resample the images if the width & height have changed.
|
2013-08-07 01:02:11 +02:00
|
|
|
if($image = File::find(urldecode(Director::makeRelative($img->getAttribute('src'))))){
|
2013-08-16 13:37:44 +02:00
|
|
|
$width = (int)$img->getAttribute('width');
|
|
|
|
$height = (int)$img->getAttribute('height');
|
2013-08-07 01:02:11 +02:00
|
|
|
|
2010-04-12 04:45:35 +02:00
|
|
|
if($width && $height && ($width != $image->getWidth() || $height != $image->getHeight())) {
|
|
|
|
//Make sure that the resized image actually returns an image:
|
|
|
|
$resized=$image->ResizedImage($width, $height);
|
2012-05-28 12:27:20 +02:00
|
|
|
if($resized) $img->setAttribute('src', $resized->getRelativePath());
|
2010-04-12 04:45:35 +02:00
|
|
|
}
|
2007-07-19 12:40:28 +02:00
|
|
|
}
|
2013-08-07 01:02:11 +02:00
|
|
|
|
2009-10-11 02:07:13 +02:00
|
|
|
// Add default empty title & alt attributes.
|
|
|
|
if(!$img->getAttribute('alt')) $img->setAttribute('alt', '');
|
|
|
|
if(!$img->getAttribute('title')) $img->setAttribute('title', '');
|
2015-08-14 02:39:33 +02:00
|
|
|
|
2014-12-10 08:36:45 +01:00
|
|
|
// Use this extension point to manipulate images inserted using TinyMCE, e.g. add a CSS class, change default title
|
|
|
|
// $image is the image, $img is the DOM model
|
|
|
|
$this->extend('processImage', $image, $img);
|
2007-07-19 12:40:28 +02:00
|
|
|
}
|
2013-08-07 01:02:11 +02:00
|
|
|
|
2014-12-10 08:36:45 +01:00
|
|
|
// optionally manipulate the HTML after a TinyMCE edit and prior to a save
|
|
|
|
$this->extend('processHTML', $htmlValue);
|
|
|
|
|
2013-08-07 01:02:11 +02:00
|
|
|
// Store into record
|
2009-10-11 02:07:27 +02:00
|
|
|
$record->{$this->name} = $htmlValue->getContent();
|
2007-07-19 12:40:28 +02:00
|
|
|
}
|
2009-11-26 23:18:59 +01:00
|
|
|
|
2009-10-11 02:07:13 +02:00
|
|
|
/**
|
|
|
|
* @return HtmlEditorField_Readonly
|
|
|
|
*/
|
|
|
|
public function performReadonlyTransformation() {
|
2012-12-13 13:51:28 +01:00
|
|
|
$field = $this->castedCopy('HtmlEditorField_Readonly');
|
2007-07-19 12:40:28 +02:00
|
|
|
$field->dontEscape = true;
|
2013-06-21 00:32:08 +02:00
|
|
|
|
2007-07-19 12:40:28 +02:00
|
|
|
return $field;
|
|
|
|
}
|
2013-06-21 00:32:08 +02:00
|
|
|
|
2012-01-02 16:19:22 +01:00
|
|
|
public function performDisabledTransformation() {
|
|
|
|
return $this->performReadonlyTransformation();
|
|
|
|
}
|
2007-07-19 12:40:28 +02:00
|
|
|
}
|
|
|
|
|
2008-01-10 01:34:18 +01:00
|
|
|
/**
|
|
|
|
* Readonly version of an {@link HTMLEditorField}.
|
|
|
|
* @package forms
|
|
|
|
* @subpackage fields-formattedinput
|
|
|
|
*/
|
2009-10-11 02:07:13 +02:00
|
|
|
class HtmlEditorField_Readonly extends ReadonlyField {
|
2012-09-19 12:07:39 +02:00
|
|
|
public function Field($properties = array()) {
|
2007-07-19 12:40:28 +02:00
|
|
|
$valforInput = $this->value ? Convert::raw2att($this->value) : "";
|
2012-09-26 23:34:00 +02:00
|
|
|
return "<span class=\"readonly typography\" id=\"" . $this->id() . "\">"
|
|
|
|
. ( $this->value && $this->value != '<p></p>' ? $this->value : '<i>(not set)</i>' )
|
|
|
|
. "</span><input type=\"hidden\" name=\"".$this->name."\" value=\"".$valforInput."\" />";
|
2007-07-19 12:40:28 +02:00
|
|
|
}
|
2012-09-19 12:07:39 +02:00
|
|
|
public function Type() {
|
2007-11-06 22:01:37 +01:00
|
|
|
return 'htmleditorfield readonly';
|
2007-07-19 12:40:28 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-01-10 01:34:18 +01:00
|
|
|
/**
|
2012-02-09 17:17:39 +01:00
|
|
|
* Toolbar shared by all instances of {@link HTMLEditorField}, to avoid too much markup duplication.
|
|
|
|
* Needs to be inserted manually into the template in order to function - see {@link LeftAndMain->EditorToolbar()}.
|
2013-06-21 00:32:08 +02:00
|
|
|
*
|
2008-01-10 01:34:18 +01:00
|
|
|
* @package forms
|
|
|
|
* @subpackage fields-formattedinput
|
|
|
|
*/
|
2008-10-30 23:03:21 +01:00
|
|
|
class HtmlEditorField_Toolbar extends RequestHandler {
|
2012-02-08 21:32:25 +01:00
|
|
|
|
2013-03-21 19:48:54 +01:00
|
|
|
private static $allowed_actions = array(
|
2012-02-08 21:32:25 +01:00
|
|
|
'LinkForm',
|
|
|
|
'MediaForm',
|
2014-07-30 00:59:13 +02:00
|
|
|
'viewfile',
|
|
|
|
'getanchors'
|
2012-02-08 21:32:25 +01:00
|
|
|
);
|
|
|
|
|
2012-02-09 17:17:39 +01:00
|
|
|
/**
|
|
|
|
* @var string
|
|
|
|
*/
|
|
|
|
protected $templateViewFile = 'HtmlEditorField_viewfile';
|
|
|
|
|
2007-07-19 12:40:28 +02:00
|
|
|
protected $controller, $name;
|
2013-06-21 00:32:08 +02:00
|
|
|
|
2012-09-19 12:07:39 +02:00
|
|
|
public function __construct($controller, $name) {
|
2008-11-05 02:59:27 +01:00
|
|
|
parent::__construct();
|
2012-02-08 21:32:25 +01:00
|
|
|
|
2012-03-24 04:38:57 +01:00
|
|
|
Requirements::javascript(FRAMEWORK_DIR . "/thirdparty/jquery/jquery.js");
|
2012-02-08 21:32:25 +01:00
|
|
|
Requirements::javascript(THIRDPARTY_DIR . '/jquery-ui/jquery-ui.js');
|
|
|
|
Requirements::javascript(THIRDPARTY_DIR . '/jquery-entwine/dist/jquery.entwine-dist.js');
|
2012-03-24 04:38:57 +01:00
|
|
|
Requirements::javascript(FRAMEWORK_ADMIN_DIR . '/javascript/ssui.core.js');
|
2015-06-09 02:01:21 +02:00
|
|
|
|
|
|
|
HtmlEditorConfig::require_js();
|
2012-03-24 04:38:57 +01:00
|
|
|
Requirements::javascript(FRAMEWORK_DIR ."/javascript/HtmlEditorField.js");
|
2012-02-08 21:32:25 +01:00
|
|
|
|
|
|
|
Requirements::css(THIRDPARTY_DIR . '/jquery-ui-themes/smoothness/jquery-ui.css');
|
2013-06-21 00:32:08 +02:00
|
|
|
|
2007-07-19 12:40:28 +02:00
|
|
|
$this->controller = $controller;
|
|
|
|
$this->name = $name;
|
|
|
|
}
|
2010-04-13 01:34:08 +02:00
|
|
|
|
2012-04-12 22:28:00 +02:00
|
|
|
public function forTemplate() {
|
|
|
|
return sprintf(
|
|
|
|
'<div id="cms-editor-dialogs" data-url-linkform="%s" data-url-mediaform="%s"></div>',
|
2012-11-09 04:44:48 +01:00
|
|
|
Controller::join_links($this->controller->Link(), $this->name, 'LinkForm', 'forTemplate'),
|
|
|
|
Controller::join_links($this->controller->Link(), $this->name, 'MediaForm', 'forTemplate')
|
2012-04-12 22:28:00 +02:00
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2010-04-13 01:34:08 +02:00
|
|
|
/**
|
|
|
|
* Searches the SiteTree for display in the dropdown
|
2013-06-21 00:32:08 +02:00
|
|
|
*
|
2010-04-13 01:34:08 +02:00
|
|
|
* @return callback
|
2013-06-21 00:32:08 +02:00
|
|
|
*/
|
2012-09-19 12:07:39 +02:00
|
|
|
public function siteTreeSearchCallback($sourceObject, $labelField, $search) {
|
2013-06-21 00:32:08 +02:00
|
|
|
return DataObject::get($sourceObject)->filterAny(array(
|
|
|
|
'MenuTitle:PartialMatch' => $search,
|
|
|
|
'Title:PartialMatch' => $search
|
|
|
|
));
|
2010-04-13 01:34:08 +02:00
|
|
|
}
|
2013-06-21 00:32:08 +02:00
|
|
|
|
2007-07-19 12:40:28 +02:00
|
|
|
/**
|
2008-11-04 05:12:54 +01:00
|
|
|
* Return a {@link Form} instance allowing a user to
|
|
|
|
* add links in the TinyMCE content editor.
|
2013-06-21 00:32:08 +02:00
|
|
|
*
|
2008-11-04 05:12:54 +01:00
|
|
|
* @return Form
|
2007-07-19 12:40:28 +02:00
|
|
|
*/
|
2012-09-19 12:07:39 +02:00
|
|
|
public function LinkForm() {
|
2013-10-25 21:49:41 +02:00
|
|
|
$siteTree = TreeDropdownField::create('internal', _t('HtmlEditorField.PAGE', "Page"),
|
2012-09-26 23:34:00 +02:00
|
|
|
'SiteTree', 'ID', 'MenuTitle', true);
|
2010-04-13 01:34:08 +02:00
|
|
|
// mimic the SiteTree::getMenuTitle(), which is bypassed when the search is performed
|
|
|
|
$siteTree->setSearchFunction(array($this, 'siteTreeSearchCallback'));
|
2013-06-21 00:32:08 +02:00
|
|
|
|
2012-09-26 23:34:00 +02:00
|
|
|
$numericLabelTmpl = '<span class="step-label"><span class="flyout">%d</span><span class="arrow"></span>'
|
|
|
|
. '<strong class="title">%s</strong></span>';
|
2007-07-19 12:40:28 +02:00
|
|
|
$form = new Form(
|
|
|
|
$this->controller,
|
2013-06-21 00:32:08 +02:00
|
|
|
"{$this->name}/LinkForm",
|
2011-05-11 09:51:54 +02:00
|
|
|
new FieldList(
|
2012-06-25 05:31:39 +02:00
|
|
|
$headerWrap = new CompositeField(
|
|
|
|
new LiteralField(
|
2013-06-21 00:32:08 +02:00
|
|
|
'Heading',
|
2012-09-26 23:34:00 +02:00
|
|
|
sprintf('<h3 class="htmleditorfield-mediaform-heading insert">%s</h3>',
|
|
|
|
_t('HtmlEditorField.LINK', 'Insert Link'))
|
2012-06-25 05:31:39 +02:00
|
|
|
)
|
2007-07-19 12:40:28 +02:00
|
|
|
),
|
2009-11-21 03:22:44 +01:00
|
|
|
$contentComposite = new CompositeField(
|
2013-10-25 21:49:41 +02:00
|
|
|
OptionsetField::create(
|
2009-11-21 03:22:44 +01:00
|
|
|
'LinkType',
|
2012-01-03 22:30:24 +01:00
|
|
|
sprintf($numericLabelTmpl, '1', _t('HtmlEditorField.LINKTO', 'Link to')),
|
2009-11-21 03:22:44 +01:00
|
|
|
array(
|
|
|
|
'internal' => _t('HtmlEditorField.LINKINTERNAL', 'Page on the site'),
|
|
|
|
'external' => _t('HtmlEditorField.LINKEXTERNAL', 'Another website'),
|
|
|
|
'anchor' => _t('HtmlEditorField.LINKANCHOR', 'Anchor on this page'),
|
|
|
|
'email' => _t('HtmlEditorField.LINKEMAIL', 'Email address'),
|
2012-05-09 07:11:59 +02:00
|
|
|
'file' => _t('HtmlEditorField.LINKFILE', 'Download a file'),
|
|
|
|
),
|
|
|
|
'internal'
|
2009-11-21 03:22:44 +01:00
|
|
|
),
|
2013-10-25 21:49:41 +02:00
|
|
|
LiteralField::create('Step2',
|
2012-09-26 23:34:00 +02:00
|
|
|
'<div class="step2">'
|
|
|
|
. sprintf($numericLabelTmpl, '2', _t('HtmlEditorField.DETAILS', 'Details')) . '</div>'
|
2012-01-03 22:30:24 +01:00
|
|
|
),
|
2010-04-13 01:34:08 +02:00
|
|
|
$siteTree,
|
2013-10-25 21:49:41 +02:00
|
|
|
TextField::create('external', _t('HtmlEditorField.URL', 'URL'), 'http://'),
|
|
|
|
EmailField::create('email', _t('HtmlEditorField.EMAIL', 'Email address')),
|
2015-06-03 01:20:29 +02:00
|
|
|
$fileField = UploadField::create('file', _t('HtmlEditorField.FILE', 'File')),
|
2013-10-25 21:49:41 +02:00
|
|
|
TextField::create('Anchor', _t('HtmlEditorField.ANCHORVALUE', 'Anchor')),
|
2014-12-15 22:56:10 +01:00
|
|
|
TextField::create('Subject', _t('HtmlEditorField.SUBJECT', 'Email subject')),
|
2013-10-25 21:49:41 +02:00
|
|
|
TextField::create('Description', _t('HtmlEditorField.LINKDESCR', 'Link description')),
|
|
|
|
CheckboxField::create('TargetBlank',
|
2012-09-26 23:34:00 +02:00
|
|
|
_t('HtmlEditorField.LINKOPENNEWWIN', 'Open link in a new window?')),
|
2013-10-25 21:49:41 +02:00
|
|
|
HiddenField::create('Locale', null, $this->controller->Locale)
|
2009-11-21 03:22:44 +01:00
|
|
|
)
|
2007-07-19 12:40:28 +02:00
|
|
|
),
|
2011-05-11 09:51:54 +02:00
|
|
|
new FieldList(
|
2012-04-04 16:59:30 +02:00
|
|
|
ResetFormAction::create('remove', _t('HtmlEditorField.BUTTONREMOVELINK', 'Remove link'))
|
2012-02-17 00:35:10 +01:00
|
|
|
->addExtraClass('ss-ui-action-destructive')
|
|
|
|
->setUseButtonTag(true)
|
|
|
|
,
|
|
|
|
FormAction::create('insert', _t('HtmlEditorField.BUTTONINSERTLINK', 'Insert link'))
|
|
|
|
->addExtraClass('ss-ui-action-constructive')
|
|
|
|
->setAttribute('data-icon', 'accept')
|
|
|
|
->setUseButtonTag(true)
|
2007-07-19 12:40:28 +02:00
|
|
|
)
|
|
|
|
);
|
2012-06-25 05:31:39 +02:00
|
|
|
|
2013-06-21 00:32:08 +02:00
|
|
|
$headerWrap->addExtraClass('CompositeField composite cms-content-header nolabel ');
|
2012-06-25 05:31:39 +02:00
|
|
|
$contentComposite->addExtraClass('ss-insert-link content');
|
2015-06-03 01:20:29 +02:00
|
|
|
$fileField->setAllowedMaxFileNumber(1);
|
2013-06-21 00:32:08 +02:00
|
|
|
|
2009-11-21 03:31:11 +01:00
|
|
|
$form->unsetValidator();
|
2007-07-19 12:40:28 +02:00
|
|
|
$form->loadDataFrom($this);
|
2012-01-03 17:38:11 +01:00
|
|
|
$form->addExtraClass('htmleditorfield-form htmleditorfield-linkform cms-dialog-content');
|
2013-06-21 00:32:08 +02:00
|
|
|
|
2010-05-25 06:56:02 +02:00
|
|
|
$this->extend('updateLinkForm', $form);
|
2013-06-21 00:32:08 +02:00
|
|
|
|
2007-07-19 12:40:28 +02:00
|
|
|
return $form;
|
|
|
|
}
|
|
|
|
|
2014-07-21 05:52:10 +02:00
|
|
|
/**
|
|
|
|
* Get the folder ID to filter files by for the "from cms" tab
|
|
|
|
*
|
|
|
|
* @return int
|
|
|
|
*/
|
|
|
|
protected function getAttachParentID() {
|
|
|
|
$parentID = $this->controller->getRequest()->requestVar('ParentID');
|
|
|
|
$this->extend('updateAttachParentID', $parentID);
|
|
|
|
return $parentID;
|
|
|
|
}
|
|
|
|
|
2008-11-04 05:12:54 +01:00
|
|
|
/**
|
|
|
|
* Return a {@link Form} instance allowing a user to
|
2012-02-08 21:32:25 +01:00
|
|
|
* add images and flash objects to the TinyMCE content editor.
|
2013-06-21 00:32:08 +02:00
|
|
|
*
|
2008-11-04 05:12:54 +01:00
|
|
|
* @return Form
|
|
|
|
*/
|
2012-09-19 12:07:39 +02:00
|
|
|
public function MediaForm() {
|
2012-09-26 23:34:00 +02:00
|
|
|
// TODO Handle through GridState within field - currently this state set too late to be useful here (during
|
|
|
|
// request handling)
|
2014-07-21 05:52:10 +02:00
|
|
|
$parentID = $this->getAttachParentID();
|
2012-02-08 21:32:25 +01:00
|
|
|
|
2012-07-10 23:19:50 +02:00
|
|
|
$fileFieldConfig = GridFieldConfig::create()->addComponents(
|
|
|
|
new GridFieldFilterHeader(),
|
|
|
|
new GridFieldSortableHeader(),
|
|
|
|
new GridFieldDataColumns(),
|
2015-07-28 00:08:25 +02:00
|
|
|
new GridFieldPaginator(7),
|
2013-06-14 13:53:09 +02:00
|
|
|
// TODO Shouldn't allow delete here, its too confusing with a "remove from editor view" action.
|
|
|
|
// Remove once we can fit the search button in the last actual title column
|
2012-07-10 23:19:50 +02:00
|
|
|
new GridFieldDeleteAction(),
|
|
|
|
new GridFieldDetailForm()
|
|
|
|
);
|
2015-09-01 02:38:58 +02:00
|
|
|
$fileField = GridField::create('Files', false, null, $fileFieldConfig);
|
2012-02-08 21:32:25 +01:00
|
|
|
$fileField->setList($this->getFiles($parentID));
|
|
|
|
$fileField->setAttribute('data-selectable', true);
|
|
|
|
$fileField->setAttribute('data-multiselect', true);
|
2012-04-19 01:25:37 +02:00
|
|
|
$columns = $fileField->getConfig()->getComponentByType('GridFieldDataColumns');
|
|
|
|
$columns->setDisplayFields(array(
|
2015-07-28 00:08:25 +02:00
|
|
|
'StripThumbnail' => false,
|
|
|
|
'Title' => _t('File.Title'),
|
|
|
|
'Created' => singleton('File')->fieldLabel('Created'),
|
|
|
|
));
|
|
|
|
$columns->setFieldCasting(array(
|
|
|
|
'Created' => 'SS_Datetime->Nice'
|
2012-02-09 17:17:39 +01:00
|
|
|
));
|
2013-06-21 00:32:08 +02:00
|
|
|
|
2012-09-26 23:34:00 +02:00
|
|
|
$numericLabelTmpl = '<span class="step-label"><span class="flyout">%d</span><span class="arrow"></span>'
|
|
|
|
. '<strong class="title">%s</strong></span>';
|
2012-03-29 02:34:55 +02:00
|
|
|
|
|
|
|
$fromCMS = new CompositeField(
|
2013-06-21 00:32:08 +02:00
|
|
|
new LiteralField('headerSelect',
|
2012-09-26 23:34:00 +02:00
|
|
|
'<h4>'.sprintf($numericLabelTmpl, '1', _t('HtmlEditorField.FindInFolder', 'Find in Folder')).'</h4>'),
|
2014-07-21 05:52:10 +02:00
|
|
|
$select = TreeDropdownField::create('ParentID', "", 'Folder')
|
|
|
|
->addExtraClass('noborder')
|
|
|
|
->setValue($parentID),
|
2012-09-26 23:34:00 +02:00
|
|
|
$fileField
|
2012-03-29 02:34:55 +02:00
|
|
|
);
|
2013-06-21 00:32:08 +02:00
|
|
|
|
2013-06-14 23:55:43 +02:00
|
|
|
$fromCMS->addExtraClass('content ss-uploadfield');
|
2012-06-22 08:04:13 +02:00
|
|
|
$select->addExtraClass('content-select');
|
2012-03-29 02:34:55 +02:00
|
|
|
|
|
|
|
|
2012-05-22 06:45:36 +02:00
|
|
|
$fromWeb = new CompositeField(
|
2012-09-26 23:34:00 +02:00
|
|
|
new LiteralField('headerURL',
|
|
|
|
'<h4>' . sprintf($numericLabelTmpl, '1', _t('HtmlEditorField.ADDURL', 'Add URL')) . '</h4>'),
|
2012-06-21 04:19:41 +02:00
|
|
|
$remoteURL = new TextField('RemoteURL', 'http://'),
|
2012-09-26 23:34:00 +02:00
|
|
|
new LiteralField('addURLImage',
|
2013-08-21 08:54:05 +02:00
|
|
|
'<button class="action ui-action-constructive ui-button field add-url" data-icon="addMedia">' .
|
|
|
|
_t('HtmlEditorField.BUTTONADDURL', 'Add url').'</button>')
|
2012-05-22 06:45:36 +02:00
|
|
|
);
|
2012-06-22 08:04:13 +02:00
|
|
|
|
2012-05-22 06:45:36 +02:00
|
|
|
$remoteURL->addExtraClass('remoteurl');
|
2013-06-14 23:55:43 +02:00
|
|
|
$fromWeb->addExtraClass('content ss-uploadfield');
|
2012-05-22 06:45:36 +02:00
|
|
|
|
2012-03-24 04:38:57 +01:00
|
|
|
Requirements::css(FRAMEWORK_DIR . '/css/AssetUploadField.css');
|
2012-03-29 02:34:55 +02:00
|
|
|
$computerUploadField = Object::create('UploadField', 'AssetUploadField', '');
|
|
|
|
$computerUploadField->setConfig('previewMaxWidth', 40);
|
|
|
|
$computerUploadField->setConfig('previewMaxHeight', 30);
|
|
|
|
$computerUploadField->addExtraClass('ss-assetuploadfield');
|
|
|
|
$computerUploadField->removeExtraClass('ss-uploadfield');
|
2012-03-30 02:44:39 +02:00
|
|
|
$computerUploadField->setTemplate('HtmlEditorField_UploadField');
|
2013-03-21 19:48:54 +01:00
|
|
|
$computerUploadField->setFolderName(Config::inst()->get('Upload', 'uploads_folder'));
|
2012-03-29 02:34:55 +02:00
|
|
|
|
|
|
|
$tabSet = new TabSet(
|
2012-05-22 06:45:36 +02:00
|
|
|
"MediaFormInsertMediaTabs",
|
2013-06-14 23:55:43 +02:00
|
|
|
Tab::create(
|
2013-03-24 10:19:45 +01:00
|
|
|
'FromComputer',
|
2012-03-29 04:09:20 +02:00
|
|
|
_t('HtmlEditorField.FROMCOMPUTER','From your computer'),
|
2012-03-29 02:34:55 +02:00
|
|
|
$computerUploadField
|
2013-06-14 23:55:43 +02:00
|
|
|
)->addExtraClass('htmleditorfield-from-computer'),
|
|
|
|
Tab::create(
|
2013-03-24 10:19:45 +01:00
|
|
|
'FromWeb',
|
2012-05-22 06:45:36 +02:00
|
|
|
_t('HtmlEditorField.FROMWEB', 'From the web'),
|
|
|
|
$fromWeb
|
2013-06-14 23:55:43 +02:00
|
|
|
)->addExtraClass('htmleditorfield-from-web'),
|
|
|
|
Tab::create(
|
2013-03-24 10:19:45 +01:00
|
|
|
'FromCms',
|
2012-03-29 04:09:20 +02:00
|
|
|
_t('HtmlEditorField.FROMCMS','From the CMS'),
|
2012-03-29 02:34:55 +02:00
|
|
|
$fromCMS
|
2013-06-14 23:55:43 +02:00
|
|
|
)->addExtraClass('htmleditorfield-from-cms')
|
2012-03-29 02:34:55 +02:00
|
|
|
);
|
2012-11-06 10:53:20 +01:00
|
|
|
$tabSet->addExtraClass('cms-tabset-primary');
|
2012-03-29 02:34:55 +02:00
|
|
|
|
|
|
|
$allFields = new CompositeField(
|
|
|
|
$tabSet,
|
2013-06-14 13:51:28 +02:00
|
|
|
new LiteralField('headerEdit', '<h4 class="field noborder header-edit">' . sprintf($numericLabelTmpl, '2',
|
2012-09-26 23:34:00 +02:00
|
|
|
_t('HtmlEditorField.ADJUSTDETAILSDIMENSIONS', 'Details & dimensions')) . '</h4>'),
|
2012-03-29 02:34:55 +02:00
|
|
|
$editComposite = new CompositeField(
|
2012-05-22 08:18:31 +02:00
|
|
|
new LiteralField('contentEdit', '<div class="content-edit ss-uploadfield-files files"></div>')
|
2012-05-28 12:27:20 +02:00
|
|
|
)
|
2007-07-19 12:40:28 +02:00
|
|
|
);
|
2012-03-29 02:34:55 +02:00
|
|
|
|
2012-05-28 12:27:20 +02:00
|
|
|
$allFields->addExtraClass('ss-insert-media');
|
2012-05-22 08:18:31 +02:00
|
|
|
|
|
|
|
$headings = new CompositeField(
|
2012-03-29 02:34:55 +02:00
|
|
|
new LiteralField(
|
|
|
|
'Heading',
|
2012-09-26 23:34:00 +02:00
|
|
|
sprintf('<h3 class="htmleditorfield-mediaform-heading insert">%s</h3>',
|
|
|
|
_t('HtmlEditorField.INSERTMEDIA', 'Insert Media')).
|
|
|
|
sprintf('<h3 class="htmleditorfield-mediaform-heading update">%s</h3>',
|
|
|
|
_t('HtmlEditorField.UpdateMEDIA', 'Update Media'))
|
2012-05-28 12:27:20 +02:00
|
|
|
)
|
2012-05-22 08:18:31 +02:00
|
|
|
);
|
|
|
|
|
|
|
|
$headings->addExtraClass('cms-content-header');
|
|
|
|
$editComposite->addExtraClass('ss-assetuploadfield');
|
|
|
|
|
|
|
|
$fields = new FieldList(
|
|
|
|
$headings,
|
2012-03-29 02:34:55 +02:00
|
|
|
$allFields
|
|
|
|
);
|
2013-06-21 00:32:08 +02:00
|
|
|
|
2011-05-11 09:51:54 +02:00
|
|
|
$actions = new FieldList(
|
2012-05-22 06:45:36 +02:00
|
|
|
FormAction::create('insertmedia', _t('HtmlEditorField.BUTTONINSERT', 'Insert'))
|
|
|
|
->addExtraClass('ss-ui-action-constructive media-insert')
|
2012-04-20 06:11:15 +02:00
|
|
|
->setAttribute('data-icon', 'accept')
|
|
|
|
->setUseButtonTag(true),
|
2012-05-22 06:45:36 +02:00
|
|
|
FormAction::create('insertmedia', _t('HtmlEditorField.BUTTONUpdate', 'Update'))
|
|
|
|
->addExtraClass('ss-ui-action-constructive media-update')
|
2012-02-17 00:35:10 +01:00
|
|
|
->setAttribute('data-icon', 'accept')
|
|
|
|
->setUseButtonTag(true)
|
2010-05-25 06:56:02 +02:00
|
|
|
);
|
2012-01-03 09:38:33 +01:00
|
|
|
|
2010-05-25 06:56:02 +02:00
|
|
|
$form = new Form(
|
|
|
|
$this->controller,
|
2012-02-08 21:32:25 +01:00
|
|
|
"{$this->name}/MediaForm",
|
2010-05-25 06:56:02 +02:00
|
|
|
$fields,
|
|
|
|
$actions
|
|
|
|
);
|
2013-06-21 00:32:08 +02:00
|
|
|
|
2012-03-29 02:34:55 +02:00
|
|
|
|
2009-11-21 03:31:11 +01:00
|
|
|
$form->unsetValidator();
|
2009-06-28 03:17:20 +02:00
|
|
|
$form->disableSecurityToken();
|
2007-07-19 12:40:28 +02:00
|
|
|
$form->loadDataFrom($this);
|
2012-02-08 21:32:25 +01:00
|
|
|
$form->addExtraClass('htmleditorfield-form htmleditorfield-mediaform cms-dialog-content');
|
2012-02-09 17:17:39 +01:00
|
|
|
// TODO Re-enable once we remove $.metadata dependency which currently breaks the JS due to $.ui.widget
|
|
|
|
// $form->setAttribute('data-urlViewfile', $this->controller->Link($this->name));
|
|
|
|
|
2013-06-21 00:32:08 +02:00
|
|
|
// Allow other people to extend the fields being added to the imageform
|
2012-02-09 17:17:39 +01:00
|
|
|
$this->extend('updateMediaForm', $form);
|
2013-06-21 00:32:08 +02:00
|
|
|
|
2007-07-19 12:40:28 +02:00
|
|
|
return $form;
|
|
|
|
}
|
|
|
|
|
2012-02-09 17:17:39 +01:00
|
|
|
/**
|
|
|
|
* View of a single file, either on the filesystem or on the web.
|
|
|
|
*/
|
|
|
|
public function viewfile($request) {
|
2012-06-08 06:42:14 +02:00
|
|
|
|
2012-02-09 17:17:39 +01:00
|
|
|
// TODO Would be cleaner to consistently pass URL for both local and remote files,
|
|
|
|
// but GridField doesn't allow for this kind of metadata customization at the moment.
|
|
|
|
if($url = $request->getVar('FileURL')) {
|
2012-03-12 16:31:32 +01:00
|
|
|
if(Director::is_absolute_url($url) && !Director::is_site_url($url)) {
|
|
|
|
$file = new File(array(
|
|
|
|
'Title' => basename($url),
|
|
|
|
'Filename' => $url
|
2013-06-21 00:32:08 +02:00
|
|
|
));
|
2012-02-09 17:17:39 +01:00
|
|
|
} else {
|
|
|
|
$url = Director::makeRelative($request->getVar('FileURL'));
|
2015-08-17 18:31:12 +02:00
|
|
|
$url = Image::strip_resampled_prefix($url);
|
2013-06-21 00:32:08 +02:00
|
|
|
$file = File::get()->filter('Filename', $url)->first();
|
2012-03-12 16:31:32 +01:00
|
|
|
if(!$file) $file = new File(array(
|
|
|
|
'Title' => basename($url),
|
|
|
|
'Filename' => $url
|
2013-06-21 00:32:08 +02:00
|
|
|
));
|
2012-02-09 17:17:39 +01:00
|
|
|
}
|
|
|
|
} elseif($id = $request->getVar('ID')) {
|
|
|
|
$file = DataObject::get_by_id('File', $id);
|
|
|
|
$url = $file->RelativeLink();
|
|
|
|
} else {
|
|
|
|
throw new LogicException('Need either "ID" or "FileURL" parameter to identify the file');
|
|
|
|
}
|
|
|
|
|
|
|
|
// Instanciate file wrapper and get fields based on its type
|
2012-09-26 23:34:00 +02:00
|
|
|
// Check if appCategory is an image and exists on the local system, otherwise use oEmbed to refference a
|
|
|
|
// remote image
|
2012-06-25 17:19:15 +02:00
|
|
|
if($file && $file->appCategory() == 'image' && Director::is_site_url($url)) {
|
2012-02-09 17:17:39 +01:00
|
|
|
$fileWrapper = new HtmlEditorField_Image($url, $file);
|
2012-05-22 06:45:36 +02:00
|
|
|
} elseif(!Director::is_site_url($url)) {
|
|
|
|
$fileWrapper = new HtmlEditorField_Embed($url, $file);
|
2012-02-09 17:17:39 +01:00
|
|
|
} else {
|
|
|
|
$fileWrapper = new HtmlEditorField_File($url, $file);
|
|
|
|
}
|
2012-03-12 16:31:32 +01:00
|
|
|
|
2012-02-09 17:17:39 +01:00
|
|
|
$fields = $this->getFieldsForFile($url, $fileWrapper);
|
|
|
|
$this->extend('updateFieldsForFile', $fields, $url, $fileWrapper);
|
|
|
|
|
|
|
|
return $fileWrapper->customise(array(
|
|
|
|
'Fields' => $fields,
|
|
|
|
))->renderWith($this->templateViewFile);
|
|
|
|
}
|
|
|
|
|
2014-07-30 00:59:13 +02:00
|
|
|
/**
|
|
|
|
* Find all anchors available on the given page.
|
|
|
|
*
|
|
|
|
* @return array
|
|
|
|
*/
|
|
|
|
public function getanchors() {
|
2015-04-30 01:04:08 +02:00
|
|
|
$id = (int)$this->getRequest()->getVar('PageID');
|
2014-07-30 00:59:13 +02:00
|
|
|
$anchors = array();
|
|
|
|
|
|
|
|
if (($page = Page::get()->byID($id)) && !empty($page)) {
|
|
|
|
if (!$page->canView()) {
|
|
|
|
throw new SS_HTTPResponse_Exception(
|
|
|
|
_t(
|
|
|
|
'HtmlEditorField.ANCHORSCANNOTACCESSPAGE',
|
|
|
|
'You are not permitted to access the content of the target page.'
|
|
|
|
),
|
|
|
|
403
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Similar to the regex found in HtmlEditorField.js / getAnchors method.
|
|
|
|
if (preg_match_all("/name=\"([^\"]+?)\"|name='([^']+?)'/im", $page->Content, $matches)) {
|
|
|
|
$anchors = $matches[1];
|
|
|
|
}
|
|
|
|
|
|
|
|
} else {
|
|
|
|
throw new SS_HTTPResponse_Exception(
|
|
|
|
_t('HtmlEditorField.ANCHORSPAGENOTFOUND', 'Target page not found.'),
|
|
|
|
404
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
return json_encode($anchors);
|
|
|
|
}
|
|
|
|
|
2012-02-09 17:17:39 +01:00
|
|
|
/**
|
|
|
|
* Similar to {@link File->getCMSFields()}, but only returns fields
|
|
|
|
* for manipulating the instance of the file as inserted into the HTML content,
|
|
|
|
* not the "master record" in the database - hence there's no form or saving logic.
|
2013-06-21 00:32:08 +02:00
|
|
|
*
|
2012-02-09 17:17:39 +01:00
|
|
|
* @param String Relative or absolute URL to file
|
|
|
|
* @return FieldList
|
|
|
|
*/
|
|
|
|
protected function getFieldsForFile($url, $file) {
|
|
|
|
$fields = $this->extend('getFieldsForFile', $url, $file);
|
|
|
|
if(!$fields) {
|
2012-05-22 06:45:36 +02:00
|
|
|
if($file instanceof HtmlEditorField_Embed) {
|
|
|
|
$fields = $this->getFieldsForOembed($url, $file);
|
|
|
|
} elseif($file->Extension == 'swf') {
|
2012-02-09 17:17:39 +01:00
|
|
|
$fields = $this->getFieldsForFlash($url, $file);
|
|
|
|
} else {
|
|
|
|
$fields = $this->getFieldsForImage($url, $file);
|
|
|
|
}
|
|
|
|
$fields->push(new HiddenField('URL', false, $url));
|
|
|
|
}
|
|
|
|
|
|
|
|
$this->extend('updateFieldsForFile', $fields, $url, $file);
|
2014-06-11 01:34:31 +02:00
|
|
|
|
2012-02-09 17:17:39 +01:00
|
|
|
return $fields;
|
|
|
|
}
|
|
|
|
|
2012-05-22 06:45:36 +02:00
|
|
|
/**
|
|
|
|
* @return FieldList
|
|
|
|
*/
|
|
|
|
protected function getFieldsForOembed($url, $file) {
|
|
|
|
if(isset($file->Oembed->thumbnail_url)) {
|
2014-06-11 01:34:31 +02:00
|
|
|
$thumbnailURL = Convert::raw2att($file->Oembed->thumbnail_url);
|
2012-05-22 06:45:36 +02:00
|
|
|
} elseif($file->Type == 'photo') {
|
2014-06-11 01:34:31 +02:00
|
|
|
$thumbnailURL = Convert::raw2att($file->Oembed->url);
|
2012-05-22 06:45:36 +02:00
|
|
|
} else {
|
2012-05-24 10:05:51 +02:00
|
|
|
$thumbnailURL = FRAMEWORK_DIR . '/images/default_media.png';
|
2012-05-22 06:45:36 +02:00
|
|
|
}
|
2014-06-11 01:34:31 +02:00
|
|
|
|
|
|
|
$fileName = Convert::raw2att($file->Name);
|
|
|
|
|
2012-05-22 06:45:36 +02:00
|
|
|
$fields = new FieldList(
|
|
|
|
$filePreview = CompositeField::create(
|
|
|
|
CompositeField::create(
|
2013-01-21 11:10:15 +01:00
|
|
|
new LiteralField(
|
|
|
|
"ImageFull",
|
|
|
|
"<img id='thumbnailImage' class='thumbnail-preview' "
|
2014-06-11 01:34:31 +02:00
|
|
|
. "src='{$thumbnailURL}?r=" . rand(1,100000) . "' alt='$fileName' />\n"
|
2013-01-21 11:10:15 +01:00
|
|
|
)
|
2012-05-22 06:45:36 +02:00
|
|
|
)->setName("FilePreviewImage")->addExtraClass('cms-file-info-preview'),
|
|
|
|
CompositeField::create(
|
|
|
|
CompositeField::create(
|
|
|
|
new ReadonlyField("FileType", _t('AssetTableField.TYPE','File type') . ':', $file->Type),
|
2014-06-11 01:34:31 +02:00
|
|
|
$urlField = ReadonlyField::create(
|
|
|
|
'ClickableURL',
|
|
|
|
_t('AssetTableField.URL','URL'),
|
|
|
|
sprintf(
|
|
|
|
'<a href="%s" target="_blank" class="file">%s</a>',
|
|
|
|
Convert::raw2att($url),
|
|
|
|
Convert::raw2att($url)
|
|
|
|
)
|
2013-01-21 11:10:15 +01:00
|
|
|
)->addExtraClass('text-wrap')
|
2012-05-22 06:45:36 +02:00
|
|
|
)
|
|
|
|
)->setName("FilePreviewData")->addExtraClass('cms-file-info-data')
|
|
|
|
)->setName("FilePreview")->addExtraClass('cms-file-info'),
|
|
|
|
new TextField('CaptionText', _t('HtmlEditorField.CAPTIONTEXT', 'Caption text')),
|
2013-01-21 11:10:15 +01:00
|
|
|
DropdownField::create(
|
2012-05-22 06:45:36 +02:00
|
|
|
'CSSClass',
|
|
|
|
_t('HtmlEditorField.CSSCLASS', 'Alignment / style'),
|
|
|
|
array(
|
|
|
|
'leftAlone' => _t('HtmlEditorField.CSSCLASSLEFTALONE', 'On the left, on its own.'),
|
|
|
|
'center' => _t('HtmlEditorField.CSSCLASSCENTER', 'Centered, on its own.'),
|
2013-06-24 22:25:16 +02:00
|
|
|
'left' => _t('HtmlEditorField.CSSCLASSLEFT', 'On the left, with text wrapping around.'),
|
|
|
|
'right' => _t('HtmlEditorField.CSSCLASSRIGHT', 'On the right, with text wrapping around.')
|
2012-05-22 06:45:36 +02:00
|
|
|
)
|
2013-01-21 11:10:15 +01:00
|
|
|
)->addExtraClass('last')
|
2012-05-22 06:45:36 +02:00
|
|
|
);
|
2014-06-11 01:34:31 +02:00
|
|
|
|
2013-01-21 11:10:15 +01:00
|
|
|
if($file->Width != null){
|
|
|
|
$fields->push(
|
|
|
|
FieldGroup::create(
|
|
|
|
_t('HtmlEditorField.IMAGEDIMENSIONS', 'Dimensions'),
|
|
|
|
TextField::create(
|
2014-06-11 01:34:31 +02:00
|
|
|
'Width',
|
|
|
|
_t('HtmlEditorField.IMAGEWIDTHPX', 'Width'),
|
2013-06-24 22:25:16 +02:00
|
|
|
$file->InsertWidth
|
2013-01-21 11:10:15 +01:00
|
|
|
)->setMaxLength(5),
|
|
|
|
TextField::create(
|
2014-06-11 01:34:31 +02:00
|
|
|
'Height',
|
|
|
|
_t('HtmlEditorField.IMAGEHEIGHTPX', 'Height'),
|
2013-06-24 22:25:16 +02:00
|
|
|
$file->InsertHeight
|
2013-01-21 11:10:15 +01:00
|
|
|
)->setMaxLength(5)
|
|
|
|
)->addExtraClass('dimensions last')
|
|
|
|
);
|
2012-06-08 06:42:14 +02:00
|
|
|
}
|
2013-01-21 11:10:15 +01:00
|
|
|
$urlField->dontEscape = true;
|
2012-05-22 06:45:36 +02:00
|
|
|
|
|
|
|
if($file->Type == 'photo') {
|
2014-01-07 17:02:43 +01:00
|
|
|
$fields->insertBefore('CaptionText', new TextField(
|
2014-06-11 01:34:31 +02:00
|
|
|
'AltText',
|
2013-06-21 00:32:08 +02:00
|
|
|
_t('HtmlEditorField.IMAGEALTTEXT', 'Alternative text (alt) - shown if image can\'t be displayed'),
|
2014-06-11 01:34:31 +02:00
|
|
|
$file->Title,
|
2012-05-22 06:45:36 +02:00
|
|
|
80
|
2014-01-07 17:02:43 +01:00
|
|
|
));
|
|
|
|
$fields->insertBefore('CaptionText', new TextField(
|
2014-06-11 01:34:31 +02:00
|
|
|
'Title',
|
2012-05-22 06:45:36 +02:00
|
|
|
_t('HtmlEditorField.IMAGETITLE', 'Title text (tooltip) - for additional information about the image')
|
2014-01-07 17:02:43 +01:00
|
|
|
));
|
2012-05-22 06:45:36 +02:00
|
|
|
}
|
|
|
|
|
2013-07-03 10:15:46 +02:00
|
|
|
$this->extend('updateFieldsForOembed', $fields, $url, $file);
|
2012-05-22 06:45:36 +02:00
|
|
|
|
|
|
|
return $fields;
|
|
|
|
}
|
|
|
|
|
2012-02-09 17:17:39 +01:00
|
|
|
/**
|
|
|
|
* @return FieldList
|
|
|
|
*/
|
|
|
|
protected function getFieldsForFlash($url, $file) {
|
|
|
|
$fields = new FieldList(
|
2013-01-21 11:10:15 +01:00
|
|
|
FieldGroup::create(
|
|
|
|
_t('HtmlEditorField.IMAGEDIMENSIONS', 'Dimensions'),
|
|
|
|
TextField::create(
|
2014-06-11 01:34:31 +02:00
|
|
|
'Width',
|
|
|
|
_t('HtmlEditorField.IMAGEWIDTHPX', 'Width'),
|
2013-01-21 11:10:15 +01:00
|
|
|
$file->Width
|
|
|
|
)->setMaxLength(5),
|
|
|
|
TextField::create(
|
2014-06-11 01:34:31 +02:00
|
|
|
'Height',
|
2013-01-21 11:10:15 +01:00
|
|
|
" x " . _t('HtmlEditorField.IMAGEHEIGHTPX', 'Height'),
|
|
|
|
$file->Height
|
|
|
|
)->setMaxLength(5)
|
|
|
|
)->addExtraClass('dimensions')
|
2012-02-09 17:17:39 +01:00
|
|
|
);
|
|
|
|
|
|
|
|
$this->extend('updateFieldsForFlash', $fields, $url, $file);
|
|
|
|
|
|
|
|
return $fields;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @return FieldList
|
|
|
|
*/
|
|
|
|
protected function getFieldsForImage($url, $file) {
|
2012-05-22 06:45:36 +02:00
|
|
|
if($file->File instanceof Image) {
|
2015-06-13 01:42:51 +02:00
|
|
|
$formattedImage = $file->File->generateFormattedImage('ScaleWidth',
|
2013-08-21 08:54:05 +02:00
|
|
|
Config::inst()->get('Image', 'asset_preview_width'));
|
2014-06-11 01:34:31 +02:00
|
|
|
$thumbnailURL = Convert::raw2att($formattedImage ? $formattedImage->URL : $url);
|
2012-03-12 16:31:32 +01:00
|
|
|
} else {
|
2014-06-11 01:34:31 +02:00
|
|
|
$thumbnailURL = Convert::raw2att($url);
|
2012-03-12 16:31:32 +01:00
|
|
|
}
|
2014-06-11 01:34:31 +02:00
|
|
|
|
|
|
|
$fileName = Convert::raw2att($file->Name);
|
|
|
|
|
2012-02-09 17:17:39 +01:00
|
|
|
$fields = new FieldList(
|
2013-01-21 11:10:15 +01:00
|
|
|
CompositeField::create(
|
2012-04-09 21:35:07 +02:00
|
|
|
CompositeField::create(
|
2013-01-21 11:10:15 +01:00
|
|
|
LiteralField::create(
|
|
|
|
"ImageFull",
|
2014-06-11 01:34:31 +02:00
|
|
|
"<img id='thumbnailImage' class='thumbnail-preview' "
|
|
|
|
. "src='{$thumbnailURL}?r=" . rand(1,100000) . "' alt='$fileName' />\n"
|
2013-01-21 11:10:15 +01:00
|
|
|
)
|
2012-02-28 18:07:55 +01:00
|
|
|
)->setName("FilePreviewImage")->addExtraClass('cms-file-info-preview'),
|
2012-04-09 21:35:07 +02:00
|
|
|
CompositeField::create(
|
|
|
|
CompositeField::create(
|
2013-06-15 09:59:03 +02:00
|
|
|
new ReadonlyField("FileType", _t('AssetTableField.TYPE','File type'), $file->FileType),
|
|
|
|
new ReadonlyField("Size", _t('AssetTableField.SIZE','File size'), $file->getSize()),
|
2014-06-11 01:34:31 +02:00
|
|
|
$urlField = new ReadonlyField(
|
|
|
|
'ClickableURL',
|
|
|
|
_t('AssetTableField.URL','URL'),
|
|
|
|
sprintf(
|
|
|
|
'<a href="%s" title="%s" target="_blank" class="file-url">%s</a>',
|
|
|
|
Convert::raw2att($file->Link()),
|
|
|
|
Convert::raw2att($file->Link()),
|
|
|
|
Convert::raw2att($file->RelativeLink())
|
|
|
|
)
|
2012-02-28 18:07:55 +01:00
|
|
|
),
|
2013-06-15 09:59:03 +02:00
|
|
|
new DateField_Disabled("Created", _t('AssetTableField.CREATED','First uploaded'),
|
2012-09-26 23:34:00 +02:00
|
|
|
$file->Created),
|
2013-06-15 09:59:03 +02:00
|
|
|
new DateField_Disabled("LastEdited", _t('AssetTableField.LASTEDIT','Last changed'),
|
2012-09-26 23:34:00 +02:00
|
|
|
$file->LastEdited)
|
2012-02-28 18:07:55 +01:00
|
|
|
)
|
|
|
|
)->setName("FilePreviewData")->addExtraClass('cms-file-info-data')
|
2014-06-11 01:34:31 +02:00
|
|
|
)->setName("FilePreview")->addExtraClass('cms-file-info'),
|
2012-09-26 23:34:00 +02:00
|
|
|
|
2012-06-13 13:12:59 +02:00
|
|
|
TextField::create(
|
2014-06-11 01:34:31 +02:00
|
|
|
'AltText',
|
|
|
|
_t('HtmlEditorField.IMAGEALT', 'Alternative text (alt)'),
|
|
|
|
$file->Title,
|
2012-06-13 13:12:59 +02:00
|
|
|
80
|
2012-09-26 23:34:00 +02:00
|
|
|
)->setDescription(
|
2013-08-22 16:07:27 +02:00
|
|
|
_t('HtmlEditorField.IMAGEALTTEXTDESC', 'Shown to screen readers or if image can\'t be displayed')),
|
2012-09-26 23:34:00 +02:00
|
|
|
|
2012-06-13 13:12:59 +02:00
|
|
|
TextField::create(
|
2014-06-11 01:34:31 +02:00
|
|
|
'Title',
|
2012-06-13 13:12:59 +02:00
|
|
|
_t('HtmlEditorField.IMAGETITLETEXT', 'Title text (tooltip)')
|
2012-09-26 23:34:00 +02:00
|
|
|
)->setDescription(
|
|
|
|
_t('HtmlEditorField.IMAGETITLETEXTDESC', 'For additional information about the image')),
|
|
|
|
|
2012-02-09 17:17:39 +01:00
|
|
|
new TextField('CaptionText', _t('HtmlEditorField.CAPTIONTEXT', 'Caption text')),
|
2013-01-21 11:10:15 +01:00
|
|
|
DropdownField::create(
|
2012-02-09 17:17:39 +01:00
|
|
|
'CSSClass',
|
|
|
|
_t('HtmlEditorField.CSSCLASS', 'Alignment / style'),
|
|
|
|
array(
|
|
|
|
'leftAlone' => _t('HtmlEditorField.CSSCLASSLEFTALONE', 'On the left, on its own.'),
|
|
|
|
'center' => _t('HtmlEditorField.CSSCLASSCENTER', 'Centered, on its own.'),
|
2013-06-24 22:25:16 +02:00
|
|
|
'left' => _t('HtmlEditorField.CSSCLASSLEFT', 'On the left, with text wrapping around.'),
|
|
|
|
'right' => _t('HtmlEditorField.CSSCLASSRIGHT', 'On the right, with text wrapping around.')
|
2012-02-09 17:17:39 +01:00
|
|
|
)
|
2013-01-21 11:10:15 +01:00
|
|
|
)->addExtraClass('last')
|
2012-02-09 17:17:39 +01:00
|
|
|
);
|
2014-06-11 01:34:31 +02:00
|
|
|
|
2013-01-21 11:10:15 +01:00
|
|
|
if($file->Width != null){
|
|
|
|
$fields->push(
|
|
|
|
FieldGroup::create(_t('HtmlEditorField.IMAGEDIMENSIONS', 'Dimensions'),
|
|
|
|
TextField::create(
|
2014-06-11 01:34:31 +02:00
|
|
|
'Width',
|
|
|
|
_t('HtmlEditorField.IMAGEWIDTHPX', 'Width'),
|
2013-06-24 22:25:16 +02:00
|
|
|
$file->InsertWidth
|
2013-01-21 11:10:15 +01:00
|
|
|
)->setMaxLength(5),
|
|
|
|
TextField::create(
|
2014-06-11 01:34:31 +02:00
|
|
|
'Height',
|
2013-01-21 11:10:15 +01:00
|
|
|
" x " . _t('HtmlEditorField.IMAGEHEIGHTPX', 'Height'),
|
2013-06-24 22:25:16 +02:00
|
|
|
$file->InsertHeight
|
2013-01-21 11:10:15 +01:00
|
|
|
)->setMaxLength(5)
|
|
|
|
)->addExtraClass('dimensions last')
|
|
|
|
);
|
2012-06-08 06:42:14 +02:00
|
|
|
}
|
2013-01-21 11:10:15 +01:00
|
|
|
$urlField->dontEscape = true;
|
2012-02-09 17:17:39 +01:00
|
|
|
|
|
|
|
$this->extend('updateFieldsForImage', $fields, $url, $file);
|
|
|
|
|
|
|
|
return $fields;
|
2012-02-08 21:32:25 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @param Int
|
|
|
|
* @return DataList
|
|
|
|
*/
|
|
|
|
protected function getFiles($parentID = null) {
|
2012-02-09 17:17:39 +01:00
|
|
|
$exts = $this->getAllowedExtensions();
|
2013-06-21 00:32:08 +02:00
|
|
|
$dotExts = array_map(function($ext) { return ".{$ext}"; }, $exts);
|
|
|
|
$files = File::get()->filter('Filename:EndsWith', $dotExts);
|
2012-02-08 21:32:25 +01:00
|
|
|
|
|
|
|
// Limit by folder (if required)
|
2012-06-15 05:49:22 +02:00
|
|
|
if($parentID) {
|
|
|
|
$files = $files->filter('ParentID', $parentID);
|
|
|
|
}
|
|
|
|
|
2012-02-08 21:32:25 +01:00
|
|
|
return $files;
|
2007-07-19 12:40:28 +02:00
|
|
|
}
|
2012-02-09 17:17:39 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @return Array All extensions which can be handled by the different views.
|
|
|
|
*/
|
|
|
|
protected function getAllowedExtensions() {
|
2012-08-17 18:17:26 +02:00
|
|
|
$exts = array('jpg', 'gif', 'png', 'swf','jpeg');
|
2012-02-09 17:17:39 +01:00
|
|
|
$this->extend('updateAllowedExtensions', $exts);
|
|
|
|
return $exts;
|
|
|
|
}
|
2012-04-12 22:28:00 +02:00
|
|
|
|
2012-02-09 17:17:39 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Encapsulation of a file which can either be a remote URL
|
|
|
|
* or a {@link File} on the local filesystem, exhibiting common properties
|
|
|
|
* such as file name or the URL.
|
|
|
|
*
|
|
|
|
* @todo Remove once core has support for remote files
|
2013-11-29 05:12:47 +01:00
|
|
|
* @package forms
|
|
|
|
* @subpackage fields-formattedinput
|
2012-02-09 17:17:39 +01:00
|
|
|
*/
|
|
|
|
class HtmlEditorField_File extends ViewableData {
|
|
|
|
|
2014-06-11 01:34:31 +02:00
|
|
|
private static $casting = array(
|
|
|
|
'URL' => 'Varchar',
|
|
|
|
'Name' => 'Varchar'
|
|
|
|
);
|
|
|
|
|
2012-02-09 17:17:39 +01:00
|
|
|
/** @var String */
|
|
|
|
protected $url;
|
|
|
|
|
|
|
|
/** @var File */
|
|
|
|
protected $file;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @param String
|
2013-06-21 00:32:08 +02:00
|
|
|
* @param File
|
2012-02-09 17:17:39 +01:00
|
|
|
*/
|
2012-09-19 12:07:39 +02:00
|
|
|
public function __construct($url, $file = null) {
|
2012-02-09 17:17:39 +01:00
|
|
|
$this->url = $url;
|
|
|
|
$this->file = $file;
|
2012-02-28 18:07:55 +01:00
|
|
|
$this->failover = $file;
|
2012-02-09 17:17:39 +01:00
|
|
|
|
|
|
|
parent::__construct();
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @return File Might not be set (for remote files)
|
|
|
|
*/
|
2012-09-19 12:07:39 +02:00
|
|
|
public function getFile() {
|
2012-02-09 17:17:39 +01:00
|
|
|
return $this->file;
|
|
|
|
}
|
|
|
|
|
2012-09-19 12:07:39 +02:00
|
|
|
public function getURL() {
|
2012-02-09 17:17:39 +01:00
|
|
|
return $this->url;
|
|
|
|
}
|
|
|
|
|
2012-09-19 12:07:39 +02:00
|
|
|
public function getName() {
|
2012-02-09 17:17:39 +01:00
|
|
|
return ($this->file) ? $this->file->Name : preg_replace('/\?.*/', '', basename($this->url));
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @return String HTML
|
|
|
|
*/
|
2012-09-19 12:07:39 +02:00
|
|
|
public function getPreview() {
|
2012-02-09 17:17:39 +01:00
|
|
|
$preview = $this->extend('getPreview');
|
|
|
|
if($preview) return $preview;
|
|
|
|
|
|
|
|
if($this->file) {
|
|
|
|
return $this->file->CMSThumbnail();
|
|
|
|
} else {
|
|
|
|
// Hack to use the framework's built-in thumbnail support without creating a local file representation
|
|
|
|
$tmpFile = new File(array('Name' => $this->Name, 'Filename' => $this->Name));
|
|
|
|
return $tmpFile->CMSThumbnail();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-09-19 12:07:39 +02:00
|
|
|
public function getExtension() {
|
2012-02-09 17:17:39 +01:00
|
|
|
return strtolower(($this->file) ? $this->file->Extension : pathinfo($this->Name, PATHINFO_EXTENSION));
|
|
|
|
}
|
|
|
|
|
2012-09-19 12:07:39 +02:00
|
|
|
public function appCategory() {
|
2012-02-09 17:17:39 +01:00
|
|
|
if($this->file) {
|
|
|
|
return $this->file->appCategory();
|
|
|
|
} else {
|
|
|
|
// Hack to use the framework's built-in thumbnail support without creating a local file representation
|
|
|
|
$tmpFile = new File(array('Name' => $this->Name, 'Filename' => $this->Name));
|
2014-06-11 01:34:31 +02:00
|
|
|
return $tmpFile->appCategory();
|
2012-02-09 17:17:39 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2013-11-29 05:12:47 +01:00
|
|
|
/**
|
|
|
|
* Encapsulation of an oembed tag, linking to an external media source.
|
|
|
|
*
|
|
|
|
* @see Oembed
|
|
|
|
* @package forms
|
|
|
|
* @subpackage fields-formattedinput
|
|
|
|
*/
|
2012-05-22 06:45:36 +02:00
|
|
|
class HtmlEditorField_Embed extends HtmlEditorField_File {
|
2014-06-11 01:34:31 +02:00
|
|
|
|
|
|
|
private static $casting = array(
|
|
|
|
'Type' => 'Varchar',
|
|
|
|
'Info' => 'Varchar'
|
|
|
|
);
|
|
|
|
|
2012-05-22 06:45:36 +02:00
|
|
|
protected $oembed;
|
|
|
|
|
|
|
|
public function __construct($url, $file = null) {
|
|
|
|
parent::__construct($url, $file);
|
|
|
|
$this->oembed = Oembed::get_oembed_from_url($url);
|
|
|
|
if(!$this->oembed) {
|
2012-05-24 04:28:47 +02:00
|
|
|
$controller = Controller::curr();
|
2015-08-14 02:39:33 +02:00
|
|
|
$response = $controller->getResponse();
|
|
|
|
$response->addHeader('X-Status',
|
2012-05-24 04:28:47 +02:00
|
|
|
rawurlencode(_t(
|
|
|
|
'HtmlEditorField.URLNOTANOEMBEDRESOURCE',
|
|
|
|
"The URL '{url}' could not be turned into a media resource.",
|
2012-09-26 23:34:00 +02:00
|
|
|
"The given URL is not a valid Oembed resource; the embed element couldn't be created.",
|
2012-05-24 04:28:47 +02:00
|
|
|
array('url' => $url)
|
|
|
|
)));
|
2015-08-14 02:39:33 +02:00
|
|
|
$response->setStatusCode(404);
|
2012-05-24 04:28:47 +02:00
|
|
|
|
2015-08-14 02:39:33 +02:00
|
|
|
throw new SS_HTTPResponse_Exception($response);
|
2012-05-22 06:45:36 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public function getWidth() {
|
2012-05-24 08:16:00 +02:00
|
|
|
return $this->oembed->Width ?: 100;
|
2012-05-22 06:45:36 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
public function getHeight() {
|
2012-05-24 08:16:00 +02:00
|
|
|
return $this->oembed->Height ?: 100;
|
2012-05-22 06:45:36 +02:00
|
|
|
}
|
|
|
|
|
2013-06-24 22:25:16 +02:00
|
|
|
/**
|
|
|
|
* Provide an initial width for inserted media, restricted based on $embed_width
|
2014-06-11 01:34:31 +02:00
|
|
|
*
|
2013-06-24 22:25:16 +02:00
|
|
|
* @return int
|
|
|
|
*/
|
|
|
|
public function getInsertWidth() {
|
|
|
|
$width = $this->getWidth();
|
|
|
|
$maxWidth = Config::inst()->get('HtmlEditorField', 'insert_width');
|
|
|
|
return ($width <= $maxWidth) ? $width : $maxWidth;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Provide an initial height for inserted media, scaled proportionally to the initial width
|
2014-06-11 01:34:31 +02:00
|
|
|
*
|
2013-06-24 22:25:16 +02:00
|
|
|
* @return int
|
|
|
|
*/
|
|
|
|
public function getInsertHeight() {
|
|
|
|
$width = $this->getWidth();
|
|
|
|
$height = $this->getHeight();
|
|
|
|
$maxWidth = Config::inst()->get('HtmlEditorField', 'insert_width');
|
|
|
|
return ($width <= $maxWidth) ? $height : round($height*($maxWidth/$width));
|
|
|
|
}
|
|
|
|
|
2012-05-22 06:45:36 +02:00
|
|
|
public function getPreview() {
|
|
|
|
if(isset($this->oembed->thumbnail_url)) {
|
2014-06-11 01:34:31 +02:00
|
|
|
return sprintf('<img src="%s" />', Convert::raw2att($this->oembed->thumbnail_url));
|
2012-05-22 06:45:36 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public function getName() {
|
|
|
|
if(isset($this->oembed->title)) {
|
|
|
|
return $this->oembed->title;
|
|
|
|
} else {
|
|
|
|
return parent::getName();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public function getType() {
|
|
|
|
return $this->oembed->type;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function getOembed() {
|
|
|
|
return $this->oembed;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function appCategory() {
|
|
|
|
return 'embed';
|
|
|
|
}
|
2013-06-21 00:32:08 +02:00
|
|
|
|
2012-06-25 17:23:26 +02:00
|
|
|
public function getInfo() {
|
|
|
|
return $this->oembed->info;
|
|
|
|
}
|
2012-05-22 06:45:36 +02:00
|
|
|
}
|
|
|
|
|
2013-11-29 05:12:47 +01:00
|
|
|
/**
|
|
|
|
* Encapsulation of an image tag, linking to an image either internal or external to the site.
|
|
|
|
*
|
|
|
|
* @package forms
|
|
|
|
* @subpackage fields-formattedinput
|
|
|
|
*/
|
2012-02-09 17:17:39 +01:00
|
|
|
class HtmlEditorField_Image extends HtmlEditorField_File {
|
|
|
|
|
|
|
|
protected $width;
|
|
|
|
|
|
|
|
protected $height;
|
|
|
|
|
2012-09-19 12:07:39 +02:00
|
|
|
public function __construct($url, $file = null) {
|
2012-02-09 17:17:39 +01:00
|
|
|
parent::__construct($url, $file);
|
|
|
|
|
|
|
|
// Get dimensions for remote file
|
|
|
|
$info = @getimagesize($url);
|
|
|
|
if($info) {
|
|
|
|
$this->width = $info[0];
|
|
|
|
$this->height = $info[1];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-09-19 12:07:39 +02:00
|
|
|
public function getWidth() {
|
2012-02-09 17:17:39 +01:00
|
|
|
return ($this->file) ? $this->file->Width : $this->width;
|
|
|
|
}
|
|
|
|
|
2012-09-19 12:07:39 +02:00
|
|
|
public function getHeight() {
|
2012-02-09 17:17:39 +01:00
|
|
|
return ($this->file) ? $this->file->Height : $this->height;
|
|
|
|
}
|
|
|
|
|
2013-06-24 22:25:16 +02:00
|
|
|
/**
|
|
|
|
* Provide an initial width for inserted image, restricted based on $embed_width
|
2013-06-21 00:32:08 +02:00
|
|
|
*
|
2013-06-24 22:25:16 +02:00
|
|
|
* @return int
|
|
|
|
*/
|
|
|
|
public function getInsertWidth() {
|
|
|
|
$width = $this->getWidth();
|
|
|
|
$maxWidth = Config::inst()->get('HtmlEditorField', 'insert_width');
|
|
|
|
return ($width <= $maxWidth) ? $width : $maxWidth;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Provide an initial height for inserted image, scaled proportionally to the initial width
|
2013-06-21 00:32:08 +02:00
|
|
|
*
|
2013-06-24 22:25:16 +02:00
|
|
|
* @return int
|
|
|
|
*/
|
|
|
|
public function getInsertHeight() {
|
|
|
|
$width = $this->getWidth();
|
|
|
|
$height = $this->getHeight();
|
|
|
|
$maxWidth = Config::inst()->get('HtmlEditorField', 'insert_width');
|
|
|
|
return ($width <= $maxWidth) ? $height : round($height*($maxWidth/$width));
|
|
|
|
}
|
|
|
|
|
2012-09-19 12:07:39 +02:00
|
|
|
public function getPreview() {
|
2014-06-11 01:34:31 +02:00
|
|
|
return ($this->file) ? $this->file->CMSThumbnail() : sprintf('<img src="%s" />', Convert::raw2att($this->url));
|
2012-02-09 17:17:39 +01:00
|
|
|
}
|
|
|
|
|
2012-03-01 09:13:42 +01:00
|
|
|
}
|