简体   繁体   中英

ezpublish 5.4 sort according to parent field

I am using ezpublish Search API to get the list of session content type objects ordered by their parent's training field (field name is code ).

So if I have two sessions S1 (linked to training with code T1) and S2 (linked to training with code T2) I want to have session S1 listed before S2 in the list.

$criterions = array (
            new Criterion\ContentTypeIdentifier( 'session' )
        );
$locationQuery = new LocationQuery();
        $locationQuery->query = $criteriaArray;
        $locationQuery->sortClauses = array(
            //new SortClause\Field('session','price'),<- this works
            new SortClause\Field('training','code',Query::SORT_ASC)
           //this second sorClause does not work as code is not a field of session while price is
            );

There might be a solution to this problem using native mysql query but it's not portable and some ids will be hardcoded.

My questions is can we achieve a sort of the sesssions according to their parent's training' code`field ?

This is not possible unfortunatelly with the built in sort clauses.

What you can do is fetch trainings sorted by the code field and then for each training load its sessions separately. This will not be efficient, ofcourse, if you have many content objects in your database.

Another possibility might be to implement a custom sort clause that might do the trick.

I managed to get it working thanks to @Edi and a colleague at my job.

The two clasess to create are : The field class:

class ParentSortClauseField extends SortClause
{

    public function __construct($typeIdentifier, $fieldIdentifier, $sortDirection = Query::SORT_ASC)
    {
        parent::__construct(
            'field',
            $sortDirection,
            new FieldTarget($typeIdentifier, $fieldIdentifier)
        );
    }

}

The handler class:

class ParentSortClauseHandler extends SortClauseHandler
{

    protected $contentTypeHandler;


    public function __construct(
        DatabaseHandler $dbHandler,
        ContentTypeHandler $contentTypeHandler
    )
    {
        $this->contentTypeHandler = $contentTypeHandler;

        parent::__construct($dbHandler);
    }


    public function accept(SortClause $sortClause)
    {
        return $sortClause instanceof ParentSortClauseField;
    }


    public function applySelect(SelectQuery $query, SortClause $sortClause, $number)
    {
        $query
            ->select(
                $query->alias(
                    $query->expr->not(
                        $query->expr->isNull(
                            $this->dbHandler->quoteColumn(
                                'sort_key_int',
                                $this->getSortTableName($number)
                            )
                        )
                    ),
                    $column1 = $this->getSortColumnName($number . '_null')
                ),
                $query->alias(
                    $query->expr->not(
                        $query->expr->isNull(
                            $this->dbHandler->quoteColumn(
                                'sort_key_string',
                                $this->getSortTableName($number)
                            )
                        )
                    ),
                    $column2 = $this->getSortColumnName($number . '_bis_null')
                ),
                $query->alias(
                    $this->dbHandler->quoteColumn(
                        'sort_key_int',
                        $this->getSortTableName($number)
                    ),
                    $column3 = $this->getSortColumnName($number)
                ),
                $query->alias(
                    $this->dbHandler->quoteColumn(
                        'sort_key_string',
                        $this->getSortTableName($number)
                    ),
                    $column4 = $this->getSortColumnName($number . '_bis')
                )
            );

        return array($column1, $column2, $column3, $column4);
    }

    public function applyJoin(
        SelectQuery $query,
        SortClause $sortClause,
        $number,
        array $languageSettings
    )
    {

        /** @var \eZ\Publish\API\Repository\Values\Content\Query\SortClause\Target\FieldTarget $fieldTarget */

        $fieldTarget = $sortClause->targetData;
        $fieldMap = $this->contentTypeHandler->getSearchableFieldMap();
        if (!isset($fieldMap[$fieldTarget->typeIdentifier][$fieldTarget->fieldIdentifier]['field_definition_id'])) {
            throw new \InvalidArgumentException(
                '$sortClause->targetData',
                'No searchable fields found for the given sort clause target ' .
                "'{$fieldTarget->fieldIdentifier}' on '{$fieldTarget->typeIdentifier}'."
            );
        }
        $fieldDefinitionId = $fieldMap[$fieldTarget->typeIdentifier][$fieldTarget->fieldIdentifier]['field_definition_id'];

        $table = $this->getSortTableName($number);
        $query
            ->innerJoin(
                $query->alias('ezcontentobject_tree', 'parent')
                ,
                $query->expr->eq(
                    $this->dbHandler->quoteColumn('parent_node_id', 'ezcontentobject_tree'),
                    $this->dbHandler->quoteColumn('node_id', 'parent')
                )
            );
        $query
            ->leftJoin(
                $query->alias(
                    $this->dbHandler->quoteTable('ezcontentobject_attribute'),
                    $this->dbHandler->quoteIdentifier($table)
                ),
                $query->expr->lAnd(
                    $query->expr->eq(
                        $query->bindValue($fieldDefinitionId, null, PDO::PARAM_INT),
                        $this->dbHandler->quoteColumn('contentclassattribute_id', $table)
                    ),
                    $query->expr->eq(
                        $this->dbHandler->quoteColumn('contentobject_id', $table),
                        $this->dbHandler->quoteColumn('contentobject_id', 'parent')
                    ),
                    $query->expr->eq(
                        $this->dbHandler->quoteColumn('version', $table),
                        $this->dbHandler->quoteColumn('contentobject_version', 'parent')
                    ),
                    $query->expr->eq(
                        $this->dbHandler->quoteColumn('language_code', $table),
                        $query->bindValue('fre-FR')
                    )
                )
            );
    }
}

Declare the handler as a service:

app.sort_clause_handler.location.parent:
            class: ...\SortClauseHandler\ParentSortClauseHandler
            arguments:
                - @ezpublish.api.storage_engine.legacy.dbhandler
                - @ezpublish.spi.persistence.content_type_handler
            tags:
                - {name: ezpublish.search.legacy.gateway.sort_clause_handler.content}
                - {name: ezpublish.search.legacy.gateway.sort_clause_handler.location}

And To call the pieces together in the cotroller I did this:

$sortQuery[] = new ParentSortClauseField('parentclassname', 'field', $sortOrder);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM