diff --git a/LICENSE.md b/LICENSE.md new file mode 100644 index 0000000..7c55fa0 --- /dev/null +++ b/LICENSE.md @@ -0,0 +1,5 @@ +Copyright (c) 2015, LiveSource All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + +Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. Neither the name LiveSource nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/code/dataobjects/EmbeddedObject.php b/code/dataobjects/EmbeddedObject.php index 70d107c..2f1896d 100644 --- a/code/dataobjects/EmbeddedObject.php +++ b/code/dataobjects/EmbeddedObject.php @@ -19,7 +19,7 @@ class EmbeddedObject extends DataObject { 'ExtraClass' => 'Varchar(64)', 'EmbedHTML' => 'Text', ); - + public function Embed() { $options = array( 'width' => $this->Width, @@ -28,35 +28,35 @@ public function Embed() { $this->setFromURL($this->SourceURL); return $this; } - + public function onBeforeWrite() { $changes = $this->getChangedFields(); - + if (isset($changes['Width']) && $changes['Width']['before']) { $this->updateEmbedHTML(); } - + if (isset($changes['Height']) && $changes['Height']['before']) { $this->updateEmbedHTML(); } - + parent::onBeforeWrite(); - + } public function updateEmbedHTML() { $this->setFromURL($this->SourceURL); } - + public function setFromURL($url) { - if($url){ + if($url) { $info = Embed\Embed::create($url); // , array('image' => array('minImageWidth' => $this->Width, 'minImageHeight' => $this->Height))); $this->setFromEmbed($info); } } - + public function setFromEmbed(\Embed\Adapters\Adapter $info) { - + $this->Title = $info->getTitle(); $this->SourceURL = $info->getUrl(); $this->Width = $info->getWidth(); @@ -64,7 +64,8 @@ public function setFromEmbed(\Embed\Adapters\Adapter $info) { $this->ThumbURL = $info->getImage(); $this->Description = $info->getDescription() ? $info->getDescription(): $info->getTitle(); $this->Type = $info->getType(); - $this->EmbedHTML = $info->getCode(); + $embed = $info->getCode(); + $this->EmbedHTML = $embed ? $embed : $this->EmbedHTML; } public function forTemplate() { diff --git a/code/dataobjects/Link.php b/code/dataobjects/Link.php index e04945a..2043b0b 100644 --- a/code/dataobjects/Link.php +++ b/code/dataobjects/Link.php @@ -8,12 +8,15 @@ * @author **/ class Link extends DataObject{ - + /** * @var string custom CSS classes for template */ protected $cssClass; + /** + * @var array + */ private static $db = array( 'Title' => 'Varchar(255)', 'Type' => 'Varchar', @@ -23,11 +26,17 @@ class Link extends DataObject{ 'OpenInNewWindow' => 'Boolean' ); + /** + * @var array + */ private static $has_one = array( 'File' => 'File', 'SiteTree' => 'SiteTree' ); + /** + * @var array + */ private static $summary_fields = array( 'Title', 'LinkType', @@ -37,6 +46,7 @@ class Link extends DataObject{ /** * A map of object types that can be linked to * Custom dataobjects can be added to this + * * @var array **/ private static $types = array( @@ -46,8 +56,10 @@ class Link extends DataObject{ 'SiteTree' => 'Page on this website' ); - - public function getCMSFields(){ + /** + * @return FieldList + */ + public function getCMSFields() { $fields = $this->scaffoldFormFields(array( // Don't allow has_many/many_many relationship editing before the record is first saved 'includeRelations' => ($this->ID > 0), @@ -55,41 +67,41 @@ public function getCMSFields(){ 'ajaxSafe' => true )); - $types = $this->config()->get('types'); - $i18nTypes = array(); - foreach ($types as $key => $label) { - $i18nTypes[$key] = _t('Linkable.TYPE'.strtoupper($key), $label); - } + $types = $this->config()->get('types'); + $i18nTypes = array(); + foreach ($types as $key => $label) { + $i18nTypes[$key] = _t('Linkable.TYPE'.strtoupper($key), $label); + } - $fields->removeByName('SiteTreeID'); - // seem to need to remove both of these for different SS versions... - $fields->removeByName('FileID'); - $fields->removeByName('File'); + $fields->removeByName('SiteTreeID'); + // seem to need to remove both of these for different SS versions... + $fields->removeByName('FileID'); + $fields->removeByName('File'); $fields->dataFieldByName('Title')->setTitle(_t('Linkable.TITLE', 'Title'))->setRightTitle(_t('Linkable.OPTIONALTITLE', 'Optional. Will be auto-generated from link if left blank')); $fields->replaceField('Type', DropdownField::create('Type', _t('Linkable.LINKTYPE', 'Link Type'), $i18nTypes)->setEmptyString(' '), 'OpenInNewWindow'); - + $fields->addFieldToTab('Root.Main', DisplayLogicWrapper::create( TreeDropdownField::create('FileID', _t('Linkable.FILE', 'File'), 'File', 'ID', 'Title') )->displayIf("Type")->isEqualTo("File")->end()); - + $fields->addFieldToTab('Root.Main', DisplayLogicWrapper::create( TreeDropdownField::create('SiteTreeID', _t('Linkable.PAGE', 'Page'), 'SiteTree') )->displayIf("Type")->isEqualTo("SiteTree")->end()); $fields->addFieldToTab('Root.Main', $newWindow = CheckboxField::create('OpenInNewWindow', _t('Linkable.OPENINNEWWINDOW', 'Open link in a new window'))); $newWindow->displayIf('Type')->isNotEmpty(); - + $fields->dataFieldByName('URL')->displayIf("Type")->isEqualTo("URL"); $fields->dataFieldByName('Email')->setTitle(_t('Linkable.EMAILADDRESS', 'Email Address'))->displayIf("Type")->isEqualTo("Email"); - if($this->SiteTreeID && !$this->SiteTree()->isPublished()){ - $fields->dataFieldByName('SiteTreeID')->setRightTitle(_t('Linkable.DELETEDWARNING', 'Warning: The selected page appears to have been deleted or unpublished. This link may not appear or may be broken in the frontend')); - } + if($this->SiteTreeID && !$this->SiteTree()->isPublished()) { + $fields->dataFieldByName('SiteTreeID')->setRightTitle(_t('Linkable.DELETEDWARNING', 'Warning: The selected page appears to have been deleted or unpublished. This link may not appear or may be broken in the frontend')); + } $fields->addFieldToTab('Root.Main', $anchor = TextField::create('Anchor', _t('Linkable.ANCHOR', 'Anchor')), 'OpenInNewWindow'); $anchor->setRightTitle('Include # at the start of your anchor name'); - $anchor->displayIf("Type")->isEqualTo("SiteTree"); + $anchor->displayIf("Type")->isEqualTo("SiteTree"); $this->extend('updateCMSFields', $fields); @@ -99,49 +111,48 @@ public function getCMSFields(){ /** * If the title is empty, set it to getLinkURL() - * @return String + * + * @return string **/ - public function onAfterWrite(){ + public function onAfterWrite() { parent::onAfterWrite(); - if(!$this->Title){ - if($this->Type == 'URL' || $this->Type == 'Email'){ + if(!$this->Title) { + if($this->Type == 'URL' || $this->Type == 'Email') { $this->Title = $this->{$this->Type}; - }elseif($this->Type == 'SiteTree'){ + }elseif($this->Type == 'SiteTree') { $this->Title = $this->SiteTree()->MenuTitle; - }else{ - if($this->Type && $component = $this->getComponent($this->Type)){ + } else { + if($this->Type && $component = $this->getComponent($this->Type)) { $this->Title = $component->Title; } } - if(!$this->Title){ + if(!$this->Title) { $this->Title = 'Link-' . $this->ID; } $this->write(); } - - - } - - + /** * Add CSS classes. + * * @param string $class CSS classes. * @return Link **/ - public function setCSSClass($class){ + public function setCSSClass($class) { $this->cssClass = $class; return $this; } - - + + /** * Gets the html class attribute for this link. - * @return String + * + * @return string **/ - public function getClassAttr(){ + public function getClassAttr() { $class = $this->cssClass ? Convert::raw2att( $this->cssClass ) : ''; return $class ? "class='$class'" : ''; } @@ -149,93 +160,95 @@ public function getClassAttr(){ /** * Renders an HTML anchor tag for this link - * @return String + * + * @return string **/ - public function forTemplate(){ - if($url = $this->getLinkURL()){ + public function forTemplate() { + if($url = $this->getLinkURL()) { $title = $this->Title ? $this->Title : $url; // legacy $target = $this->getTargetAttr(); $class = $this->getClassAttr(); - return "$title"; + return "$title"; } } /** * Works out what the URL for this link should be based on it's Type - * @return String + * + * @return string **/ - public function getLinkURL(){ + public function getLinkURL() { if(!$this->ID) return; - if($this->Type == 'URL'){ + if($this->Type == 'URL') { return $this->URL; - }elseif($this->Type == 'Email'){ + }elseif($this->Type == 'Email') { return $this->Email ? "mailto:$this->Email" : null; - }else{ - if($this->Type && $component = $this->getComponent($this->Type)){ - if(!$component->exists()){ + } else { + if($this->Type && $component = $this->getComponent($this->Type)) { + if(!$component->exists()) { return false; - } + } - if($component->hasMethod('Link')){ + if($component->hasMethod('Link')) { return $component->Link() . $this->Anchor; - }else{ + } else { return "Please implement a Link() method on your dataobject \"$this->Type\""; } } } } - /** - * Gets the html target attribute for the anchor tag - * @return String - **/ - public function getTargetAttr(){ - return $this->OpenInNewWindow ? "target='_blank'" : ''; + * Gets the html target attribute for the anchor tag + * + * @return string + **/ + public function getTargetAttr() { + return $this->OpenInNewWindow ? "target='_blank'" : ''; } - /** * Gets the description label of this links type - * @return String + * + * @return string **/ - public function getLinkType(){ + public function getLinkType() { $types = $this->config()->get('types'); return isset($types[$this->Type]) ? $types[$this->Type] : null; } - /** * Validate + * * @return ValidationResult **/ - protected function validate(){ + protected function validate() { $valid = true; $message = null; - if($this->Type == 'URL'){ - if($this->URL ==''){ + if($this->Type == 'URL') { + if($this->URL =='') { $valid = false; $message = _t('Linkable.VALIDATIONERROR_EMPTYURL', 'You must enter a URL for a link type of "URL"'); - }else{ + } else { $allowedFirst = array('#', '/'); - if(!in_array(substr($this->URL, 0, 1), $allowedFirst) && !filter_var($this->URL, FILTER_VALIDATE_URL)){ + if(!in_array(substr($this->URL, 0, 1), $allowedFirst) && !filter_var($this->URL, FILTER_VALIDATE_URL)) { $valid = false; $message = _t('Linkable.VALIDATIONERROR_VALIDURL', 'Please enter a valid URL. Be sure to include http:// for an external URL. Or begin your internal url/anchor with a "/" character'); } } - }elseif($this->Type == 'Email'){ - if($this->Email ==''){ + }elseif($this->Type == 'Email') { + if($this->Email =='') { $valid = false; $message = _t('Linkable.VALIDATIONERROR_EMPTYEMAIL', 'You must enter an Email Address for a link type of "Email"'); - }else{ - if(!filter_var($this->Email, FILTER_VALIDATE_EMAIL)){ + } else { + if(!filter_var($this->Email, FILTER_VALIDATE_EMAIL)) { $valid = false; $message = _t('Linkable.VALIDATIONERROR_VALIDEMAIL', 'Please enter a valid Email address'); } } - }else{ - if($this->Type && empty($this->{$this->Type.'ID'})){ + } else { + if($this->Type && empty($this->{$this->Type.'ID'})) { $valid = false; $message = _t('Linkable.VALIDATIONERROR_OBJECT', "Please select a {value} object to link to", array('value' => $this->Type)); } @@ -245,7 +258,4 @@ protected function validate(){ $this->extend('validate', $result); return $result; } - - - } diff --git a/code/forms/EmbeddedObjectField.php b/code/forms/EmbeddedObjectField.php index c922cda..215c7fc 100644 --- a/code/forms/EmbeddedObjectField.php +++ b/code/forms/EmbeddedObjectField.php @@ -8,15 +8,17 @@ * @author **/ class EmbeddedObjectField extends FormField { - + private static $allowed_actions = array( 'update' ); + + protected $editableEmbedCode = false; protected $object; - + protected $message; - + public function setValue($value) { if ($value instanceof EmbeddedObject) { $this->object = $value; @@ -25,14 +27,19 @@ public function setValue($value) { parent::setValue($value); } + public function setEditableEmbedCode($v) { + $this->editableEmbedCode = $v; + return $this; + } + public function getMessage() { return $this->message; } - + public function FieldHolder($properties = array()) { Requirements::css(LINKABLE_PATH . '/css/embeddedobjectfield.css'); Requirements::javascript(LINKABLE_PATH . '/javascript/embeddedobjectfield.js'); - + if ($this->object && $this->object->ID) { $properties['SourceURL'] = TextField::create($this->getName() . '[sourceurl]', '')->setAttribute('placeholder', _t('Linkable.SOURCEURL', 'Source URL')); @@ -42,7 +49,12 @@ public function FieldHolder($properties = array()) { $properties['Height'] = TextField::create($this->getName() . '[height]', _t('Linkable.HEIGHT', 'Height')); $properties['ThumbURL'] = HiddenField::create($this->getName() . '[thumburl]', ''); $properties['Type'] = HiddenField::create($this->getName() . '[type]', ''); - $properties['EmbedHTML'] = HiddenField::create($this->getName() . '[embedhtml]', ''); + if ($this->editableEmbedCode) { + $properties['EmbedHTML'] = TextareaField::create($this->getName() . '[embedhtml]', 'Embed code'); + } else { + $properties['EmbedHTML'] = HiddenField::create($this->getName() . '[embedhtml]', ''); + } + $properties['ObjectDescription'] = TextAreaField::create($this->getName() . '[description]', _t('Linkable.DESCRIPTION', 'Description')); $properties['ExtraClass'] = TextField::create($this->getName() . '[extraclass]', _t('Linkable.CSSCLASS', 'CSS class')); @@ -70,9 +82,9 @@ public function FieldHolder($properties = array()) { public function saveInto(DataObjectInterface $record) { $val = $this->Value(); $field = $this->getName() . 'ID'; - + if (!strlen($val['sourceurl']) && $this->object) { - if($this->object->exists()){ + if($this->object->exists()) { $this->object->delete(); } $record->$field = 0; @@ -82,28 +94,27 @@ public function saveInto(DataObjectInterface $record) { if (!$this->object) { $this->object = EmbeddedObject::create(); } - + $props = array_keys(Config::inst()->get('EmbeddedObject', 'db')); foreach ($props as $prop) { - $this->object->$prop = isset($val[strtolower($prop)]) ? $val[strtolower($prop)] : null; + $this->object->$prop = isset($val[strtolower($prop)]) ? $val[strtolower($prop)] : null; } $this->object->write(); $record->$field = $this->object->ID; } - + public function update(SS_HTTPRequest $request) { if (!SecurityToken::inst()->checkRequest($request)) { return ''; } $url = $request->postVar('URL'); if (strlen($url)) { - $info = Oembed::get_oembed_from_url($url); $info = Embed\Embed::create($url); if ($info) { $object = EmbeddedObject::create(); $object->setFromEmbed($info); - + $this->object = $object; // needed to make sure the check in FieldHolder works out $object->ID = -1; @@ -112,7 +123,7 @@ public function update(SS_HTTPRequest $request) { $this->message = _t('EmbeddedObjectField.ERROR', 'Could not look up provided URL: ' . Convert::raw2xml($url)); return $this->FieldHolder(); } - }else{ + } else { $this->object = null; return $this->FieldHolder(); } diff --git a/code/forms/LinkField.php b/code/forms/LinkField.php index 3b20a40..4b240f4 100644 --- a/code/forms/LinkField.php +++ b/code/forms/LinkField.php @@ -28,7 +28,7 @@ class LinkField extends TextField{ ); - public function Field($properties = array()){ + public function Field($properties = array()) { Requirements::javascript(LINKABLE_PATH . '/javascript/linkfield.js'); return parent::Field(); } @@ -39,29 +39,29 @@ public function Field($properties = array()){ * * @return Form **/ - public function LinkForm(){ + public function LinkForm() { $link = $this->getLinkObject(); $action = FormAction::create('doSaveLink', _t('Linkable.SAVE', 'Save'))->setUseButtonTag('true'); - if(!$this->isFrontend){ + if(!$this->isFrontend) { $action->addExtraClass('ss-ui-action-constructive')->setAttribute('data-icon', 'accept'); } $link = null; - if($linkID = (int)$this->request->getVar('LinkID')){ + if($linkID = (int) $this->request->getVar('LinkID')) { $link = Link::get()->byID($linkID); } $link = $link ? $link : singleton('Link'); $fields = $link->getCMSFields(); - + $title = $link ? _t('Linkable.EDITLINK', 'Edit Link') : _t('Linkable.ADDLINK', 'Add Link'); $fields->insertBefore(HeaderField::create('LinkHeader', $title), _t('Linkable.TITLE', 'Title')); $actions = FieldList::create($action); $form = Form::create($this, 'LinkForm', $fields, $actions); - if($link){ + if($link) { $form->loadDataFrom($link); $fields->push(HiddenField::create('LinkID', 'LinkID', $link->ID)); } @@ -75,13 +75,13 @@ public function LinkForm(){ /** * Either updates the current link or creates a new one * Returns field template to update the interface - * @return String + * @return string **/ - public function doSaveLink($data, $form){ + public function doSaveLink($data, $form) { $link = $this->getLinkObject() ? $this->getLinkObject() : Link::create(); $form->saveInto($link); try { - $link->write(); + $link->write(); } catch (ValidationException $e) { $form->sessionMessage($e->getMessage(), 'bad'); return $form->forTemplate(); @@ -95,31 +95,31 @@ public function doSaveLink($data, $form){ /** * Delete link action - TODO * - * @return String + * @return string **/ - public function doRemoveLink(){ + public function doRemoveLink() { $this->setValue(''); return $this->FieldHolder(); } - + /** * Returns the current link object * * @return Link **/ - public function getLinkObject(){ + public function getLinkObject() { $requestID = Controller::curr()->request->requestVar('LinkID'); - - if($requestID == '0'){ + + if($requestID == '0') { return; } - if(!$this->linkObject){ + if(!$this->linkObject) { $id = $this->Value() ? $this->Value() : $requestID; - if((int)$id){ + if((int) $id) { $this->linkObject = Link::get()->byID($id); - } + } } return $this->linkObject; } @@ -128,19 +128,19 @@ public function getLinkObject(){ /** * Returns the HTML of the LinkForm for the dialog * - * @return String + * @return string **/ - public function LinkFormHTML(){ + public function LinkFormHTML() { return $this->LinkForm()->forTemplate(); } - public function getIsFrontend(){ + public function getIsFrontend() { return $this->isFrontend; } - public function setIsFrontend($bool){ + public function setIsFrontend($bool) { $this->isFrontend = $bool; return $this->this; } diff --git a/composer.json b/composer.json index 81c5ea2..df048fa 100644 --- a/composer.json +++ b/composer.json @@ -23,6 +23,9 @@ "embed/embed": "~2.2.2" }, "extra": { - "installer-name": "linkable" + "installer-name": "linkable", + "branch-alias": { + "dev-master": "1.2.x-dev" + } } } diff --git a/javascript/embeddedobjectfield.js b/javascript/embeddedobjectfield.js index f693e9c..b2d772d 100644 --- a/javascript/embeddedobjectfield.js +++ b/javascript/embeddedobjectfield.js @@ -13,10 +13,10 @@ $.post($(this).data('href'), params, function (data) { button.val(buttonText).removeAttr('disabled'); if (data && data.length) { - container.html($(data).html()); + container.html(data); delete container; } }) } }) -})(jQuery); \ No newline at end of file +})(jQuery); diff --git a/templates/EmbeddedObjectField.ss b/templates/EmbeddedObjectField.ss index 8e05e6c..217032d 100644 --- a/templates/EmbeddedObjectField.ss +++ b/templates/EmbeddedObjectField.ss @@ -18,10 +18,10 @@
$ThumbImage
- +
$ObjectTitle.SmallFieldHolder - +
$Width.SmallFieldHolder @@ -30,11 +30,11 @@ $Height.SmallFieldHolder
- + $ObjectDescription.SmallFieldHolder $ExtraClass.SmallFieldHolder - + $ThumbURL.SmallFieldHolder $Type.SmallFieldHolder $EmbedHTML.SmallFieldHolder