dari88's diary

これから趣味にするプログラミング/PHP/javascript/kohana/CMS/web design/

kohanaのテスト12-3・・・スタイルシートやスクリプトのオートローダーを作る

 WordPress の HTML を見ると、スタイルシートやスクリプトをオートローダーを使ってリンクしています。WordPress を kohana に移植するために今回は kohana 用のオートローダーを作りました。

 オートローダーを使うと、沢山のスクリプトをロードさせる場合に HTML をシンプルに見せることが出来ます。その割には WordPress の新規投稿ページのソースを見ると長々とスクリプトが書いてあったりして見苦しかったりしますけど。

*注1:5月13日に修正あり

 

準備作業

WordPressスタイルシートやスクリプトを別の場所にコピーします。
  wordpress\wp-admin\css      →  \includes\wp\admin\css
  wordpress\wp-admin\js       →  \includes\wp\admin\js
  wordpress\wp-admin\images       →  \includes\wp\admin\images *注1
  wordpress\wp-includes\css   →  \includes\wp\includes\css
  wordpress\wp-includes\js    →  \includes\wp\includes\js
  wordpress\wp-includes\images    →  \includes\wp\includes\images *注1
  wordpress\wp-content\themes    →  \includes\wp\includes\themes *注1
   (.php ファイルは使わないので削除)

 

名前とパスの対応表を作る

 WordPress の対応表は wordpress/wp-includes/script-loader.php です。この対応表から抜き取って、kohana の定義ファイルを作ります。
・kohana/application/config/wp-js-css.php
 themes\twentyeleven\style.css に対応する定義は無かったので、’twentyeleven' という名前を付けて追加しています。
*注1:パスにミスがあり、更新しました。

<?php defined('SYSPATH') or die('No direct access allowed.');

