function unLock(eZContentObject $object)
{
    $filterConds = array('action' => 'creating_translation', 'param' => $object->attribute('id'));
    $rows = eZPersistentObject::fetchObjectList(eZPendingActions::definition(), null, $filterConds);
    foreach ($rows as $row) {
        $row->remove();
    }
}
    /**
     * @param int $nodeID
     * @param string $action
     */
    public function updateNodeVisibility( $nodeID, $action )
    {
        $node = eZContentObjectTreeNode::fetch( $nodeID );
        eZContentOperationCollection::registerSearchObject($node->attribute( 'contentobject_id' ));

        if ( $node->childrenCount( false ) )
        {
            $pendingAction = new eZPendingActions(
                array(
                    'action'    => self::PENDING_ACTION_INDEX_SUBTREE,
                    'created'   => time(),
                    'param'     => $nodeID
                )
            );

            $pendingAction->store();
        }
    }
 /**
  * Deletes a content object, or a list of content objects
  *
  * @param array $deleteIDArray
  * @param bool $moveToTrash
  *
  * @return array An array with operation status, always true
  */
 public static function deleteObject($deleteIDArray, $moveToTrash = false)
 {
     $ini = eZINI::instance();
     $delayedIndexingValue = $ini->variable('SearchSettings', 'DelayedIndexing');
     if ($delayedIndexingValue === 'enabled' || $delayedIndexingValue === 'classbased') {
         $pendingActionsToDelete = array();
         $classList = $ini->variable('SearchSettings', 'DelayedIndexingClassList');
         // Will be used below if DelayedIndexing is classbased
         $assignedNodesByObject = array();
         $nodesToDeleteByObject = array();
         $aNodes = eZContentObjectTreeNode::fetch($deleteIDArray);
         if (!is_array($aNodes)) {
             $aNodes = array($aNodes);
         }
         foreach ($aNodes as $node) {
             $object = $node->object();
             $objectID = $object->attribute('id');
             $assignedNodes = $object->attribute('assigned_nodes');
             // Only delete pending action if this is the last object's node that is requested for deletion
             // But $deleteIDArray can also contain all the object's node (mainly if this method is called programmatically)
             // So if this is not the last node, then store its id in a temp array
             // This temp array will then be compared to the whole object's assigned nodes array
             if (count($assignedNodes) > 1) {
                 // $assignedNodesByObject will be used as a referent to check if we want to delete all lasting nodes
                 if (!isset($assignedNodesByObject[$objectID])) {
                     $assignedNodesByObject[$objectID] = array();
                     foreach ($assignedNodes as $assignedNode) {
                         $assignedNodesByObject[$objectID][] = $assignedNode->attribute('node_id');
                     }
                 }
                 // Store the node assignment we want to delete
                 // Then compare the array to the referent node assignment array
                 $nodesToDeleteByObject[$objectID][] = $node->attribute('node_id');
                 $diff = array_diff($assignedNodesByObject[$objectID], $nodesToDeleteByObject[$objectID]);
                 if (!empty($diff)) {
                     continue;
                 }
             }
             if ($delayedIndexingValue !== 'classbased' || is_array($classList) && in_array($object->attribute('class_identifier'), $classList)) {
                 $pendingActionsToDelete[] = $objectID;
             }
         }
         if (!empty($pendingActionsToDelete)) {
             $filterConds = array('param' => array($pendingActionsToDelete));
             eZPendingActions::removeByAction('index_object', $filterConds);
         }
     }
     eZContentObjectTreeNode::removeSubtrees($deleteIDArray, $moveToTrash);
     return array('status' => true);
 }
 /**
  * Test for eZPendingActions::removeByAction()
  */
 public function testRemoveByAction()
 {
     // Insert several fixtures at one time. Can't use @dataProvider to do that
     $fixtures = $this->providerForTestFecthByAction();
     foreach ($fixtures as $fixture) {
         $this->insertPendingAction($fixture[0], $fixture[1], $fixture[2]);
     }
     eZPendingActions::removeByAction('test');
     $res = eZPendingActions::fetchByAction('test');
     $this->assertTrue(empty($res));
 }
 /**
  * Adds a "pending clear cache" action if ViewCaching is disabled.
  * This method should be called at publish time.
  * Cache should then be cleared by a cronjob
  * @return void
  */
 public function addPendingClearCacheIfNeeded()
 {
     if (eZINI::instance()->variable('ContentSettings', 'ViewCaching') === 'disabled') {
         $rowPending = array('action' => self::ACTION_CLEAR_CACHE, 'created' => time(), 'param' => $this->contentObject->attribute('id'));
         $pendingItem = new eZPendingActions($rowPending);
         $pendingItem->store();
     }
 }
 /**
  * Update index when node's visibility is modified.
  *
  * If the node has children, they will be also re-indexed, but this action is deferred to ezfindexsubtree cronjob.
  *
  * @param int $nodeID
  * @param string $action
  */
 public function updateNodeVisibility($nodeID, $action)
 {
     $node = eZContentObjectTreeNode::fetch($nodeID);
     eZContentOperationCollection::registerSearchObject($node->attribute('contentobject_id'));
     $params = array('Depth' => 1, 'DepthOperator' => 'eq', 'Limitation' => array(), 'IgnoreVisibility' => true);
     if ($node->subTreeCount($params) > 0) {
         $pendingAction = new eZPendingActions(array('action' => 'index_subtree', 'created' => time(), 'param' => $nodeID));
         $pendingAction->store();
     }
 }
