0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

eZ Publish / eZ PlatformAdvent Calendar 2016

Day 23

eZ Publish 5.x フィールドタイプ チュートリアル

Last updated at Posted at 2016-12-25

バンドルのスケルトン生成

php ezpublish/console generate:bundle \
--namespace=EzSystems/TweetFieldTypeBundle \
--bundle-name=EzSystemsTweetFieldTypeBundle \
--dir=src \
--format=yml
Do you want to generate the whole directory structure [no]? no<enter>

バンドルの構造

eZ
└── Publish
   └── FieldType
       └── Tweet
           ├── Type.php
           └── Value.php

Type クラス

Type にはフィールドタイプのロジックが含まれる:データのバリデーション、さまざまなフォーマットからの変換、バリデーターの説明...
Type クラスは eZ\Publish\SPI\FieldType\FieldType を実装する必要がある。また、eZ\Publish\Core\FieldType\FieldType 抽象クラスを拡張することもできる。

Value クラス

Value はコンテンツアイテム内のタイプのインスタンスを表すために使用される。各フィールドは Type の Value クラスのインスタンスを使用してデータを出力する。
Value クラスは eZ\Publish\SPI\FieldType\Value を実装する必要がある。また、eZ\Publish\Core\FieldType\Value 抽象クラスを拡張することもできる。

Tweet\Value クラスの実装

FieldType の Value クラスは設計上は非常にシンプルである。ステートレスで、できるだけ軽量であることを意図している。従って、Type クラスの責任として、このクラスはできるだけロジックを含まないようにしなくてはならない。

Value には少なくとも以下が含まれる:

  • パブリックプロパティー(実際のデータを格納するために使用)
  • __toString() メソッドの実装(継承する Value インタフェースで必要)

デフォルトでは、FieldType\Value のコンストラクタが使用され、プロパティ/値のペアのハッシュを渡すことができる。この例では、必要に応じて上書きすることができる。

Tweet FieldType は3つのものを保存する:

  • ツイートの URL
  • ツイートのオーサーの URL
  • 本文(HTML 文字列として)

ここでは格納される場所は考慮しない。FieldType を API として公開することのみ。以下のプロパティで終わる:

eZ/FieldType/Tweet/Value.php
/**
* Tweet URL on twitter.com (http://twitter.com/UserName/status/id).
* @var string
*/
public $url;
 
  
/**
* Author's tweet URL (http://twitter.com/UserName)
* @var string
*/
public $authorUrl;
 
  
/**
* The tweet's embed HTML
* @var string
*/
public $contents;

FieldType\Value インターフェイスに残るのは __toString() メソッドのみ。ツイートの URL を返そう。

eZ/FieldType/Tweet/Value.php
public function __toString()
{
   return $this->url;
}

Tweet\Type クラスの実装

識別メソッド: getFieldTypeIdentifier()

この FieldType を一意に識別する文字列 (eZ Publish 4 の DataTypeString) を返す必要がある。

eZ/FieldType/Tweet/Type
public function getFieldTypeIdentifier()
{
   return 'eztweet';
}

Value 処理メソッド: createValueFromInput()checkValueStructure()

両メソッドは acceptValue() の抽象 FieldType 実装で使われる。この FieldType インターフェースメソッドはさまざまな入力値をチェックし、type 自身の Value クラス (eZ\FieldType\Tweet\Value) に変換する。このメソッドは以下のいずれかの必要がある。

  • 入力値から作成できた Value オブジェクトを返す
  • この値を変更しないで返す。 API はこれを検出し、入力値が受け入れられなかったことを通知する。

この type に許容される値はツイートの URL のみ。

protected function createValueFromInput( $inputValue )
{
   if ( is_string( $inputValue ) )
   {
       $inputValue = new Value( array( 'url' => $inputValue ) );
   }
 
   return $inputValue;
}

このメソッドを使用して、API を使用して属性の値を設定する便利な方法を提供する。単純なものから複雑なビジネスオブジェクトまで何でもよい。

次に checkValueStructure() を実装する。これは Type に供給される Value が受け入れられることを保証するために抽象 FieldType によって呼び出される。ここでは Tweet\Value::$url が文字列であることを確認する。

