Skip to content

Commit

Permalink
Added: Added default support for sorting enhanced selection options b…
Browse files Browse the repository at this point in the history
…y enhanced selection option priority and added copyright and license documentation for bundle
  • Loading branch information
brookinsconsulting committed May 4, 2015
1 parent 3758a61 commit 58bdd0b
Show file tree
Hide file tree
Showing 6 changed files with 308 additions and 2 deletions.
16 changes: 16 additions & 0 deletions COPYRIGHT
@@ -0,0 +1,16 @@
COPYRIGHT NOTICE: Copyright (C) 2014-2015 Netgen and Brookins Consulting
SOFTWARE LICENSE: GNU General Public License v2.0
NOTICE: >
This program is free software; you can redistribute it and/or
modify it under the terms of version 2.0 of the GNU General
Public License as published by the Free Software Foundation.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.

You should have received a copy of version 2.0 of the GNU General
Public License along with this program; if not, write to the Free
Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
MA 02110-1301, USA.
Expand Up @@ -2,11 +2,13 @@

namespace Netgen\Bundle\EnhancedSelectionBundle\Core\Persistence\Legacy\Content\FieldValue\Converter;

use eZ\Publish\Core\FieldType\FieldSettings;
use eZ\Publish\Core\Persistence\Legacy\Content\FieldValue\Converter;
use eZ\Publish\Core\Persistence\Legacy\Content\StorageFieldDefinition;
use eZ\Publish\Core\Persistence\Legacy\Content\StorageFieldValue;
use eZ\Publish\SPI\Persistence\Content\FieldValue;
use eZ\Publish\SPI\Persistence\Content\Type\FieldDefinition;
use DOMDocument;

