silverstripe, как использовать doPublish()

Я работаю с SilverStripe и работаю над созданием страницы новостей. Я использую модуль DataObjectAsPage (http://www.ssbits.com/tutorials/2012/dataobject-as-pages-the-module/ ), у меня все заработало, когда я использую администратора для публикации новостей. Теперь я хочу использовать модуль DataObjectManager вместо административного модуля для управления своими новостями. Но именно здесь существует проблема. В режиме черновика все работает нормально, я могу создать новую новость, и она отображается в черновике. Но когда я хочу опубликовать новость, она не будет отображаться ни в реальном, ни в опубликованном режиме.

Я использую следующие таблицы:
-таблица Dataobjectaspage,
-таблица Dataobjectaspage_live,
-таблица NewsArticle,
-таблица NewsArticle_Live

Статьи были вставлены при публикации в таблицу Dataobjectaspage и в таблицу NewsArticle... Но не в таблицы _Live...

Кажется, функция doPublish() не использовалась во время публикации. Итак, я пытаюсь использовать следующее:

function onAfterWrite() {
    parent::onAfterWrite();   
    DataObjectAsPage::doPublish();
}

Но когда я использую это, возникает ошибка: вот это изображение

Кажется, это зациклено... У меня есть файл NewsArticle.php, в котором я использую эту функцию:

 function onAfterWrite() {
    parent::onAfterWrite();   
    DataObjectAsPage::doPublish();
}

Эта функция вызывает файл DataObjectAsPage.php и использует следующий код:

function doPublish() {
        if (!$this->canPublish()) return false;

        $original = Versioned::get_one_by_stage("DataObjectAsPage", "Live", "\"DataObjectAsPage\".\"ID\" = $this->ID");
        if(!$original) $original = new DataObjectAsPage();

        // Handle activities undertaken by decorators
        $this->invokeWithExtensions('onBeforePublish', $original);
        $this->Status = "Published";
        //$this->PublishedByID = Member::currentUser()->ID;
        $this->write();
        $this->publish("Stage", "Live");

        // Handle activities undertaken by decorators
        $this->invokeWithExtensions('onAfterPublish', $original);

        return true;
    }

А затем переходит к файлу DataObject.php и использует функцию записи():

public function write($showDebug = false, $forceInsert = false, $forceWrite = false, $writeComponents = false) {
    $firstWrite = false;
    $this->brokenOnWrite = true;
    $isNewRecord = false;

    if(self::get_validation_enabled()) {
        $valid = $this->validate();
        if(!$valid->valid()) {
            // Used by DODs to clean up after themselves, eg, Versioned
            $this->extend('onAfterSkippedWrite');
            throw new ValidationException($valid, "Validation error writing a $this->class object: " . $valid->message() . ".  Object not written.", E_USER_WARNING);
            return false;
        }
    }

    $this->onBeforeWrite();
    if($this->brokenOnWrite) {
        user_error("$this->class has a broken onBeforeWrite() function.  Make sure that you call parent::onBeforeWrite().", E_USER_ERROR);
    }

    // New record = everything has changed

    if(($this->ID && is_numeric($this->ID)) && !$forceInsert) {
        $dbCommand = 'update';

        // Update the changed array with references to changed obj-fields
        foreach($this->record as $k => $v) {
            if(is_object($v) && method_exists($v, 'isChanged') && $v->isChanged()) {
                $this->changed[$k] = true;
            }
        }

    } else{
        $dbCommand = 'insert';

        $this->changed = array();
        foreach($this->record as $k => $v) {
            $this->changed[$k] = 2;
        }

        $firstWrite = true;
    }

    // No changes made
    if($this->changed) {
        foreach($this->getClassAncestry() as $ancestor) {
            if(self::has_own_table($ancestor))
            $ancestry[] = $ancestor;
        }

        // Look for some changes to make
        if(!$forceInsert) unset($this->changed['ID']);

        $hasChanges = false;
        foreach($this->changed as $fieldName => $changed) {
            if($changed) {
                $hasChanges = true;
                break;
            }
        }

        if($hasChanges || $forceWrite || !$this->record['ID']) {

            // New records have their insert into the base data table done first, so that they can pass the
            // generated primary key on to the rest of the manipulation
            $baseTable = $ancestry[0];

            if((!isset($this->record['ID']) || !$this->record['ID']) && isset($ancestry[0])) {  

                DB::query("INSERT INTO \"{$baseTable}\" (\"Created\") VALUES (" . DB::getConn()->now() . ")");
                $this->record['ID'] = DB::getGeneratedID($baseTable);
                $this->changed['ID'] = 2;

                $isNewRecord = true;
            }

            // Divvy up field saving into a number of database manipulations
            $manipulation = array();
            if(isset($ancestry) && is_array($ancestry)) {
                foreach($ancestry as $idx => $class) {
                    $classSingleton = singleton($class);

                    foreach($this->record as $fieldName => $fieldValue) {
                        if(isset($this->changed[$fieldName]) && $this->changed[$fieldName] && $fieldType = $classSingleton->hasOwnTableDatabaseField($fieldName)) {
                            $fieldObj = $this->dbObject($fieldName);
                            if(!isset($manipulation[$class])) $manipulation[$class] = array();

                            // if database column doesn't correlate to a DBField instance...
                            if(!$fieldObj) {
                                $fieldObj = DBField::create('Varchar', $this->record[$fieldName], $fieldName);
                            }

                            // Both CompositeDBFields and regular fields need to be repopulated
                            $fieldObj->setValue($this->record[$fieldName], $this->record);

                            if($class != $baseTable || $fieldName!='ID')
                                $fieldObj->writeToManipulation($manipulation[$class]);
                        }
                    }

                    // Add the class name to the base object
                    if($idx == 0) {
                        $manipulation[$class]['fields']["LastEdited"] = "'".SS_Datetime::now()->Rfc2822()."'";
                        if($dbCommand == 'insert') {
                            $manipulation[$class]['fields']["Created"] = "'".SS_Datetime::now()->Rfc2822()."'";
                            //echo "<li>$this->class - " .get_class($this);
                            $manipulation[$class]['fields']["ClassName"] = "'$this->class'";
                        }
                    }

                    // In cases where there are no fields, this 'stub' will get picked up on
                    if(self::has_own_table($class)) {
                        $manipulation[$class]['command'] = $dbCommand;
                        $manipulation[$class]['id'] = $this->record['ID'];
                    } else {
                        unset($manipulation[$class]);
                    }
                }
            }
            $this->extend('augmentWrite', $manipulation);

            // New records have their insert into the base data table done first, so that they can pass the
            // generated ID on to the rest of the manipulation
            if(isset($isNewRecord) && $isNewRecord && isset($manipulation[$baseTable])) {
                $manipulation[$baseTable]['command'] = 'update';
            }

            DB::manipulate($manipulation);

            if(isset($isNewRecord) && $isNewRecord) {
                DataObjectLog::addedObject($this);
            } else {
                DataObjectLog::changedObject($this);
            }

            $this->onAfterWrite();

            $this->changed = null;
        } elseif ( $showDebug ) {
            echo "<b>Debug:</b> no changes for DataObject<br />";
            // Used by DODs to clean up after themselves, eg, Versioned
            $this->extend('onAfterSkippedWrite');
        }

        // Clears the cache for this object so get_one returns the correct object.
        $this->flushCache();

        if(!isset($this->record['Created'])) {
            $this->record['Created'] = SS_Datetime::now()->Rfc2822();
        }
        $this->record['LastEdited'] = SS_Datetime::now()->Rfc2822();
    } else {
        // Used by DODs to clean up after themselves, eg, Versioned
        $this->extend('onAfterSkippedWrite');
    }

    // Write ComponentSets as necessary
    if($writeComponents) {
        $this->writeComponents(true);
    }
    return $this->record['ID'];
}

Посмотрите на $this->onAfterWrite();
Вероятно, он переходит к моей собственной функции в NewsArticle.php, и там начинается цикл! Я не уверен, хотя, поэтому мне может понадобиться помощь!!

Кто-нибудь знает, как использовать функцию doPublish()?


person Jeroen Neplenbroek    schedule 11.06.2012    source источник
comment
ссылка на изображение с ошибкой кажется неработающей, не могли бы вы разместить изображение где-нибудь еще?   -  person schellmax    schedule 13.06.2012
comment
надеюсь, что это работает: i.imgur.com/pSDtR.png   -  person Jeroen Neplenbroek    schedule 13.06.2012
comment
довольно сложно понять, что здесь происходит, не глядя на код. может быть, вы могли бы опубликовать почтовый индекс с папкой вашего сайта?   -  person schellmax    schedule 14.06.2012


Ответы (1)


Причина этого заключается в том, что в методе DataObjectAsPage::publish() он вызывает ->write() — строка 11 вашего третьего примера кода.

Итак, что происходит, это вызывает ->write(), в конце ->write() вызывается ваш метод onAfterWrite(), который вызывает publish(), который снова вызывает write().

Если вы удалите добавленную функцию onAfterWrite(), она должна работать должным образом.

Метод doPublish() в DataObjectAsPage позаботится о публикации из Stage в Live за вас.

person Matt    schedule 07.05.2013