PageRenderTime 50ms CodeModel.GetById 12ms RepoModel.GetById 0ms app.codeStats 0ms

/code/dataobjects/Link.php

https://github.com/Leapfrognz/silverstripe-linkable
PHP | 211 lines | 137 code | 38 blank | 36 comment | 28 complexity | 4b4e055174a6d7215035a85bc7ab48d2 MD5 | raw file
  1. <?php
  2. /**
  3. * Link
  4. *
  5. * @package silverstripe-linkable
  6. * @license BSD License http://www.silverstripe.org/bsd-license
  7. * @author <shea@silverstripe.com.au>
  8. **/
  9. class Link extends DataObject{
  10. private static $db = array(
  11. 'Title' => 'Varchar(255)',
  12. 'Type' => 'Varchar',
  13. 'URL' => 'Varchar(255)',
  14. 'Email' => 'Varchar(255)',
  15. 'Anchor' => 'Varchar(255)',
  16. 'OpenInNewWindow' => 'Boolean'
  17. );
  18. private static $has_one = array(
  19. 'File' => 'File',
  20. 'SiteTree' => 'SiteTree'
  21. );
  22. private static $summary_fields = array(
  23. 'Title',
  24. 'LinkType',
  25. 'LinkURL'
  26. );
  27. /**
  28. * A map of object types that can be linked to
  29. * Custom dataobjects can be added to this
  30. * @var array
  31. **/
  32. private static $types = array(
  33. 'URL' => 'URL',
  34. 'Email' => 'Email address',
  35. 'File' => 'File on this website',
  36. 'SiteTree' => 'Page on this website'
  37. );
  38. public function getCMSFields(){
  39. $fields = parent::getCMSFields();
  40. $types = $this->config()->get('types');
  41. $i18nTypes = array();
  42. foreach ($types as $key => $label) {
  43. $i18nTypes[$key] = _t('Linkable.TYPE'.strtoupper($key), $label);
  44. }
  45. $fields->dataFieldByName('Title')->setTitle(_t('Linkable.TITLE', 'Title'))->setRightTitle(_t('Linkable.OPTIONALTITLE', 'Optional. Will be auto-generated from link if left blank'));
  46. $fields->replaceField('Type', DropdownField::create('Type', _t('Linkable.LINKTYPE', 'Link Type'), $i18nTypes)->setEmptyString(' '), 'OpenInNewWindow');
  47. $fields->replaceField('File', TreeDropdownField::create('FileID', _t('Linkable.FILE', 'File'), 'File', 'ID', 'Title'), 'OpenInNewWindow');
  48. $fields->addFieldToTab('Root.Main', TreeDropdownField::create('SiteTreeID', _t('Linkable.PAGE', 'Page'), 'SiteTree'));
  49. $fields->addFieldToTab('Root.Main', $newWindow = CheckboxField::create('OpenInNewWindow', _t('Linkable.OPENINNEWWINDOW', 'Open link in a new window')));
  50. $newWindow->displayIf('Type')->isNotEmpty();
  51. $fields->dataFieldByName('URL')->displayIf("Type")->isEqualTo("URL");
  52. $fields->dataFieldByName('Email')->setTitle(_t('Linkable.EMAILADDRESS', 'Email Address'))->displayIf("Type")->isEqualTo("Email");
  53. $fields->dataFieldByName('FileID')->displayIf("Type")->isEqualTo("File");
  54. $fields->dataFieldByName('SiteTreeID')->displayIf("Type")->isEqualTo("SiteTree");
  55. if($this->SiteTreeID && !$this->SiteTree()->isPublished()){
  56. $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'));
  57. }
  58. $fields->addFieldToTab('Root.Main', $anchor = TextField::create('Anchor', _t('Linkable.ANCHOR', 'Anchor')), 'OpenInNewWindow');
  59. $anchor->setRightTitle('Include # at the start of your anchor name');
  60. $anchor->displayIf("Type")->isEqualTo("SiteTree");
  61. $this->extend('updateCMSFields', $fields);
  62. return $fields;
  63. }
  64. /**
  65. * If the title is empty, set it to getLinkURL()
  66. * @return String
  67. **/
  68. public function onAfterWrite(){
  69. parent::onAfterWrite();
  70. if(!$this->Title){
  71. if($this->Type == 'URL' || $this->Type == 'Email'){
  72. $this->Title = $this->{$this->Type};
  73. }elseif($this->Type == 'SiteTree'){
  74. $this->Title = $this->SiteTree()->MenuTitle;
  75. }else{
  76. if($component = $this->getComponent($this->Type)){
  77. $this->Title = $component->Title;
  78. }
  79. }
  80. if(!$this->Title){
  81. $this->Title = 'Link-' . $this->ID;
  82. }
  83. $this->write();
  84. }
  85. }
  86. /**
  87. * Renders an HTML anchor tag for this link
  88. * @return String
  89. **/
  90. public function forTemplate(){
  91. if($url = $this->getLinkURL()){
  92. $title = $this->Title ? $this->Title : $url; // legacy
  93. $target = $this->getTargetAttr();
  94. return "<a href='$url' $target>$title</a>";
  95. }
  96. }
  97. /**
  98. * Works out what the URL for this link should be based on it's Type
  99. * @return String
  100. **/
  101. public function getLinkURL(){
  102. if(!$this->ID) return;
  103. if($this->Type == 'URL'){
  104. return $this->URL;
  105. }elseif($this->Type == 'Email'){
  106. return $this->Email ? "mailto:$this->Email" : null;
  107. }else{
  108. if($this->Type && $component = $this->getComponent($this->Type)){
  109. if(!$component->exists()){
  110. return false;
  111. }
  112. if($component->hasMethod('Link')){
  113. return $component->Link() . $this->Anchor;
  114. }else{
  115. return "Please implement a Link() method on your dataobject \"$this->Type\"";
  116. }
  117. }
  118. }
  119. }
  120. /**
  121. * Gets the html target attribute for the anchor tag
  122. * @return String
  123. **/
  124. public function getTargetAttr(){
  125. return $this->OpenInNewWindow ? "target='_blank'" : '';
  126. }
  127. /**
  128. * Gets the description label of this links type
  129. * @return String
  130. **/
  131. public function getLinkType(){
  132. $types = $this->config()->get('types');
  133. return isset($types[$this->Type]) ? $types[$this->Type] : null;
  134. }
  135. /**
  136. * Validate
  137. * @return ValidationResult
  138. **/
  139. protected function validate(){
  140. $valid = true;
  141. $message = null;
  142. if($this->Type == 'URL'){
  143. if($this->URL ==''){
  144. $valid = false;
  145. $message = _t('Linkable.VALIDATIONERROR_EMPTYURL', 'You must enter a URL for a link type of "URL"');
  146. }else{
  147. $allowedFirst = array('#', '/');
  148. if(!in_array(substr($this->URL, 0, 1), $allowedFirst) && !filter_var($this->URL, FILTER_VALIDATE_URL)){
  149. $valid = false;
  150. $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');
  151. }
  152. }
  153. }elseif($this->Type == 'Email'){
  154. if($this->Email ==''){
  155. $valid = false;
  156. $message = _t('Linkable.VALIDATIONERROR_EMPTYEMAIL', 'You must enter an Email Address for a link type of "Email"');
  157. }else{
  158. if(!filter_var($this->Email, FILTER_VALIDATE_EMAIL)){
  159. $valid = false;
  160. $message = _t('Linkable.VALIDATIONERROR_VALIDEMAIL', 'Please enter a valid Email address');
  161. }
  162. }
  163. }else{
  164. if(!$this->getComponent($this->Type)->exists()){
  165. $valid = false;
  166. $message = _t('Linkable.VALIDATIONERROR_OBJECT', "Please select a {value} object to link to", array('value' => $this->Type));
  167. }
  168. }
  169. $result = ValidationResult::create($valid, $message);
  170. $this->extend('validate', $result);
  171. return $result;
  172. }
  173. }