From e7d87add9f6cafb8fdfd49310a0106ce94356762 Mon Sep 17 00:00:00 2001 From: Damian Mooyman Date: Thu, 25 May 2017 13:43:13 +1200 Subject: [PATCH] API Remove legacy HTMLEditor classes --- .upgrade.yml | 2 +- .../Field_types/03_HTMLEditorField.md | 12 +- docs/en/04_Changelogs/4.0.0.md | 8 + .../HTMLEditor/HTMLEditorField_Embed.php | 167 ------ src/Forms/HTMLEditor/HTMLEditorField_File.php | 402 -------------- .../HTMLEditor/HTMLEditorField_Flash.php | 17 - .../HTMLEditor/HTMLEditorField_Image.php | 213 -------- .../HTMLEditor/HTMLEditorField_Toolbar.php | 495 ------------------ src/Forms/Schema/FormSchema.php | 3 + .../Forms/HTMLEditor/HTMLEditorFieldTest.php | 108 +--- .../DummyMediaFormFieldExtension.php | 22 - .../HTMLEditor/HTMLEditorFieldToolbarTest.php | 92 ---- .../HTMLEditor/HTMLEditorFieldToolbarTest.yml | 18 - .../HTMLEditorFieldToolbarTest/Toolbar.php | 18 - 14 files changed, 25 insertions(+), 1552 deletions(-) delete mode 100644 src/Forms/HTMLEditor/HTMLEditorField_Embed.php delete mode 100644 src/Forms/HTMLEditor/HTMLEditorField_File.php delete mode 100644 src/Forms/HTMLEditor/HTMLEditorField_Flash.php delete mode 100644 src/Forms/HTMLEditor/HTMLEditorField_Image.php delete mode 100644 src/Forms/HTMLEditor/HTMLEditorField_Toolbar.php delete mode 100644 tests/php/Forms/HTMLEditor/HTMLEditorFieldTest/DummyMediaFormFieldExtension.php delete mode 100644 tests/php/Forms/HTMLEditor/HTMLEditorFieldToolbarTest.php delete mode 100644 tests/php/Forms/HTMLEditor/HTMLEditorFieldToolbarTest.yml delete mode 100644 tests/php/Forms/HTMLEditor/HTMLEditorFieldToolbarTest/Toolbar.php diff --git a/.upgrade.yml b/.upgrade.yml index c793add3c..74caf9ebc 100644 --- a/.upgrade.yml +++ b/.upgrade.yml @@ -352,7 +352,7 @@ mappings: HTMLEditorConfig: SilverStripe\Forms\HTMLEditor\HTMLEditorConfig HTMLEditorField: SilverStripe\Forms\HTMLEditor\HTMLEditorField HTMLEditorField_Readonly: SilverStripe\Forms\HTMLEditor\HTMLEditorField_Readonly - HTMLEditorField_Toolbar: SilverStripe\Forms\HTMLEditor\HTMLEditorField_Toolbar + HTMLEditorField_Toolbar: SilverStripe\Admin\ModalController\HTMLEditorField_Toolbar HTMLEditorField_Embed: SilverStripe\Forms\HTMLEditor\HTMLEditorField_Embed HTMLEditorField_File: SilverStripe\Forms\HTMLEditor\HTMLEditorField_File HTMLEditorField_Flash: SilverStripe\Forms\HTMLEditor\HTMLEditorField_Flash diff --git a/docs/en/02_Developer_Guides/03_Forms/Field_types/03_HTMLEditorField.md b/docs/en/02_Developer_Guides/03_Forms/Field_types/03_HTMLEditorField.md index fa8bc7471..ace321085 100644 --- a/docs/en/02_Developer_Guides/03_Forms/Field_types/03_HTMLEditorField.md +++ b/docs/en/02_Developer_Guides/03_Forms/Field_types/03_HTMLEditorField.md @@ -261,19 +261,11 @@ of the CMS you have to take care of instantiate yourself: :::php // File: mysite/code/MyController.php class MyObjectController extends Controller { - public function EditorToolbar() { - return HtmlEditorField_Toolbar::create($this, "EditorToolbar"); + public function Modals() { + return ModalController::create($this, "Modals"); } } - :::ss - // File: mysite/templates/MyController.ss - $Form - <% with $EditorToolbar %> - $MediaForm - $LinkForm - <% end_with %> - Note: The dialogs rely on CMS-access, e.g. for uploading and browsing files, so this is considered advanced usage of the field. diff --git a/docs/en/04_Changelogs/4.0.0.md b/docs/en/04_Changelogs/4.0.0.md index 4ba1342f5..8d07b6fb3 100644 --- a/docs/en/04_Changelogs/4.0.0.md +++ b/docs/en/04_Changelogs/4.0.0.md @@ -1309,6 +1309,8 @@ After (`mysite/_config/config.yml`): * `getsubtree()` -> moved to `CMSMain` * `updatetreenodes()` -> moved to `CMSMain` * `savetreenodes()` -> moved to `CMSMain` + * `EditorToolbar()` method renamed to `Modals()` and now returns a `ModalController` handler + instance rather than a `HTMLEditorField_Toolbar` * Some `Director` API have been removed. * $dev_servers * $test_servers @@ -1857,6 +1859,12 @@ New `TimeField` methods replace `getConfig()` / `setConfig()` * `setOption` * Removed `MemberDatetimeOptionsetField` (no replacement) * Removed `DateField_View_JQuery` (replaced with native HTML5 support in `DateField`) +* The following HTMLEditorField_* classes have been removed: + * `HTMLEditorField_Toolbar` (replaced With `ModalController` in admin module) + * `HTMLEditorField_Embed` (replaced with `EmbedResource` in asset-admin module) + * `HTMLEditorField_File` + * `HTMLEditorField_Flash` + * `HTMLEditorField_Image` ### i18n API diff --git a/src/Forms/HTMLEditor/HTMLEditorField_Embed.php b/src/Forms/HTMLEditor/HTMLEditorField_Embed.php deleted file mode 100644 index 40489c8fe..000000000 --- a/src/Forms/HTMLEditor/HTMLEditorField_Embed.php +++ /dev/null @@ -1,167 +0,0 @@ - 'Varchar', - 'Info' => 'Varchar' - ); - - /** - * Embed result - * - * @var Adapter - */ - protected $embed; - - public function __construct($url, File $file = null) - { - parent::__construct($url, $file); - $this->embed = Embed::create($url); - if (!$this->embed) { - $controller = Controller::curr(); - $response = $controller->getResponse(); - $response->addHeader( - 'X-Status', - rawurlencode(_t( - 'SilverStripe\\Forms\\HTMLEditor\\HTMLEditorField.URLNOTANOEMBEDRESOURCE', - "The URL '{url}' could not be turned into a media resource.", - "The given URL is not a valid Oembed resource; the embed element couldn't be created.", - array('url' => $url) - )) - ); - $response->setStatusCode(404); - - throw new HTTPResponse_Exception($response); - } - } - - /** - * Get file-edit fields for this filed - * - * @return FieldList - */ - public function getFields() - { - $fields = parent::getFields(); - if ($this->getType() === 'photo') { - $fields->insertBefore('CaptionText', new TextField( - 'AltText', - _t('SilverStripe\\Forms\\HTMLEditor\\HTMLEditorField.IMAGEALTTEXT', 'Alternative text (alt) - shown if image can\'t be displayed'), - $this->Title, - 80 - )); - $fields->insertBefore('CaptionText', new TextField( - 'Title', - _t('SilverStripe\\Forms\\HTMLEditor\\HTMLEditorField.IMAGETITLE', 'Title text (tooltip) - for additional information about the image') - )); - } - return $fields; - } - - /** - * Get width of this Embed - * - * @return int - */ - public function getWidth() - { - return $this->embed->getWidth() ?: 100; - } - - /** - * Get height of this Embed - * - * @return int - */ - public function getHeight() - { - return $this->embed->getHeight() ?: 100; - } - - public function getPreviewURL() - { - // Use thumbnail url - if ($this->embed->image) { - return $this->embed->image; - } - - // Use direct image type - if ($this->getType() == 'photo' && !empty($this->embed->url)) { - return $this->embed->url; - } - - // Default media - return FRAMEWORK_ADMIN_DIR . '/client/dist/images/src/default_media.png'; - } - - public function getName() - { - if ($this->embed->title) { - return $this->embed->title; - } else { - return parent::getName(); - } - } - - /** - * Get Embed type - * - * @return string - */ - public function getType() - { - return $this->embed->type; - } - - /** - * Get filetype - * - * @return string - */ - public function getFileType() - { - return $this->getType() - ?: parent::getFileType(); - } - - /** - * @return AdapterInterface - */ - public function getEmbed() - { - return $this->embed; - } - - public function appCategory() - { - return 'embed'; - } - - /** - * Info for this Embed - * - * @return string - */ - public function getInfo() - { - return $this->embed->info; - } -} diff --git a/src/Forms/HTMLEditor/HTMLEditorField_File.php b/src/Forms/HTMLEditor/HTMLEditorField_File.php deleted file mode 100644 index 3dd3bd215..000000000 --- a/src/Forms/HTMLEditor/HTMLEditorField_File.php +++ /dev/null @@ -1,402 +0,0 @@ - 'Varchar', - 'Name' => 'Varchar' - ); - - /** - * Absolute URL to asset - * - * @var string - */ - protected $url; - - /** - * File dataobject (if available) - * - * @var File - */ - protected $file; - - /** - * @param string $url - * @param File $file - */ - public function __construct($url, File $file = null) - { - $this->url = $url; - $this->file = $file; - $this->failover = $file; - parent::__construct(); - } - - /** - * @return FieldList - */ - public function getFields() - { - $fields = new FieldList( - CompositeField::create( - CompositeField::create(LiteralField::create("ImageFull", $this->getPreview())) - ->setName("FilePreviewImage") - ->addExtraClass('cms-file-info-preview'), - CompositeField::create($this->getDetailFields()) - ->setName("FilePreviewData") - ->addExtraClass('cms-file-info-data') - ) - ->setName("FilePreview") - ->addExtraClass('cms-file-info'), - TextField::create('CaptionText', _t('SilverStripe\\Forms\\HTMLEditor\\HTMLEditorField.CAPTIONTEXT', 'Caption text')), - DropdownField::create( - 'CSSClass', - _t('SilverStripe\\Forms\\HTMLEditor\\HTMLEditorField.CSSCLASS', 'Alignment / style'), - array( - 'leftAlone' => _t('SilverStripe\\Forms\\HTMLEditor\\HTMLEditorField.CSSCLASSLEFTALONE', 'On the left, on its own.'), - 'center' => _t('SilverStripe\\Forms\\HTMLEditor\\HTMLEditorField.CSSCLASSCENTER', 'Centered, on its own.'), - 'left' => _t('SilverStripe\\Forms\\HTMLEditor\\HTMLEditorField.CSSCLASSLEFT', 'On the left, with text wrapping around.'), - 'right' => _t('SilverStripe\\Forms\\HTMLEditor\\HTMLEditorField.CSSCLASSRIGHT', 'On the right, with text wrapping around.') - ), - HtmlEditorField::config()->uninherited('media_alignment') - ), - FieldGroup::create( - _t('SilverStripe\\Forms\\HTMLEditor\\HTMLEditorField.IMAGEDIMENSIONS', 'Dimensions'), - TextField::create( - 'Width', - _t('SilverStripe\\Forms\\HTMLEditor\\HTMLEditorField.IMAGEWIDTHPX', 'Width'), - $this->getInsertWidth() - )->setMaxLength(5), - TextField::create( - 'Height', - " x " . _t('SilverStripe\\Forms\\HTMLEditor\\HTMLEditorField.IMAGEHEIGHTPX', 'Height'), - $this->getInsertHeight() - )->setMaxLength(5) - )->addExtraClass('dimensions last'), - HiddenField::create('URL', false, $this->getURL()), - HiddenField::create('FileID', false, $this->getFileID()) - ); - return $fields; - } - - /** - * Get list of fields for previewing this records details - * - * @return FieldList - */ - protected function getDetailFields() - { - $fields = new FieldList( - ReadonlyField::create("FileType", _t(__CLASS__.'.TYPE', 'File type'), $this->getFileType()), - HTMLReadonlyField::create( - 'ClickableURL', - _t(__CLASS__.'.URL', 'URL'), - $this->getExternalLink() - ) - ); - // Get file size - if ($this->getSize()) { - $fields->insertAfter( - 'FileType', - ReadonlyField::create("Size", _t(__CLASS__.'.SIZE', 'File size'), $this->getSize()) - ); - } - // Get modified details of local record - if ($this->getFile()) { - $fields->push(new DateField_Disabled( - "Created", - _t(__CLASS__.'.CREATED', 'First uploaded'), - $this->getFile()->Created - )); - $fields->push(new DateField_Disabled( - "LastEdited", - _t(__CLASS__.'.LASTEDIT', 'Last changed'), - $this->getFile()->LastEdited - )); - } - return $fields; - } - - /** - * Get file DataObject - * - * Might not be set (for remote files) - * - * @return File - */ - public function getFile() - { - return $this->file; - } - - /** - * Get file ID - * - * @return int - */ - public function getFileID() - { - if ($file = $this->getFile()) { - return $file->ID; - } - return null; - } - - /** - * Get absolute URL - * - * @return string - */ - public function getURL() - { - return $this->url; - } - - /** - * Get basename - * - * @return string - */ - public function getName() - { - return $this->file - ? $this->file->Name - : preg_replace('/\?.*/', '', basename($this->url)); - } - - /** - * Get descriptive file type - * - * @return string - */ - public function getFileType() - { - return File::get_file_type($this->getName()); - } - - /** - * Get file size (if known) as string - * - * @return string|false String value, or false if doesn't exist - */ - public function getSize() - { - if ($this->file) { - return $this->file->getSize(); - } - return false; - } - - /** - * HTML content for preview - * - * @return string HTML - */ - public function getPreview() - { - $preview = $this->extend('getPreview'); - if ($preview) { - return $preview; - } - - // Generate tag from preview - $thumbnailURL = Convert::raw2att( - Controller::join_links($this->getPreviewURL(), "?r=" . rand(1, 100000)) - ); - $fileName = Convert::raw2att($this->Name); - return sprintf( - "%s\n", - $thumbnailURL, - $fileName - ); - } - - /** - * HTML Content for external link - * - * @return string - */ - public function getExternalLink() - { - $title = $this->file - ? $this->file->getTitle() - : $this->getName(); - return sprintf( - '%1$s', - Convert::raw2att($this->url), - Convert::raw2att($title) - ); - } - - /** - * Generate thumbnail url - * - * @return string - */ - public function getPreviewURL() - { - // Get preview from file - if ($this->file) { - return $this->getFilePreviewURL(); - } - - // Generate default icon html - return File::get_icon_for_extension($this->getExtension()); - } - - /** - * Generate thumbnail URL from file dataobject (if available) - * - * @return string - */ - protected function getFilePreviewURL() - { - // Get preview from file - if ($this->file) { - $width = HTMLEditorField_File::config()->media_preview_width; - $height = HTMLEditorField_File::config()->media_preview_height; - return $this->file->ThumbnailURL($width, $height); - } - return null; - } - - /** - * Get file extension - * - * @return string - */ - public function getExtension() - { - $extension = File::get_file_extension($this->getName()); - return strtolower($extension); - } - - /** - * Category name - * - * @return string - */ - public function appCategory() - { - if ($this->file) { - return $this->file->appCategory(); - } else { - return File::get_app_category($this->getExtension()); - } - } - - /** - * Get height of this item - */ - public function getHeight() - { - if ($this->file) { - $height = $this->file->getHeight(); - if ($height) { - return $height; - } - } - return HTMLEditorField_File::config()->insert_height; - } - - /** - * Get width of this item - * - * @return int - */ - public function getWidth() - { - if ($this->file) { - $width = $this->file->getWidth(); - if ($width) { - return $width; - } - } - return HTMLEditorField_File::config()->insert_width; - } - - /** - * Provide an initial width for inserted media, restricted based on $embed_width - * - * @return int - */ - public function getInsertWidth() - { - $width = $this->getWidth(); - $maxWidth = HTMLEditorField_File::config()->insert_width; - return ($width <= $maxWidth) ? $width : $maxWidth; - } - - /** - * Provide an initial height for inserted media, scaled proportionally to the initial width - * - * @return int - */ - public function getInsertHeight() - { - $width = $this->getWidth(); - $height = $this->getHeight(); - $maxWidth = HTMLEditorField_File::config()->insert_width; - return ($width <= $maxWidth) ? $height : round($height * ($maxWidth / $width)); - } -} diff --git a/src/Forms/HTMLEditor/HTMLEditorField_Flash.php b/src/Forms/HTMLEditor/HTMLEditorField_Flash.php deleted file mode 100644 index c39b64970..000000000 --- a/src/Forms/HTMLEditor/HTMLEditorField_Flash.php +++ /dev/null @@ -1,17 +0,0 @@ -removeByName('CaptionText', true); - return $fields; - } -} diff --git a/src/Forms/HTMLEditor/HTMLEditorField_Image.php b/src/Forms/HTMLEditor/HTMLEditorField_Image.php deleted file mode 100644 index d53cd315b..000000000 --- a/src/Forms/HTMLEditor/HTMLEditorField_Image.php +++ /dev/null @@ -1,213 +0,0 @@ -size = $size; - } - - // Get dimensions of remote file - $info = @getimagesize($url); - if ($info) { - $this->width = $info[0]; - $this->height = $info[1]; - } - } - - public function getFields() - { - $fields = parent::getFields(); - - // Alt text - $fields->insertBefore( - 'CaptionText', - TextField::create( - 'AltText', - _t('SilverStripe\\Forms\\HTMLEditor\\HTMLEditorField.IMAGEALT', 'Alternative text (alt)'), - $this->Title, - 80 - )->setDescription( - _t('SilverStripe\\Forms\\HTMLEditor\\HTMLEditorField.IMAGEALTTEXTDESC', 'Shown to screen readers or if image can\'t be displayed') - ) - ); - - // Tooltip - $fields->insertAfter( - 'AltText', - TextField::create( - 'Title', - _t('SilverStripe\\Forms\\HTMLEditor\\HTMLEditorField.IMAGETITLETEXT', 'Title text (tooltip)') - )->setDescription( - _t('SilverStripe\\Forms\\HTMLEditor\\HTMLEditorField.IMAGETITLETEXTDESC', 'For additional information about the image') - ) - ); - - return $fields; - } - - protected function getDetailFields() - { - $fields = parent::getDetailFields(); - $width = $this->getOriginalWidth(); - $height = $this->getOriginalHeight(); - - // Show dimensions of original - if ($width && $height) { - $fields->insertAfter( - 'ClickableURL', - ReadonlyField::create( - "OriginalWidth", - _t(__CLASS__.'.WIDTH', 'Width'), - $width - ) - ); - $fields->insertAfter( - 'OriginalWidth', - ReadonlyField::create( - "OriginalHeight", - _t(__CLASS__.'.HEIGHT', 'Height'), - $height - ) - ); - } - return $fields; - } - - /** - * Get width of original, if known - * - * @return int - */ - public function getOriginalWidth() - { - if ($this->width) { - return $this->width; - } - if ($this->file) { - $width = $this->file->getWidth(); - if ($width) { - return $width; - } - } - return null; - } - - /** - * Get height of original, if known - * - * @return int - */ - public function getOriginalHeight() - { - if ($this->height) { - return $this->height; - } - - if ($this->file) { - $height = $this->file->getHeight(); - if ($height) { - return $height; - } - } - return null; - } - - public function getWidth() - { - if ($this->width) { - return $this->width; - } - return parent::getWidth(); - } - - public function getHeight() - { - if ($this->height) { - return $this->height; - } - return parent::getHeight(); - } - - public function getSize() - { - if ($this->size) { - return File::format_size($this->size); - } - return parent::getSize(); - } - - /** - * Provide an initial width for inserted image, restricted based on $embed_width - * - * @return int - */ - public function getInsertWidth() - { - $width = $this->getWidth(); - $maxWidth = HTMLEditorField_Image::config()->insert_width; - return $width <= $maxWidth - ? $width - : $maxWidth; - } - - /** - * Provide an initial height for inserted image, scaled proportionally to the initial width - * - * @return int - */ - public function getInsertHeight() - { - $width = $this->getWidth(); - $height = $this->getHeight(); - $maxWidth = HTMLEditorField_Image::config()->insert_width; - return ($width <= $maxWidth) ? $height : round($height * ($maxWidth / $width)); - } - - public function getPreviewURL() - { - // Get preview from file - if ($this->file) { - return $this->getFilePreviewURL(); - } - - // Embed image directly - return $this->url; - } -} diff --git a/src/Forms/HTMLEditor/HTMLEditorField_Toolbar.php b/src/Forms/HTMLEditor/HTMLEditorField_Toolbar.php deleted file mode 100644 index d9f5a5dcf..000000000 --- a/src/Forms/HTMLEditor/HTMLEditorField_Toolbar.php +++ /dev/null @@ -1,495 +0,0 @@ -EditorToolbar()}. - */ -class HTMLEditorField_Toolbar extends RequestHandler -{ - - private static $allowed_actions = array( - 'LinkForm', - 'EditorExternalLink', - 'EditorEmailLink', - 'viewfile', - 'getanchors' - ); - - /** - * @return string - */ - public function getTemplateViewFile() - { - return SSViewer::get_templates_by_class(static::class, '_viewfile', __CLASS__); - } - - /** - * @var Controller - */ - protected $controller; - - /** - * @var string - */ - protected $name; - - public function __construct($controller, $name) - { - parent::__construct(); - - $this->controller = $controller; - $this->name = $name; - } - - public function forTemplate() - { - return sprintf( - '
', - Controller::join_links($this->controller->Link(), $this->name, 'LinkForm', 'forTemplate') - ); - } - - /** - * Searches the SiteTree for display in the dropdown - * - * @param string $sourceObject - * @param string $labelField - * @param string $search - * @return DataList - */ - public function siteTreeSearchCallback($sourceObject, $labelField, $search) - { - return DataObject::get($sourceObject)->filterAny(array( - 'MenuTitle:PartialMatch' => $search, - 'Title:PartialMatch' => $search - )); - } - - /** - * Return a {@link Form} instance allowing a user to - * add links in the TinyMCE content editor. - * - * @skipUpgrade - * @return Form - */ - public function LinkForm() - { - $siteTree = TreeDropdownField::create( - 'internal', - _t(__CLASS__.'.PAGE', "Page"), - SiteTree::class, - 'ID', - 'MenuTitle', - true - ); - // mimic the SiteTree::getMenuTitle(), which is bypassed when the search is performed - $siteTree->setSearchFunction(array($this, 'siteTreeSearchCallback')); - - $numericLabelTmpl = 'Step %d.' - . '%s'; - - $form = new Form( - $this->controller, - "{$this->name}/LinkForm", - new FieldList( - $headerWrap = new CompositeField( - new LiteralField( - 'Heading', - sprintf( - '

