Skip to content

Commit

Permalink
Merge pull request #774 from silverstripe-terraformers/feature/page-a…
Browse files Browse the repository at this point in the history
…ware

Top page feature (performance enhancement)
  • Loading branch information
Garion Herman authored Mar 26, 2020
2 parents cd5433f + 20e1c3e commit 4704380
Show file tree
Hide file tree
Showing 16 changed files with 1,163 additions and 22 deletions.
4 changes: 2 additions & 2 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,9 @@ env:

matrix:
include:
- php: 5.6
- php: 7.1
env: DB=MYSQL RECIPE_VERSION=4.4.x-dev PHPCS_TEST=1 PHPUNIT_TEST=1
- php: 7.0
- php: 7.1
env: DB=PGSQL RECIPE_VERSION=4.4.x-dev PHPUNIT_TEST=1
- php: 7.1
env: DB=MYSQL RECIPE_VERSION=4.4.x-dev PHPUNIT_COVERAGE_TEST=1
Expand Down
4 changes: 4 additions & 0 deletions _config/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,3 +31,7 @@ Symbiote\GridFieldExtensions\GridFieldAddNewMultiClassHandler:
SilverStripe\Core\Injector\Injector:
SilverStripe\CMS\Controllers\CMSSiteTreeFilter_Search:
class: DNADesign\Elemental\Controllers\ElementSiteTreeFilterSearch
SilverStripe\Dev\State\SapphireTestState:
properties:
States:
topPageTestState: '%$DNADesign\Elemental\TopPage\TestState'
1 change: 1 addition & 0 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
"minimum-stability": "dev",
"prefer-stable": true,
"require": {
"php": "^7.1",
"silverstripe/cms": "^4.4@dev",
"silverstripe/admin": "^1.4@dev",
"silverstripe/versioned-admin": "^1.2@dev",
Expand Down
79 changes: 63 additions & 16 deletions docs/en/advanced_setup.md
Original file line number Diff line number Diff line change
Expand Up @@ -92,31 +92,31 @@ class BlockPage extends Page
private static $field_include = [
'ElementalAreaID',
];

// ...
}
```

This configuration allows us to have different `ElementalArea` for different locales of the page.
We also need to create a copy of the `ElementalArea` when content is being localised.
We also need to create a copy of the `ElementalArea` when content is being localised.

```php
class BlockPage extends Page
{
public function onBeforeWrite()
{
parent::onBeforeWrite();

if (!$this->isDraftedInLocale() && $this->isInDB()) {
$elementalArea = $this->ElementalArea();

$elementalAreaNew = $elementalArea->duplicate();
$this->ElementalAreaID = $elementalAreaNew->ID;
}

return;
}

// ...
}
```
Expand Down Expand Up @@ -159,7 +159,7 @@ class BlockPage extends Page
ElementalPageExtension::class,
BlockPageFluentExtension::class,
];

// ...
}
```
Expand All @@ -175,15 +175,6 @@ class BlockPage extends Page
* the blocks are unaware of their locales which makes bottom up relation lookup slower
* this can be remedied by some extra data stored in blocks (see notes below)

### Block performance increase

If only one page can own a block, we can store page reference directly on the block.
This can be done when block is created (`onBeforeWrite`). This is helps significantly when traversing relation from block up to a page.
Note that there may be a lot of objects sitting between block and a page.
For example `Content block -> Elemental area -> Layout block -> Elemental area -> Page`.

Additional information can be stored like page locale (relevant for `Fluent` module) to specify the target data even further.

### Unit tests

Writing unit tests for `Elemental` with `Fluent` can be rather tricky to figure out.
Expand Down Expand Up @@ -275,3 +266,59 @@ FluentState::singleton()->withState(function (FluentState $state) {

This is very important as global state is reverted back after the callback is executed so it's safe to be used.
Unit tests benefit mostly from this as this makes sure that there are no dependencies between unit tests as the global state is always changed only locally in one test.

## Top Page reference performance enhancement

In some cases your project setup may have deeply nested blocks, for example:

```
Page
ElementalArea
RowBlock (represents grid row on frontend)
ElementalArea
AccordionBlock (block which can contain other content blocks)
ElementalArea
ContentBlock
```

It's quite common to use top page lookups from block context, i.e. a block is querying data from the page that the block
belongs to.

When blocks are owned by a single ElementArea (and therefore a single Page), we can store a reference to the page
directly on the block as a performance enhancement for this query. A set of extensions to manage this are provided out
of the box, and can be enabled by applying the following configuration:

```
DNADesign\Elemental\Models\BaseElement:
extensions:
topPageDataExtension: DNADesign\Elemental\TopPage\DataExtension
DNADesign\Elemental\Models\ElementalArea:
extensions:
topPageDataExtension: DNADesign\Elemental\TopPage\DataExtension
Page:
extensions:
topPageSiteTreeExtension: DNADesign\Elemental\TopPage\SiteTreeExtension
```

These extensions will be enabled by default in Elemental 5.

If your project makes use of the Fluent module, it is recommended to use the following extensions in place of the ones
above:

```
DNADesign\Elemental\Models\BaseElement:
extensions:
topPageDataExtension: DNADesign\Elemental\TopPage\FluentExtension
DNADesign\Elemental\Models\ElementalArea:
extensions:
topPageDataExtension: DNADesign\Elemental\TopPage\FluentExtension
```

These variants will also store the locale of the top page on blocks, which simplifies top page lookup in case the locale
is unknown at the time of page lookup from block context.

The page reference on the blocks can also be useful for maintenance dev tasks, as it's easy to identify which blocks
belong to which pages in which locale.
6 changes: 2 additions & 4 deletions src/Extensions/ElementalPageExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,14 @@

namespace DNADesign\Elemental\Extensions;

use Exception;
use DNADesign\Elemental\Models\ElementalArea;
use SilverStripe\Control\Controller;
use SilverStripe\View\Parsers\HTML4Value;
use SilverStripe\Core\Config\Config;
use SilverStripe\View\SSViewer;

/**
* @method ElementalArea ElementalArea
* @property ElementalArea ElementalArea
* @method ElementalArea ElementalArea()
* @property int ElementalAreaID
*/
class ElementalPageExtension extends ElementalAreasExtension
{
Expand Down
1 change: 1 addition & 0 deletions src/Models/BaseElement.php
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
* @property int $Sort
* @property string $ExtraClass
* @property string $Style
* @property int $ParentID
*
* @method ElementalArea Parent()
*/
Expand Down
Loading

0 comments on commit 4704380

Please sign in to comment.