すべてのhabrazhitelの健康!
MODx Revolutionは多くの点で便利です。 すべてがMODx Evolutionで実行できる場合、絶対にすべてがMODx Revolutionで実行できます。 幻想と忍耐があるでしょう。 しかし、革命の登場後、多くの人が疑問を抱いていました。つまり、あるエンジンから別のエンジンにコンテンツをドラッグする方法です。 あなたがたくさんのリソースを持っているなら、それは一つのことです。 ここでコピー&ペーストしてください。 別のことは、コンテンツ、カタログなどのコレクションです。
背景
逸話と叙事詩という2つのコレクションがありました。 最初にお気に入りのジョークを収集し、2番目にYaPlakal、IThappens、その他の興味深いポータルからのストーリーを収集しました。 これはすべてEvolution 1.0.5にかかっていました。 しかし、ある晴れた日、マルチドメインサイト全体を1つのエンジンと1つのデータベースに移行しました。 一般的に、私は革命に切り替えました。 当然、コンテンツを転送するという疑問が生じました。 「自分自身について」セクションと音楽セクションでは、すべてが簡単でした-コピー&ペースト。 私はフォーラムについてまったくスチームバスを浴びませんでした-まだphpBBにあります。 しかし、逸話とエピキュアでは、そこに蓄積されたすべての忍耐をコピーするだけでは十分ではなかったため、質問は延期されなければなりませんでした...
輸出する
古いサイトに住んでいたジョークからランダムなジョークをインポートする小さな断片。 実際、逸話はデータをエクスポートできます。 その後、サイトのすべてのコンテンツをJSON形式にエクスポートする特別なページを作成し、それを忘れました。 データ転送に関する質問が生じたとき、私は彼女についてそれを思い出しました。
なぜJSON はい、おそらく、単に私が多くのXMLパーサーの地獄にうんざりしているからです。 JSONの場合でも 、 json_encodeとjson_decodeという単純な関数があります。 この非常に便利な状況により、JSONを使用したオプションは、他のすべてのオプションよりもはるかに望ましいものになります。
JSONへのエクスポートは簡単です。 したがって、エクスポート用のページのコンテンツ(_blankテンプレート):
{"items":[ [[Ditto? &startID=`162` &tpl=`cat` &tplLast=`catLast`]] ]}
猫チャンクの内容:
{ "name":"[+pagetitle+]", "alias":"[+alias+]", "template":"[+template+]", "hidemenu":"[+hidemenu+]", "content":[ [!Ditto? &startID=`[+id+]` &tpl=`item` &tplLast=`itemLast`!] ] },
catLastも同じですが、最後にコンマがありません。 チャンクコンテンツアイテム:
{ "name":"[+pagetitle+]", "alias":"[+alias+]", "template":"[+template+]", "hidemenu":"[+hidemenu+]", "content":"[+content:strip:noquotes+]" },
itemLastも同じですが、最後にコンマがありません。
スニペットphx:noquotes:
<?php // Remove r & n return str_replace('"','& quot ;',$output); // ! * ?>
*スペースは、HTMLエンティティがHabrahabrを解釈する方法に関連しています。
結果は印象的なそのようなファイルです。 はい、主なことは、エクスポートページでデータ型を設定することを忘れないことです。 データ型はtext / javascriptです。 何らかのマクロを使用すると、DittoデータをすぐにJSONにエクスポートできます。 しかし、この問題に対処する時間はありませんでした。
インポート
ファイルを受信しました。 次は? そして、 MODxでソーシャルネットワークを作成することに関する記事に出会い、MODx Revolutionでプログラムで新しいドキュメントを作成する方法を正確に確認しました。 アイデアが生まれた後、スニペット:
<?php // JSON- // function addItem($ctx,$pagetitle,$template,$isfolder,$hidemenu,$parent,$alias,$content,$td){ global $modx; $newResource = $modx->newObject('modResource'); $newResource->fromArray(array( 'pagetitle'=>$pagetitle, 'longtitle'=>$pagetitle, 'content'=>$content, 'template'=>$template, 'isfolder'=>$isfolder, 'hidemenu'=>$hidemenu, 'parent'=>$parent, 'published'=>'1', 'alias'=>$alias, 'context_key'=>$ctx )); if ($newResource->save()) { $id = $newResource->get('id'); $modx->cacheManager->refresh(); $modx->reloadConfig(); if (is_array($td)) { foreach($td as $key=>$val) { $tvar = $modx->newObject('modTemplateVarResource'); $tvar->set('contentid',$id); $tvar->set('tmplvarid',$key); $tvar->set('value',$val); $tvar->save(); } } return $id; } else { return false; } } // , function handleItem($ctx,$item,$parent,$tpls,$tvs,$handleChildren=false){ $hidm = isset($item['hidemenu'])?$item['hidemenu']:'0'; $isf = is_array($item['content'])?'1':'0'; $content = is_array($item['content'])?'':$item['content']; $tpl = array_key_exists('tpl'.$item['template'],$tpls)?$tpls['tpl'.$item['template']]:'0'; $td = array(); foreach($tvs as $tvn=>$tvv) if (array_key_exists($tvn,$item)) $td[$tvv] = $item[$tvn]; $ret = ''; if ($id = addItem($ctx,$item['name'],$tpl,$isf,$hidm,$parent,$item['alias'],$content,$td)) { $ret = 'Resource «<b>'.$item['name'].'</b>» imported successfully! ' . 'New ID: <b>'.$id.'</b><br />'; if (is_array($item['content']) && $handleChildren) foreach ($item['content'] as $i) $ret.= handleItem($ctx,$i,$id,$tpls,$tvs,$handleChildren); return $ret; } else { return 'Resource «<b>'.$item['name'].'</b>» not imported!<br />'; } } // $cons = '<h1>Import item log</h1>'; // ( ) $item_count = isset($itemCount)?$itemCount:4; // , if (!isset($curContext)) $curContext = 'web'; // "" ( ) $next_items = isset($_GET['jsonimportnext'])?intval($_GET['jsonimportnext']):0; // $tpls = array(); if (isset($templates)) { $tmp = explode(',',$templates); foreach($tmp as $val) { $tpls_d = explode('=>',$val); $tpls['tpl'.$tpls_d[0]] = $tpls_d[1]; } } // TV- $tvs = array(); if (isset($tvParams)) { $tmp = explode(',',$tvParams); foreach($tmp as $val) { $tvs_d = explode('=>',$val); $tvs[$tvs_d[0]] = $tvs_d[1]; } } // if (isset($source) && isset($rootID)) { if ($import_content = @file_get_contents($source)) { $import_data = json_decode($import_content,true); $import_count = count($import_data['items']); if ($item_count != 0) { for($c = 0; $c < $item_count; $c++) { $n = $item_count*$next_items+$c; if (isset($import_data['items'][$n])) $cons.= handleItem($curContext,$import_data['items'][$n],$rootID,$tpls,$tvs); } $this_res = $modx->resource->get('alias'); $this_res.= '.html'; if (($item_count*$next_items+$item_count-1)<$import_count) { $cons.= '<br /><a href="'.$this_res.'?jsonimportnext=' . ($next_items+1).'">' . 'Import next items</a><br />'; } else { $cons.= '<br /><a href="'.$this_res.'">Start</a>'; } } else { foreach ($import_data['items'] as $item) $cons.= handleItem($curContext,$item,$rootID,$tpls,$tvs,true); } } else { $cons.= 'Cannot get source!<br />'; } } else { $cons.= 'Invalid execution parameters!<br />'; } return $cons;
私はすぐに言わなければなりません:これは普遍的な解決策であると主張していません。 残念ながら、コードのコメントはほとんどありません。 急ぎすぎて困っている人たちと共有する。 解決策が興味深いと思われる場合は、引き続き作業を開発し、MODxで本格的なアドインを作成します。
入力スニペットは次のパラメーターを受け取ります。
- source (必須)-JSONファイルのソース。
- itemCount -1回のパスでインポートされるアイテムの数(あまり生産的でないシステムの場合)。 デフォルトは4です。0に設定すると、すべてが一度に、さらに再帰的に処理されます。
- テンプレート -パターンマッチング。 マッピングは、old_id => new_idの形式でコンマで区切られます。ここで、old_idは古いサイトテンプレートのID、new_idは新しいサイトテンプレートのIDです。 パーサーが一致を検出しない場合、テンプレート0(空)が設定されます。
- tvParams -TVパラメーターのマッピング。 マッピングは、old_name => new_idの形式でコンマで区切られます。ここで、old_nameは古いサイトの変数の名前、new_idは新しいサイトの変数のIDです。 パーサーが一致を検出しない場合、変数はスキップされます。
- curContext (必須)は現在のコンテキストです。 原則として、コンテキストを設定しない場合、「web」にインストールされます。
- rootID (必須)-ドキュメントがインポートされるリソースのID。
パフォーマンスについて話す理由。 しかし、実際には、すべてを再帰的に処理する必要があるスニペットの最初のバージョンを起動したときに、サーバーから502番目のエラーが返されました。 簡単に言えば、ホスティング事業者は高負荷を遮断しました。 まあ-非常に多くの文書がありました。
使い方
まず、簡単なテンプレートを作成します。
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ru"><head> <meta http-equiv="content-type" content="text/html; charset=utf-8" /> <base href="/" /> <title>[[*pagetitle]]</title> <style type="text/css"> body { font: 12px monospace; } </style> </head><body><div align="center"><div style="text-align: left; width: 800px;"> [[!importJSON? &source=`[[*sourceURL]]` &itemCount=`6` &templates=`[[*templatesReplace]]` &tvParams=`[[*tvsReplace]]` &curContext=`[[*currentContext]]` &rootID=`[[*importDestination]]`]] </div></div></body></html>
次に、TVパラメータsourceURL、templatesReplace、tvsReplace、currentContext、importDestinationを作成し、テンプレートにバインドします。 currentContextを誓い、context_keyについてブロードキャストする必要はありません。 理論的には、1つのページを作成して、データを異なるコンテキストにインポートできます。 実際にはすべて。 さらに、私はこのことをどのように使用したかを説明します。 エクスポートテンプレートにカテゴリなしで行ったことをすぐにメモし、startIDのたびに変更します。 負荷制限のため。 私の行動のシーケンス。
- 古いサイトで、エクスポートファイルを開いて編集します。 さらなるアクションに「継続」します。
- 新しいサイトで、コンテンツを転送する編集用ファイル(以降、インポートファイル)を開きます。 テンプレートをJSONからインポートテンプレートに変更し、保存します。
- インポートファイルのパラメーターで、現在のコンテキスト、エクスポートファイルのURL、テンプレートとTVパラメーターのマッピングを設定します。 保存します。
- エクスポートファイルで、startIDの値を、コンテンツのエクスポート元の親リソースのIDに変更します。 保存します。
- インポートファイルで、インポートするリソースIDを設定します。 保存します。
- インポートファイルを表示用に呼び出します。 次に、最後に「Start」という表記のリンクが表示されるまで繰り返します。
- ダウンロードが完了するのを待っています。
- 「次のアイテムをインポート」リンクをクリックします
- 目的のリソースからすべてをインポートした後、他に何かをインポートする必要がある場合は、手順4に戻ります。
はい、パフォーマンスを向上させるために、データベースへの直接クエリですべてを実行できることを知っています。 第一に、これが502番目のエラーで状況を修正するという事実だけではありません。 第二に、site_contentを除いて、リソースを作成するときにデータベースで何が影響を受けるかを調べる時間がありませんでした。 第三に、私はそのような解決策を書くでしょう、彼らはすぐに「a-how-same-XPDO」という言葉で私をつまずかせます。
これはソリューションの予備的なドラフトにすぎないことを改めて思い出します。 私の次の自転車に注目してくれてありがとう!