Skip to content

Instantly share code, notes, and snippets.

@bdunogier
Last active November 29, 2018 09:42
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save bdunogier/e05ed564770fa6a51e51 to your computer and use it in GitHub Desktop.
Save bdunogier/e05ed564770fa6a51e51 to your computer and use it in GitHub Desktop.
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

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

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