From cee9b3f2bf1381306e52dd74d5562952427cca0d Mon Sep 17 00:00:00 2001 From: madmatt Date: Tue, 24 Sep 2019 17:41:54 +1200 Subject: [PATCH] Initial commit of pre-alpha module --- .gitignore | 3 + README.md | 20 ++++ _config/extensions.yml | 6 + composer.json | 51 ++++++++ phpcs.xml.dist | 17 +++ src/Controller/ShopFrontPageController.php | 25 ++++ src/Extension/ProductSection.php | 13 ++ src/Model/ShopFrontSection.php | 112 ++++++++++++++++++ src/Page/ShopFrontPage.php | 45 +++++++ .../ShopFront/Page/Layout/ShopFrontPage.ss | 30 +++++ 10 files changed, 322 insertions(+) create mode 100644 .gitignore create mode 100644 README.md create mode 100644 _config/extensions.yml create mode 100644 composer.json create mode 100644 phpcs.xml.dist create mode 100644 src/Controller/ShopFrontPageController.php create mode 100644 src/Extension/ProductSection.php create mode 100644 src/Model/ShopFrontSection.php create mode 100644 src/Page/ShopFrontPage.php create mode 100644 templates/SilverShop/ShopFront/Page/Layout/ShopFrontPage.ss diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..b182ee6 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +/composer.lock +/resources +/vendor diff --git a/README.md b/README.md new file mode 100644 index 0000000..e4533e7 --- /dev/null +++ b/README.md @@ -0,0 +1,20 @@ +# Shop Front Module + +An extension to the [SilverShop module](https://github.com/silvershop/) that provides a custom page type for a 'shop front'. The shop front allows a CMS author to create 'sections', each of which can contain arbitrary products (or a product category). + +## Maintainer Contact + + * [madmatt](https://github.com/madmatt/) + +## Requirements + + * silvershop/core: ^3 + +## Installation Instructions + + * Install via composer: `composer require silvershop/shopfront` + * Run `vendor/bin/sake dev/build flush=1` to add the new page types + * Create a new 'Shop Front page' in the CMS, define your sections and add products to each one + * The module ships with a super basic template that you are expected to override in your own theme: + * Create a new file under `themes//templates/SilverShop/ShopFront/Page/Layout/ShopFrontPage.ss` + * Add your custom styles and classes to this file, using the existing file as an example diff --git a/_config/extensions.yml b/_config/extensions.yml new file mode 100644 index 0000000..ee2aad4 --- /dev/null +++ b/_config/extensions.yml @@ -0,0 +1,6 @@ +--- +name: shopfront-extensions +--- +SilverShop\Page\Product: + extensions: + - SilverShop\ShopFront\Extension\ProductSection diff --git a/composer.json b/composer.json new file mode 100644 index 0000000..73defd8 --- /dev/null +++ b/composer.json @@ -0,0 +1,51 @@ +{ + "name": "silvershop/shopfront", + "description": "Provides a 'shopfront' page type that can be used to display products or product categories.", + "license": "BSD-2-Clause", + "type": "silverstripe-vendormodule", + "homepage": "http://silvershop.github.io/", + "minimum-stability": "dev", + + "support": { + "source": "https://github.com/silvershop/silvershop-shopfront", + "issues": "https://github.com/silvershop/silvershop-shopfront/issues" + }, + + "require": { + "silvershop/core": "^3", + "unclecheese/display-logic": "^2", + "symbiote/silverstripe-gridfieldextensions": "^3" + }, + + "require-dev": { + "squizlabs/php_codesniffer": "^3" + }, + + "autoload": { + "psr-4": { + "SilverShop\\ShopFront\\": "src/" + } + }, + + "keywords": [ + "silverstripe", + "shop", + "shopfront" + ], + + "authors": [ + { + "name": "madmatt", + "homepage": "https://github.com/madmatt" + }, + + { + "name": "SilverShop Contributors", + "homepage": "https://github.com/silvershop/silvershop-shopfront/graphs/contributors" + } + ], + + "scripts": { + "lint": "vendor/bin/phpcs src/" + } +} diff --git a/phpcs.xml.dist b/phpcs.xml.dist new file mode 100644 index 0000000..9b40191 --- /dev/null +++ b/phpcs.xml.dist @@ -0,0 +1,17 @@ + + + Coding standard for SilverStripe 4.x + + + */vendor/* + + + + + + + + + + + diff --git a/src/Controller/ShopFrontPageController.php b/src/Controller/ShopFrontPageController.php new file mode 100644 index 0000000..f49d50a --- /dev/null +++ b/src/Controller/ShopFrontPageController.php @@ -0,0 +1,25 @@ +|null + */ + public function SectionsForDisplay(): ?DataList + { + $sections = $this->data()->Sections()->filter('HideFromDisplay', 0)->sort('Sort ASC'); + + $this->extend('updateSectionsForDisplay', $sections); + + return $sections; + } +} diff --git a/src/Extension/ProductSection.php b/src/Extension/ProductSection.php new file mode 100644 index 0000000..fa17d91 --- /dev/null +++ b/src/Extension/ProductSection.php @@ -0,0 +1,13 @@ + ShopFrontSection::class + ]; +} diff --git a/src/Model/ShopFrontSection.php b/src/Model/ShopFrontSection.php new file mode 100644 index 0000000..d531d2e --- /dev/null +++ b/src/Model/ShopFrontSection.php @@ -0,0 +1,112 @@ + 'Varchar(200)', + 'Content' => 'HTMLText', + 'HideFromDisplay' => 'Boolean', + 'Sort' => 'Int', + ]; + + private static $has_one = [ + 'ShopFront' => ShopFrontPage::class, // Parent relationship - indicates which shopfront page this section is on + 'ProductCategory' => ProductCategory::class, + ]; + + private static $many_many = [ + 'Products' => Page::class + ]; + + private static $many_many_extraFields = [ + 'Products' => [ + 'Sort' => 'Int' + ] + ]; + + private static $indexes = [ + 'Sort' => true, + ]; + + private static $summary_fields = [ + 'Title', + 'HideFromDisplay.Nice' + ]; + + public function getCMSFields() + { + $gridField = Wrapper::create( + new GridField( + 'Products', + 'Products (if no category is set)', + $this->Products(), + GridFieldConfig_RelationEditor::create() + ) + ); + + $fields = new FieldList([ + new TextField('Title'), + new CheckboxField('HideFromDisplay', 'Hide this section from display on the website'), + new HTMLEditorField('Content') + ]); + + if ($this->isInDB() && $this->ShopFront()) { + $productCategoryField = TreeDropdownField::create( + 'ProductCategoryID', + 'Product Category', + ProductCategory::class + ); + + $productCategoryField->setTreeBaseID($this->ShopFront()->ID)->setTitle('DisplayLogicWrap'); + $fields->push(Wrapper::create($productCategoryField)); + $fields->push($gridField); + } else { + $helperField = LiteralField::create( + 'ProductSelectionHelper', + '