return array
    (
    'js' => array
        (
        'admin-bar' => '/includes/wp/includes/js/admin-bar.js',
        'admin-categories' => '/includes/wp/admin/js/categories.js',
        'admin-comments' => '/includes/wp/admin/js/edit-comments.js',
        'admin-custom-fields' => '/includes/wp/admin/js/custom-fields.js',
        'admin-gallery' => '/includes/wp/admin/js/gallery.js',
        'admin-tags' => '/includes/wp/admin/js/tags.js',
        'admin-widgets' => '/includes/wp/admin/js/widgets.js',
        'ajaxcat' => '/includes/wp/admin/js/cat.js',
        'autosave' => '/includes/wp/includes/js/autosave.js',
        'colorpicker' => '/includes/wp/includes/js/colorpicker.js',
        'comment' => '/includes/wp/admin/js/comment.js',
        'comment-reply' => '/includes/wp/includes/js/comment-reply.js',
        'common' => '/includes/wp/admin/js/common.js',
        'cropper' => '/includes/wp/includes/js/crop/cropper.js',
        'custom-background' => '/includes/wp/admin/js/custom-background.js',
        'dashboard' => '/includes/wp/admin/js/dashboard.js',
        'editor' => '/includes/wp/admin/js/editor.js',
        'farbtastic' => '/includes/wp/admin/js/farbtastic.js',
        'hoverIntent' => '/includes/wp/includes/js/hoverIntent.js',
        'image-edit' => '/includes/wp/admin/js/image-edit.js',
        'imgareaselect' => '/includes/wp/includes/js/imgareaselect/jquery.imgareaselect.js',
        'inline-edit-post' => '/includes/wp/admin/js/inline-edit-post.js',
        'inline-edit-tax' => '/includes/wp/admin/js/inline-edit-tax.js',
        'jcrop' => '/includes/wp/includes/js/jcrop/jquery.Jcrop.js',
        'jquery' => '/includes/wp/includes/js/jquery/jquery.js',
        'jquery-color' => '/includes/wp/includes/js/jquery/jquery.color.js',
        'jquery-effects-blind' => '/includes/wp/includes/js/jquery/ui/jquery.effects.blind.min.js',
        'jquery-effects-bounce' => '/includes/wp/includes/js/jquery/ui/jquery.effects.bounce.min.js',
        'jquery-effects-clip' => '/includes/wp/includes/js/jquery/ui/jquery.effects.clip.min.js',
        'jquery-effects-core' => '/includes/wp/includes/js/jquery/ui/jquery.effects.core.min.js',
        'jquery-effects-drop' => '/includes/wp/includes/js/jquery/ui/jquery.effects.drop.min.js',
        'jquery-effects-explode' => '/includes/wp/includes/js/jquery/ui/jquery.effects.explode.min.js',
        'jquery-effects-fade' => '/includes/wp/includes/js/jquery/ui/jquery.effects.fade.min.js',
        'jquery-effects-fold' => '/includes/wp/includes/js/jquery/ui/jquery.effects.fold.min.js',
        'jquery-effects-highlight' => '/includes/wp/includes/js/jquery/ui/jquery.effects.highlight.min.js',
        'jquery-effects-pulsate' => '/includes/wp/includes/js/jquery/ui/jquery.effects.pulsate.min.js',
        'jquery-effects-scale' => '/includes/wp/includes/js/jquery/ui/jquery.effects.scale.min.js',
        'jquery-effects-shake' => '/includes/wp/includes/js/jquery/ui/jquery.effects.shake.min.js',
        'jquery-effects-slide' => '/includes/wp/includes/js/jquery/ui/jquery.effects.slide.min.js',
        'jquery-effects-transfer' => '/includes/wp/includes/js/jquery/ui/jquery.effects.transfer.min.js',
        'jquery-form' => '/includes/wp/includes/js/jquery/jquery.form.js',
        'jquery-hotkeys' => '/includes/wp/includes/js/jquery/jquery.hotkeys.js',
        'jquery-query' => '/includes/wp/includes/js/jquery/jquery.query.js',
        'jquery-serialize-object' => '/includes/wp/includes/js/jquery/jquery.serialize-object.js',
        'jquery-table-hotkeys' => '/includes/wp/includes/js/jquery/jquery.table-hotkeys.js',
        'jquery-ui-accordion' => '/includes/wp/includes/js/jquery/ui/jquery.ui.accordion.min.js',
        'jquery-ui-autocomplete' => '/includes/wp/includes/js/jquery/ui/jquery.ui.autocomplete.min.js',
        'jquery-ui-button' => '/includes/wp/includes/js/jquery/ui/jquery.ui.button.min.js',
        'jquery-ui-core' => '/includes/wp/includes/js/jquery/ui/jquery.ui.core.min.js',
        'jquery-ui-datepicker' => '/includes/wp/includes/js/jquery/ui/jquery.ui.datepicker.min.js',
        'jquery-ui-dialog' => '/includes/wp/includes/js/jquery/ui/jquery.ui.dialog.min.js',
        'jquery-ui-draggable' => '/includes/wp/includes/js/jquery/ui/jquery.ui.draggable.min.js',
        'jquery-ui-droppable' => '/includes/wp/includes/js/jquery/ui/jquery.ui.droppable.min.js',
        'jquery-ui-mouse' => '/includes/wp/includes/js/jquery/ui/jquery.ui.mouse.min.js',
        'jquery-ui-position' => '/includes/wp/includes/js/jquery/ui/jquery.ui.position.min.js',
        'jquery-ui-progressbar' => '/includes/wp/includes/js/jquery/ui/jquery.ui.progressbar.min.js',
        'jquery-ui-resizable' => '/includes/wp/includes/js/jquery/ui/jquery.ui.resizable.min.js',
        'jquery-ui-selectable' => '/includes/wp/includes/js/jquery/ui/jquery.ui.selectable.min.js',
        'jquery-ui-slider' => '/includes/wp/includes/js/jquery/ui/jquery.ui.slider.min.js',
        'jquery-ui-sortable' => '/includes/wp/includes/js/jquery/ui/jquery.ui.sortable.min.js',
        'jquery-ui-tabs' => '/includes/wp/includes/js/jquery/ui/jquery.ui.tabs.min.js',
        'jquery-ui-widget' => '/includes/wp/includes/js/jquery/ui/jquery.ui.widget.min.js',
        'json2' => '/includes/wp/includes/js/json2.js',
        'link' => '/includes/wp/admin/js/link.js',
        'list-revisions' => '/includes/wp/includes/js/wp-list-revisions.js',
        'media' => '/includes/wp/admin/js/media.js',
        'media-upload' => '/includes/wp/admin/js/media-upload.js',
        'nav-menu' => '/includes/wp/admin/js/nav-menu.js',
        'password-strength-meter' => '/includes/wp/admin/js/password-strength-meter.js',
        'plugin-install' => '/includes/wp/admin/js/plugin-install.js',
        'plupload' => '/includes/wp/includes/js/plupload/plupload.js',
        'plupload-flash' => '/includes/wp/includes/js/plupload/plupload.flash.js',
        'plupload-handlers' => '/includes/wp/includes/js/plupload/handlers.js',
        'plupload-html4' => '/includes/wp/includes/js/plupload/plupload.html4.js',
        'plupload-html5' => '/includes/wp/includes/js/plupload/plupload.html5.js',
        'plupload-silverlight' => '/includes/wp/includes/js/plupload/plupload.silverlight.js',
        'post' => '/includes/wp/admin/js/post.js',
        'postbox' => '/includes/wp/admin/js/postbox.js',
        'prototype' => '/includes/wp/includes/js/prototype.js',
        'quicktags' => '/includes/wp/includes/js/quicktags.js',
        'sack' => '/includes/wp/includes/js/tw-sack.js',
        'schedule' => '/includes/wp/includes/js/jquery/jquery.schedule.js',
        'scriptaculous-builder' => '/includes/wp/includes/js/scriptaculous/builder.js',
        'scriptaculous-controls' => '/includes/wp/includes/js/scriptaculous/controls.js',
        'scriptaculous-dragdrop' => '/includes/wp/includes/js/scriptaculous/dragdrop.js',
        'scriptaculous-effects' => '/includes/wp/includes/js/scriptaculous/effects.js',
        'scriptaculous-root' => '/includes/wp/includes/js/scriptaculous/wp-scriptaculous.js',
        'scriptaculous-slider' => '/includes/wp/includes/js/scriptaculous/slider.js',
        'scriptaculous-sound' => '/includes/wp/includes/js/scriptaculous/sound.js',
        'set-post-thumbnail' => '/includes/wp/admin/js/set-post-thumbnail.js',
        'suggest' => '/includes/wp/includes/js/jquery/suggest.js',
        'swfobject' => '/includes/wp/includes/js/swfobject.js',
        'swfupload' => '/includes/wp/includes/js/swfupload/swfupload.js',
        'swfupload-all' => '/includes/wp/includes/js/swfupload/swfupload-all.js',
        'swfupload-handlers' => '/includes/wp/includes/js/swfupload/handlers.js',
        'swfupload-queue' => '/includes/wp/includes/js/swfupload/plugins/swfupload.queue.js',
        'swfupload-speed' => '/includes/wp/includes/js/swfupload/plugins/swfupload.speed.js',
        'swfupload-swfobject' => '/includes/wp/includes/js/swfupload/plugins/swfupload.swfobject.js',
        'theme' => '/includes/wp/admin/js/theme.js',
        'theme-preview' => '/includes/wp/admin/js/theme-preview.js',
        'thickbox' => '/includes/wp/includes/js/thickbox/thickbox.js',
        'user-profile' => '/includes/wp/admin/js/user-profile.js',
        'utils' => '/includes/wp/admin/js/utils.js',
        'word-count' => '/includes/wp/admin/js/word-count.js',
        'wp-ajax-response' => '/includes/wp/includes/js/wp-ajax-response.js',
        'wpdialogs' => '/includes/wp/includes/js/tinymce/plugins/wpdialogs/js/wpdialog.js',
        'wpdialogs-popup' => '/includes/wp/includes/js/tinymce/plugins/wpdialogs/js/popup.js',
        'wp-fullscreen' => '/includes/wp/admin/js/wp-fullscreen.js',
        'wplink' => '/includes/wp/includes/js/wplink.js',
        'wp-lists' => '/includes/wp/includes/js/wp-lists.js',
        'wp-pointer' => '/includes/wp/includes/js/wp-pointer.js',
        'xfn' => '/includes/wp/admin/js/xfn.js',
    ),
    'css' => array
        (
        'admin-bar' => '/includes/wp/includes/css/admin-bar.css',
        'colors-classic' => '/includes/wp/admin/css/colors-classic.css',
        'colors-fresh' => '/includes/wp/admin/css/colors-fresh.css',
        'editor-buttons' => '/includes/wp/includes/css/editor-buttons.css',
        'farbtastic' => '/includes/wp/admin/css/farbtastic.css',
        'ie' => '/includes/wp/admin/css/ie.css',
        'imgareaselect' => '/includes/wp/includes/js/imgareaselect/imgareaselect.css',
        'install' => '/includes/wp/admin/css/install.css',
        'jcrop' => '/includes/wp/includes/js/jcrop/jquery.Jcrop.css',
        'media' => '/includes/wp/admin/css/media.css',
        'thickbox' => '/includes/wp/includes/js/thickbox/thickbox.css',
        'twentyeleven' => '/includes/wp/themes/twentyeleven/style.css',
        'wp-admin' => '/includes/wp/admin/css/wp-admin.css',
        'wp-jquery-ui-dialog' => '/includes/wp/includes/css/jquery-ui-dialog.css',
        'wp-pointer' => '/includes/wp/includes/css/wp-pointer.css',
    ),
);

 