class EnhancedSelectionConverter implements Converter
{
Expand Down Expand Up @@ -53,6 +55,60 @@ public function toFieldValue( StorageFieldValue $value, FieldValue $fieldValue )
*/
public function toStorageFieldDefinition( FieldDefinition $fieldDef, StorageFieldDefinition $storageDef )
{
$fieldSettings = $fieldDef->fieldTypeConstraints->fieldSettings;
$options = array();
$isMultiple = false;
$delimiter = false;
$query = false;

if ( !empty( $fieldSettings["options"] ) )
{
// Options
$xml = new DOMDocument( "1.0", "utf-8" );
$xml->appendChild(
$selection = $xml->createElement( "content" )
);
$selection->appendChild(
$options = $xml->createElement( "options" )
);

foreach( $fieldSettings["options"] as $key => $option )
{
$options->appendChild(
$optionNode = $xml->createElement( "option" )
);

$optionNode->setAttribute( "id", (int)$option["id"] );
$optionNode->setAttribute( "name", (string)$option["name"] );
$optionNode->setAttribute( "identifier", (string)$option["identifier"] );
$optionNode->setAttribute( "priority", (int)$option["priority"] );
}

// Multiselect
if ( isset( $fieldSettings["isMultiple"] ) )
{
$multiSelectNode = $xml->createElement( "multiselect", intval( $fieldSettings["isMultiple"] ) );
$selection->appendChild( $multiSelectNode );
}

// Delimiter
if( isset( $fieldSettings["delimiter"] ) )
{
$delimiterElement = $xml->createElement("delimiter");
$delimiterElement->appendChild( $xml->createCDATASection( $fieldSettings["delimiter"] ) );
$selection->appendChild( $delimiterElement );
}

// DB Query
if( isset( $fieldSettings["query"] ) )
{
$queryElement = $xml->createElement("query");
$queryElement->appendChild( $xml->createCDATASection( $fieldSettings["query"] ) );
$selection->appendChild( $queryElement );
}

$storageDef->dataText5 = $xml->saveXML();
}
}

/**
Expand All @@ -63,6 +119,43 @@ public function toStorageFieldDefinition( FieldDefinition $fieldDef, StorageFiel
*/
public function toFieldDefinition( StorageFieldDefinition $storageDef, FieldDefinition $fieldDef )
{
$simpleXml = simplexml_load_string( $storageDef->dataText5 );
$options = array();
$isMultiple = false;
$delimiter = false;
$query = false;

if ( $simpleXml !== false )
{
foreach ( $simpleXml->options->option as $option )
{
$options[] = array( "id" => (int)$option["id"],
"name" => (string)$option["name"],
"identifier" => (string)$option["identifier"],
"priority" => (int)$option["priority"] );
}
if( $simpleXml->multiselect == 1 )
{
$isMultiple = true;
}
if( (string)$simpleXml->delimiter != null )
{
$delimiter = (string)$simpleXml->delimiter;
}
if( $simpleXml->query )
{
$query = (string)$simpleXml->query;
}
}

$fieldDef->fieldTypeConstraints->fieldSettings = new FieldSettings(
array(
"isMultiple" => $isMultiple,
"delimiter" => $delimiter,
"options" => $options,
"query" => $query,
)
);
}

/**
Expand Down
5 changes: 5 additions & 0 deletions Resources/config/storage_engines.yml
@@ -1,8 +1,13 @@
parameters:
ezpublish.fieldType.sckenhancedselection.converter.class: Netgen\Bundle\EnhancedSelectionBundle\Core\Persistence\Legacy\Content\FieldValue\Converter\EnhancedSelectionConverter
ezpublish.twig.twig_extension.sortbyfield.class: Netgen\Bundle\EnhancedSelectionBundle\Twig\Extension\SortBySelectionFieldExtension

services:
ezpublish.fieldType.sckenhancedselection.converter:
class: %ezpublish.fieldType.sckenhancedselection.converter.class%
tags:
- {name: ezpublish.storageEngine.legacy.converter, alias: sckenhancedselection, lazy: true, callback: "::create"}
ezpublish.twig.twig_extension.sortbyfield:
class: %ezpublish.twig.twig_extension.sortbyfield.class%
tags:
- { name: twig.extension }
50 changes: 50 additions & 0 deletions Resources/doc/INSTALL.md
Expand Up @@ -6,6 +6,8 @@ Requirements

* Recent version of eZ Publish 5

* The default sorting of enhanced selection options requires unique numeric selection option priority values otherwise the order they are created is used

Installation steps
------------------

Expand Down Expand Up @@ -49,3 +51,51 @@ php ezpublish/console cache:clear
### Use the bundle

You can now load and create content with `sckenhancedselection` field type.

## Using the content field within your own custom template

Add the following template code into your template:

```twig
{% if not ez_is_field_empty(content, "selection") %}
{{ez_render_field(content, "selection")}}
{% else %}
Empty selection
{% endif %}
```

Replaced the text: "selection" with your own contenttype field identifier text string as needed.

Save these additions to your custom template and clear caches as required.

Custom usage
------------------

### Custom content_field template override

Edit your `ezpublish/config/config.yml` file, add and customize the following yaml configuration:

```yaml
parameters:
ezsettings.YOUR_SITEACCESS_NAME.field_templates:
- {template: EzPublishCoreBundle::content_fields.html.twig, priority: 0}
- {template: YourCustomDesignTemplateBundle::sckenhancedselection_content_field.html.twig, priority: 0}
```

Then create a copy of the default `sckenhancedselection_content_field.html.twig` template into your activated custom bundle and customize as needed.

### Sort selection options by any other selection option field besides priority

The default display order of enhanced selection options is by priority. Other sort orders supported by default are: id, identifier and name.

You can sort your selection options display order by any other selection option field besides priority by creating a `sckenhancedselection_content_field.html.twig` template override (described above).

Then edit the `sckenhancedselection_content_field.html.twig` template in your custom bundle and changing the twig filter 'sort_by_selection_field' first parameter (sortByField), a string, 'priority' to any one of the following values supported by default.

The twig filter 'sort_by_selection_field' provided by this extension uses the php function 'usort' and a custom 'usort value_compare_func' to sort selection options.

The twig filter 'sort_by_selection_field' will not sort selection options by 'priority' if the FieldType options 'priority' field values contain duplicate values.

By default each time you create an enhanced selection option the default priority is set to 1. This is historically due to a bug in the legacy datatype where each time a new option is created the priority is set to 1 even if another option with priority of 1 already exists.

If you do not manually edit your enhanced selection options priority values to be unique then the default order, the order they were created is the order they will be displayed.
23 changes: 21 additions & 2 deletions Resources/views/sckenhancedselection_content_field.html.twig
@@ -1,7 +1,26 @@
{% block sckenhancedselection_field %}
{% spaceless %}
{% for identifier in field.value.identifiers %}
{{ identifier }}{% if not loop.last %}, {% endif %}

{% set available_options = fieldSettings.options|sort_by_selection_field( 'priority', 'asc' ) %}
{% set identifiers = field.value.identifiers %}

{% if fieldSettings.delimiter is not empty %}
{% set delimiter = fieldSettings.delimiter %}
{% else %}
{% set delimiter = ', ' %}
{% endif %}

{% if available_options is not empty and identifiers is not empty %}
{% for option in available_options %}
{% if option.identifier in identifiers %}
{{ option.name }}{% if not loop.last %}{{ delimiter }}{% endif %}
{% endif %}
{% endfor %}
{% elseif identifiers is not empty %}
{% for identifier in identifiers %}
{{ identifier }}{% if not loop.last %}{{ delimiter }}{% endif %}
{% endfor %}
{% endif %}

{% endspaceless %}
{% endblock %}
123 changes: 123 additions & 0 deletions Twig/Extension/SortBySelectionFieldExtension.php
@@ -0,0 +1,123 @@
<?php
/**
* File containing the SortBySelectionFieldExtension class.
*
* @copyright Copyright (C) Brookins Consulting. All rights reserved.
* @license For full copyright and license information view LICENSE file distributed with this source code.
* @version //autogentag//
*/

namespace Netgen\Bundle\EnhancedSelectionBundle\Twig\Extension;

use Twig_Extension;
use Twig_SimpleFilter;
use InvalidArgumentException;

/**
* Twig extension providing the 'sort_by_selection_field' filter
*/
class SortBySelectionFieldExtension extends Twig_Extension
{
/**
* The "sort_by_selection_field" twig filter sorts an array of items ( objects or arrays ) by the specified sort by field value
*
* Usage: {% set available_options = options|sort_by_selection_field( 'priority', 'desc' ) %}
*
* @return array The array of Twig_SimpleFilter objects
*/
public function getFilters()
{
return array(
new Twig_SimpleFilter( 'sort_by_selection_field', array( $this, 'sortBySelectionField' ) )
);
}

/**
* The "sortBySelectionField" method sorts an array of items by the specified sort by field value
* if the available options priority values do not contain duplicates which returns the options without modifications
*
* @param array $content Array of selection options
* @param string $sortByField String of selection sort field. Supports: priority|id|identifier|name. Default: priority
* @param string $sortDirection String of selection sort direction. Supports: asc|desc. Default: asc
*
* @return array The array of FieldType selection options sorted as best as possible
*/
public function sortBySelectionField( $content, $sortByField = 'priority', $sortDirection = 'asc' )
{
$selection_options_field_content_not_sortable = false;

if( !is_array( $content ) )
{
throw new InvalidArgumentException( 'Input passed to sort_by_selection_field twig filter is not an array' );
}
else if ( $sortByField === null )
{
throw new InvalidArgumentException( 'Sort by field parameter passed to the sort_by_selection_field twig filter can not be null' );
}
else if ( !isset( $content[ 0 ][ $sortByField ] ) )
{
throw new InvalidArgumentException( 'Sort by field parameter passed to the sort_by_selection_field twig filter must be either: priority, id, identifier or name' );
}
else
{
for( $i = 0, $j = 0, $n = count( $content ); $i < $n; ++$i )
{
for( $g = $i + 1; $g < $n; ++$g )
{
if( $content[ $i ][ $sortByField ] == $content[ $g ][ $sortByField ] )
{
$selection_options_field_content_not_sortable = true;
}
}

if( $selection_options_field_content_not_sortable == true )
{
break;
}
}

if( $selection_options_field_content_not_sortable == false )
{
usort( $content, self::usortByPriority( $sortByField, $sortDirection ) );
}
}

return $content;
}

/**
* Provides usort value_compare_func function to sort selection options
*
* @return int The usort value_compare_func function result to determin sort order
*/
public function usortByPriority( $sortByField = 'priority', $sortDirection = 'asc' )
{
return function ( $a, $b ) use ( $sortByField, $sortDirection )
{
$sortDirectionInt = $sortDirection === 'desc' ? -1 : 1;

if ( $a[ $sortByField ] == $b[ $sortByField ] )
{
return 0;
}
elseif ( $a[ $sortByField ] > $b[ $sortByField ] )
{
return ( 1 * $sortDirectionInt );
}
else
{
return ( -1 * $sortDirectionInt );
}
};
}

/**
* Returns the name of the twig extension.
*
* @return string The twig extension name
*/
public function getName()
{
return 'sort_by_selection_field';
}
}

0 comments on commit 58bdd0b

Please sign in to comment.