$nodeID = $module->actionParameter( 'NodeID' );
$languageCode = $module->actionParameter( 'LanguageCode' );

$viewMode = 'full';
if ( !$module->hasActionParameter( 'ViewMode' ) )
{
    $viewMode = $module->actionParameter( 'ViewMode' );
}

if ( $module->isCurrentAction( 'IndexObject' )
     || $module->isCurrentAction( 'IndexSubtree' )) {
    eZContentOperationCollection::registerSearchObject( $objectID );
}

if ( $module->isCurrentAction( 'IndexSubtree' ) ) {
    $pendingAction = new eZPendingActions(
        array(
            'action' => eZSolr::PENDING_ACTION_INDEX_SUBTREE,
            'created' => time(),
            'param' => $nodeID
        )
    );
    $pendingAction->store();
}

if ( $module->isCurrentAction( 'RemoveObject' ) ) {
    $object = eZContentObject::fetch($objectID);
    eZSearch::removeObject($object, true);
}

return $module->redirect( 'content', 'view', array( $viewMode, $nodeID, $languageCode ) );
$entries = eZPendingActions::fetchByAction(eZSolr::PENDING_ACTION_INDEX_SUBTREE);
if (!empty($entries)) {
    $parentNodeIDList = array();
    foreach ($entries as $entry) {
        $parentNodeID = $entry->attribute('param');
        $parentNodeIDList[] = (int) $parentNodeID;
        $offset = 0;
        while (true) {
            $nodes = eZContentObjectTreeNode::subTreeByNodeID(array('IgnoreVisibility' => true, 'Offset' => $offset, 'Limit' => $limit, 'Limitation' => array()), $parentNodeID);
            if (!empty($nodes) && is_array($nodes)) {
                foreach ($nodes as $node) {
                    ++$offset;
                    $cli->output("\tIndexing object ID #{$node->attribute('contentobject_id')}");
                    // delay commits with passing false for $commit parameter
                    $eZSolr->addObject($node->attribute('object'), false);
                }
                // finish up with commit
                $eZSolr->commit();
                // clear object cache to conserver memory
                eZContentObject::clearCache();
            } else {
                break;
                // No valid nodes
            }
        }
    }
    eZPendingActions::removeByAction(eZSolr::PENDING_ACTION_INDEX_SUBTREE, array('param' => array($parentNodeIDList)));
}
if (!$isQuiet) {
    $cli->output("Done");
}
    /**
     * Same test as {@link self::testRemovePendingSearchSeveralNodesForObject()}, with not all nodes removed
     * Use case
     * --------
     * 1. If all nodes are removed, pending action must also be removed
     * 2. If NOT all nodes are removed (at least one node remaining for object), pending action must NOT be removed (case tested here)
     *
     * @group issue_17932
     */
    public function testRemovePendingSearchNotAllNodesRemoved()
    {
        $this->folder->addNode( 43 );
        $folderObjectID = $this->folder->object->attribute( 'id' );

        $aNodeID = array( $this->folder->nodes[0]->attribute( 'node_id' ) ); // Only delete the first node

        eZContentOperationCollection::deleteObject( $aNodeID );
        $filterConds = array(
            'action'        => 'index_object',
            'param'         => $folderObjectID
        );
        $pendingCount = eZPersistentObject::count( eZPendingActions::definition(), $filterConds );
        self::assertGreaterThan( 0, $pendingCount, "eZContentOperationCollection::deleteObject() must remove pending action for object #$folderObjectID as all nodes have been removed" );
    }
