Version: current

      1 <?php
      2
      3 // FIXME вынести задачу в webylon чтобы не ставить ненужный модуль на каждый сайт
      4 class ImportTestContentTask extends BuildTask {
      5
      6     private $importedObjects = array();
      7
      8     private $module = '';
      9
     10     private $locale = '';
     11
     12     private $subsiteID = 0;
     13
     14     private $baseUrl = '';
     15
     16     static $module_url = 'http://content.mediaweb.ru/demo_content/export/';
     17
     18     static $skip_object_classes = array('Folder', 'Member', 'SiteConfig');
     19
     20     static function get_api_data($url) {
     21         $urlData = parse_url($url);
     22         $path = str_replace('/', '_', $urlData["host"] . '_' . $urlData["path"]);
     23         if (0 && is_file(TEMP_FOLDER . '/' . $path)) {
     24             $xml = simplexml_load_string(file_get_contents(TEMP_FOLDER . '/' . $path));
     25         } else {
     26             $file = file_get_contents($url);
     27             file_put_contents(TEMP_FOLDER . '/' . $path, $file);
     28             $xml = simplexml_load_string($file);
     29         }
     30         return $xml;
     31     }
     32
     33     function run($request) {
     34         ini_set('user_agent','php');
     35
     36         if ($request->getVar('module')) {
     37             $this->module = $request->getVar('module');
     38         } else {
     39             return print "No required parameter 'module' \n";
     40         }
     41
     42         if ($request->getVar('locale')) {
     43             $this->locale = $request->getVar('locale');
     44             i18n::set_locale($this->locale);
     45         } else {
     46             $this->locale = i18n::get_locale();
     47         }
     48
     49         // если есть подсайты, то ищем его по заданной локали
     50         if (class_exists('Subsite')) {
     51             if ($subsite = DataObject::get_one('Subsite', "Language = '{$this->locale}'")) {
     52                 $this->subsiteID = $subsite->ID;
     53                 Subsite::changeSubsite($subsite);
     54             }
     55         }
     56
     57         $data = file_get_contents(self::$module_url . $this->module);
     58         if ($data) {
     59             $data = json_decode($data, true);
     60         }
     61
     62         if (!$data || !$data['rs']) {
     63             die('Getting data error');
     64         }
     65
     66         if ($data['rs'] == 404) {
     67             echo "No demo data for module $this->module\n";
     68             return;
     69         }
     70
     71         $this->baseUrl = $data['URL'];
     72
     73         // импортнем-ка SiteConfig для начала
     74         $sc = SiteConfig::current_site_config();
     75         if ($this->subsiteID) {
     76             $sc = DataObject::get_one('SiteConfig', "SubsiteID = {$this->subsiteID}");
     77             if (!$sc) {
     78                 $sc = new SiteConfig();
     79                 $sc->SubsiteID = $this->subsiteID;
     80                 $sc->write();
     81             }
     82         }
     83
     84         $siteConfigData = self::get_api_data($this->baseUrl . "api/v1/SiteConfig");
     85         foreach($siteConfigData as $siteConfigXml) {
     86             $this->import_object($siteConfigXml, $sc);
     87         }
     88
     89         // импортируем сначала файлы
     90         if (isset($data['Folders']) && is_array($data['Folders']) && count($data['Folders'])) {
     91 //          $moduleFolder = Folder::findOrMake('demo/' . $this->module);
     92             foreach($data['Folders'] as $folderID) {
     93                 $folderData = self::get_api_data($this->baseUrl . "api/v1/Folder/{$folderID}.xml");
     94
     95 //              $folder = Folder::findOrMake($moduleFolder->Filename.  (string)$folderData->Name);
     96                 $folder = Folder::findOrMake((string) $folderData->Filename);
     97                 $folder->Title = (string)$folderData->Title;
     98                 $folder->write();
     99
    100                 if(!file_exists($folder->getFullPath())) {
    101                     mkdir($folder->getFullPath(), Filesystem::$folder_create_mask);
    102                 }
    103
    104                 $filesData = self::get_api_data($this->baseUrl . "api/v1/File.xml");
    105                 foreach($filesData as $fileData) {
    106                     if ((int)$fileData->ParentID == $folderID) {
    107                         $this->import_file($folder, $fileData);
    108                     }
    109                 }
    110             }
    111         }
    112
    113         // импортируем потом необходимые объекты
    114         if (isset($data['Objects']) && is_array($data['Objects']) && count($data['Objects'])) {
    115             foreach($data['Objects'] as $object) {
    116                 $objectData = self::get_api_data($this->baseUrl . "api/v1/{$object}.xml");
    117                 foreach($objectData as $objXml) {
    118                     $this->import_object($objXml);
    119                 }
    120             }
    121         }
    122
    123         // импортируем страницы
    124         if (isset($data['Pages']) && is_array($data['Pages']) && count($data['Pages'])) {
    125             $importPages = $data['Pages'];
    126             $allPagesXML = self::get_api_data($this->baseUrl . 'api/v1/Page');
    127             foreach($importPages as $startID=>$startClass) {
    128                 $importPage = false;
    129                 foreach($allPagesXML->$startClass as $page) {
    130                     if ($page->ID == $startID) {
    131                         $importPage = $page;
    132                     }
    133                 }
    134
    135                 if ($importPage) {
    136                     $this->importChildPages($importPage, 0);
    137                 }
    138             }
    139         }
    140     }
    141
    142     function importChildPages($root, $parentID) {
    143         $rootClass = (string)$root->getName();
    144         $rootID = (int)$root->ID;
    145
    146         // FIXME не создавать добликаты страниц если они уже есть на сайте
    147         // по страницам проходим в любом случае, т.к. при импорте объектов выше некоторые из них уже могли импортнуться , но не полностью (у SiteTree нет has_many Children - связи)
    148         if (isset($this->importedObjects["{$rootClass}:{$rootID}"])) {
    149             echo "$rootClass: " . $this->importedObjects["{$rootClass}:{$rootID}"] . "\n";
    150             $rootPage = DataObject::get_by_id($rootClass, $this->importedObjects["{$rootClass}:{$rootID}"]);
    151         } else {
    152             $rootPage = new $rootClass();
    153         }
    154
    155         //echo "\n\n $rootClass";
    156
    157         $pageFullData = self::get_api_data((string)$root->attributes()->href);
    158         foreach($rootPage->db() as $name=>$type) {
    159             $rootPage->$name = (string)$pageFullData->$name;
    160         }
    161         $rootPage->ParentID = isset($this->importedObjects["SiteTree:{$parentID}"]) ? $this->importedObjects["SiteTree:{$parentID}"] : 0;
    162         $rootPage->writeToStage('Stage');
    163         $rootPage->publish('Stage', 'Live');
    164
    165         foreach($rootPage->getClassAncestry() as $class) {
    166             $this->importedObjects["{$class}:{$rootID}"] = $rootPage->ID;
    167         }
    168
    169         $this->importPageObjects($rootPage, $pageFullData);
    170
    171         $allPagesXML = self::get_api_data($this->baseUrl . '/api/v1/Page');
    172         foreach($allPagesXML as $pageXML) {
    173             if ((int)$pageXML->ParentID == $rootID) {
    174                 $this->importChildPages($pageXML, $rootID);
    175             }
    176         }
    177     }
    178
    179     // Файл, но не папка
    180     static function is_file($class) {
    181         if (($class == 'File') || ClassInfo::is_subclass_of($class, 'File')) {
    182             return true;
    183         }
    184         return false;
    185     }
    186
    187     // DataObject, но не страница
    188     static function is_object($class) {
    189         if (ClassInfo::is_subclass_of($class, 'DataObject') && ($class != 'SiteTree') && ($class != 'Folder') && !ClassInfo::is_subclass_of($class, 'SiteTree')) {
    190             return true;
    191         }
    192         return false;
    193     }
    194
    195     function importPageObjects($object, $xmlData) {
    196         if ($object->has_one()) {
    197             // сохраняем объекты по has_one-связям
    198             foreach($object->has_one() as $name=>$type) {
    199                 if (in_array($type, self::$skip_object_classes)) {
    200                     continue;
    201                 }
    202                 if (($line = $xmlData->$name) && ($line->attributes()->linktype == 'has_one') && ($line->attributes()->id > 0)) {
    203                     $key = $type . ':' . (int)$line->attributes()->id;
    204                     $ID = false;
    205                     if (isset($this->importedObjects[$key])) {
    206                         $ID = $this->importedObjects[$key];
    207                     } else {
    208                         if (self::is_file($type)) {
    209                             $folder = Folder::findOrMake('demo/' . $this->module);
    210                             if ($object && $object->hasMethod('getAssociatedFolder')) {
    211                                 $folder = $object->getAssociatedFolder();
    212                             }
    213                             $ID = $this->import_file($folder, $line);
    214                         } else {
    215                             if (ClassInfo::exists($type)) {
    216                                 $objXml = self::get_api_data((string)$line->attributes()->href);
    217                                 if ($objXml) {
    218                                     if ($newObj = $this->import_object($objXml)) {
    219                                         $ID = $newObj->ID;
    220                                     }
    221                                 }
    222                             }
    223                         }
    224                     }
    225                     // сохраняем объект по связи
    226                     if ($ID) {
    227                         $object->{$name . 'ID'} = $ID;
    228                         if (ClassInfo::is_subclass_of($object->class, 'SiteTree')) {
    229                             $object->writeToStage('Stage');
    230                             $object->publish('Stage', 'Live');
    231                         } else {
    232                             $object->write();
    233                         }
    234                     }
    235                 }
    236             }
    237         }
    238
    239         if ($object->has_many()) {
    240             // сохраняем объекты по has_many-связям
    241             foreach($object->has_many() as $name=>$type) {
    242                 if (in_array($type, self::$skip_object_classes)) {
    243                     continue;
    244                 }
    245                 if (($line = $xmlData->$name) && ($line->$type) && ($line->attributes()->linktype == 'has_many')) {
    246                     if (ClassInfo::exists($type)) {
    247                         //if(self::is_object($type)) { // ?? могут ли быть has_many страницы ??
    248                             $itemsXml = self::get_api_data((string)$line->attributes()->href);
    249                             if ($itemsXml) {
    250                                 foreach($itemsXml->$type as $itemLine) {
    251                                     $key = $type . ':' . (int)$itemLine->ID;
    252                                     if (!isset($this->importedObjects[$key])) {
    253                                         if ($newObj = $this->import_object($itemLine)) {
    254                                             // ищем родителя для импортированного объекта
    255                                             $hasParent = false;
    256                                             foreach($newObj->has_one() as $newObjName=>$newObjType) {
    257                                                 if (($newObjType == $object->class) || ClassInfo::is_subclass_of($object->class, $newObjType)) {
    258                                                     $newObj->{$newObjName . 'ID'} = $object->ID;
    259
    260                                                     if (ClassInfo::is_subclass_of($newObj->class, 'SiteTree')) {
    261                                                         $newObj->writeToStage('Stage');
    262                                                         $newObj->publish('Stage', 'Live');
    263                                                     } else {
    264                                                         $newObj->write();
    265                                                     }
    266                                                     $hasParent = true;
    267                                                     break;
    268                                                 }
    269                                             }
    270
    271                                             if (!$hasParent) { // если не нашли родителя по связям, то удаляем объект
    272                                                 if (ClassInfo::is_subclass_of($newObj->class, 'SiteTree')) {
    273                                                     $newObj->doUnpublish();
    274                                                 }
    275                                                 $newObj->delete();
    276                                             }
    277                                         }
    278                                     }
    279                                 }
    280                             }
    281                         //}
    282                     }
    283                 }
    284             }
    285         }
    286
    287         if ($object->many_many()) {
    288             // сохраняем объекты по many_many-связям
    289             foreach($object->many_many() as $name=>$type) {
    290                 if (in_array($type, self::$skip_object_classes)) {
    291                     continue;
    292                 }
    293                 if (($line = $xmlData->$name) && ($line->$type) && ($line->attributes()->linktype == 'many_many')) {
    294                     if (ClassInfo::exists($type)) {
    295                         $itemsXml = self::get_api_data((string)$line->attributes()->href);
    296                         if ($itemsXml) {
    297                             foreach($itemsXml->$type as $itemLine) {
    298                                 $newObj = false;
    299                                 $newObjID = false;
    300                                 $key = $type . ':' . (int)$itemLine->ID;
    301                                 if (isset($this->importedObjects[$key])) {
    302                                     $newObjID = $this->importedObjects[$key];
    303                                 } else {
    304                                     if ($newObj = $this->import_object($itemLine)) {
    305                                         $newObjID = $newObj->ID;
    306                                     }
    307                                 }
    308                                 // если создали объект, добавляем его по связи
    309                                 if ($newObjID) {
    310                                     $object->$name()->add($newObjID);
    311                                 }
    312                             }
    313                         }
    314                     }
    315                 }
    316             }
    317         }
    318     }
    319
    320     //
    321     function import_object($objXml, $newObj=false) {
    322         $id = (int)$objXml->ID;
    323         $type = (string)$objXml->getName();
    324
    325         if (isset($this->importedObjects["{$type}:{$id}"])) {
    326             return false;
    327         }
    328         if (!ClassInfo::exists($type)) {
    329             return false;
    330         }
    331
    332
    333
    334         echo "$type ($id) \n";
    335
    336         if (!$newObj) {
    337             $newObj = new $type();
    338         }
    339
    340         foreach($newObj->db() as $newObjName=>$newObjType) {
    341             $newObj->$newObjName = (string)$objXml->$newObjName;
    342         }
    343
    344         if ($this->subsiteID) {
    345             $newObj->SubsiteID = $this->subsiteID;
    346         }
    347
    348         if (ClassInfo::is_subclass_of($newObj->class, 'SiteTree')) {
    349             $newObj->writeToStage('Stage');
    350             $newObj->publish('Stage', 'Live');
    351         } else {
    352             $newObj->write();
    353         }
    354
    355         // сохраняем импортиованные объекты (по всем подклассам)
    356         foreach($newObj->getClassAncestry() as $class) {
    357             $this->importedObjects["{$class}:{$id}"] = $newObj->ID;
    358         }
    359
    360         // берем полную информацию об объекте и импортируем его связи
    361         $fullObjXml = self::get_api_data((string)$objXml->attributes()->href);
    362         $this->importPageObjects($newObj, $fullObjXml);
    363
    364         // сохраняем те данные, что уже импортированы
    365         foreach($newObj->has_one() as $newObjName=>$newObjType) {
    366             if ($id = (int)$objXml->{$newObjName . 'ID'}) {
    367                 if (isset($this->importedObjects["{$newObjType}:{$id}"])) {
    368                     $newObj->{$newObjName . "ID"} = $this->importedObjects["{$newObjType}:{$id}"];
    369                     continue;
    370                 }
    371                 // для SiteTree-объектов ищем дополнительно по SiteTree-записи
    372                 if (ClassInfo::is_subclass_of($newObj->class, 'SiteTree')) {
    373                     if (isset($this->importedObjects["SiteTree:{$id}"])) {
    374                         $newObj->{$newObjName . "ID"} = $this->importedObjects["SiteTree:{$id}"];
    375                         continue;
    376                     }
    377                 }
    378             }
    379         }
    380
    381         if (ClassInfo::is_subclass_of($newObj->class, 'SiteTree')) {
    382             $newObj->writeToStage('Stage');
    383             $newObj->publish('Stage', 'Live');
    384         } else {
    385             $newObj->write();
    386         }
    387         return $newObj;
    388     }
    389
    390     function import_file($folder, $params) {
    391         $fileXml = self::get_api_data((string)$params->attributes()->href);
    392         if ($fileXml) {
    393             $type = (string) $fileXml->getName();
    394             $fname = (string) $fileXml->Name;
    395
    396             if ($fileContent = file_get_contents($this->baseUrl . $fileXml->Filename)) {
    397                 file_put_contents($folder->getFullPath() . (string) $fileXml->Name, $fileContent);
    398                 if (!$file = File::find($folder->Filename . $fname)) {
    399                     $file = new $type();
    400                 }
    401                 $file->Title = (string)$fileXml->Title;
    402                 $file->Filename = $folder->getRelativePath() . (string) $fileXml->Name;
    403                 $file->ParentID = $folder->ID;
    404                 $file->write();
    405
    406                 $id = (int) $params->attributes()->id;
    407                 $this->importedObjects["{$type}:{$id}"] = $file->ID;
    408
    409                 return $file->ID;
    410             }
    411         }
    412         return false;
    413     }
    414 }
    415

[Raise a SilverStripe Framework issue/bug](https://github.com/silverstripe/silverstripe-framework/issues/new)
- [Raise a SilverStripe CMS issue/bug](https://github.com/silverstripe/silverstripe-cms/issues/new)
- Please use the Silverstripe Forums to ask development related questions. -