Source of file RemoteFileFormFactory.php
Size: 12,474 Bytes - Last Modified: 2021-12-23T10:27:34+00:00
/var/www/docs.ssmods.com/process/src/code/Forms/RemoteFileFormFactory.php
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389 | <?php namespace SilverStripe\AssetAdmin\Forms; use Embed\Exceptions\InvalidUrlException; use InvalidArgumentException; use SilverStripe\Control\Director; use SilverStripe\Control\RequestHandler; use SilverStripe\Core\Config\Configurable; use SilverStripe\Core\Extensible; use SilverStripe\Core\Injector\Injector; use SilverStripe\Forms\CompositeField; use SilverStripe\Forms\FieldGroup; use SilverStripe\Forms\FieldList; use SilverStripe\Forms\Form; use SilverStripe\Forms\FormAction; use SilverStripe\Forms\FormFactory; use SilverStripe\Forms\HiddenField; use SilverStripe\Forms\LiteralField; use SilverStripe\Forms\OptionsetField; use SilverStripe\Forms\RequiredFields; use SilverStripe\Forms\TextField; use SilverStripe\View\Embed\Embeddable; class RemoteFileFormFactory implements FormFactory { use Extensible; use Configurable; /** * Force whitelist for resource protocols to the given list. * * @config * @var array */ private static $fileurl_scheme_whitelist = ['http', 'https']; /** * Blacklist of resources. Takes priority over whitelists if both are provided. * * @config * @var array */ private static $fileurl_scheme_blacklist = []; /** * Force whitelist for resource domains to the given list * * @config * @var array */ private static $fileurl_domain_whitelist = []; /** * Blacklist of domains. For example, live sites should probably * include 'localhost' and other protected urls. * Takes priority over whitelists if both are provided. * * @config * @var array */ private static $fileurl_domain_blacklist = []; /** * Whitelist of ports allowed. * * @config * @var array */ private static $fileurl_port_whitelist = [80, 443]; /** * Blacklist of ports allowed. * Takes priority over whitelists if both are provided. * * @config * @var array */ private static $fileurl_port_blacklist = []; /** * Allow oembed to be disabled * * @config * @var bool */ private static $enabled = true; /** * @param RequestHandler $controller * @param string $name * @param array $context * @return Form */ public function getForm(RequestHandler $controller = null, $name = self::DEFAULT_NAME, $context = []) { // Allow form to be disabled if (!static::config()->get('enabled')) { return null; } // Validate context foreach ($this->getRequiredContext() as $required) { if (!isset($context[$required])) { throw new InvalidArgumentException("Missing required context $required"); } } $fields = $this->getFormFields($controller, $name, $context); $actions = $this->getFormActions($controller, $name, $context); $validator = new RequiredFields(); $form = Form::create($controller, $name, $fields, $actions, $validator); $form->addExtraClass('form--fill-height'); $form->addExtraClass('form--no-dividers'); $form->addExtraClass('insert-embed-modal--'. strtolower($context['type'])); // Extend form $this->invokeWithExtensions('updateForm', $form, $controller, $name, $context); return $form; } public function getRequiredContext() { return ['type']; } protected function getFormFields($controller, $name, $context) { $formType = $context['type']; switch ($formType) { case 'create': return $this->getCreateFormFields(); case 'edit': return $this->getEditFormFields($context); default: throw new InvalidArgumentException("Unknown media form type: {$formType}"); } } protected function getFormActions($controller, $name, $context) { $actions = []; if ($context['type'] === 'create') { $actions = [ FormAction::create('addmedia', _t(__CLASS__.'.AddMedia', 'Add media')) ->setSchemaData(['data' => ['buttonStyle' => 'primary']]), ]; } if ($context['type'] === 'edit') { $actions = [ FormAction::create('insertmedia', _t(__CLASS__.'.InsertMedia', 'Insert media')) ->setSchemaData(['data' => ['buttonStyle' => 'primary']]), FormAction::create('cancel', _t(__CLASS__.'.Cancel', 'Cancel')), ]; } return FieldList::create($actions); } /** * @param string $url * @return bool * @throws InvalidUrlException */ protected function validateUrl($url) { $this->validateURLAbsolute($url); $this->validateURLScheme($url); $this->validateURLHost($url); $this->validateURLPort($url); return true; } /** * Checks if the embed generated is not just a link * * @param Embeddable $embed * @return bool * @throws InvalidUrlException */ protected function validateEmbed(Embeddable $embed) { if (!$embed->validate()) { throw new InvalidUrlException(_t( __CLASS__.'.ERROR_EMBED', 'There is currently no embeddable media available from this URL' )); } return true; } /** * Get form fields for create new embed * * @return FieldList */ protected function getCreateFormFields() { return FieldList::create([ TextField::create( 'Url', 'Embed URL' ) ->setInputType('url') ->addExtraClass('insert-embed-modal__url-create') ->setDescription(_t( __CLASS__.'.UrlDescription', 'Embed Youtube and Vimeo videos, images and other media directly from the web.' )), ]); } /** * Get form fields for edit form * * @param array $context * @return FieldList * @throws InvalidUrlException */ protected function getEditFormFields($context) { // Check if the url is valid $url = (isset($context['url'])) ? $context['url'] : null; if (empty($url)) { return $this->getCreateFormFields(); } $url = trim($url); // Get embed $this->validateUrl($url); /** @var Embeddable $embed */ $embed = Injector::inst()->create(Embeddable::class, $url); $this->validateEmbed($embed); // Build form $alignments = array( 'leftAlone' => _t('SilverStripe\\AssetAdmin\\Controller\\AssetAdmin.AlignmentLeftAlone', 'Left'), 'center' => _t('SilverStripe\\AssetAdmin\\Controller\\AssetAdmin.AlignmentCenter', 'Center'), 'rightAlone' => _t('SilverStripe\\AssetAdmin\\Controller\\AssetAdmin.AlignmentRightAlone', 'Right'), 'left' => _t('SilverStripe\\AssetAdmin\\Controller\\AssetAdmin.AlignmentLeft', 'Left wrap'), 'right' => _t('SilverStripe\\AssetAdmin\\Controller\\AssetAdmin.AlignmentRight', 'Right wrap'), ); $width = $embed->getWidth(); $height = $embed->getHeight(); $fields = CompositeField::create([ LiteralField::create( 'Preview', sprintf( '<img src="%s" class="%s" />', $embed->getPreviewURL(), 'insert-embed-modal__preview' ) )->addExtraClass('insert-embed-modal__preview-container'), HiddenField::create('PreviewUrl', 'PreviewUrl', $embed->getPreviewURL()), CompositeField::create([ TextField::create('UrlPreview', $embed->getName(), $url) ->setReadonly(true), HiddenField::create('Url', false, $url), TextField::create( 'CaptionText', _t('SilverStripe\\AssetAdmin\\Controller\\AssetAdmin.Caption', 'Caption') ), OptionsetField::create( 'Placement', _t('SilverStripe\\AssetAdmin\\Controller\\AssetAdmin.Placement', 'Placement'), $alignments ) ->addExtraClass('insert-embed-modal__placement'), $dimensions = FieldGroup::create( _t('SilverStripe\\AssetAdmin\\Controller\\AssetAdmin.ImageSpecs', 'Dimensions'), TextField::create('Width', '', $width) ->setRightTitle(_t( 'SilverStripe\\AssetAdmin\\Controller\\AssetAdmin.ImageWidth', 'Width' )) ->setMaxLength(5) ->addExtraClass('flexbox-area-grow'), TextField::create('Height', '', $height) ->setRightTitle(_t( 'SilverStripe\\AssetAdmin\\Controller\\AssetAdmin.ImageHeight', 'Height' )) ->setMaxLength(5) ->addExtraClass('flexbox-area-grow') )->addExtraClass('fieldgroup--fill-width') ->setName('Dimensions') ])->addExtraClass('flexbox-area-grow'), ])->addExtraClass('insert-embed-modal__fields--fill-width'); if ($dimensions && $width && $height) { $ratio = $width / $height; $dimensions->setSchemaComponent('ProportionConstraintField'); $dimensions->setSchemaState([ 'data' => [ 'ratio' => $ratio, 'isRemoteFile' => true ] ]); } return FieldList::create($fields); } /** * @param string $url * @throws InvalidUrlException */ protected function validateURLScheme($url) { $scheme = strtolower(parse_url($url, PHP_URL_SCHEME)); $allowedSchemes = self::config()->get('fileurl_scheme_whitelist'); $disallowedSchemes = self::config()->get('fileurl_scheme_blacklist'); if (!$scheme || ($allowedSchemes && !in_array($scheme, $allowedSchemes)) || ($disallowedSchemes && in_array($scheme, $disallowedSchemes)) ) { throw new InvalidUrlException(_t( __CLASS__ . '.ERROR_SCHEME', 'This file scheme is not allowed' )); } } /** * @param string $url * @throws InvalidUrlException */ protected function validateURLHost($url) { $domain = strtolower(parse_url($url, PHP_URL_HOST)); $allowedDomains = self::config()->get('fileurl_domain_whitelist'); $disallowedDomains = self::config()->get('fileurl_domain_blacklist'); if (!$domain || ($allowedDomains && !in_array($domain, $allowedDomains)) || ($disallowedDomains && in_array($domain, $disallowedDomains)) ) { throw new InvalidUrlException(_t( __CLASS__ . '.ERROR_HOSTNAME', 'This file hostname is not allowed' )); } } /** * @param string $url * @throws InvalidUrlException */ protected function validateURLPort($url) { $port = (int)parse_url($url, PHP_URL_PORT); if (!$port) { return; } $allowedPorts = self::config()->get('fileurl_port_whitelist'); $disallowedPorts = self::config()->get('fileurl_port_blacklist'); if (($allowedPorts && !in_array($port, $allowedPorts)) || ($disallowedPorts && in_array($port, $disallowedPorts)) ) { throw new InvalidUrlException(_t( __CLASS__ . '.ERROR_PORT', 'This file port is not allowed' )); } } /** * @param string $url * @throws InvalidUrlException */ protected function validateURLAbsolute($url) { if (!Director::is_absolute_url($url)) { throw new InvalidUrlException(_t( __CLASS__ . '.ERROR_ABSOLUTE', 'Only absolute urls can be embedded' )); } } } |