$entries = eZPendingActions::fetchByAction('index_subtree');
if (!empty($entries)) {
    $parentNodeIDList = array();
    foreach ($entries as $entry) {
        $parentNodeID = $entry->attribute('param');
        $parentNodeIDList[] = (int) $parentNodeID;
        $offset = 0;
        while (true) {
            $nodes = eZContentObjectTreeNode::subTreeByNodeID(array('IgnoreVisibility' => true, 'Offset' => $offset, 'Limit' => $limit, 'Limitation' => array()), $parentNodeID);
            if (!empty($nodes) && is_array($nodes)) {
                foreach ($nodes as $node) {
                    ++$offset;
                    $cli->output("\tIndexing object ID #{$node->attribute('contentobject_id')}");
                    // delay commits with passing false for $commit parameter
                    $searchEngine->addObject($node->attribute('object'), false);
                }
                // finish up with commit
                $searchEngine->commit();
                // clear object cache to conserve memory
                eZContentObject::clearCache();
            } else {
                break;
                // No valid nodes
            }
        }
    }
    eZPendingActions::removeByAction('index_subtree', array('param' => array($parentNodeIDList)));
}
if (!$isQuiet) {
    $cli->output("Done");
}
 /**
  * Clears view cache for imported content objects.
  * ObjectIDs are stored in 'ezpending_actions' table, with {@link SQLIContent::ACTION_CLEAR_CACHE} action
  */
 public static function viewCacheClear()
 {
     $db = eZDB::instance();
     $isCli = isset($_SERVER['argv']);
     $output = null;
     $progressBar = null;
     $i = 0;
     $conds = array('action' => SQLIContent::ACTION_CLEAR_CACHE);
     $limit = array('offset' => 0, 'length' => 50);
     $count = (int) eZPersistentObject::count(eZPendingActions::definition(), $conds);
     if ($isCli && $count > 0) {
         // Progress bar implementation
         $output = new ezcConsoleOutput();
         $output->outputLine('Starting to clear view cache for imported objects...');
         $progressBarOptions = array('emptyChar' => ' ', 'barChar' => '=');
         $progressBar = new ezcConsoleProgressbar($output, $count, $progressBarOptions);
         $progressBar->start();
     }
     /*
      * To avoid fatal errors due to memory exhaustion, pending actions are fetched by packets
      */
     do {
         $aObjectsToClear = eZPendingActions::fetchObjectList(eZPendingActions::definition(), null, $conds, null, $limit);
         $jMax = count($aObjectsToClear);
         if ($jMax > 0) {
             for ($j = 0; $j < $jMax; ++$j) {
                 if ($isCli) {
                     $progressBar->advance();
                 }
                 $db->begin();
                 eZContentCacheManager::clearContentCacheIfNeeded((int) $aObjectsToClear[$j]->attribute('param'));
                 $aObjectsToClear[$j]->remove();
                 $db->commit();
                 $i++;
             }
         }
         unset($aObjectsToClear);
         eZContentObject::clearCache();
         if (eZINI::instance('site.ini')->variable('ContentSettings', 'StaticCache') == 'enabled') {
             $optionArray = array('iniFile' => 'site.ini', 'iniSection' => 'ContentSettings', 'iniVariable' => 'StaticCacheHandler');
             $options = new ezpExtensionOptions($optionArray);
             $staticCacheHandler = eZExtension::getHandlerClass($options);
             $staticCacheHandler::executeActions();
         }
     } while ($i < $count);
     if ($isCli && $count > 0) {
         $progressBar->finish();
         $output->outputLine();
     }
 }
 /**
  * @param int $remoteNodeID
  * @param int $localParentNodeID
  *
  * @return eZContentObject
  * @throws Exception
  */
 public function import($remoteNodeID, $localParentNodeID)
 {
     if (!class_exists('OCOpenDataApiNode')) {
         throw new Exception("Libreria OCOpenDataApiNode non trovata");
     }
     $apiNodeUrl = rtrim($this->attributes['definition']['Url'], '/') . '/api/opendata/v1/content/node/' . $remoteNodeID;
     $remoteApiNode = OCOpenDataApiNode::fromLink($apiNodeUrl);
     if (!$remoteApiNode instanceof OCOpenDataApiNode) {
         throw new Exception("Url remoto \"{$apiNodeUrl}\" non raggiungibile");
     }
     $newObject = $remoteApiNode->createContentObject($localParentNodeID);
     if (!$newObject instanceof eZContentObject) {
         throw new Exception("Fallita la creazione dell'oggetto da nodo remoto");
     }
     $rowPending = array('action' => self::ACTION_SYNC_OBJECT, 'param' => $newObject->attribute('id'));
     $pendingItem = new eZPendingActions($rowPending);
     $pendingItem->store();
     return $newObject;
 }
