Opencartのオンラインストア用のOcmodファイルジェネレータ

人気のあるOpencartオンラインストアエンジンの変更を開発するときにアルゴリズムに焦点を合わせ、特別なスクリプトに翻弄されてこのCMSにアップロードするためのファイルの準備を任せるのは現実的ですか?実際、これはOpencartの下での開発者の生活をはるかに楽にするものであり、この記事では私の解決策を提供します。







簡単 な紹介:ocmod形式は、形式に関係なく、ソースファイルへの変更を定義するための非常に洗練されたソリューションです。形式の一部の1つはXMLファイルであり、このファイルのどのファイルで、このファイルのどこで特定の変更を行う必要があるかを指定します。ocmodファイルの例を次に示します(ocmod.netから取得、より詳細な説明はそこにあります)。



<?xml version="1.0" encoding="utf-8"?>
<modification>
    <name>   </name>
    <code>product-page-views</code>
    <version>1.0</version>
    <author>https://ocmod.net</author>
    <link>https://ocmod.net</link>
    <file path="catalog/controller/product/product.php">
        <operation>
            <search>
                <![CDATA[$data['images'] = array();]]>
            </search>
            <add position="after">
                <![CDATA[
                	$data['view'] = $product_info['viewed'];
                ]]>
            </add>
        </operation>
    </file>
    <file path="catalog/language/en-gb/product/product.php">
        <operation>
            <search>
                <![CDATA[$_['text_search']]]>
            </search>
            <add position="before">
                <![CDATA[
                	$_['text_view']              = 'View: ';
                ]]>
            </add>
        </operation>
    </file>
</modification>


一般的に、次のように設定します。



<file path="  ">
        <operation>
            <search><![CDATA[ ]]></search>
            <add position=" – ,   ">
                <![CDATA[    ]]>
            </add>
        </operation>
    </file>


原則は非常に透過的ですが、疑問が生じます。プログラマーはプログラミングに従事する必要がありばかげた日常的な活動で自慰行為をするべきではないため、作成プロセスを自動化することは可能ですか、それとも手書きで書く必要がありますか



理想的には、Opencartの変更を書くと、次のようになります。ストアの「完全な」バージョンをダウンロードし、ソースコードにいくつかの変更を加え、その場でocmod全体を生成する「魔法の」スクリプトを実行しました。実際、すべてがもう少し複雑ですが、このスキームに近づこうとします。主な問題は、挿入するファイル内の場所(<search> ... </ search>の間にあるもの)を決定することです。これはプログラマーが行う必要があります。原則として、彼らはソースのより多くの潜在的なバージョンをカバーするために、そして同時にそれが必要な場所で正確に変更されるように、それを可能な限り用途の広いものにしようとします。これは明らかに手作りです。他のすべては自動化されています。



小さな逸脱:検索は文字列全体で行われ、挿入は文字列の前、後、または代わりにのみ可能ですが、内部ではできません(Opencartの従来のOCMODパッケージ)。これは私には理解できない制限です。また、一貫して処理される目的の挿入ポイントを見つけるために複数の<search>タグを設定できない理由もわかりません。結局のところ、検索ははるかに柔軟になります。たとえば、PHPコードの場合、たとえば、関数の名前を見つけてから、その中の適切な場所を見つけるか、プログラマーの裁量で他の方法を見つけます。でも見つかりませんでした。間違えた場合は訂正してください。



そして今、最も重要なことは、ocmodファイルを作成するプロセスを自動化することができ、必要なスキームに従う必要があるということです。まず、ソースファイルで、変更の場所を何らかの方法で示す必要があります。これは、順序のためだけでなく、ocmodジェネレーターがすべてを適切に認識できるようにするためです。私たちの名前がPyotrNikolaevich Ivanovだとしましょう(偶然の一致はランダムです)。<PNI> ... </ PNI>タグ間のすべての変更を囲み、タグがソースを台無しにしないように、これらのタグを現在作業している言語のコメントに配置します。タグ間で、適切な場所に、検索文字列を<search> </ search>の間に設定し、追加されたコードを<add> </ add>の間に設定します。例を使用すると、より明確になります。PHPの



変更の場合:




(   opencart)
// <PNI>
//             -
//      ,    (   )
// <search> public function index() {</search>
// <add position=”after”>
$x = 5;
$y = 6;
//</add> </PNI>


またはこのように:




(   opencart)
/* <PNI>
     <search> public function index() {</search>
     <add position=”after”> */
$x = 5;
$y = 6;
/*</add> </PNI> */


