diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..723ef36 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +.idea \ No newline at end of file diff --git a/_config.php b/_config.php new file mode 100755 index 0000000..b3d9bbc --- /dev/null +++ b/_config.php @@ -0,0 +1 @@ +Elements()->renderWith(static::class.'_AccordionArea'); + } +} diff --git a/src/Elements/CustomSnippetElement.php b/src/Elements/CustomSnippetElement.php new file mode 100755 index 0000000..db81241 --- /dev/null +++ b/src/Elements/CustomSnippetElement.php @@ -0,0 +1,42 @@ +replaceField( + 'HTML', + TextareaField::create('HTML') + ); + + return $fields; + } +} diff --git a/src/Elements/ElementListExtension.php b/src/Elements/ElementListExtension.php new file mode 100644 index 0000000..41fe7bf --- /dev/null +++ b/src/Elements/ElementListExtension.php @@ -0,0 +1,15 @@ +owner->getRequest()->param('ID'); + + if (!$id) { + user_error('No element ID supplied', E_USER_ERROR); + return false; + } + + /** @var SiteTree $elementOwner */ + //$elementOwner = $this->owner->data(); + + /*$elementalAreaRelations = $this->owner->getElementalRelations(); + + if (!$elementalAreaRelations) { + user_error(get_class($this->owner) . ' has no ElementalArea relationships', E_USER_ERROR); + return false; + }*/ + + $element = BaseElement::get()->byID($id); + + if ($element) { + return $element->getController(); + } + + user_error('Element $id not found', E_USER_ERROR); + return false; + } +} diff --git a/src/Elements/EmptyPageController.php b/src/Elements/EmptyPageController.php new file mode 100644 index 0000000..9ba50f9 --- /dev/null +++ b/src/Elements/EmptyPageController.php @@ -0,0 +1,23 @@ +dataRecord->Title = SiteConfig::current_site_config()->getField('Title'); + + $this->setFailover($this->dataRecord); + } + + public static function DefaultContainer() + { + return \Page::DefaultContainer(); + } +} diff --git a/src/Elements/InstagramElement.php b/src/Elements/InstagramElement.php new file mode 100755 index 0000000..1aecbc2 --- /dev/null +++ b/src/Elements/InstagramElement.php @@ -0,0 +1,103 @@ + 'Varchar(255)', + 'Tag' => 'Varchar(255)', + 'DisplayProfile' => 'Boolean(0)', + 'DisplayBiography' => 'Boolean(0)', + 'DisplayGallery' => 'Boolean(0)', + 'DisplayCaptions' => 'Boolean(0)', + ]; + + private static $defaults = [ + 'DisplayGallery' => true, + ]; + + public function getType() + { + return self::$singular_name; + } + + /** + * @return array + */ + public function getAttributes(): array + { + return [ + 'data-username' => $this->Username, + 'data-display-profile' => $this->DisplayProfile, + 'data-display-biography' => $this->DisplayBiography, + 'data-display-gallery' => $this->DisplayGallery, + 'data-display-captions' => $this->DisplayCaptions, + 'data-items' => 12, + ]; + } + /** + * Custom attributes to process. + * + * @param array $attributes + * + * @return string + */ + public function AttributesHTML($attributes = null): string + { + if (!$attributes) { + $attributes = $this->getAttributes(); + } + + $attributes = (array) $attributes; + + $attributes = array_filter($attributes, static function ($v) { + return ($v || $v === 0 || $v === '0'); + }); + + // Create markup + $parts = []; + + foreach ($attributes as $name => $value) { + if ($value === true) { + $value = $name; + } else if (is_scalar($value)) { + $value = (string) $value; + } else { + $value = json_encode($value); + } + + $parts[] = sprintf('%s=%s', Convert::raw2att($name), Convert::raw2att($value)); + } + + return implode(' ', $parts); + } + + public function FeedLink() + { + return 'https://www.instagram.com/'.($this->Username ? $this->Username : 'explore/tags/'.$this->Tag).'/'; + } + + public function FeedTitle() + { + return ($this->Username ? '@'.$this->Username : '#'.$this->Tag); + } +} diff --git a/src/Elements/MapElement.php b/src/Elements/MapElement.php new file mode 100755 index 0000000..3b8796a --- /dev/null +++ b/src/Elements/MapElement.php @@ -0,0 +1,98 @@ +remove('HTML'); + + $tab = $fields->findOrMakeTab('Root.MapPins'); + $tab->setTitle('Description'); + $tab->push(HTMLEditorField::create('HTML', 'Content')); + + $fields->addFieldsToTab('Root.Main', [ + NumericField::create('MapZoom', 'Initial Map Zoom (enter a number from 0 to 24)'), + GridField::create( + 'Locations', + 'Locations', + $this->owner->Locations(), + $cfg = GridFieldConfig_RelationEditor::create(100) + ) + ]); + + $cfg->getComponentByType(GridFieldDataColumns::class)->setFieldFormatting([ + 'ShowAtMap' => static function ($v, $obj) { + return $v ? 'YES' : 'NO'; + } + ]); + $cfg->addComponent(new BulkManager()); + + return $fields; + } + + public static function MapAPIKey(): string + { + $type = self::config()->get('map_type'); + + switch ($type) { + case 'mapbox': + $key = MapboxField::getAccessToken(); + break; + case 'google-maps': + $cfg = Config::inst()->get(GoogleMapField::class, 'default_options'); + $key = $cfg['api_key']; + break; + default: + $key = ''; + break; + } + + return $key; + } +} diff --git a/src/Elements/SliderElement.php b/src/Elements/SliderElement.php new file mode 100755 index 0000000..0e7302d --- /dev/null +++ b/src/Elements/SliderElement.php @@ -0,0 +1,133 @@ + 'Int', + ]; + + private static $extensions = [ + FlexSlider::class, + ]; + + private static $owns = [ + 'Slides', + ]; + + private $items; + + public function getType() + { + return self::$singular_name; + } + + public function getSlideWidth() + { + return self::config()->get('slide_width'); + } + + public function getSlideHeight() + { + return self::config()->get('slide_height'); + } + + public function getCMSFields() + { + $fields = parent::getCMSFields(); + + // remove in case you don't need to provide this functionality + $fields->removeByName([ + 'ConfigHD', + 'Animation', + 'Loop', + 'Animate', + 'ThumbnailNav', + 'SliderControlNav', + 'SliderDirectionNav', + 'CarouselControlNav', + 'CarouselDirectionNav', + 'CarouselThumbnailCt', + ]); + + $fields->addFieldsToTab('Root.Settings', [ + NumericField::create('Interval', 'Auto-play Interval'), + ]); + + $grid = $fields->dataFieldByName('Slides'); + if ($grid) { + $config = $grid->getConfig(); + + $columns = new GridFieldEditableColumns(); + $columns->setDisplayFields([ + 'Hide' => [ + 'title' => 'Hide it?', + 'field' => CheckboxField::class, + ], + ]); + + $config->addComponent($columns); + } + + return $fields; + } + + /** + * @return mixed + */ + public function getSlideShow() + { + if ($this->items) { + return $this->items; + } + + $date = date('Y-m-d H:i:s'); + $this->items = $this->Slides()->filter([ + 'Hide' => '0', + ])->filterByCallback(static function ($item, $list) use ($date) { + $on = $item->getField('DateOn'); + $off = $item->getField('DateOff'); + + return ($on <= $date) && (!$off || $off > $date); + })->sort('SortOrder'); + + return $this->items; + } + + public function onBeforeWrite() + { + parent::onBeforeWrite(); + + if (!$this->getField('Interval')) { + $this->setField('Interval', 5000); + } + } +} diff --git a/src/Elements/TeamMembersElement.php b/src/Elements/TeamMembersElement.php new file mode 100755 index 0000000..574f1ba --- /dev/null +++ b/src/Elements/TeamMembersElement.php @@ -0,0 +1,30 @@ +sort('RAND()'); + } +} diff --git a/src/Extensions/BaseElementEx.php b/src/Extensions/BaseElementEx.php new file mode 100755 index 0000000..3bc6552 --- /dev/null +++ b/src/Extensions/BaseElementEx.php @@ -0,0 +1,89 @@ +owner; + parent::updateCMSFields($fields); + $tab = $fields->findOrMakeTab('Root.Settings'); + + $tab->push(LiteralField::create( + 'ClassName', + '
' + .'
Class
' + .'
'.$obj->getField('ClassName').'
' + .'
' + )); + + if($this->owner->ID) { + $tab->push(TreeDropdownField::create( + 'MoveElementIDToPage', + 'Move an element to page', + SiteTree::class + )->setEmptyString('(select an element to move)')); + } + } + + public static function MoveElementToPage($ID, $moveToID) + { + $el = BaseElement::get()->byID($ID); + $page = SiteTree::get()->byID($moveToID); + if (!$page || !$el) { + return false; + } + + $el->setField('ParentID', $page->ElementalArea()->ID); + $el->write(); + + return true; + } + + public function updateCMSEditLink(&$link): void + { + if (!$this->owner->inlineEditable()) { + $page = $this->owner->getPage(); + + if (!$page || $page instanceof SiteTree) { + return; + } + + // As non-page DataObject's are managed via GridFields, we have to grab their CMS edit URL + // and replace the trailing /edit/ with a link to the nested ElementalArea edit form + $relationName = $this->owner->getAreaRelationName(); + $link = preg_replace( + '/edit\/?$/', + "ItemEditForm/field/{$relationName}/item/{$this->owner->ID}/edit/", + $page->CMSEditLink() + ); + } + } + + + public function onBeforeWrite() + { + parent::onBeforeWrite(); + + $moveID = $this->owner->getField('MoveElementIDToPage'); + if($this->owner->ID && $moveID) { + self::MoveElementToPage($this->owner->ID, $moveID); + } + } +} diff --git a/src/Extensions/ElementContentWidget.php b/src/Extensions/ElementContentWidget.php new file mode 100755 index 0000000..eed6fe6 --- /dev/null +++ b/src/Extensions/ElementContentWidget.php @@ -0,0 +1,15 @@ + 'Small (300px)', + '400' => 'Medium (400px)', + '600' => 'Big (600px)', + ]; + + private static $available_widths = [ + '300' => 'Small (300px)', + '400' => 'Medium (400px)', + '600' => 'Big (600px)', + ]; + + private static $available_ratios = [ + '1:1' => '1:1', + '3:2' => '3:2', + '2:3' => '2:3', + '16:9' => '16:9' + ]; + + private static $db = [ + 'Resize' => 'Boolean(1)', + 'ManualWidth' => 'Boolean(0)', + 'ImageHeight' => 'Float', + 'ImageWidth' => 'Float', + 'ImageAspectRatio' => 'Text', + 'Content' => 'HTMLText', + ]; + + private static $has_one = [ + 'ImageLink' => Link::class, + ]; + + public function updateCMSFields(FieldList $fields) + { + parent::updateCMSFields($fields); + + $fields->insertBefore( + 'Image', + LinkField::create('ImageLinkID', 'Link') + ); + + $this->owner->ImageHeight = $this->getHeight(); + + $heights = Config::inst()->get(__CLASS__, 'available_heights'); + $widths = Config::inst()->get(__CLASS__, 'available_widths'); + $ratios = Config::inst()->get(__CLASS__, 'available_ratios'); + + $fields->replaceField('Resize', CheckboxField::create( + 'Resize', + 'Would you like to scale image?' + )); + $fields->removeByName(['ManualWidth','ImageWidth','ImageAspectRatio',]); + + if (count($heights)) { + $fields->replaceField( + 'ImageHeight', + CompositeField::create( + CheckboxField::create( + 'ManualAspectRatio', + 'Set Aspect Ratio', + ($this->owner->getField('ImageAspectRatio') ? '1' : '0') + ), + DropdownField::create( + 'ImageAspectRatio', + 'Image Aspect Ratio (width:height)', + $ratios + ) + ->setEmptyString('(original)') + ->displayIf('ManualAspectRatio')->isChecked() + ->andIf('ManualWidth')->isNotChecked() + ->end(), + DropdownField::create( + 'ImageHeight', + 'Image Height', + $heights, + $this->getHeight() + ) + ->setEmptyString('(auto)') + ->displayIf('Resize')->isChecked()->end(), + CheckboxField::create('ManualWidth', 'Set Width Manually') + ->displayIf('Resize')->isChecked() + ->andIf('ManualAspectRatio')->isNotChecked() + ->end(), + DropdownField::create( + 'ImageWidth', + 'Image Width', + $widths + ) + ->setEmptyString('(auto)') + ->displayIf('ManualWidth')->isChecked() + ->end() + ) + ); + } else { + $fields->dataFieldByName('ImageHeight') + ->setValue($this->getHeight()); + } + } + + public function ImageResized() + { + $image = $this->owner->Image(); + + if (!$this->owner->Resize) { + return $image; + } + + $width = $this->getWidth(); + $height = $this->getHeight(); + $ratio = $this->owner->getField('ImageAspectRatio'); + + if ($ratio) { + $v = explode(':', $this->owner->getField('ImageAspectRatio')); + $x = $v[0]; + $y = $v[1]; + + if ($width > 0 && $width !== 'auto') { + $height = $width*$y/$x; + echo 'a1'; + } elseif ($height && $height > 0) { + $width = $height*$x/$y; + echo 'a2'; + } + var_dump($width); + var_dump($height); + } + + if (!$width || $width === 'auto') { + return $height > 0 + ? $image->ScaleHeight($height) + : $image; + } + + return $height > 0 + ? $image->FocusFill($width, $height) + : $image->ScaleWidth($width); + } + + public function getWidth() + { + $obj = $this->owner; + return $obj->getField('ManualWidth') && $obj->getField('ImageWidth') + ? $obj->getField('ImageWidth') + : $obj->getColumnWidthRecursive(); + } + + public function getHeight() + { + $height = $this->owner->getField('ImageHeight'); + if ($height > 0) { + return $height; + } + + $sibling = $this->owner->getSibling(false, [ + 'ImageHeight:GreaterThan' => '0' + ]); + + if ($sibling && $sibling->getField('ImageHeight')) { + return $sibling->getField('ImageHeight'); + } + + return 0; + } +} diff --git a/src/Extensions/ElementRows.php b/src/Extensions/ElementRows.php new file mode 100755 index 0000000..4fca652 --- /dev/null +++ b/src/Extensions/ElementRows.php @@ -0,0 +1,303 @@ + 'Fixed container', + 'container-fluid' => 'Fluid Container', + ]; + + private static $db = [ + 'ContainerType' => 'Varchar(254)', + //'SidebarOnly' => 'Boolean(0)', + 'Size' => 'Enum("1,2,3,4,5,6,7,8,9,10,11,12,auto","auto")', + ]; + + public function updateCMSFields(FieldList $fields) + { + $obj = $this->owner; + parent::updateCMSFields($fields); + + $fields->removeByName(['AvailableGlobally', 'TopPageLocale', 'TopPageID']); + //$fields->removeByName('SidebarOnly'); + + // move available globaly to main tab + $tab = $fields->findOrMakeTab('Root.Main'); + $tab->push(CheckboxField::create('AvailableGlobally')); + //$tab->push(CheckboxField::create('SidebarOnly', 'Hidden (Sidebar Only)')); + + // container type + if ($this->isRoot()) { + $tab->push(DropdownField::create( + 'ContainerType', + _t(__CLASS__.'.CONTAINERTYPE', 'Container Type'), + self::$container_styles + )); + } else { + $fields->removeByName('ContainerType'); + } + + // site-specific + $fields->removeByName('ContainerType'); + + // column size + if ($this->isColumn()) { + $sizes = $obj->dbObject('Size'); + + $sizeDropdown = DropdownField::create( + 'Size', + _t( + __CLASS__.'.SIZE', + 'Column Width (max 12 cols)' + ), + array_combine( + array_values($sizes->enumValues()), + [ + '8.3% (1 of 12)', + '16.6% (2 of 12)', + '25% (3 of 12)', + '33% (4 of 12)', + '41.6% (5 of 12)', + '50% (6 of 12)', + '58.3% (7 of 12)', + '66.4% (8 of 12)', + '74.7% (9 of 12)', + '83% (10 of 12)', + '91.3% (11 of 12)', + '100% (12 of 12)', + 'auto', + ] + ) + ); + $tab->push($sizeDropdown); + + // set default size if size field wasn't set or if it's new object without title set and the size is default + $size = $obj->getField('Size'); + if (!$size || (!$obj->getField('Title') && $size === 'auto')) { + $sibling = $this->getSibling(); + + $defaultSize = $sizes->getDefaultValue(); + $defaultSize = $sibling ? $sibling->getField('Size') : $defaultSize; + + $obj->setField('Size', $defaultSize); + $sizeDropdown->setValue($defaultSize); + } + } else { + $fields->removeByName('Size'); + } + + // move parent elements + if ($this->isList()) { + $currEls = $obj->getField('Elements')->Elements(); + if ($currEls->count()) { + $tab->push(DropdownField::create( + 'MoveElementIDToParent', + 'Move an element from the current list to parent', + $currEls->map('ID', 'Title') + )->setEmptyString('(select an element to move)')); + } + + $parentEls = $obj->Parent()->Elements()->exclude('ID', $obj->ID); + if ($parentEls->count()) { + $tab->push(DropdownField::create( + 'MoveElementIDFromParent', + 'Move an element from the parent to the current list', + $parentEls->map('ID', 'Title') + )->setEmptyString('(select an element to move)')); + } + } + } + + public function getWidthPercetage() + { + return $this->isColumn() ? $this->owner->getField('Size') / self::colsNumber() * 100 : false; + } + + public function isList() + { + return is_a($this->owner, ElementList::class) && !is_a($this->owner, AccordionElement::class); + } + + public function isRow() + { + if (!$this->isList()) { + return false; + } + + return true; + } + + public function isColumn() + { + if (!$this->isRoot()) { + return true; + } + + return false; + } + + public function isRoot() + { + $parent = $this->owner->Parent()->getOwnerPage(); + if (is_a($parent, 'Page')) { + return true; + } + + return false; + } + + public function getSibling($any = true, $filter = [], $exclude = []) + { + $class = $any ? $this->owner->baseClass() : $this->owner->ClassName; + + return $class::get()->filter(array_merge( + ['ParentID' => $this->owner->Parent()->ID], + $filter + ))->exclude(array_merge( + ['ID' => $this->owner->ID], + $exclude + ))->last(); + } + + public function getColumnSizeRecursive($object = null) + { + $object = $object ? $object : $this->owner; + + if ($object->isColumn() && $object->getField('Size')) { + return $object->getField('Size'); + } + + $parent = $object->Parent()->getOwnerPage(); + + if (is_a($parent, 'Page')) { + return ($this->owner->getField('ContainerType') === 'container-fluid') ? false : self::colsNumber(); + } + + return $object->getColumnSizeRecursive($parent); + } + + public function getColumnWidthRecursive($object = null, $max = null) + { + $max = $max ? $max : self::maxWidth(); + + $object = $object ? $object : $this->owner; + + if (!$object->isRoot()) { + $size = $object->getField('Size'); + $cols = self::colsNumber(); + + if ($size === 'auto') { + return $size; + } + + $max = $size ? $max / ($cols / $size) : $max; + $parent = $object->Parent()->getOwnerPage(); + + return $this->getColumnWidthRecursive($parent, $max); + } + + return $max; + } + + public static function colsNumber() + { + $db = Config::inst()->get(self::class, 'db'); + $sizes = $db['Size']; + $sizes = preg_replace('!Enum\("([0-9A-z,]+)","([0-9A-z]+)"\)!i', '$1', $sizes); + $sizes = explode(',', $sizes); + + // remove auto + $k = array_search('auto', $sizes); + if ($k !== false) { + unset($sizes[$k]); + } + + return max($sizes); + } + + public static function maxWidth() + { + return Config::inst()->get(self::class, 'container_max_width'); + } + + public function ExtraClass() + { + $object = $this->owner; + + return $object->getField('ExtraClass') + .( + $this->isColumn() + ? ' '.Config::inst()->get(self::class, 'column_class') + .($object->getField('Size') === 'auto' ? '' : '-'.$object->getField('Size')) + : '' + ); + } + + /* + * if it's root element and it doesn't contain any container styles + * add the first one + */ + public function ContainerClass() + { + $type = $this->owner->getField('ContainerType'); + $container_styles = array_keys(self::$container_styles); + + if (!$type && $this->isRoot()) { + $type = \Page::DefaultContainer(); + } + + return $type; + } + + public static function MoveElement($moveID, $targetID) + { + $el = BaseElement::get_by_id($moveID); + if (!$el) { + return false; + } + + $el->setField('ParentID', $targetID); + $el->write(); + + return true; + } + + public function onBeforeWrite() + { + parent::onBeforeWrite(); + + $moveID = $this->owner->getField('MoveElementIDFromParent'); + $targetID = $moveID ? $this->owner->Elements()->ID : null; + + if ($moveID && $targetID) { + self::MoveElement($moveID, $targetID); + } + + $moveID = $this->owner->getField('MoveElementIDToParent'); + $targetID = $moveID ? $this->owner->Parent()->ID : null; + + if ($moveID && $targetID) { + self::MoveElement($moveID, $targetID); + } + } +} diff --git a/src/Extensions/ElementalArea.php b/src/Extensions/ElementalArea.php new file mode 100755 index 0000000..7f03961 --- /dev/null +++ b/src/Extensions/ElementalArea.php @@ -0,0 +1,49 @@ +Elements() instanceof UnsavedRelationList) { + return ArrayList::create(); + } + + $controllers = ArrayList::create(); + $items = $this->Elements()->filterByCallback(static function (BaseElement $item) { + return $item->canView(); + }); + + if ($items !== null) { + foreach ($items as $element) { + $controller = $element->getController(); + $controllers->push($controller); + } + } + + return $controllers; + } + + /** + * A cache-aware accessor for the elements + * @return ArrayList|HasManyList|BaseElement[] + */ + public function Elements() + { + return $this->owner->Elements();//->exclude('SidebarOnly', true); + } +} diff --git a/src/Extensions/MapExtension.php b/src/Extensions/MapExtension.php new file mode 100755 index 0000000..adb2250 --- /dev/null +++ b/src/Extensions/MapExtension.php @@ -0,0 +1,73 @@ + 'Int', + ]; + + private static $many_many = [ + 'Locations' => MapPin::class, + ]; + + private static $owns = [ + 'Locations', + ]; + + public function updateCMSFields(FieldList $fields): void + { + parent::updateCMSFields($fields); + + $fields->removeByName('Locations'); + $fields->addFieldsToTab('Root.MapPins', [ + NumericField::create('MapZoom', 'Initial Map Zoom (enter a number from 0 to 24)'), + GridField::create( + 'Locations', + 'Locations', + $this->owner->Locations(), + $cfg = GridFieldConfig_RelationEditor::create(100) + ) + ]); + + $cfg->getComponentByType(GridFieldDataColumns::class)->setFieldFormatting([ + 'ShowAtMap' => static function ($v, $obj) { + return $v ? 'YES' : 'NO'; + } + ]); + + $fields->findOrMakeTab('Root.MapPins')->setTitle('Locations'); + } + + public function getGeoJSON(): string + { + $locs = $this->owner->Locations()->filter('ShowAtMap', true); + + $pins = []; + foreach ($locs as $off) { + $pins[] = $off->getGeo(); + } + + return json_encode([ + 'type' => 'MarkerCollection', + 'features' => $pins + ]); + } +} diff --git a/src/Extensions/UserDefinedFormExtension.php b/src/Extensions/UserDefinedFormExtension.php new file mode 100755 index 0000000..a323ca0 --- /dev/null +++ b/src/Extensions/UserDefinedFormExtension.php @@ -0,0 +1,79 @@ + 'HTMLText', + 'RedirectOnComplete' => 'Boolean(0)', + 'RedirectOnCompleteURL' => 'Varchar(255)', + ];*/ + + private static $many_many = [ + 'SubmissionColumns' => EditableFormField::class, + ]; + + public function updateCMSFields(FieldList $fields) + { + parent::updateCMSFields($fields); + + $fields->removeByName('RedirectOnComplete'); + $fields->removeByName('RedirectOnCompleteURL'); + + $fields->removeByName('SubmissionColumns'); + + $fields->addFieldToTab( + 'Root.Main', + ListboxField::create( + 'SubmissionColumns', + 'Display following columns at submissions list', + $this->owner->Fields()->map('ID', 'Title') + ) + ); + + $tab = $fields->findOrMakeTab('Root.FormOptions'); + + /*$tab->push(CheckboxField::create('RedirectOnComplete')); + $tab->push(TextField::create('RedirectOnCompleteURL'));*/ + //$tab->push(TextareaField::create('CustomThankYouCode')); + + $grid = $fields->dataFieldByName('Submissions'); + + $config = $grid->getConfig(); + $config->getComponentByType(GridFieldPaginator::class)->setItemsPerPage(100); + + $cols = $this->owner->SubmissionColumns(); + if ($grid && $cols->count()) { + $dataCols = $config->getComponentByType(GridFieldDataColumns::class); + + $columns = [ + 'ID' => 'ID', + 'Created' => 'Created', + ]; + + foreach ($cols as $col) { + $title = $col->getField('Title'); + $name = $col->getField('Name'); + $columns[$name] = [ + 'title' => $title, + 'callback' => function ($item) use ($name) { + return $item->relField($name); + } + ]; + } + + $columns['Actions'] = 'Actions'; + + $dataCols->setDisplayFields($columns); + } + } +} diff --git a/src/Models/MapPin.php b/src/Models/MapPin.php new file mode 100755 index 0000000..c1ca9aa --- /dev/null +++ b/src/Models/MapPin.php @@ -0,0 +1,144 @@ + 'Varchar(255)', + 'ShowAtMap' => 'Boolean(1)', + ]; + + private static $has_one = [ + 'PhoneNumber' => Link::class, + 'Fax' => Link::class, + ]; + + private static $extensions = [ + Addressable::class, + MarkerExtension::class, + Versioned::class, + ]; + + private static $belongs_many_many = [ + 'MapElements' => MapElement::class, + ]; + + private static $default_sort = 'Title ASC, ID DESC'; + + private static $summary_fields = [ + 'Title', + 'Address', + 'ShowAtMap', + ]; + + private static $defaults = [ + 'ShowAtMap' => '1', + 'Suburb' => 'Syracuse', + 'State' => 'NY', + 'Postcode' => '13210', + 'Country' => 'US', + ]; + + public function getCMSFields() + { + $fields = parent::getCMSFields(); + + $fields->removeByName('MapElements'); + + $fields->replaceField( + 'PhoneNumberID', + LinkField::create('PhoneNumberID', 'Phone Number') + ->setAllowedTypes(['Phone']) + ); + + $fields->replaceField( + 'FaxID', + LinkField::create('FaxID', 'FAX') + ->setAllowedTypes(['Phone']) + ); + $fields->removeByName(['Map', 'LatLngOverride', 'Lng','Lat']); + + $fields->addFieldsToTab('Root.Main', [ + CheckboxField::create('ShowAtMap', 'Show at the map?'), + CheckboxField::create('LatLngOverride', 'Override Latitude and Longitude?') + ->setDescription('Check this box and save to be able to edit the latitude and longitude manually.'), + MapboxField::create('Map', 'Choose a location', 'Lat', 'Lng'), + ]); + + return $fields; + } + + public function onBeforeWrite() + { + parent::onBeforeWrite(); + + $lng = $this->getField('Lng'); + $lat = $this->getField('Lat'); + + + if (!$this->getField('Country')) { + $this->setField('Country', 'us'); + } + + // geocode + try { + // reverse geocoding get address + if (!$this->hasAddress() && $lng && $lat) { + require_once BASE_PATH . '/app/thirdparty/geocoding-example/php/Mapbox.php'; + $mapbox = new \Mapbox(MapboxField::getAccessToken()); + + // GET Address + $res = $mapbox->reverseGeocode($lng, $lat); + if ($res->success() && $res->getCount()) { + $res = $res->getData(); + if (count($res) && isset($res[0]['place_name'])) { + $details = explode(',', $res[0]['place_name']); + $fields = [ + 'Address', + 'City', + 'State', + //'Country', + ]; + + $n = count($fields); + for ($i = 0; $i < $n; $i++) { + if (!isset($details[$i])) { + continue; + } + + $name = $fields[$i]; + $val = $details[$i]; + + // get postal code + if ($name === 'State') { + $this->setField('PostalCode', substr($val, strrpos($val, ' ')+1)); + } + + $this->setField($name, $val); + } + } + } + } + } catch (\Exception $e) { + } + } +} diff --git a/src/Models/TeamMember.php b/src/Models/TeamMember.php new file mode 100755 index 0000000..dd151f9 --- /dev/null +++ b/src/Models/TeamMember.php @@ -0,0 +1,63 @@ + 'Varchar(254)', + 'LastName' => 'Varchar(254)', + 'Company' => 'Varchar(254)', + 'Position' => 'Varchar(254)', + 'Content' => 'HTMLText', + ]; + + private static $has_one = [ + 'Photo' => Image::class, + ]; + + private static $extensions = [ + SocialExtension::class, + Versioned::class, + ]; + + private static $owns = [ + 'Photo', + ]; + + private static $summary_fields = [ + 'Company', + 'FirstName', + 'LastName', + 'Position', + ]; + + private static $searchable_fields = [ + 'FirstName', + 'LastName', + ]; + + private static $frontend_searchable_fields = [ + 'FirstName:PartialMatch', + 'LastName:PartialMatch', + 'Content:PartialMatch', + ]; + + public function getTitle() + { + return $this->getField('Company').' | '.$this->getField('FirstName').' '.$this->getField('LastName'); + } +}