%s

', - _t(__CLASS__.'.LINK', 'Insert Link') - ) - ) - ), - $contentComposite = new CompositeField( - OptionsetField::create( - 'LinkType', - DBField::create_field( - 'HTMLFragment', - sprintf($numericLabelTmpl, '1', _t(__CLASS__.'.LINKTO', 'Link type')) - ), - array( - 'internal' => _t(__CLASS__.'.LINKINTERNAL', 'Link to a page on this site'), - 'external' => _t(__CLASS__.'.LINKEXTERNAL', 'Link to another website'), - 'anchor' => _t(__CLASS__.'.LINKANCHOR', 'Link to an anchor on this page'), - 'email' => _t(__CLASS__.'.LINKEMAIL', 'Link to an email address'), - 'file' => _t(__CLASS__.'.LINKFILE', 'Link to download a file'), - ), - 'internal' - ), - LiteralField::create( - 'Step2', - '
' - . sprintf($numericLabelTmpl, '2', _t(__CLASS__.'.LINKDETAILS', 'Link details')) . '
' - ), - $siteTree, - TextField::create('external', _t(__CLASS__.'.URL', 'URL'), 'http://'), - EmailField::create('email', _t(__CLASS__.'.EMAIL', 'Email address')), - $fileField = TreeDropdownField::create( - 'file', - _t(__CLASS__.'.FILE', 'File'), - File::class, - 'ID', - 'Name' - ), - TextField::create('Anchor', _t(__CLASS__.'.ANCHORVALUE', 'Anchor')), - TextField::create('Subject', _t(__CLASS__.'.SUBJECT', 'Email subject')), - TextField::create('Description', _t(__CLASS__.'.LINKDESCR', 'Link description')), - CheckboxField::create( - 'TargetBlank', - _t(__CLASS__.'.LINKOPENNEWWIN', 'Open link in a new window?') - ), - HiddenField::create('Locale', null, $this->controller->Locale) - ) - ), - new FieldList() - ); - - $headerWrap->setName('HeaderWrap'); - $headerWrap->addExtraClass('CompositeField composite cms-content-header form-group--no-label '); - $contentComposite->setName('ContentBody'); - $contentComposite->addExtraClass('ss-insert-link content'); - - $form->unsetValidator(); - $form->loadDataFrom($this); - $form->addExtraClass('htmleditorfield-form htmleditorfield-linkform cms-linkform-content'); - - $this->extend('updateLinkForm', $form); - - return $form; - } - - /** - * Builds and returns the external link form - * - * @return null|Form - */ - public function EditorExternalLink($id = null) - { - /** @var EditorExternalLinkFormFactory $factory */ - $factory = Injector::inst()->get(EditorExternalLinkFormFactory::class); - if ($factory) { - return $factory->getForm($this->controller, "{$this->name}/EditorExternalLink"); - } - return null; - } - - /** - * Builds and returns the external link form - * - * @return null|Form - */ - public function EditorEmailLink($id = null) - { - /** @var EditorEmailLinkFormFactory $factory */ - $factory = Injector::inst()->get(EditorEmailLinkFormFactory::class); - - if ($factory) { - return $factory->getForm($this->controller, "{$this->name}/EditorEmailLink"); - } - return null; - } - - /** - * 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; - } - - /** - * List of allowed schemes (no wildcard, all lower case) or empty to allow all schemes - * - * @config - * @var array - */ - private static $fileurl_scheme_whitelist = array('http', 'https'); - - /** - * List of allowed domains (no wildcard, all lower case) or empty to allow all domains - * - * @config - * @var array - */ - private static $fileurl_domain_whitelist = array(); - - /** - * Find local File dataobject given ID - * - * @param int $id - * @return array - */ - protected function viewfile_getLocalFileByID($id) - { - /** @var File $file */ - $file = DataObject::get_by_id(File::class, $id); - if ($file && $file->canView()) { - return array($file, $file->getURL()); - } - return [null, null]; - } - - /** - * Get remote File given url - * - * @param string $fileUrl Absolute URL - * @return array - * @throws HTTPResponse_Exception - */ - protected function viewfile_getRemoteFileByURL($fileUrl) - { - if (!Director::is_absolute_url($fileUrl)) { - throw $this->getErrorFor(_t( - "SilverStripe\\Forms\\HTMLEditor\\HTMLEditorField_Toolbar.ERROR_ABSOLUTE", - "Only absolute urls can be embedded" - )); - } - $scheme = strtolower(parse_url($fileUrl, PHP_URL_SCHEME)); - $allowed_schemes = self::config()->get('fileurl_scheme_whitelist'); - if (!$scheme || ($allowed_schemes && !in_array($scheme, $allowed_schemes))) { - throw $this->getErrorFor(_t( - "SilverStripe\\Forms\\HTMLEditor\\HTMLEditorField_Toolbar.ERROR_SCHEME", - "This file scheme is not included in the whitelist" - )); - } - $domain = strtolower(parse_url($fileUrl, PHP_URL_HOST)); - $allowed_domains = self::config()->get('fileurl_domain_whitelist'); - if (!$domain || ($allowed_domains && !in_array($domain, $allowed_domains))) { - throw $this->getErrorFor(_t( - "SilverStripe\\Forms\\HTMLEditor\\HTMLEditorField_Toolbar.ERROR_HOSTNAME", - "This file hostname is not included in the whitelist" - )); - } - return [null, $fileUrl]; - } - - /** - * Prepare error for the front end - * - * @param string $message - * @param int $code - * @return HTTPResponse_Exception - */ - protected function getErrorFor($message, $code = 400) - { - $exception = new HTTPResponse_Exception($message, $code); - $exception->getResponse()->addHeader('X-Status', $message); - return $exception; - } - - /** - * View of a single file, either on the filesystem or on the web. - * - * @throws HTTPResponse_Exception - * @param HTTPRequest $request - * @return string - */ - public function viewfile($request) - { - $file = null; - $url = null; - // Get file and url by request method - if ($fileUrl = $request->getVar('FileURL')) { - // Get remote url - list($file, $url) = $this->viewfile_getRemoteFileByURL($fileUrl); - } elseif ($id = $request->getVar('ID')) { - // Or we could have been passed an ID directly - list($file, $url) = $this->viewfile_getLocalFileByID($id); - } else { - // Or we could have been passed nothing, in which case panic - throw $this->getErrorFor(_t( - "SilverStripe\\Forms\\HTMLEditor\\HTMLEditorField_Toolbar.ERROR_ID", - 'Need either "ID" or "FileURL" parameter to identify the file' - )); - } - - // Validate file exists - if (!$url) { - throw $this->getErrorFor(_t( - "SilverStripe\\Forms\\HTMLEditor\\HTMLEditorField_Toolbar.ERROR_NOTFOUND", - 'Unable to find file to view' - )); - } - - // Instantiate file wrapper and get fields based on its type - // Check if appCategory is an image and exists on the local system, otherwise use Embed to reference a - // remote image - $fileCategory = $this->getFileCategory($url, $file); - switch ($fileCategory) { - case 'image': - case 'image/supported': - $fileWrapper = new HTMLEditorField_Image($url, $file); - break; - case 'flash': - $fileWrapper = new HTMLEditorField_Flash($url, $file); - break; - default: - // Only remote files can be linked via o-embed - // {@see HTMLEditorField_Toolbar::getAllowedExtensions()) - if ($file) { - throw $this->getErrorFor(_t( - "SilverStripe\\Forms\\HTMLEditor\\HTMLEditorField_Toolbar.ERROR_OEMBED_REMOTE", - "Embed is only compatible with remote files" - )); - } - - // Other files should fallback to embed - $fileWrapper = new HTMLEditorField_Embed($url, $file); - break; - } - - // Render fields and return - $fields = $this->getFieldsForFile($url, $fileWrapper); - return $fileWrapper->customise(array( - 'Fields' => $fields, - ))->renderWith($this->getTemplateViewFile()); - } - - /** - * Guess file category from either a file or url - * - * @param string $url - * @param File $file - * @return string - */ - protected function getFileCategory($url, $file) - { - if ($file) { - return $file->appCategory(); - } - if ($url) { - return File::get_app_category(File::get_file_extension($url)); - } - return null; - } - - /** - * Find all anchors available on the given page. - * - * @return array - * @throws HTTPResponse_Exception - */ - public function getanchors() - { - $id = (int)$this->getRequest()->getVar('PageID'); - $anchors = array(); - - if (($page = SiteTree::get()->byID($id)) && !empty($page)) { - if (!$page->canView()) { - throw new HTTPResponse_Exception( - _t( - 'SilverStripe\\Forms\\HTMLEditor\\HTMLEditorField.ANCHORSCANNOTACCESSPAGE', - 'You are not permitted to access the content of the target page.' - ), - 403 - ); - } - - // Parse the shortcodes so [img id=x] doesn't end up as anchor x - $htmlValue = $page->obj('Content')->forTemplate(); - - // Similar to the regex found in HTMLEditorField.js / getAnchors method. - if (preg_match_all( - "/\\s+(name|id)\\s*=\\s*([\"'])([^\\2\\s>]*?)\\2|\\s+(name|id)\\s*=\\s*([^\"']+)[\\s +>]/im", - $htmlValue, - $matches - )) { - $anchors = array_values(array_unique(array_filter( - array_merge($matches[3], $matches[5]) - ))); - } - } else { - throw new HTTPResponse_Exception( - _t('SilverStripe\\Forms\\HTMLEditor\\HTMLEditorField.ANCHORSPAGENOTFOUND', 'Target page not found.'), - 404 - ); - } - - return json_encode($anchors); - } - - /** - * 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. - * - * @param string $url Abolute URL to asset - * @param HTMLEditorField_File $file Asset wrapper - * @return FieldList - */ - protected function getFieldsForFile($url, HTMLEditorField_File $file) - { - $fields = $this->extend('getFieldsForFile', $url, $file); - if (!$fields) { - $fields = $file->getFields(); - $file->extend('updateFields', $fields); - } - $this->extend('updateFieldsForFile', $fields, $url, $file); - return $fields; - } - - - /** - * Gets files filtered by a given parent with the allowed extensions - * - * @param int $parentID - * @return DataList - */ - protected function getFiles($parentID = null) - { - $exts = $this->getAllowedExtensions(); - $dotExts = array_map(function ($ext) { - return ".{$ext}"; - }, $exts); - $files = File::get()->filter('Name:EndsWith', $dotExts); - - // Limit by folder (if required) - if ($parentID) { - $files = $files->filter('ParentID', $parentID); - } - - return $files; - } - - /** - * @return array All extensions which can be handled by the different views. - */ - protected function getAllowedExtensions() - { - $exts = array('jpg', 'gif', 'png', 'swf', 'jpeg'); - $this->extend('updateAllowedExtensions', $exts); - return $exts; - } -} diff --git a/src/Forms/Schema/FormSchema.php b/src/Forms/Schema/FormSchema.php index 9eb9d6c42..0b3235623 100644 --- a/src/Forms/Schema/FormSchema.php +++ b/src/Forms/Schema/FormSchema.php @@ -4,6 +4,7 @@ namespace SilverStripe\Forms\Schema; use InvalidArgumentException; use SilverStripe\Control\HTTPRequest; +use SilverStripe\Core\Injector\Injectable; use SilverStripe\Forms\CompositeField; use SilverStripe\Forms\Form; use SilverStripe\Forms\FormField; @@ -16,6 +17,8 @@ use SilverStripe\ORM\ValidationResult; */ class FormSchema { + use Injectable; + /** * Request the schema part */ diff --git a/tests/php/Forms/HTMLEditor/HTMLEditorFieldTest.php b/tests/php/Forms/HTMLEditor/HTMLEditorFieldTest.php index df2c59fb1..ac3a960b5 100644 --- a/tests/php/Forms/HTMLEditor/HTMLEditorFieldTest.php +++ b/tests/php/Forms/HTMLEditor/HTMLEditorFieldTest.php @@ -2,40 +2,27 @@ namespace SilverStripe\Forms\Tests\HTMLEditor; -use Page; use SilverStripe\Assets\File; use SilverStripe\Assets\FileNameFilter; use SilverStripe\Assets\Filesystem; use SilverStripe\Assets\Folder; use SilverStripe\Assets\Image; use SilverStripe\Assets\Tests\Storage\AssetStoreTest\TestAssetStore; -use SilverStripe\Control\Controller; -use SilverStripe\Control\HTTPRequest; use SilverStripe\Core\Config\Config; use SilverStripe\Dev\CSSContentParser; use SilverStripe\Dev\FunctionalTest; use SilverStripe\Forms\HTMLEditor\HTMLEditorField; -use SilverStripe\Forms\HTMLEditor\HTMLEditorField_Toolbar; -use SilverStripe\Forms\HTMLEditor\HTMLEditorField_Image; use SilverStripe\Forms\HTMLReadonlyField; -use SilverStripe\Forms\Tests\HTMLEditor\HTMLEditorFieldTest\DummyMediaFormFieldExtension; use SilverStripe\Forms\Tests\HTMLEditor\HTMLEditorFieldTest\TestObject; use SilverStripe\ORM\FieldType\DBHTMLText; use SilverStripe\Forms\HTMLEditor\TinyMCEConfig; class HTMLEditorFieldTest extends FunctionalTest { - protected static $fixture_file = 'HTMLEditorFieldTest.yml'; protected static $use_draft_site = true; - protected static $required_extensions= array( - HTMLEditorField_Toolbar::class => array( - DummyMediaFormFieldExtension::class, - ), - ); - protected static $extra_dataobjects = [ TestObject::class, ]; @@ -48,16 +35,16 @@ class HTMLEditorFieldTest extends FunctionalTest TestAssetStore::activate('HTMLEditorFieldTest'); // Set the File Name Filter replacements so files have the expected names - Config::inst()->update( + Config::modify()->set( FileNameFilter::class, 'default_replacements', - array( - '/\s/' => '-', // remove whitespace - '/_/' => '-', // underscores to dashes - '/[^A-Za-z0-9+.\-]+/' => '', // remove non-ASCII chars, only allow alphanumeric plus dash and dot - '/[\-]{2,}/' => '-', // remove duplicate dashes - '/^[\.\-_]+/' => '', // Remove all leading dots, dashes or underscores - ) + [ + '/\s/' => '-', // remove whitespace + '/_/' => '-', // underscores to dashes + '/[^A-Za-z0-9+.\-]+/' => '', // remove non-ASCII chars, only allow alphanumeric plus dash and dot + '/[\-]{2,}/' => '-', // remove duplicate dashes + '/^[\.\-_]+/' => '', // Remove all leading dots, dashes or underscores + ] ); // Create a test files for each of the fixture references @@ -175,73 +162,6 @@ class HTMLEditorFieldTest extends FunctionalTest ); } - public function testGetAnchors() - { - if (!class_exists('Page')) { - $this->markTestSkipped(); - } - $linkedPage = new Page(); - $linkedPage->Title = 'Dummy'; - $linkedPage->write(); - - $html = << -
-
-[sitetree_link id="{$linkedPage->ID}"] -
-
-
-
-
-EOS - ; - $expected = array( - 'foo', - 'bar', - 'baz', - 'bam', - "some'id", - ); - $page = new Page(); - $page->Title = 'Test'; - $page->Content = $html; - $page->write(); - $this->useDraftSite(true); - - $request = new HTTPRequest( - 'GET', - '/', - array( - 'PageID' => $page->ID, - ) - ); - - $toolBar = new HTMLEditorField_Toolbar(new Controller(), 'test'); - $toolBar->setRequest($request); - - $results = json_decode($toolBar->getanchors(), true); - $this->assertEquals($expected, $results); - } - - public function testHTMLEditorFieldFileLocal() - { - $file = new HTMLEditorField_Image('http://domain.com/folder/my_image.jpg?foo=bar'); - $this->assertEquals('http://domain.com/folder/my_image.jpg?foo=bar', $file->URL); - $this->assertEquals('my_image.jpg', $file->Name); - $this->assertEquals('jpg', $file->Extension); - // TODO Can't easily test remote file dimensions - } - - public function testHTMLEditorFieldFileRemote() - { - $fileFixture = new File(array('Name' => 'my_local_image.jpg', 'Filename' => 'folder/my_local_image.jpg')); - $file = new HTMLEditorField_Image('http://localdomain.com/folder/my_local_image.jpg', $fileFixture); - $this->assertEquals('http://localdomain.com/folder/my_local_image.jpg', $file->URL); - $this->assertEquals('my_local_image.jpg', $file->Name); - $this->assertEquals('jpg', $file->Extension); - } - public function testReadonlyField() { $editor = new HTMLEditorField('Content'); @@ -252,13 +172,9 @@ EOS $fileID ) ); - /** - * @var HTMLReadonlyField $readonly -*/ + /** @var HTMLReadonlyField $readonly */ $readonly = $editor->performReadonlyTransformation(); - /** - * @var DBHTMLText $readonlyContent -*/ + /** @var DBHTMLText $readonlyContent */ $readonlyContent = $readonly->Field(); $this->assertEquals( @@ -276,9 +192,7 @@ EOS // Test with include input tag $readonly = $editor->performReadonlyTransformation() ->setIncludeHiddenField(true); - /** - * @var DBHTMLText $readonlyContent -*/ + /** @var DBHTMLText $readonlyContent */ $readonlyContent = $readonly->Field(); $this->assertEquals( <<Fields(); - } -} diff --git a/tests/php/Forms/HTMLEditor/HTMLEditorFieldToolbarTest.php b/tests/php/Forms/HTMLEditor/HTMLEditorFieldToolbarTest.php deleted file mode 100644 index 05b4bb77d..000000000 --- a/tests/php/Forms/HTMLEditor/HTMLEditorFieldToolbarTest.php +++ /dev/null @@ -1,92 +0,0 @@ -set('fileurl_scheme_whitelist', array('http')); - HTMLEditorField_Toolbar::config()->set('fileurl_domain_whitelist', array('example.com')); - - // Filesystem mock - TestAssetStore::activate(__CLASS__); - - // Load up files - /** @var File $file1 */ - $file1 = $this->objFromFixture(File::class, 'example_file'); - $file1->setFromString(str_repeat('x', 1000), $file1->Name); - $file1->write(); - - /** @var Image $image1 */ - $image1 = $this->objFromFixture(Image::class, 'example_image'); - $image1->setFromLocalFile( - __DIR__ . '/HTMLEditorFieldTest/images/example.jpg', - 'folder/subfolder/example.jpg' - ); - $image1->write(); - } - - public function testValidLocalReference() - { - /** @var File $exampleFile */ - $exampleFile = $this->objFromFixture(File::class, 'example_file'); - $expectedUrl = $exampleFile->AbsoluteLink(); - HTMLEditorField_Toolbar::config()->set( - 'fileurl_domain_whitelist', - [ - 'example.com', - strtolower(parse_url($expectedUrl, PHP_URL_HOST)) - ] - ); - - list(, $url) = $this->getToolbar()->viewfile_getRemoteFileByURL($exampleFile->AbsoluteLink()); - $this->assertEquals($expectedUrl, $url); - } - - public function testValidScheme() - { - list(, $url) = $this->getToolbar()->viewfile_getRemoteFileByURL('http://example.com/test.pdf'); - $this->assertEquals($url, 'http://example.com/test.pdf'); - } - - public function testInvalidScheme() - { - $this->setExpectedException(HTTPResponse_Exception::class); - $this->getToolbar()->viewfile_getRemoteFileByURL('nosuchscheme://example.com/test.pdf'); - } - - public function testValidDomain() - { - list(, $url) = $this->getToolbar()->viewfile_getRemoteFileByURL('http://example.com/test.pdf'); - $this->assertEquals($url, 'http://example.com/test.pdf'); - } - - public function testInvalidDomain() - { - $this->setExpectedException(HTTPResponse_Exception::class); - $this->getToolbar()->viewfile_getRemoteFileByURL('http://evil.com/test.pdf'); - } -} diff --git a/tests/php/Forms/HTMLEditor/HTMLEditorFieldToolbarTest.yml b/tests/php/Forms/HTMLEditor/HTMLEditorFieldToolbarTest.yml deleted file mode 100644 index 635c4f3a2..000000000 --- a/tests/php/Forms/HTMLEditor/HTMLEditorFieldToolbarTest.yml +++ /dev/null @@ -1,18 +0,0 @@ -SilverStripe\Assets\Folder: - folder1: - Name: folder - Title: folder - folder2: - Name: subfolder - Title: subfolder - Parent: =>SilverStripe\Assets\Folder.folder1 - -SilverStripe\Assets\File: - example_file: - Name: example.pdf - Parent: =>SilverStripe\Assets\Folder.folder2 - -SilverStripe\Assets\Image: - example_image: - Name: HTMLEditorFieldTest_example.jpg - Parent: =>SilverStripe\Assets\Folder.folder2 diff --git a/tests/php/Forms/HTMLEditor/HTMLEditorFieldToolbarTest/Toolbar.php b/tests/php/Forms/HTMLEditor/HTMLEditorFieldToolbarTest/Toolbar.php deleted file mode 100644 index 1b9ee5166..000000000 --- a/tests/php/Forms/HTMLEditor/HTMLEditorFieldToolbarTest/Toolbar.php +++ /dev/null @@ -1,18 +0,0 @@ -