Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Trigger an eZ Publish Legacy publish operation on content created via the public APIProvided as a Symfony 2 command. Drop in a bundle and adapt namespace.
<?php
/**
* @copyright Copyright (C) 2012 eZ Systems AS. All rights reserved.
* @license http://www.gnu.org/licenses/gpl-2.0.txt GNU General Public License v2
* @version //autogentag//
*/
namespace BD\SandboxBundle\Command;
use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand;
use Symfony\Component\Config\Definition\Exception\Exception;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputOption;
use eZ\Publish\Core\FieldType\XmlText\Value as XmlTextValue;
/**
* Missing workflow workaround
*/
class CreateContentWithoutPublishingCommand extends ContainerAwareCommand
{
/**
* User ID the operations must be executed as
* @var int
*/
protected $editorUserId = 2935;
protected function configure()
{
$this->setName( 'sandbox:create_content_without_publishing' )->setDefinition(
array(
new InputArgument( 'parentLocationId', InputArgument::REQUIRED, 'An existing parent location ID' ),
new InputArgument( 'contentType', InputArgument::REQUIRED, 'An existing content type identifier - the content type must contain a title field and a body field' ),
new InputArgument( 'title', InputArgument::REQUIRED, 'Content for the Title field' ),
new InputArgument( 'intro', InputArgument::REQUIRED, 'Content for the Intro field' ),
new InputArgument( 'body', InputArgument::REQUIRED, 'Content for the Body field' ),
)
);
}
protected function execute( InputInterface $input, OutputInterface $output )
{
/** @var $repository \eZ\Publish\API\Repository\Repository */
$repository = $this->getContainer()->get( 'ezpublish.api.repository' );
$contentService = $repository->getContentService();
$locationService = $repository->getLocationService();
$contentTypeService = $repository->getContentTypeService();
$repository->setCurrentUser( $repository->getUserService()->loadUser( $this->editorUserId ) );
// fetch the input arguments
$parentLocationId = $input->getArgument( 'parentLocationId' );
$contentTypeIdentifier = $input->getArgument( 'contentType' );
$title = $input->getArgument( 'title' );
$intro = $input->getArgument( 'intro' );
$body = $input->getArgument( 'body' );
try
{
$contentType = $contentTypeService->loadContentTypeByIdentifier( $contentTypeIdentifier );
$contentCreateStruct = $contentService->newContentCreateStruct( $contentType, 'eng-GB' );
$contentCreateStruct->setField( 'title', $title );
$contentCreateStruct->setField( 'intro', $intro );
$contentCreateStruct->setField( 'body', $body );
// instantiate a location create struct from the parent location
$locationCreateStruct = $locationService->newLocationCreateStruct( $parentLocationId );
// create a draft using the content and location create struct and publish it
$draft = $contentService->createContent( $contentCreateStruct, array( $locationCreateStruct ) );
$output->writeln( "Draft created with content ID {$draft->contentInfo->id} and title '{$title}''" );
if ( $this->runLegacyPublish( $draft->contentInfo->id, $draft->versionInfo->versionNo, $this->editorUserId ) === true )
{
$output->writeln( "Draft published" );
}
else
{
$output->writeln( "Draft published, but operation interrupted" );
}
}
// Content type or location not found
catch ( NotFoundException $e )
{
$output->writeln( $e->getMessage() );
}
// Invalid field value
catch ( \eZ\Publish\API\Repository\Exceptions\ContentFieldValidationException $e )
{
$output->writeln( $e->getMessage() );
}
// Required field missing or empty
catch ( \eZ\Publish\API\Repository\Exceptions\ContentValidationException $e )
{
$output->writeln( $e->getMessage() );
}
}
/**
* Returns the legacy kernel object.
*
* @return \eZ\Publish\Core\MVC\Legacy\Kernel
*/
protected function getLegacyKernel()
{
$closure = $this->getContainer()->get( 'ezpublish_legacy.kernel' );
return $closure();
}
/**
* @param $contentId Content object ID
* @param $versionId Version number
* @param $runAsUserId User Id the executed should be executed as
* @return bool true if the operation was completed, false if it was interrupted
*/
protected function runLegacyPublish( $contentId, $versionId, $runAsUserId = null )
{
$legacyKernel = $this->getLegacyKernel();
return $legacyKernel->runCallback(
function () use ( $contentId, $versionId, $runAsUserId )
{
$script = \eZScript::instance( array( 'use-modules' => true ) );
$script->initialize();
$db = \eZDB::instance();
$transactionCounter = $db->transactionCounter();
if ( $runAsUserId )
{
\eZUser::setCurrentlyLoggedInUser( \eZUser::fetch( $runAsUserId ), $runAsUserId );
}
$operationResult = \eZOperationHandler::execute(
'content', 'publish', array( 'object_id' => $contentId, 'version' => $versionId )
);
if ( ( array_key_exists( 'status', $operationResult ) && $operationResult['status'] != \eZModuleOperationInfo::STATUS_CONTINUE ) )
{
// Required by https://jira.ez.no/browse/EZP-20558
for ( $i = 0, $counter = ( $db->transactionCounter() - $transactionCounter ); $i < $counter; ++$i )
{
$db->commit();
}
return false;
}
return true;
}
);
}
}
@yannickmodahgouez
Copy link

yannickmodahgouez commented Nov 24, 2015

Somehow the following code :

\eZUser::setCurrentlyLoggedInUser( \eZUser::fetch( $runAsUserId ), $runAsUserId );

causes a "Trying to run recursive callback in legacy kernel! Inception!" error. Any ideas why ?

@monsieurmechant
Copy link

monsieurmechant commented Nov 25, 2015

A workaround is to set the ez user before running the callback closure.

<?php

     protected function runLegacyPublish( $contentId, $versionId, $runAsUserId = null )
    {
     if ( $runAsUserId ) {
        \eZUser::setCurrentlyLoggedInUser( \eZUser::fetch( $runAsUserId ), $runAsUserId );
    }

    $legacyKernel = $this->getLegacyKernel();
    return $legacyKernel->runCallback(
        function () use ( $contentId, $versionId, $runAsUserId )
        {
            $script = \eZScript::instance( array( 'use-modules' => true ) );
            $script->initialize();
            $db = \eZDB::instance();
            $transactionCounter = $db->transactionCounter();

            $operationResult = \eZOperationHandler::execute(
                'content', 'publish', array( 'object_id' => $contentId, 'version' => $versionId )
            );
            if ( ( array_key_exists( 'status', $operationResult ) && $operationResult['status'] != \eZModuleOperationInfo::STATUS_CONTINUE ) )
            {
                // Required by https://jira.ez.no/browse/EZP-20558
                for ( $i = 0, $counter = ( $db->transactionCounter() - $transactionCounter ); $i < $counter; ++$i )
                {
                    $db->commit();
                }
                return false;
            }
            return true;
        }
    );
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment