diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..592d72f --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,59 @@ +on: + push: + # Sequence of patterns matched against refs/tags + tags: + - '3*' + +name: create_release + +jobs: + build: + name: create_release + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v2 + + - name: Slack Notification on Start + uses: rtCamp/action-slack-notify@v2.2.0 + env: + SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK_RELEASE }} + SLACK_CHANNEL: notify-nc3-release + SLACK_TITLE: "${{ github.repository }}" + SLACK_COLOR: "#f0ad4e" + SLACK_MESSAGE: "Start Job" + + - name: Create Release + id: create_release + uses: actions/create-release@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # This token is provided by Actions, you do not need to create your own token + with: + tag_name: ${{ github.ref }} + release_name: ${{ github.ref }} + body: | + NetCommons ${{ github.ref }} released. + draft: false + prerelease: false + + # テスト成功時はこちらのステップが実行される + - name: Slack Notification on Finish + uses: rtCamp/action-slack-notify@v2.2.0 + if: success() + env: + SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK_RELEASE }} + SLACK_CHANNEL: notify-nc3-release + SLACK_TITLE: "${{ github.repository }}" + SLACK_COLOR: good + SLACK_MESSAGE: "Job Success" + + # テスト失敗時はこちらのステップが実行される + - name: Slack Notification on Failure + uses: rtCamp/action-slack-notify@v2.2.0 + if: failure() + env: + SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK_RELEASE }} + SLACK_CHANNEL: notify-nc3-tests + SLACK_TITLE: "${{ github.repository }}" + SLACK_COLOR: danger + SLACK_MESSAGE: "Job Failure" diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml new file mode 100644 index 0000000..6da4321 --- /dev/null +++ b/.github/workflows/tests.yml @@ -0,0 +1,168 @@ +on: + push: + branches: + - main + - master + pull_request: + branches: + - main + - master + +name: tests + +jobs: + setup: + name: setup + runs-on: ubuntu-latest + steps: + - name: Slack Notification on Start + uses: rtCamp/action-slack-notify@v2.2.0 + if: env.SLACK_WEBHOOK != '' + env: + SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK_TESTS }} + SLACK_CHANNEL: notify-nc3-tests + SLACK_TITLE: "${{ github.repository }}" + SLACK_COLOR: "#f0ad4e" + + tests: + name: tests + needs: setup + runs-on: ubuntu-latest + strategy: + matrix: + php: [ '7.1', '7.2', '7.3', '7.4' ] + mysql: [ '5.7', '8.0' ] + + env: + NC3_BUILD_DIR: "/opt/nc3" + NC3_DOCKER_DIR: "/opt/docker" + NC3_GIT_URL: "git://github.com/NetCommons3/NetCommons3.git" + NC3_GIT_BRANCH: "master" + PLUGIN_BUILD_DIR: ${{ github.workspace }} + PHP_VERSION: ${{ matrix.php }} + MYSQL_VERSION: ${{ matrix.mysql }} + MYSQL_ROOT_PASSWORD: root + MYSQL_DATABASE: cakephp_test + COMPOSER_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + steps: + - uses: actions/checkout@v2 + + - name: Fix up git URLs + run: echo -e '[url "https://github.com/"]\n insteadOf = "git://github.com/"' >> ~/.gitconfig + + - name: environment + run: | + echo "GITHUB_WORKSPACE=${GITHUB_WORKSPACE}" + echo "PLUGIN_BUILD_DIR=${PLUGIN_BUILD_DIR}" + echo "PHP_VERSION=${PHP_VERSION}" + echo "MYSQL_VERSION=${MYSQL_VERSION}" + ls -al ${PLUGIN_BUILD_DIR} + + - name: docker-compose install + run: | + curl -L https://github.com/docker/compose/releases/download/1.29.2/docker-compose-`uname -s`-`uname -m` > ~/docker-compose + chmod +x ~/docker-compose + sudo mv ~/docker-compose /usr/local/bin/docker-compose + docker-compose --version + + - name: git clone nc3 + run: git clone -b ${NC3_GIT_BRANCH} ${NC3_GIT_URL} ${NC3_BUILD_DIR} + + - name: git clone nc3_docker + run: git clone https://github.com/NetCommons3/nc3app-docker.git ${NC3_DOCKER_DIR} + + - name: docker-compose start + run: | + cd ${NC3_DOCKER_DIR} + docker-compose up -d + docker-compose start + + - run: docker ps + + - name: check libraries + run: | + cd ${NC3_DOCKER_DIR} + docker-compose exec -T nc3app bash /opt/scripts/start-on-docker.sh + + - name: nc3 build + run: | + cd ${NC3_DOCKER_DIR} + docker-compose exec -T nc3app bash /opt/scripts/app-build.sh + + - name: phpcs (PHP CodeSniffer) + if: always() + run: | + cd ${NC3_DOCKER_DIR} + docker-compose exec -T nc3app bash /opt/scripts/phpcs.sh + + - name: phpmd (PHP Mess Detector) + if: always() + run: | + cd ${NC3_DOCKER_DIR} + docker-compose exec -T nc3app bash /opt/scripts/phpmd.sh + + - name: phpcpd (PHP Copy/Paste Detector) + if: always() + run: | + cd ${NC3_DOCKER_DIR} + docker-compose exec -T nc3app bash /opt/scripts/phpcpd.sh + + - name: gjslint (JavaScript Style Check) + if: always() + run: | + cd ${NC3_DOCKER_DIR} + docker-compose exec -T nc3app bash /opt/scripts/gjslint.sh + + - name: phpdoc (PHP Documentor) + if: always() + run: | + cd ${NC3_DOCKER_DIR} + docker-compose exec -T nc3app bash /opt/scripts/phpdoc.sh + + - name: phpunit (PHP UnitTest) + if: always() + run: | + cd ${NC3_DOCKER_DIR} + docker-compose exec -T nc3app bash /opt/scripts/phpunit.sh + sudo -s chmod a+w -R ${NC3_BUILD_DIR}/build + +# - name: push coveralls +# env: +# COVERALLS_REPO_TOKEN: ${{ secrets.GITHUB_TOKEN }} +# COVERALLS_FLAG_NAME: ${{ matrix.php }} +# run: | +# cd ${NC3_BUILD_DIR} +# ls -la ${NC3_BUILD_DIR} +# vendors/bin/php-coveralls --coverage_clover=build/logs/clover.xml -v + + - name: docker-compose remove + if: always() + run: | + cd ${NC3_DOCKER_DIR} + docker-compose rm -f + + # テスト失敗時はこちらのステップが実行される + - name: Slack Notification on Failure + uses: rtCamp/action-slack-notify@v2.2.0 + if: env.SLACK_WEBHOOK != '' && failure() + env: + SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK_TESTS }} + SLACK_CHANNEL: notify-nc3-tests + SLACK_TITLE: "${{ github.repository }}(php${{ matrix.php }}, mysql${{ matrix.mysql }})" + SLACK_COLOR: danger + + teardown: + name: teardown + runs-on: ubuntu-latest + needs: tests + steps: + # テスト成功時はこちらのステップが実行される + - name: Slack Notification on Success + uses: rtCamp/action-slack-notify@v2.2.0 + if: env.SLACK_WEBHOOK != '' && success() + env: + SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK_TESTS }} + SLACK_CHANNEL: notify-nc3-tests + SLACK_TITLE: "${{ github.repository }}" + SLACK_COLOR: good diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index a05bf85..0000000 --- a/.travis.yml +++ /dev/null @@ -1,43 +0,0 @@ -language: php - -php: - - 5.4 - - 5.5 - - 5.6 - - 7.0 - - 7.1 - -sudo: false - -env: - matrix: - - NETCOMMONS_VERSION=master DB=mysql - global: - - secure: "FhZx+mu1fwG7ghoF5jKKwW672cRbAhiSG9IY3q0og1FaNfUjMVMzryAhoM9/76BgRFom9hLKBuM/5pKvhSHZCV9u4EdDoMB38TeJwCv0Fh7L/C7ubfcTrT2cbMFOD9JxkIgt8lOM5vHnnDWi0UFjaFrv3cBCZgVrLW4ejUoUD4RFi+hps5WoG6GcAwHw0nkyM01WZQjZ43YAciiD5/vC1cnaaXwXCzOugIUdjDISN9q/KeVjRp2bhD852GkvBT+qhGRph5+0msCG7ch+ve1xAfPO4QNcgl/+01Op8djj5T+c3TPpFDpOapE4vQ4dD0DWasSRdftlzCyiwyCBLAhYa/8AXJG6rVK2IKyoGyHUZcn8YGDANSLyB4UTdp/7QJKKX5PUrh3ejywr35kJvnCVVQ3o4oyQk5TOJ96i9tYkoOs0d2KZ4dF+bdCfKeyO1zmJp7ILtWBJJrPzE3Rw+OyDI7oqbVpvjHJDt7gKv7cUU/Gpn3vnPtqzTWKqEiTck/K6MEFlWv5T4LY5YtHuPNH2Pmko5Zg1ljnmkuBqHZLg6HCCRoYkYq9TVUL/4N4Q+rEDstrCocVytGecryh+RgNaCvtHxvrPNp3A306s1DrtzXcWZVQ1L3MS1Nj0gdodEAxugRM92Jy/0ouMxmu/0Juv1sXWOOi6GVzfa04BbJmLf9A=" - - GIT_COMMITTER_NAME=s-nakajima - - GIT_COMMITTER_EMAIL=nakajimashouhei@gmail.com - - GIT_AUTHOR_NAME=s-nakajima - - GIT_AUTHOR_EMAIL=nakajimashouhei@gmail.com - -sudo: required - -before_script: - - export NETCOMMONS_BUILD_DIR=`dirname $TRAVIS_BUILD_DIR`/NetCommons3 - - git clone git://github.com/NetCommons3/NetCommons3 $NETCOMMONS_BUILD_DIR - - cd $NETCOMMONS_BUILD_DIR - - git checkout $NETCOMMONS_VERSION - - travis_wait . tools/build/plugins/cakephp/travis/pre.sh - - . tools/build/plugins/cakephp/travis/environment.sh - -script: - - . tools/build/plugins/cakephp/travis/main.sh - -after_script: - - . tools/build/plugins/cakephp/travis/post.sh - -notifications: - email: - recipients: - - netcommons3@googlegroups.com - on_success: never # default: change - on_failure: always # default: always diff --git a/Console/Command/Task/CopyAllWebrootFilesTask.php b/Console/Command/Task/CopyAllWebrootFilesTask.php new file mode 100644 index 0000000..5adf2ad --- /dev/null +++ b/Console/Command/Task/CopyAllWebrootFilesTask.php @@ -0,0 +1,59 @@ + + * @author Shohei Nakajima + * @link http://www.netcommons.org NetCommons Project + * @license http://www.netcommons.org/license.txt NetCommons License + * @copyright Copyright 2014, NetCommons Project + */ + +App::uses('AppShell', 'Console/Command'); +App::uses('PluginUpdateUtil', 'PluginManager.Utility'); + +/** + * webrootファイルの一括コピーシェル + * + * @author Shohei Nakajima + * @package NetCommons\PluginManager\Console\Command + */ +class CopyAllWebrootFilesTask extends AppShell { + +/** + * Execution method always used for tasks + * + * @return void + */ + public function execute() { + $this->Plugin = ClassRegistry::init('PluginManager.Plugin'); + + if (! isset($this->PluginUpdateUtil)) { + $this->PluginUpdateUtil = new PluginUpdateUtil(); + } + if ($this->PluginUpdateUtil->copyAllWebrootFiles()) { + $this->out( + '' . + __d('plugin_manager', 'Successfully webroot files copy of all plugins.') . + '' + ); + } else { + $this->out( + '' . __d('plugin_manager', 'Failure webroot files copy of all plugins.') . '' + ); + } + } + +/** + * Gets the option parser instance and configures it. + * + * @return ConsoleOptionParser + */ + public function getOptionParser() { + $parser = parent::getOptionParser(); + + $parser->description(__d('plugin_manager', 'Webroot files copy of all plugins')); + + return $parser; + } +} diff --git a/Console/Command/UpdateAllShell.php b/Console/Command/UpdateAllShell.php index 7ec894c..f30f9ff 100644 --- a/Console/Command/UpdateAllShell.php +++ b/Console/Command/UpdateAllShell.php @@ -26,6 +26,7 @@ class UpdateAllShell extends AppShell { */ public $tasks = array( 'PluginManager.UpdateAll', + 'PluginManager.CopyAllWebrootFiles', ); /** @@ -80,6 +81,10 @@ public function getOptionParser() { ->addSubcommand('update_all', array( 'help' => __d('plugin_manager', 'Update of all plugins'), 'parser' => $this->UpdateAll->getOptionParser(), + )) + ->addSubcommand('copy_all_webroot_files', array( + 'help' => __d('plugin_manager', 'Webroot files copy of all plugins'), + 'parser' => $this->UpdateAll->getOptionParser(), )); } diff --git a/Controller/PluginManagerController.php b/Controller/PluginManagerController.php index 5f9ea80..68c5635 100644 --- a/Controller/PluginManagerController.php +++ b/Controller/PluginManagerController.php @@ -117,10 +117,11 @@ public function index() { $this->set('plugins', $plugins); $this->set('pluginsMap', $pluginsMap); - $nc3plugin = $this->Plugin->getPlugins( - Plugin::PLUGIN_TYPE_CORE, 'net_commons' - ); - $this->set('nc3plugin', $nc3plugin); + if (file_exists(APP . 'VERSION')) { + $this->set('nc3version', trim(file_get_contents(APP . 'VERSION'))); + } else { + $this->set('nc3version', '3.2.1'); + } $this->set('hasNewPlugin', (bool)$this->Plugin->getNewPlugins(Plugin::PLUGIN_TYPE_FOR_NOT_YET)); $this->set('hasUpdate', $this->Plugin->hasUpdate()); @@ -153,11 +154,6 @@ public function view() { $this->set('plugin', $plugins); } - $nc3plugin = $this->Plugin->getPlugins( - Plugin::PLUGIN_TYPE_CORE, 'net_commons' - ); - $this->set('nc3plugin', $nc3plugin); - $this->set('pluginType', $pluginType); //レイアウトの設定 diff --git a/Model/Behavior/PluginBehavior.php b/Model/Behavior/PluginBehavior.php index 79938dc..419877d 100644 --- a/Model/Behavior/PluginBehavior.php +++ b/Model/Behavior/PluginBehavior.php @@ -32,11 +32,14 @@ class PluginBehavior extends ModelBehavior { public function setup(Model $model, $config = array()) { parent::setup($model, $config); - $this->connection = Hash::get($config, 'connection', 'master'); + $this->connection = Hash::get($config, 'connection', $model->useDbConfig); $this->corePluginPatterns = Hash::get($config, 'corePluginPatterns', [ '#^netcommons/#' => Plugin::PLUGIN_TYPE_CORE, ]); + $this->migrationPlugins = Hash::get($config, 'migrationPlugins', [ + 'cakephp-plugin', + ]); } /** @@ -55,16 +58,24 @@ public function runVersionUp(Model $model, $plugin) { $model->begin(); if (! Hash::get($plugin, 'latest') && Hash::get($plugin, 'Plugin.id')) { - if (! $model->uninstallPlugin(Hash::get($plugin, 'Plugin.key'))) { + $pluginKey = Hash::get($plugin, 'Plugin.key'); + if (! $model->uninstallPlugin($pluginKey)) { throw new InternalErrorException(__d('net_commons', 'Internal Server Error')); } $model->deleteOldPackageDir($plugin, true); + + //img,js,cssをwebrootから削除。エラーとはしない + $model->deleteFromWebroot($plugin); } else { - if (Hash::get($plugin, 'latest.packageType') === 'cakephp-plugin') { + if (in_array(Hash::get($plugin, 'latest.packageType'), $this->migrationPlugins, true)) { if (! $model->runMigration(Hash::get($plugin, 'latest.key'))) { throw new InternalErrorException(__d('net_commons', 'Internal Server Error')); } } + + //img,js,cssをwebrootにコピー。エラーとはしない + $model->copyToWebroot($plugin); + if (! $model->updateVersion(array(Hash::get($plugin, 'latest')))) { throw new InternalErrorException(__d('net_commons', 'Internal Server Error')); } @@ -72,6 +83,9 @@ public function runVersionUp(Model $model, $plugin) { $model->deleteOldPackageDir($plugin); } + //キャッシュのクリア + $model->cacheClear(); + CakeLog::info( sprintf('[version up] Successfully version up "%s"', Hash::get($plugin, 'Plugin.name')) ); @@ -137,6 +151,9 @@ public function uninstallPlugin(Model $model, $data) { CakeLog::info(sprintf('[uninstall] Successfully uninstall plugin "%s"', $key)); + //キャッシュのクリア + $model->Plugin->cacheClear(); + //トランザクションCommit $model->commit(); @@ -181,10 +198,12 @@ public static function staticRunMigration($plugin, $connection = null) { $messages = array(); $ret = null; - exec(sprintf( + $cmd = sprintf( 'cd %s && Console%scake Migrations.migration run all -p %s -c %s -i %s 2>&1', ROOT . DS . APP_DIR, DS, escapeshellcmd($plugin), $connection, $connection - ), $messages, $ret); + ); + CakeLog::info('[migration] ' . $cmd); + exec($cmd, $messages, $ret); // Write logs foreach ($messages as $message) { @@ -319,7 +338,7 @@ public function updateVersion(Model $model, $packages) { 'version' => '\'' . $package['version'] . '\'', 'commit_version' => '\'' . $package['commit_version'] . '\'', 'commited' => '\'' . $package['commited'] . '\'', - 'serialize_data' => '\'' . serialize($package) . '\'', + 'serialize_data' => $model->Plugin->getDataSource()->value(serialize($package), 'string'), ); if (! $model->Plugin->updateAll($update, $conditions)) { CakeLog::info(sprintf('[update version] Line(' . __LINE__ . ') Error')); diff --git a/Model/Behavior/PluginComposerBehavior.php b/Model/Behavior/PluginComposerBehavior.php index 4e955cd..aca7cbd 100644 --- a/Model/Behavior/PluginComposerBehavior.php +++ b/Model/Behavior/PluginComposerBehavior.php @@ -67,7 +67,10 @@ public function getComposer(Model $model, $namespace = null, $filePath = null) { $composers = array(); foreach ($packages['packages'] as $package) { $composer = $this->_parseComposer($package); - $composers[$composer['namespace']] = $composer; + if ($composer['packageType'] !== 'netcommons-theme') { + //テーマは別途設定するため除外する + $composers[$composer['namespace']] = $composer; + } } if (! $filePath) { @@ -91,24 +94,23 @@ public function getComposer(Model $model, $namespace = null, $filePath = null) { * @SuppressWarnings(PHPMD.NPathComplexity) */ protected function _parseComposer($package) { + $composerExtType = true; foreach ($this->ignorePatterns as $pattern) { if (preg_match($pattern, $package['name'])) { $key = strtr(preg_replace($pattern, '', $package['name']), '-', '_'); $name = Inflector::humanize($key); $originalSource = Inflector::camelize($key); - $composerType = false; + $composerExtType = false; } } if (Hash::get($package, 'type') === 'cakephp-plugin') { $key = strtr(substr($package['name'], strrpos($package['name'], '/') + 1), '-', '_'); $name = Inflector::humanize(strtr($package['name'], '/', ' ')); $originalSource = Inflector::camelize($key); - $composerType = false; } elseif (empty($key)) { $key = $package['name']; $name = $package['name']; $originalSource = $package['name']; - $composerType = true; } $result = array( @@ -134,7 +136,7 @@ protected function _parseComposer($package) { } if (isset($package['plugin-type'])) { $result['type'] = $package['plugin-type']; - } elseif ($composerType) { + } elseif ($composerExtType) { $result['type'] = Plugin::PLUGIN_TYPE_FOR_EXT_COMPOSER; } diff --git a/Model/Behavior/PluginWebrootBehavior.php b/Model/Behavior/PluginWebrootBehavior.php new file mode 100644 index 0000000..0349611 --- /dev/null +++ b/Model/Behavior/PluginWebrootBehavior.php @@ -0,0 +1,105 @@ + + * @author Shohei Nakajima + * @link http://www.netcommons.org NetCommons Project + * @license http://www.netcommons.org/license.txt NetCommons License + * @copyright Copyright 2014, NetCommons Project + */ + +App::uses('ModelBehavior', 'Model'); +App::uses('Folder', 'Utility'); + +/** + * Plugin Behavior + * + * @author Shohei Nakajima + * @package NetCommons\PluginManager\Model\Behavior + */ +class PluginWebrootBehavior extends ModelBehavior { + +/** + * 各プラグインにあるimg(css,js)をapp/webroot/img(css,js)にコピーする + * + * @param Model $model 呼び出し元Model + * @param array $plugin プラグイン情報 + * @return bool + */ + public function copyToWebroot(Model $model, $plugin) { + $pluginKey = Hash::get($plugin, 'Plugin.key'); + if (! $pluginKey) { + return true; + } + + //既存のapp/webroot/img(css,js)を削除する + $this->deleteFromWebroot($model, $plugin); + $camelPlugin = Inflector::camelize($pluginKey); + $originalSource = Hash::get($plugin, 'latest.originalSource'); + if (CakePlugin::loaded($camelPlugin)) { + $pluginWebrootPath = CakePlugin::path($camelPlugin); + $pluginWebrootPath .= WEBROOT_DIR . DS; + if (file_exists($pluginWebrootPath . 'img')) { + $Folder = new Folder($pluginWebrootPath . 'img'); + $Folder->copy(IMAGES . DS . $pluginKey); + } + if (file_exists($pluginWebrootPath . 'css')) { + $Folder = new Folder($pluginWebrootPath . 'css'); + $Folder->copy(CSS . DS . $pluginKey); + } + if (file_exists($pluginWebrootPath . 'js')) { + $Folder = new Folder($pluginWebrootPath . 'js'); + $Folder->copy(JS . DS . $pluginKey); + } + } elseif (file_exists(APP . 'View' . DS . 'Themed' . DS . $originalSource)) { + $pluginWebrootPath = APP . 'View' . DS . 'Themed' . DS . $originalSource . DS; + $pluginWebrootPath .= WEBROOT_DIR; + if (file_exists($pluginWebrootPath)) { + $Folder = new Folder($pluginWebrootPath); + $Folder->copy(WWW_ROOT . 'theme' . DS . $originalSource); + } + } else { + return true; + } + + return true; + } + +/** + * app/webroot/img(css,js)から削除する + * + * @param Model $model 呼び出し元Model + * @param array $plugin プラグイン情報 + * @return bool + */ + public function deleteFromWebroot(Model $model, $plugin) { + $pluginKey = Hash::get($plugin, 'Plugin.key'); + if (! $pluginKey) { + return true; + } + $camelPlugin = Inflector::camelize($pluginKey); + $originalSource = Hash::get($plugin, 'latest.originalSource'); + + if (CakePlugin::loaded($camelPlugin)) { + if (file_exists(IMAGES . $pluginKey)) { + $Folder = new Folder(IMAGES . $pluginKey); + $Folder->delete(); + } + if (file_exists(CSS . $pluginKey)) { + $Folder = new Folder(CSS . $pluginKey); + $Folder->delete(); + } + if (file_exists(JS . $pluginKey)) { + $Folder = new Folder(JS . $pluginKey); + $Folder->delete(); + } + } elseif (file_exists(WWW_ROOT . 'theme' . DS . $originalSource)) { + $Folder = new Folder(WWW_ROOT . 'theme' . DS . $originalSource); + $Folder->delete(); + } + + return true; + } + +} diff --git a/Model/Plugin.php b/Model/Plugin.php index 659552c..915d67b 100644 --- a/Model/Plugin.php +++ b/Model/Plugin.php @@ -91,6 +91,8 @@ class Plugin extends AppModel { 'PluginManager.PluginBower', 'PluginManager.PluginComposer', 'PluginManager.PluginTheme', + 'PluginManager.PluginWebroot', + 'NetCommons.NetCommonsCache', ); /** @@ -196,19 +198,22 @@ public function getMaxWeight($type) { * * @param int $type プラグインタイプ * @param string $key プラグインキー + * @param string|array|null $langId 取得する言語。nullの場合、typeにより共通言語もしくCurrentにセットされているものを使用する * @return array */ - public function getPlugins($type, $key = null) { - $notLangTypes = array( - self::PLUGIN_TYPE_CORE, - self::PLUGIN_TYPE_FOR_THEME, - self::PLUGIN_TYPE_FOR_EXT_COMPOSER, - self::PLUGIN_TYPE_FOR_EXT_BOWER - ); - if (! is_array($type) && in_array($type, $notLangTypes)) { - $langId = '0'; - } else { - $langId = Current::read('Language.id'); + public function getPlugins($type, $key = null, $langId = null) { + if (! $langId) { + $notLangTypes = array( + self::PLUGIN_TYPE_CORE, + self::PLUGIN_TYPE_FOR_THEME, + self::PLUGIN_TYPE_FOR_EXT_COMPOSER, + self::PLUGIN_TYPE_FOR_EXT_BOWER + ); + if (! is_array($type) && in_array($type, $notLangTypes)) { + $langId = '0'; + } else { + $langId = Current::read('Language.id'); + } } $conditions = array( @@ -226,7 +231,7 @@ public function getPlugins($type, $key = null) { } //pluginsテーブルの取得 - $plugins = $this->find('all', array( + $plugins = $this->cacheFindQuery('all', array( 'recursive' => -1, 'conditions' => $conditions, 'order' => $order, @@ -234,6 +239,22 @@ public function getPlugins($type, $key = null) { if (! $plugins) { return array(); } + $plugins = $this->convertSerializeData($plugins); + + if (count($plugins) > 1) { + return $plugins; + } else { + return $plugins[0]; + } + } + +/** + * serialize_dataのデータをコンバートする + * + * @param array $plugins PluginモデルからfindAllしたもの + * @return array + */ + public function convertSerializeData($plugins) { foreach ($plugins as $i => $plugin) { $plugin['Plugin']['serialize_data'] = unserialize( Hash::get($plugin, 'Plugin.serialize_data', serialize(array())) @@ -251,11 +272,7 @@ public function getPlugins($type, $key = null) { $plugins[$i] = $plugin; } - if (count($plugins) > 1) { - return $plugins; - } else { - return $plugins[0]; - } + return $plugins; } /** @@ -299,7 +316,7 @@ public function getNewPlugins($type, $key = null) { } $packages = Hash::combine($packages, '{s}.key', '{s}'); - $currents = $this->find('list', array( + $currents = $this->cacheFindQuery('list', array( 'recursive' => -1, 'fields' => array('key', 'commit_version'), 'conditions' => $conditions, @@ -430,6 +447,9 @@ public function saveEnableM17n($data) { throw new InternalErrorException(__d('net_commons', 'Internal Server Error')); } + //キャッシュのクリア + $this->cacheClear(); + return true; } @@ -463,4 +483,32 @@ public function hasUpdate() { return $return; } +/** + * プラグインの全タイプを取得 + * + * 一括アップデートで使用する + * + * @return array + */ + public function getTypes() { + //pluginsテーブルの取得 + $plugins = $this->find('all', array( + 'recursive' => -1, + 'fields' => ['type'], + 'group' => 'type', + 'order' => ['type' => 'asc'], + 'callbacks' => false, + )); + if (! $plugins) { + return array(); + } + + $result = []; + foreach ($plugins as $plugin) { + $result[] = $plugin[$this->alias]['type']; + } + + return $result; + } + } diff --git a/Model/PluginsRole.php b/Model/PluginsRole.php index 9c68e4f..027a763 100644 --- a/Model/PluginsRole.php +++ b/Model/PluginsRole.php @@ -45,6 +45,15 @@ class PluginsRole extends AppModel { ), ); +/** + * Behaviors + * + * @var array + */ + public $actsAs = array( + 'NetCommons.NetCommonsCache', + ); + /** * RoleKeyに対するプラグインデータ取得 * @@ -59,7 +68,7 @@ public function getPlugins($pluginType, $roleKey, $joinType = 'LEFT', $queryType return false; } - $plugins = $this->Plugin->find($queryType, array( + $plugins = $this->Plugin->cacheFindQuery($queryType, array( 'recursive' => -1, 'fields' => array( $this->alias . '.id', @@ -96,6 +105,23 @@ public function getPlugins($pluginType, $roleKey, $joinType = 'LEFT', $queryType return $plugins; } +/** + * Called after each successful save operation. + * + * @param bool $created True if this save created a new record + * @param array $options Options passed from Model::save(). + * @return void + * @throws InternalErrorException + * @link http://book.cakephp.org/2.0/en/models/callback-methods.html#aftersave + * @see Model::save() + */ + public function afterSave($created, $options = array()) { + parent::afterSave($created, $options); + + //キャッシュクリア + $this->Plugin->cacheClear(); + } + /** * Save plugin roles * Here does not transaction. Please do the transaction and validation in the caller. diff --git a/README.md b/README.md index 74edda5..ef0a851 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,6 @@ PluginManager ============== -PluginManager Plugin for NetCommons - -[![Build Status](https://api.travis-ci.org/NetCommons3/PluginManager.svg?branch=master)](https://travis-ci.org/NetCommons3/PluginManager) +[![Tests Status](https://github.com/NetCommons3/PluginManager/actions/workflows/tests.yml/badge.svg?branch=master)](https://github.com/NetCommons3/PluginManager/actions/workflows/tests.yml) [![Coverage Status](https://coveralls.io/repos/NetCommons3/PluginManager/badge.svg?branch=master)](https://coveralls.io/r/NetCommons3/PluginManager?branch=master) - -| dependencies | status | -| ------------- | ------ | -| composer.json | [![Dependency Status](https://www.versioneye.com/user/projects/55531fa006c31830550002f4/badge.svg?style=flat)](https://www.versioneye.com/user/projects/55531fa006c31830550002f4) | +[![Stable Version](https://img.shields.io/packagist/v/netcommons/plugin-manager.svg?label=stable)](https://packagist.org/packages/netcommons/plugin-manager) diff --git a/Test/Case/Controller/PluginManagerControllerEditTest.php b/Test/Case/Controller/PluginManagerControllerEditTest.php index fec1f22..89dc49f 100644 --- a/Test/Case/Controller/PluginManagerControllerEditTest.php +++ b/Test/Case/Controller/PluginManagerControllerEditTest.php @@ -104,6 +104,13 @@ public function testNoPluginData() { public function testRunVersionUpTrue() { $this->__setMockPluginRunVersionUp(true); + $data['Plugin']['key'] = 'plugin_manager'; + + $this->controller->Plugin + ->expects($this->once()) + ->method('getPlugins') + ->will($this->returnValue($data)); + $MockNetCommons = $this->getMock('NetCommonsComponent', ['setFlashNotification'], [$this->controller->Components]); $MockNetCommons ->expects($this->once()) @@ -115,7 +122,6 @@ public function testRunVersionUpTrue() { $this->controller->Components->set('NetCommons', $MockNetCommons); $this->controller->Components->enable('NetCommons'); - $data['Plugin']['key'] = 'plugin_manager'; $this->testAction('plugin_manager/plugin_manager/edit/2', ['data' => $data]); $this->assertStringEndsWith('plugin_manager/plugin_manager/index/2', $this->headers['Location']); } @@ -128,6 +134,13 @@ public function testRunVersionUpTrue() { public function testRunVersionUpFalse() { $this->__setMockPluginRunVersionUp(false); + $data['Plugin']['key'] = 'plugin_manager'; + + $this->controller->Plugin + ->expects($this->once()) + ->method('getPlugins') + ->will($this->returnValue($data)); + $MockNetCommons = $this->getMock('NetCommonsComponent', ['setFlashNotification'], [$this->controller->Components]); $MockNetCommons ->expects($this->once()) @@ -142,7 +155,6 @@ public function testRunVersionUpFalse() { $this->controller->Components->set('NetCommons', $MockNetCommons); $this->controller->Components->enable('NetCommons'); - $data['Plugin']['key'] = 'plugin_manager'; $this->testAction('plugin_manager/plugin_manager/edit/2', ['data' => $data]); $this->assertStringEndsWith('plugin_manager/plugin_manager/index/2', $this->headers['Location']); } @@ -156,6 +168,12 @@ public function testTypeSystem() { $this->__setMockPluginRunVersionUp(true); $data['Plugin']['key'] = 'plugin_manager'; + + $this->controller->Plugin + ->expects($this->once()) + ->method('getPlugins') + ->will($this->returnValue($data)); + $this->testAction('plugin_manager/plugin_manager/edit/3', ['data' => $data]); $this->assertStringEndsWith('plugin_manager/plugin_manager/index/2', $this->headers['Location']); } @@ -188,7 +206,10 @@ public function testTypeNotYet() { * @return void */ private function __setMockPluginRunVersionUp($returnValue) { - $this->controller->Plugin = $this->getMockForModel('PluginManager.Plugin', ['runVersionUp', 'getNewPlugins']); + $this->controller->Plugin = $this->getMockForModel( + 'PluginManager.Plugin', + ['runVersionUp', 'getPlugins', 'getNewPlugins'] + ); $this->controller->Plugin ->expects($this->once()) ->method('runVersionUp') diff --git a/Test/Case/Controller/PluginManagerControllerIndexTest.php b/Test/Case/Controller/PluginManagerControllerIndexTest.php index eadf224..06197a7 100644 --- a/Test/Case/Controller/PluginManagerControllerIndexTest.php +++ b/Test/Case/Controller/PluginManagerControllerIndexTest.php @@ -140,9 +140,9 @@ public function testNgClickValue($type) { 'latest' => null ]; - $count = 2; + $count = 1; if ($type == Plugin::PLUGIN_TYPE_FOR_NOT_YET) { - $count = 1; + $count = 0; } $this->controller->Plugin ->expects($this->exactly($count)) diff --git a/Test/Case/Model/Behavior/PluginBehavior/UpdateVersionPhotoAlbumsTest.php b/Test/Case/Model/Behavior/PluginBehavior/UpdateVersionPhotoAlbumsTest.php index 36d8cad..878b645 100644 --- a/Test/Case/Model/Behavior/PluginBehavior/UpdateVersionPhotoAlbumsTest.php +++ b/Test/Case/Model/Behavior/PluginBehavior/UpdateVersionPhotoAlbumsTest.php @@ -66,7 +66,7 @@ public function testUpdateVersion() { 'version' => '\'' . $package['version'] . '\'', 'commit_version' => '\'' . $package['commit_version'] . '\'', 'commited' => '\'' . $package['commited'] . '\'', - 'serialize_data' => '\'' . serialize($package) . '\'', + 'serialize_data' => $this->TestModel->Plugin->getDataSource()->value(serialize($package), 'string'), ); $expectedConditions = array( 'namespace' => array('netcommons/photo-albums', 'netcommons/photo_albums') diff --git a/Test/Case/Model/Behavior/PluginBehavior/UpdateVersionTest.php b/Test/Case/Model/Behavior/PluginBehavior/UpdateVersionTest.php index 946e52a..984498e 100644 --- a/Test/Case/Model/Behavior/PluginBehavior/UpdateVersionTest.php +++ b/Test/Case/Model/Behavior/PluginBehavior/UpdateVersionTest.php @@ -64,7 +64,7 @@ private function __prepareUpdateAll($namespace, $return) { 'version' => '\'' . $package['version'] . '\'', 'commit_version' => '\'' . $package['commit_version'] . '\'', 'commited' => '\'' . $package['commited'] . '\'', - 'serialize_data' => '\'' . serialize($package) . '\'', + 'serialize_data' => $this->TestModel->Plugin->getDataSource()->value(serialize($package), 'string'), ); $expectedConditions = array( 'namespace' => $namespace diff --git a/Test/Case/Model/PluginsRole/GetPluginsTest.php b/Test/Case/Model/PluginsRole/GetPluginsTest.php index fc8e60b..f462d85 100644 --- a/Test/Case/Model/PluginsRole/GetPluginsTest.php +++ b/Test/Case/Model/PluginsRole/GetPluginsTest.php @@ -10,6 +10,7 @@ */ App::uses('NetCommonsGetTest', 'NetCommons.TestSuite'); +App::uses('CurrentLib', 'NetCommons.Lib'); /** * PluginsRole::getPlugins()のテスト @@ -61,7 +62,8 @@ public function testGetPlugins() { $methodName = $this->_methodName; //データ生成 - $pluginType = '2'; + CurrentLib::write('Language.id', '2'); + $pluginType = '1'; $roleKey = 'system_administrator'; $joinType = 'LEFT'; diff --git a/Test/Fixture/Plugin4managerFixture.php b/Test/Fixture/Plugin4managerFixture.php new file mode 100644 index 0000000..e758b7d --- /dev/null +++ b/Test/Fixture/Plugin4managerFixture.php @@ -0,0 +1,67 @@ + + * @link http://www.netcommons.org NetCommons Project + * @license http://www.netcommons.org/license.txt NetCommons License + * @copyright Copyright 2014, NetCommons Project + */ + +App::uses('PluginFixture', 'PluginManager.Test/Fixture'); + +/** + * PluginFixture + * + * @author Shohei Nakajima + * @package NetCommons\PluginManager\Test\Fixture + */ +class Plugin4managerFixture extends PluginFixture { + +/** + * Model name + * + * @var string + */ + public $name = 'Plugin'; + +/** + * Full Table Name + * + * @var string + */ + public $table = 'plugins'; + +/** + * Records + * + * @var array + */ + public $records = array( + //サイト管理プラグイン + array( + 'id' => 3, + 'language_id' => 2, + 'key' => 'test_plugin', + 'name' => 'Lorem ipsum dolor sit amet', + 'namespace' => 'Lorem ipsum dolor sit amet', + 'weight' => 1, + 'type' => 2, + 'default_action' => '', + 'default_setting_action' => '', + ), + //システム管理プラグイン + array( + 'id' => 4, + 'language_id' => 2, + 'key' => 'test_plugin', + 'name' => 'Lorem ipsum dolor sit amet', + 'namespace' => 'Lorem ipsum dolor sit amet', + 'weight' => 1, + 'type' => 3, + 'default_action' => '', + 'default_setting_action' => '', + ), + ); + +} diff --git a/Test/Fixture/PluginFixture.php b/Test/Fixture/PluginFixture.php index eebf3d1..5c1757b 100644 --- a/Test/Fixture/PluginFixture.php +++ b/Test/Fixture/PluginFixture.php @@ -45,30 +45,6 @@ class PluginFixture extends CakeTestFixture { 'default_action' => '', 'default_setting_action' => '', ), - //サイト管理プラグイン - array( - 'id' => 3, - 'language_id' => 2, - 'key' => 'test_plugin', - 'name' => 'Lorem ipsum dolor sit amet', - 'namespace' => 'Lorem ipsum dolor sit amet', - 'weight' => 1, - 'type' => 2, - 'default_action' => '', - 'default_setting_action' => '', - ), - //システム管理プラグイン - array( - 'id' => 4, - 'language_id' => 2, - 'key' => 'test_plugin', - 'name' => 'Lorem ipsum dolor sit amet', - 'namespace' => 'Lorem ipsum dolor sit amet', - 'weight' => 1, - 'type' => 3, - 'default_action' => '', - 'default_setting_action' => '', - ), ); /** diff --git a/Utility/PluginUpdateUtil.php b/Utility/PluginUpdateUtil.php index 178f6df..a95df47 100644 --- a/Utility/PluginUpdateUtil.php +++ b/Utility/PluginUpdateUtil.php @@ -9,6 +9,8 @@ * @copyright Copyright 2014, NetCommons Project */ +App::uses('NetCommonsCache', 'NetCommons.Utility'); + /** * PluginUpdate Utility * @@ -33,17 +35,9 @@ public function __construct() { */ public function updateAll() { $result = true; - $types = array( - Plugin::PLUGIN_TYPE_CORE, - Plugin::PLUGIN_TYPE_FOR_FRAME, - Plugin::PLUGIN_TYPE_FOR_SITE_MANAGER, - Plugin::PLUGIN_TYPE_FOR_SYSTEM_MANGER, - Plugin::PLUGIN_TYPE_FOR_THEME, - Plugin::PLUGIN_TYPE_FOR_EXT_COMPOSER, - Plugin::PLUGIN_TYPE_FOR_EXT_BOWER - ); + $types = $this->Plugin->getTypes(); foreach ($types as $type) { - $plugins = $this->Plugin->getPlugins($type); + $plugins = $this->Plugin->getPlugins($type, null, ['0', '2']); if (! $this->__updatePackages($plugins)) { $result = false; break; @@ -66,6 +60,10 @@ public function updateAll() { } } + if (file_exists(APP . 'VERSION')) { + $ncCache = new NetCommonsCache('version', false, 'netcommons_core'); + $ncCache->write(trim(file_get_contents(APP . 'VERSION'))); + } return $result; } @@ -89,4 +87,20 @@ private function __updatePackages($plugins) { return true; } +/** + * 一括アップデート + * + * @return bool + */ + public function copyAllWebrootFiles() { + $types = $this->Plugin->getTypes(); + foreach ($types as $type) { + $plugins = $this->Plugin->getPlugins($type, null, ['0', '2']); + foreach ($plugins as $plugin) { + $this->Plugin->copyToWebroot($plugin); + } + } + return true; + } + } diff --git a/VERSION.txt b/VERSION.txt new file mode 100644 index 0000000..86fb650 --- /dev/null +++ b/VERSION.txt @@ -0,0 +1 @@ +3.3.7 diff --git a/View/Elements/PluginManager/title.ctp b/View/Elements/PluginManager/title.ctp index 1eb0e3f..b2dd950 100644 --- a/View/Elements/PluginManager/title.ctp +++ b/View/Elements/PluginManager/title.ctp @@ -12,10 +12,14 @@ start('subtitle'); ?>
- - - - () + + + + + ( ' . $nc3version; + ?>) +
end(); diff --git a/phpunit.xml.dist b/phpunit.xml.dist index 8f02b5d..8518a86 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -1,5 +1,8 @@ + + + app/Plugin/PluginManager @@ -15,6 +18,6 @@ - +