diff --git a/composer.json b/composer.json index c71031f..f2b1a75 100644 --- a/composer.json +++ b/composer.json @@ -17,9 +17,16 @@ "require": { "silverstripe/framework": "^4 || ^5", "unclecheese/display-logic": "^2 || ^3", - "giggsey/libphonenumber-for-php": "^8.0" + "giggsey/libphonenumber-for-php": "^8.0", + "sheadawson/silverstripe-dependentdropdownfield": "dev-master" }, "extra": { "installer-name": "link" - } + }, + "repositories": [ + { + "type": "vcs", + "url": "https://github.com/anhld/silverstripe-dependentdropdownfield" + } + ] } diff --git a/src/extensions/LinkSiteTree.php b/src/extensions/LinkSiteTree.php index 2d2ec90..f9879b6 100644 --- a/src/extensions/LinkSiteTree.php +++ b/src/extensions/LinkSiteTree.php @@ -3,6 +3,8 @@ namespace gorriecoe\Link\Extensions; use gorriecoe\Link\Models\Link; +use Page; +use Sheadawson\DependentDropdown\Forms\DependentDropdownField; use SilverStripe\CMS\Model\SiteTree; use SilverStripe\Forms\FieldList; use SilverStripe\Forms\TreeDropdownField; @@ -26,6 +28,7 @@ class LinkSiteTree extends DataExtension * @var array */ private static $db = [ + 'QueryString' => 'Varchar(255)', 'Anchor' => 'Varchar(255)', ]; @@ -34,7 +37,7 @@ class LinkSiteTree extends DataExtension * @var array */ private static $has_one = [ - 'SiteTree' => SiteTree::class, + 'SiteTree' => SiteTree::class ]; /** @@ -49,7 +52,7 @@ class LinkSiteTree extends DataExtension /** * Defines the label used in the sitetree dropdown. - * @param String $sitetree_field_label + * @param string $sitetree_field_label */ private static $sitetree_field_label = 'MenuTitle'; @@ -61,7 +64,33 @@ public function updateCMSFields(FieldList $fields) { $owner = $this->owner; $config = $owner->config(); - $sitetree_field_label = $config->get('sitetree_field_label') ? : 'MenuTitle'; + $sitetree_field_label = $config->get('sitetree_field_label') ?: 'MenuTitle'; + + // Get source data for the ElementID field + $anchorOptions = function ($pageID) { + $anchorOptions = []; + $page = Page::get_by_id($pageID); + if($page) { + $list = $page->getAnchorsOnPage(); + $anchorOptions = array_combine($list, $list); + } + + if (!empty($anchorOptions)) { + $results = array_merge( + ['' => _t(__CLASS__ . '.SELECTANCHOR', '(Select an anchor)')], + $anchorOptions + ); + } else { + $results = [ + '' => _t(__CLASS__ . '.ANCHORSNOTAVAILABLE', '(Anchors are not available for the selected page)') + ]; + } + + return $results; + }; + + // Get field label for the ElementID field + $anchorLabel = _t(__CLASS__ . '.AnchorLabel', 'Anchor on page'); // Insert site tree field after the file selection field $fields->insertAfter( @@ -72,12 +101,18 @@ public function updateCMSFields(FieldList $fields) _t(__CLASS__ . '.PAGE', 'Page'), SiteTree::class ) - ->setTitleField($sitetree_field_label), + ->setTitleField($sitetree_field_label) + ->setHasEmptyDefault(true), TextField::create( + 'Querystring', + _t(__CLASS__ . '.QUERYSTRING', 'Querystring') + ), + DependentDropdownField::create( 'Anchor', - _t(__CLASS__ . '.ANCHOR', 'Anchor/Querystring') + $anchorLabel, + $anchorOptions ) - ->setDescription(_t(__CLASS__ . '.ANCHORINFO', 'Include # at the start of your anchor name or, ? at the start of your querystring')) + ->setDepends($sitetreeField), ) ->displayIf('Type')->isEqualTo('SiteTree')->end() ); @@ -88,9 +123,6 @@ public function updateCMSFields(FieldList $fields) } } - /** - * @return bool - */ public function updateIsCurrent(&$status) { $owner = $this->owner; @@ -99,14 +131,11 @@ public function updateIsCurrent(&$status) isset($owner->SiteTreeID) && $owner->CurrentPage instanceof SiteTree && $currentPage = $owner->CurrentPage - ){ + ) { $status = $currentPage === $owner->SiteTree() || $currentPage->ID === $owner->SiteTreeID; } } - /** - * @return bool - */ public function updateIsSection(&$status) { $owner = $this->owner; @@ -115,14 +144,11 @@ public function updateIsSection(&$status) isset($owner->SiteTreeID) && $owner->CurrentPage instanceof SiteTree && $currentPage = $owner->CurrentPage - ){ + ) { $status = $owner->isCurrent() || in_array($owner->SiteTreeID, $currentPage->getAncestors()->column()); } } - /** - * @return bool - */ public function updateIsOrphaned(&$status) { $owner = $this->owner; @@ -131,7 +157,7 @@ public function updateIsOrphaned(&$status) isset($owner->SiteTreeID) && $owner->CurrentPage instanceof SiteTree && $currentPage = $owner->CurrentPage - ){ + ) { // Always false for root pages if (empty($owner->SiteTree()->ParentID)) { $status = false; @@ -139,8 +165,25 @@ public function updateIsOrphaned(&$status) } // Parent must exist and not be an orphan itself - $parent = $this->Parent(); + $parent = $owner->Parent(); $status = !$parent || !$parent->exists() || $parent->isOrphaned(); } } + + + /** + * {@inheritDoc} + */ + public function onBeforeWrite() + { + parent::onBeforeWrite(); + + $owner = $this->getOwner(); + + if (empty($owner->Title) && $owner->Type === "SiteTree" && $owner->SiteTreeID && $owner->ElementID && $element = $owner->Element()) { + $owner->Title = $element->Title; + } + $owner->Querystring = $owner->Querystring ? str_replace('?', '', (string) $owner->QueryString) : $owner->Querystring; + $owner->Anchor = $owner->Anchor ? str_replace('#', '', (string) $owner->Anchor) : $owner->Anchor; + } } diff --git a/src/models/Link.php b/src/models/Link.php index 5fe600b..b457407 100644 --- a/src/models/Link.php +++ b/src/models/Link.php @@ -67,9 +67,9 @@ class Link extends DataObject private static $has_one = [ 'File' => File::class ]; - + private static $owns = [ - 'File', + 'File', ]; /** @@ -276,7 +276,7 @@ public function getCMSMainFields() ->displayIf('Type')->isEqualTo('Phone')->end(), CheckboxField::create( 'OpenInNewWindow', - _t(__CLASS__ . '.OPENINNEWWINDOW','Open link in a new window') + _t(__CLASS__ . '.OPENINNEWWINDOW', 'Open link in a new window') ) ->displayIf('Type')->isEqualTo('URL') ->orIf()->isEqualTo('File') @@ -502,7 +502,7 @@ public function getTypes() $allowed_types = $this->allowed_types; } if ($allowed_types) { - foreach ($allowed_types as $type) { + foreach ($allowed_types as $type) { if (!array_key_exists($type, $types)) { user_error("{$type} is not a valid link type"); } @@ -583,7 +583,24 @@ public function getLinkURL() $LinkURL = false; } if ($component->hasMethod('Link')) { - $LinkURL = $component->Link() . $this->Anchor; + $LinkURL = $component->Link(); + + // add QueryString + if(!empty($this->QueryString)) { + if(strpos($LinkURL, '?') === false && strpos($this->QueryString, '?') === false) { + $LinkURL .= '?'; + } + $LinkURL .= $this->QueryString; + } + + // add anchor + if(!empty($this->Anchor)) { + if(strpos($LinkURL, '#') === false && strpos($this->Anchor, '#') === false) { + $LinkURL .= '#'; + } + $LinkURL .= $this->Anchor; + } + } else { $LinkURL = _t( __CLASS__ . '.LINKMETHODMISSING', @@ -612,7 +629,7 @@ public function getClass() { if ($this->SelectedStyle) { $this->setClass($this->SelectedStyle); - } else if ($this->template_style) { + } elseif ($this->template_style) { $this->setClass($this->template_style); } @@ -826,7 +843,9 @@ public function getRenderTemplates() { $ClassName = $this->ClassName; - if (is_object($ClassName)) $ClassName = get_class($ClassName); + if (is_object($ClassName)) { + $ClassName = get_class($ClassName); + } if (!is_subclass_of($ClassName, DataObject::class)) { throw new InvalidArgumentException($ClassName . ' is not a subclass of DataObject');