オートローダーを作る

 WordPress のオートローダーは wordpress/wp-admin/load-styles.php と load-scripts.php です。これを参考にして作りました。元のコードにはないテスト機能を追加しています。引数に c=test を付けてアクセスするとロードしたファイルのリストと中身を text/plain 属性で出力します。

・kohana/application/classes/controller/loadcss.php
 スタイルシート用のオートローダーです。30行目にドキュメントルートの絶対パスを書いているので、必要に応じて書きなおして下さい。
*注1:URL を記述しているスタイルシートの場合リンクが狂うので修正しました。
   引数に dir=rtl を付けて使います。
   スタイルシートは多くないので、直接リンクを書いた方が良いかも。

<?php defined('SYSPATH') OR die('No direct access allowed.');

class Controller_Loadcss extends Controller {

    public function action_index() {

        error_reporting(0);

        $load = preg_replace('/[^a-z0-9,_-]+/i', '', $_GET['load']);
        $load = explode(',', $load);

        if (empty($load))
            exit;

        $compress = ( isset($_GET['c']) && $_GET['c'] );
        $force_gzip = ( $compress && 'gzip' == $_GET['c'] );
        $rtl = ( isset($_GET['dir']) && 'rtl' == $_GET['dir'] );
        $test = ( isset($_GET['c']) AND $_GET['c'] == 'test');
        $expires_offset = 31536000;
        $out = '';
        $pathlist = '';

        $config = Kohana::$config->load('wp-js-css')->css;

        foreach ($load as $handle) {
            if (!$config[$handle]) {
                $pathlist .= '*** ' . $handle . " is not defined! ***\n";
                continue;
            }

            $path = 'c:/xampp/htdocs' . $config[$handle];
            $pathlist .= $path . "\n";
            $content = file_get_contents($path) . "\n";

            if ($rtl) {
                $dir = dirname($config[$handle]);
                $content = str_replace('../images/', $dir . '/../images/', $content);
                $content = str_replace('url(images/', 'url('.$dir . '/images/', $content);
            }

            $out .= $content;
        }

        if ($test) {
            header('Content-Type: text/plain; charset=UTF-8');
            header('Expires: ' . gmdate("D, d M Y H:i:s", time() + $expires_offset) . ' GMT');
            header("Cache-Control: public, max-age=$expires_offset");
            print $pathlist . "\n";
            echo $out;
            exit;
        } else {
            header('Content-Type: text/css');
            header('Expires: ' . gmdate("D, d M Y H:i:s", time() + $expires_offset) . ' GMT');
            header("Cache-Control: public, max-age=$expires_offset");

            if ($compress && !ini_get('zlib.output_compression') && 'ob_gzhandler' != ini_get('output_handler') && isset($_SERVER['HTTP_ACCEPT_ENCODING'])) {
                header('Vary: Accept-Encoding'); // Handle proxies
                if (false !== stripos($_SERVER['HTTP_ACCEPT_ENCODING'], 'deflate') && function_exists('gzdeflate') && !$force_gzip) {
                    header('Content-Encoding: deflate');
                    $out = gzdeflate($out, 3);
                } elseif (false !== stripos($_SERVER['HTTP_ACCEPT_ENCODING'], 'gzip') && function_exists('gzencode')) {
                    header('Content-Encoding: gzip');
                    $out = gzencode($out, 3);
                }
            }

            echo $out;
            exit;
        }
    }

}