Exemple #13
0
 /**
  * Called when a node's visibility is modified.
  * Will re-index content identified by $nodeID.
  * If the node has children, they will be also re-indexed, but this action is deferred to ezfindexsubtree cronjob.
  *
  * @todo when Solr supports it: update fields only
  *
  * @param $nodeID
  * @param $action
  * @return void
  * @see eZSearch::updateNodeVisibility()
  */
 public function updateNodeVisibility($nodeID, $action)
 {
     $node = eZContentObjectTreeNode::fetch($nodeID);
     $this->addObject($node->attribute('object'));
     $params = array('Depth' => 1, 'DepthOperator' => 'eq', 'Limitation' => array(), 'IgnoreVisibility' => true);
     if ($node->subTreeCount($params) > 0) {
         $pendingAction = new eZPendingActions(array('action' => self::PENDING_ACTION_INDEX_SUBTREE, 'created' => time(), 'param' => $nodeID));
         $pendingAction->store();
     }
 }
 public function unlock()
 {
     eZPendingActions::removeByAction(self::ACTION_KEY);
 }
    /**
     * Deletes a content object, or a list of content objects
     *
     * @param array $deleteIDArray
     * @param bool $moveToTrash
     *
     * @return array An array with operation status, always true
     */
    static public function deleteObject( $deleteIDArray, $moveToTrash = false )
    {
        $ini = eZINI::instance();
        $aNodes = eZContentObjectTreeNode::fetch( $deleteIDArray );
        if( !is_array( $aNodes ) )
        {
            $aNodes = array( $aNodes );
        }

        $delayedIndexingValue = $ini->variable( 'SearchSettings', 'DelayedIndexing' );
        if ( $delayedIndexingValue === 'enabled' || $delayedIndexingValue === 'classbased' )
        {
            $pendingActionsToDelete = array();
            $classList = $ini->variable( 'SearchSettings', 'DelayedIndexingClassList' ); // Will be used below if DelayedIndexing is classbased
            $assignedNodesByObject = array();
            $nodesToDeleteByObject = array();

            foreach ( $aNodes as $node )
            {
                $object = $node->object();
                $objectID = $object->attribute( 'id' );
                $assignedNodes = $object->attribute( 'assigned_nodes' );
                // Only delete pending action if this is the last object's node that is requested for deletion
                // But $deleteIDArray can also contain all the object's node (mainly if this method is called programmatically)
                // So if this is not the last node, then store its id in a temp array
                // This temp array will then be compared to the whole object's assigned nodes array
                if ( count( $assignedNodes ) > 1 )
                {
                    // $assignedNodesByObject will be used as a referent to check if we want to delete all lasting nodes
                    if ( !isset( $assignedNodesByObject[$objectID] ) )
                    {
                        $assignedNodesByObject[$objectID] = array();

                        foreach ( $assignedNodes as $assignedNode )
                        {
                            $assignedNodesByObject[$objectID][] = $assignedNode->attribute( 'node_id' );
                        }
                    }

                    // Store the node assignment we want to delete
                    // Then compare the array to the referent node assignment array
                    $nodesToDeleteByObject[$objectID][] = $node->attribute( 'node_id' );
                    $diff = array_diff( $assignedNodesByObject[$objectID], $nodesToDeleteByObject[$objectID] );
                    if ( !empty( $diff ) ) // We still have more node assignments for object, pending action is not to be deleted considering this iteration
                    {
                        continue;
                    }
                }

                if ( $delayedIndexingValue !== 'classbased' ||
                     ( is_array( $classList ) && in_array( $object->attribute( 'class_identifier' ), $classList ) ) )
                {
                    $pendingActionsToDelete[] = $objectID;
                }
            }

            if ( !empty( $pendingActionsToDelete ) )
            {
                $filterConds = array( 'param' => array ( $pendingActionsToDelete ) );
                eZPendingActions::removeByAction( 'index_object', $filterConds );
            }
        }

        // Add assigned nodes to the clear cache list
        // This allows to clear assigned nodes separately (e.g. in reverse proxies)
        // as once content is removed, there is no more assigned nodes, and http cache clear is not possible any more.
        // See https://jira.ez.no/browse/EZP-22447
        foreach ( $aNodes as $node )
        {
            eZContentCacheManager::addAdditionalNodeIDPerObject( $node->attribute( 'contentobject_id' ), $node->attribute( 'node_id' ) );
        }
        eZContentObjectTreeNode::removeSubtrees( $deleteIDArray, $moveToTrash );
        return array( 'status' => true );
    }