protected function checkValueStructure( BaseValue $value )
{
   if ( !is_string( $value->url ) )
   {
       throw new eZ\Publish\Core\Base\Exceptions\InvalidArgumentType(
           '$value->url',
           'string',
           $value->url
       );
   }
}
public function getEmptyValue()
{
   return new Value;
}
array(
   'StringLengthValidator' => array(
       'minStringLength' => 0,
       'maxStringLength' => 100
   )
);
array(
   TweetAuthorValidator => array(
       AuthorList => array( johndoe, janedoe )
   )
);
public function validateValidatorConfiguration( $validatorConfiguration )
{
   $validationErrors = array();
 
   foreach ( $validatorConfiguration as $validatorIdentifier => $constraints )
   {
       // Report unknown validators
       if ( !$validatorIdentifier != 'TweetAuthorValidator' )
       {
           $validationErrors[] = new ValidationError( "Validator '$validatorIdentifier' is unknown" );
           continue;
       }
 
       // Validate arguments from TweetAuthorValidator
       if ( !isset( $constraints['AuthorList'] ) || !is_array( $constraints['AuthorList'] ) )
       {
           $validationErrors[] = new ValidationError( "Missing or invalid AuthorList argument" );
           continue;
       }
 
       foreach ( $constraints['AuthorList'] as $authorName )
       {
           if ( !preg_match( '/^[a-z0-9_]{1,15}$/i', $authorName ) )
           {
               $validationErrors[] = new ValidationError( "Invalid twitter username" );
           }
       }
   }
 
 
   return $validationErrors;
}
public function validate( FieldDefinition $fieldDefinition, SPIValue $fieldValue )
{
    $errors = array();
 
    if ( $this->isEmptyValue( $fieldValue ) )
    {
        return $errors;
    }
 
    // Tweet Url validation
    if ( !preg_match( '#^https?://twitter.com/([^/]+)/status/[0-9]+$#', $fieldValue->url, $m ) )
        $errors[] = new ValidationError( "Invalid twitter status url %url%", null, array( $fieldValue->url ) );
 
    $validatorConfiguration = $fieldDefinition->getValidatorConfiguration();
    if ( isset( $validatorConfiguration['TweetAuthorValidator'] ) )
    {
        if ( !in_array( $m[1], $validatorConfiguration['TweetAuthorValidator']['AuthorList'] ) )
        {
            $errors[] = new ValidationError(
                "Twitter user %user% is not in the approved author list",
                null,
                array( $m[1] )
            );
        }
    }
 
    return $errors;
}
public function getName( SPIValue $value )
{
   return preg_replace(
       '#^https?://twitter\.com/([^/]+)/status/([0-9]+)$#',
       '$1-$2',
       (string)$value->url );
}
 
 
protected function getSortInfo( CoreValue $value )
{
   return $this->getName( $value );
}
public function fromHash( $hash )
{
   if ( $hash === null )
   {
       return $this->getEmptyValue();
   }
   return new Value( $hash );
}
 
public function toHash( SPIValue $value )
{
   if ( $this->isEmptyValue( $value ) )
   {
       return null;
   }
   return array(
       'url' => $value->url
   );
}
Tweet\Type
/**
 * @param \EzSystems\TweetFieldTypeBundle\eZ\Publish\FieldType\Tweet\Value $value
 * @return \eZ\Publish\SPI\Persistence\Content\FieldValue
 */
public function toPersistenceValue( SPIValue $value )
{
    if ( $value === null )
    {
        return new PersistenceValue(
            array(
                "data" => null,
                "externalData" => null,
                "sortKey" => null,
            )
        );
    }
    return new PersistenceValue(
        array(
            "data" => $this->toHash( $value ),
            "sortKey" => $this->getSortInfo( $value ),
        )
    );
}
/**
 * @param \eZ\Publish\SPI\Persistence\Content\FieldValue $fieldValue
 * @return \EzSystems\TweetFieldTypeBundle\eZ\Publish\FieldType\Tweet\Value
 */
public function fromPersistenceValue( PersistenceValue $fieldValue )
{
    if ( $fieldValue->data === null )
    {
        return $this->getEmptyValue();
    }
    return new Value( $fieldValue->data );
}
eZ/Publish/FieldType/Tweet/Type.php
use EzSystems\TweetFieldTypeBundle\Twitter\TwitterClientInterface;
 
class Type extends FieldType
{
    /** @var TwitterClientInterface */
    protected $twitterClient;
 
    public function __construct( TwitterClientInterface $twitterClient )
    {
        $this->twitterClient = $twitterClient;
    }
}
eZ/Publish/FieldType/Tweet/Type.php
 public function toPersistenceValue( SPIValue $value )
{
    // if ( $value === null )
    // {...}
 
 
    if ( $value->contents === null )
    {
        $value->contents = $this->twitterClient->getEmbed( $value->url );
    }
    return new PersistenceValue(
    // array(...)
}
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?