You can select products to be displayed in this section once you have saved for the first ' + . 'time.

' + ); + + $fields->push($helperField); + } + + $this->extend('updateCMSFields', $fields); + return $fields; + } + + /** + * Returns a {@link DataList} of {@link Products} to include in the section. + * + * If the section is attached to a category, it pulls all the products from + * that category, otherwise uses the products attached. + * + * @return DataList + */ + public function Products() + { + if ($this->ProductCategoryID) { + return Page::get()->filter('ParentID', $this->ProductCategoryID); + } + + return $this->getManyManyComponents('Products'); + } +} diff --git a/src/Page/ShopFrontPage.php b/src/Page/ShopFrontPage.php new file mode 100644 index 0000000..a5af553 --- /dev/null +++ b/src/Page/ShopFrontPage.php @@ -0,0 +1,45 @@ + ShopFrontSection::class + ]; + + private static $owns = ['Sections']; + + private static $cascade_duplicates = ['Sections']; + + private static $cascade_deletes = ['Sections']; + + public function getCMSFields() + { + $fields = parent::getCMSFields(); + + $config = GridFieldConfig_RecordEditor::create(); + $config->addComponent(new GridFieldOrderableRows('Sort')); + + $grid = GridField::create('Sections', 'Sections', $this->Sections(), $config); + $fields->addFieldToTab('Root.Main', $grid); + + return $fields; + } +} diff --git a/templates/SilverShop/ShopFront/Page/Layout/ShopFrontPage.ss b/templates/SilverShop/ShopFront/Page/Layout/ShopFrontPage.ss new file mode 100644 index 0000000..c78b80c --- /dev/null +++ b/templates/SilverShop/ShopFront/Page/Layout/ShopFrontPage.ss @@ -0,0 +1,30 @@ +<%-- + This template is intended to be used as an example only, + and would generally be overridden within your own project +--%> + +<% if $SectionsForDisplay %> +
+

$Title

+ + <% loop $SectionsForDisplay %> +
+

$Title

+
+
    + <% loop $Products %> + <% if $canView %> +
  • +

    $Title

    + <% if $Image %> + + <% end_if %> +
  • + <% end_if %> + <% end_loop %> +
+
+
+ <% end_loop %> +
+<% end_if %>