Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] Base field type #191

Open
wants to merge 9 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<?php

namespace Kore\RatingFieldTypeBundle\DependencyInjection;

use Symfony\Component\Config\Definition\Builder\TreeBuilder;
use Symfony\Component\Config\Definition\ConfigurationInterface;

/**
* This is the class that validates and merges configuration from your app/config files.
*
* To learn more see {@link http://symfony.com/doc/current/cookbook/bundles/configuration.html}
*/
class Configuration implements ConfigurationInterface
{
/**
* {@inheritdoc}
*/
public function getConfigTreeBuilder()
{
$treeBuilder = new TreeBuilder();
$rootNode = $treeBuilder->root('kore_rating_field_type');

// Here you should define the parameters that are allowed to
// configure your bundle. See the documentation linked above for
// more information on that topic.

return $treeBuilder;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<?php

namespace Kore\RatingFieldTypeBundle\DependencyInjection;

use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\Config\FileLocator;
use Symfony\Component\HttpKernel\DependencyInjection\Extension;
use Symfony\Component\DependencyInjection\Extension\PrependExtensionInterface;
use Symfony\Component\DependencyInjection\Loader;
use Symfony\Component\Yaml\Yaml;

/**
* This is the class that loads and manages your bundle configuration.
*
* @link http://symfony.com/doc/current/cookbook/bundles/extension.html
*/
class KoreRatingFieldTypeExtension extends Extension implements PrependExtensionInterface
{
public function prepend(ContainerBuilder $container)
{
$config = Yaml::parse(file_get_contents(__DIR__ . '/../Resources/config/ezpublish.yml'));
$container->prependExtensionConfig('ezpublish', $config);
}

/**
* {@inheritdoc}
*/
public function load(array $configs, ContainerBuilder $container)
{
$configuration = new Configuration();
$config = $this->processConfiguration($configuration, $configs);

$loader = new Loader\XmlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config'));
$loader->load('services.xml');
}
}
9 changes: 9 additions & 0 deletions src/Kore/RatingFieldTypeBundle/KoreRatingFieldTypeBundle.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<?php

namespace Kore\RatingFieldTypeBundle;

use Symfony\Component\HttpKernel\Bundle\Bundle;

class KoreRatingFieldTypeBundle extends Bundle
{
}
8 changes: 8 additions & 0 deletions src/Kore/RatingFieldTypeBundle/Resources/config/ezpublish.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
system:
default:
fielddefinition_settings_templates:
- { template: "KoreRatingFieldTypeBundle::fielddefinition_settings.html.twig"}
field_edit_templates:
- { template: "KoreRatingFieldTypeBundle::field_edit.html.twig"}
field_templates:
- { template: "KoreRatingFieldTypeBundle::field_view.html.twig"}
20 changes: 20 additions & 0 deletions src/Kore/RatingFieldTypeBundle/Resources/config/services.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<?xml version="1.0" ?>

<container xmlns="http://symfony.com/schema/dic/services"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">

<services>
<service id="kore_rating_field_type.field_type.rating"
class="Kore\RatingFieldTypeBundle\Storage\FieldType\Type">

<tag name="ezpublish.fieldType" alias="koreRating" />
</service>

<service id="kore_rating_field_type.legacy.converter"
class="Kore\RatingFieldTypeBundle\Storage\Legacy\Converter">

<tag name="ezpublish.storageEngine.legacy.converter" alias="koreRating" />
</service>
</services>
</container>
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Edit?
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{% block koreRating_field %}
{% set field_value %}
{{ field.value.rating }}
{% endset %}
{{ block( 'simple_block_field' ) }}
{% endblock %}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{% block koreRating_settings %}
<em>No settings</em>
{% endblock %}
208 changes: 208 additions & 0 deletions src/Kore/RatingFieldTypeBundle/Storage/FieldType/Type.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,208 @@
<?php

namespace Kore\RatingFieldTypeBundle\Storage\FieldType;

use eZ\Publish\Core\FieldType\FieldType;
use eZ\Publish\API\Repository\Values\ContentType\FieldDefinition;
use eZ\Publish\SPI\FieldType\Value as SPIValue;
use eZ\Publish\Core\FieldType\Value as CoreValue;
use eZ\Publish\SPI\Persistence\Content\FieldValue;
use eZ\Publish\Core\Base\Exceptions\InvalidArgumentException;

class Type extends FieldType
{
/**
* Returns the field type identifier for this field type.
*
* This identifier should be globally unique and the implementer of a
* FieldType must take care for the uniqueness. It is therefore recommended
* to prefix the field-type identifier by a unique string that identifies
* the implementer. A good identifier could for example take your companies
* main domain name as a prefix in reverse order.
*
* @return string
*/
public function getFieldTypeIdentifier()
{
// @EXT: Necessary
return 'koreRating';
}

/**
* Inspects given $inputValue and potentially converts it into a dedicated
* value object.
*
* If given $inputValue could not be converted or is already an instance of
* dedicate value object, the method should simply return it.
*
* This is an operation method for {@see acceptValue()}.
*
* Example implementation:
* <code>
* protected function createValueFromInput( $inputValue )
* {
* if ( is_array( $inputValue ) )
* {
* $inputValue = \eZ\Publish\Core\FieldType\CookieJar\Value( $inputValue );
* }
*
* return $inputValue;
* }
* </code>
*
* @param mixed $inputValue
*
* @return mixed The potentially converted input value.
*/
protected function createValueFromInput($inputValue)
{
// @EXT: Default possible depending on value class, at least for
// trivial values
//
// There is probably a connection with the edit template, which is
// missing in the tutoorial.
if ($inputValue instanceof Value) {
return $inputValue;
}

if (!is_numeric($inputValue)) {
return new Value(['rating' => false]);
}

return new Value(['rating' => (int) $inputValue]);
}

/**
* Throws an exception if value structure is not of expected format.
*
* Note that this does not include validation after the rules
* from validators, but only plausibility checks for the general data
* format.
*
* This is an operation method for {@see acceptValue()}.
*
* Example implementation:
* <code>
* protected function checkValueStructure( Value $value )
* {
* if ( !is_array( $value->cookies ) )
* {
* throw new InvalidArgumentException( "An array of assorted cookies was expected." );
* }
* }
* </code>
*
* @throws \eZ\Publish\API\Repository\Exceptions\InvalidArgumentException If the value does not match the expected structure.
*
* @param \eZ\Publish\Core\FieldType\Value $value
*/
protected function checkValueStructure(CoreValue $value)
{
// @EXT: Default possible depending on value
if (!$value->rating) {
throw new InvalidArgumentException(
'$value->rating',
'Expected rating to be a number'
);
}
}

/**
* Returns the empty value for this field type.
*
* This value will be used, if no value was provided for a field of this
* type and no default value was specified in the field definition. It is
* also used to determine that a user intentionally (or unintentionally)
* did not set a non-empty value.
*
* @return \eZ\Publish\SPI\FieldType\Value
*/
public function getEmptyValue()
{
// @EXT: Default possible when we know about the value class
return new Value();
}

/**
* Returns a human readable string representation from the given $value.
*
* It will be used to generate content name and url alias if current field
* is designated to be used in the content name/urlAlias pattern.
*
* The used $value can be assumed to be already accepted by {@link *
* acceptValue()}.
*
* @deprecated Since 6.3/5.4.7, use \eZ\Publish\SPI\FieldType\Nameable
* @param \eZ\Publish\SPI\FieldType\Value $value
*
* @return string
*/
public function getName(SPIValue $value)
{
return (string) $value;
}

/**
* Returns information for FieldValue->$sortKey relevant to the field type.
*
* Return value is mixed. It should be something which is sensible for
* sorting.
*
* It is up to the persistence implementation to handle those values.
* Common string and integer values are safe.
*
* For the legacy storage it is up to the field converters to set this
* value in either sort_key_string or sort_key_int.
*
* @param \eZ\Publish\Core\FieldType\Value $value
*
* @return mixed
*/
protected function getSortInfo(CoreValue $value)
{
return $this->getName($value);
}

/**
* Converts an $hash to the Value defined by the field type.
*
* This is the reverse operation to {@link toHash()}. At least the hash
* format generated by {@link toHash()} must be converted in reverse.
* Additional formats might be supported in the rare case that this is
* necessary. See the class description for more details on a hash format.
*
* @param mixed $hash
*
* @return \eZ\Publish\SPI\FieldType\Value
*/
public function fromHash($hash)
{
if ($hash === null) {
return $this->getEmptyValue();
}

// The default constructor at least works for the top level objects.
// For more complex values a manual conversion is necessary.
return new Value($hash);
}

/**
* Converts the given $value into a plain hash format.
*
* Converts the given $value into a plain hash format, which can be used to
* transfer the value through plain text formats, e.g. XML, which do not
* support complex structures like objects. See the class level doc block
* for additional information. See the class description for more details
* on a hash format.
*
* @param \eZ\Publish\SPI\FieldType\Value $value
*
* @return mixed
*/
public function toHash(SPIValue $value)
{
// Simplest way to ensure a deep structure is cloned and converted into
// scalars and has maps.
return json_decode(json_encode($value), true);
}
}
15 changes: 15 additions & 0 deletions src/Kore/RatingFieldTypeBundle/Storage/FieldType/Value.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<?php

namespace Kore\RatingFieldTypeBundle\Storage\FieldType;

use eZ\Publish\Core\FieldType\Value as BaseValue;

class Value extends BaseValue
{
public $rating = 3;

public function __toString(): string
{
return (string) $this->rating;
}
}
42 changes: 42 additions & 0 deletions src/Kore/RatingFieldTypeBundle/Storage/Legacy/Converter.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<?php

namespace Kore\RatingFieldTypeBundle\Storage\Legacy;

use eZ\Publish\Core\Persistence\Legacy\Content\FieldValue\Converter as ConverterInterface;
use eZ\Publish\Core\Persistence\Legacy\Content\StorageFieldValue;
use eZ\Publish\SPI\Persistence\Content\FieldValue;
use eZ\Publish\Core\Persistence\Legacy\Content\StorageFieldDefinition;
use eZ\Publish\SPI\Persistence\Content\Type\FieldDefinition;

class Converter implements ConverterInterface
{
public function toStorageValue(FieldValue $value, StorageFieldValue $storageFieldValue)
{
$storageFieldValue->dataText = json_encode($value->data);
$storageFieldValue->sortKeyString = $value->sortKey;
$storageFieldValue->sortKeyInt = $value->sortKey;
}

public function toFieldValue(StorageFieldValue $value, FieldValue $fieldValue)
{
$fieldValue->data = json_decode($value->dataText, true) ?: [];
$fieldValue->sortKey = $value->sortKeyInt ?? $value->sortKeyString;
}

public function toStorageFieldDefinition(FieldDefinition $fieldDef, StorageFieldDefinition $storageDef)
{
}

public function toFieldDefinition(StorageFieldDefinition $storageDef, FieldDefinition $fieldDef)
{
}

public function getIndexColumn()
{
// How to decide between sort_key_(int|string)
//
// How do we get access to the currently used value class to reason
// about this?
return 'sort_key_int';
}
}
Loading