・kohana/application/classes/controller/loadjs.php
 Javascript 用のオートローダーです。30行目にドキュメントルートの絶対パスを書いているので、必要に応じて書きなおして下さい。

<?php defined('SYSPATH') OR die('No direct access allowed.');

class Controller_Loadjs extends Controller {

    public function action_index() {

        error_reporting(0);

        $load = preg_replace('/[^a-z0-9,_-]+/i', '', $_GET['load']);
        $load = explode(',', $load);

        if (empty($load))
            exit;

        $compress = ( isset($_GET['c']) && $_GET['c'] );
        $force_gzip = ( $compress && 'gzip' == $_GET['c'] );
        $test = ( isset($_GET['c']) AND $_GET['c'] == 'test');
        $expires_offset = 31536000;
        $out = '';
        $pathlist = '';

        $config = Kohana::$config->load('wp-js-css')->js;

        foreach ($load as $handle) {
            if (!$config[$handle]){
                $pathlist .= '*** '.$handle." is not defined! ***\n";
                continue;
            }

            $path = 'c:/xampp/htdocs' . $config[$handle];
            $pathlist .= $path . "\n";
            $out .= file_get_contents($path) . "\n";
        }

        if ($test) {
            header('Content-Type: text/plain; charset=UTF-8');
            header('Expires: ' . gmdate("D, d M Y H:i:s", time() + $expires_offset) . ' GMT');
            header("Cache-Control: public, max-age=$expires_offset");
            echo $pathlist."\n";
            echo $out;
            exit;
            
        } else {
            header('Content-Type: application/x-javascript; charset=UTF-8');
            header('Expires: ' . gmdate("D, d M Y H:i:s", time() + $expires_offset) . ' GMT');
            header("Cache-Control: public, max-age=$expires_offset");

            if ($compress && !ini_get('zlib.output_compression') && 'ob_gzhandler' != ini_get('output_handler') && isset($_SERVER['HTTP_ACCEPT_ENCODING'])) {
                header('Vary: Accept-Encoding'); // Handle proxies
                if (false !== stripos($_SERVER['HTTP_ACCEPT_ENCODING'], 'deflate') && function_exists('gzdeflate') && !$force_gzip) {
                    header('Content-Encoding: deflate');
                    $out = gzdeflate($out, 3);
                } elseif (false !== stripos($_SERVER['HTTP_ACCEPT_ENCODING'], 'gzip') && function_exists('gzencode')) {
                    header('Content-Encoding: gzip');
                    $out = gzencode($out, 3);
                }
            }

            echo $out;
            exit;
        }
    }

}

 

試験

 WordPress の新規投稿画面では沢山の Javascript を使っています。沢山ロードしている部分を今回のローダーで記述すると下記例のようになります。ブラウザで試してみて下さい。実戦では c=test& を省いて使います。

http://localhost/kohana/loadjs?c=test&load=admin-bar,hoverIntent,common,jquery-color,schedule,wp-ajax-response,autosave,suggest,wp-lists,jquery-ui-core,jquery-ui-widget,jquery-ui-mouse,jquery-ui-sortable,postbox,post,thickbox,media-upload,word-count,editor,quicktags,jquery-ui-resizable,jquery-ui-draggable,jquery-ui-button,jquery-ui-position,jquery-ui-dialog,wpdialogs,wplink,wpdialogs-popup,wp-fullscreen