<search>または<add>に属性がある場合(たとえば、<search index =” 1”>)、それらは「そのまま」ocmodファイルに転送されます。その間に書くものはXMLエスケープを必要とせず、検索文字列とコードを書くだけです。



別の例として、すでに変更している小枝ファイルの場合:



            {# <PNI>
            <search><li><span style="text-decoration: line-through;">{{ price }}</span></li></search>
            <add position="replace">
            #}
            <li><span class="combination-base-price" style="text-decoration: line-through;">{{ price }}</span></li>
            {# </add></PNI> #}


この方法ですべての変更を形式化した後、これらすべてを処理するスクリプトとアーカイバーが必要です。私はあなたと私のバージョンを共有しています:それは構成ファイルとスクリプト自体で構成されています。



構成ファイルmake-ocmod.opencart.local.cfg.php(UTF-8エンコーディング、これは例です。誰もが自分で行います):



<?php

define("ROOT_PATH", "../../opencart.local");

define("ENCODING", "utf-8");
define("NAME", " ocmod");
define("CODE", "product-page-views");
define("VERSION", "1.0");
define("AUTHOR", "AS");
define("LINK", "");

define("TAG_OPERATION_BEGIN", "<PNI>");
define("TAG_OPERATION_END", "</PNI>");
define("TAG_SEARCH_BEGIN", "<search"); // !!  >
define("TAG_SEARCH_END", "</search>");
define("TAG_ADD_BEGIN", "<add"); // !!  >
define("TAG_ADD_END", "</add>");

//     </add>      
// ( ,   , ).
//    ,   , 
//   </add> ( , \t, \r, \n  ,  )
$commentsBegin = [ '//', '/*', '<!--', '{#' ];
//     <add>      
// ( ,   , ).
//    ,   , 
//   <add> ( , \t, \r, \n  ,  )
$commentsEnd = [ '*/', '-->', '#}' ];

//       ,     
//  .
$exclude = [ '/cache/', '/cache-/' ];

//      upload.
//     ,   .
$upload = [
  'admin/view/stylesheet/combined-options.css',
  'admin/view/javascript/combined-options.js',
  'catalog/view/theme/default/stylesheet/combined-options.css',
  'admin/view/image/combined-options/cross.png',
  'catalog/view/javascript/combined-options/combined.js',
  'catalog/view/javascript/combined-options/aswmultiselect.js',
  'admin/view/image/combined-options/select.png'
];

//     install.sql.
// (   Opencart  )
$sql = "";

?>


ここで重要なのは、ocmodxmlファイルジェネレーターです。

Make-ocmod.phpスクリプト(UTF-8エンコーディング):



<?php

include_once ($argv[1]);

function processFile($fileName, $relativePath) {
  global $commentsBegin, $commentsEnd, $xml, $exclude;

  if ($exclude)
    foreach ($exclude as $ex)
      if (false !== strpos($relativePath, $ex))
        return;

  $text = file_get_contents($fileName);
  $end = -1;
  while (false !== ($begin = strpos($text, TAG_OPERATION_BEGIN, $end + 1))) {
    $end = strpos($text, TAG_OPERATION_END, $begin + 1);
    if (false === $end)
      die ("No close operation tag in ".$fileName);
    $search = false;
    $searchEnd = $begin;
    while (false !== ($searchBegin = strpos($text, TAG_SEARCH_BEGIN, $searchEnd + 1)) and $searchBegin < $end) {
      $searchBeginR = strpos($text, '>', $searchBegin + 1);
      $searchAttributes = substr($text, $searchBegin + strlen(TAG_SEARCH_BEGIN), $searchBeginR - $searchBegin - strlen(TAG_SEARCH_BEGIN));
      if (false === $searchBeginR or $searchBeginR >= $end)
        die ("Invalid search tag in ".$fileName);
      $searchEnd = strpos($text, TAG_SEARCH_END, $searchBeginR + 1);
      if (false === $searchEnd or $searchEnd >= $end)
        die ("No close search tag in ".$fileName);
      //  
      $search = substr($text, $searchBeginR + 1, $searchEnd - $searchBeginR - 1);
    }
    $addBegin = strpos($text, TAG_ADD_BEGIN, $begin + 1);
    if (false === $addBegin or $addBegin >= $end)
      die ("No begin add tag in ".$fileName);
    $addBeginR = strpos($text, '>', $addBegin + 1);
    $addAttributes = substr($text, $addBegin + strlen(TAG_ADD_BEGIN), $addBeginR - $addBegin - strlen(TAG_ADD_BEGIN));
    if (false === $addBeginR or $addBeginR >= $end)
      die ("Invalid add tag in ".$fileName);
    $addEnd = strpos($text, TAG_ADD_END, $addBeginR + 1);
    if (false === $addEnd or $addEnd >= $end)
      die ("No close add tag in ".$fileName);
    $codeBegin = $addBeginR + 1;
    $codeEnd = $addEnd;
    //       ,
    //    - .        .
    $p = $codeBegin;
    while (@$text[$p] === " " or @$text[$p] === "\t" or @$text[$p] === "\r" or @$text[$p] === "\n")
      $p ++;
    if ($p < $addEnd) {
      foreach ($commentsEnd as $tag)
        if (substr($text, $p, strlen($tag)) === $tag)
          $codeBegin = $p + strlen($tag);
    }
    $p = $codeEnd - 1;
    while (@$text[$p] === " " or @$text[$p] === "\t" or @$text[$p] === "\r" or @$text[$p] === "\n")
      $p --;
    if ($p >= $codeBegin) {
      foreach ($commentsBegin as $tag)
        if (substr($text, $p - strlen($tag) + 1, strlen($tag)) === $tag)
          $codeEnd = $p - strlen($tag) + 1;
    }
    $code = substr($text, $codeBegin, $codeEnd - $codeBegin - 1);

    $xml .= "
    <file path=\"".str_replace('"', '\"', $relativePath)."\">
        <operation>".(false !== $search ? "
            <search{$searchAttributes}>
                <![CDATA[{$search}]]>
            </search>" : "")."
            <add{$addAttributes}>
                <![CDATA[{$code}]]>
            </add>
        </operation>
    </file>";
  }
}

function processDir($dir, $relativePath = '') {
  global $exclude;

  $cdir = scandir($dir);
  foreach ($cdir as $key => $value) {
    if (!in_array($value,array(".", ".."))) {
      $fileName = $dir . DIRECTORY_SEPARATOR . $value;
      $newRelativePath = ($relativePath ? $relativePath.'/' : '').$value;
      $excluded = false;
      if ($exclude)
        foreach ($exclude as $ex)
          $excluded = $excluded or false !== strpos($newRelativePath, $ex);
      if ($excluded)
        continue;
      if (is_dir($fileName)) {
        processDir($fileName, $newRelativePath);
      } else {
        processFile($fileName, $newRelativePath);
      }
    }
  }
}

function delTree($dir, $delRoot = false) {
  $files = array_diff(scandir($dir), array('.','..'));
  foreach ($files as $file) {
    (is_dir("$dir/$file")) ? delTree("$dir/$file", true) : unlink("$dir/$file");
  }
  return $delRoot ? rmdir($dir) : true;
}

$xml = "<?xml version=\"1.0\" encoding=\"".ENCODING."\"?>
<modification>
    <name>".NAME."</name>
    <code>".CODE."</code>
    <version>".VERSION."</version>
    <author>".AUTHOR."</author>
    <link>".LINK."</link>";

processDir(ROOT_PATH);

$xml .= "
</modification>";

file_put_contents('publish/install.xml', $xml);
file_put_contents('publish/install.sql', $sql);

delTree('publish/upload');
foreach ($upload as $file) {
  $srcfile = ROOT_PATH.(@$file[0] === '/' ? '' : '/').$file;
  $dstfile = 'publish/upload'.(@$file[0] === '/' ? '' : '/').$file;
  mkdir(dirname($dstfile), 0777, true);
  copy($srcfile, $dstfile);
}

?>


これらすべてを実行するmake-ocmod.cmdコマンドライン:



del /f/q/s publish.ocmod.zip
php make-ocmod.php make-ocmod.opencart.local.cfg.php
cd publish
..\7z.exe a -r -tZip ..\publish.ocmod.zip *.*


私は7zipを使用しているので、7z.exeはコマンドラインと同じ場所にあるはずです。使用したい人は誰でもhttps://www.7-zip.org/からダウンロードできます



これはWindows用のコマンドマネージャーです。Linuxの誰が、問題なく書き直すことができると思います。



要約:私の意見では、毎回手動でocmodを編集するよりも、この方法で作業する方がはるかに簡単です。コードを追加するときは、このコードの検索タグをその場で設定し、作業のみに集中します。xmlファイルの構造は気にせず、その場で変更を修正し、すぐにその動作を確認してから、ワンクリックで新しいocmodファイルを生成します。



All Articles