diff --git a/.gitattributes b/.gitattributes
new file mode 100644
index 0000000..8764193
--- /dev/null
+++ b/.gitattributes
@@ -0,0 +1,5 @@
+# Remove files for archives generated using `git archive`
+Test export-ignore
+.gitattributes export-ignore
+.travis.yml export-ignore
+phpunit.xml.dist export-ignore
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/Config/Migration/001_plugin_records.php b/Config/Migration/001_plugin_records.php
new file mode 100644
index 0000000..3bcad83
--- /dev/null
+++ b/Config/Migration/001_plugin_records.php
@@ -0,0 +1,139 @@
+
+ * @link http://www.netcommons.org NetCommons Project
+ * @license http://www.netcommons.org/license.txt NetCommons License
+ * @copyright Copyright 2014, NetCommons Project
+ */
+
+App::uses('NetCommonsMigration', 'NetCommons.Config/Migration');
+App::uses('Space', 'Rooms.Model');
+
+/**
+ * Add plugin migration
+ *
+ * @package NetCommons\PluginManager\Config\Migration
+ */
+class PluginRecords extends NetCommonsMigration {
+
+/**
+ * Migration description
+ *
+ * @var string
+ */
+ public $description = 'plugin_records';
+
+/**
+ * Actions to be performed
+ *
+ * @var array $migration
+ */
+ public $migration = array(
+ 'up' => array(),
+ 'down' => array(),
+ );
+
+/**
+ * plugin data
+ *
+ * @var array $migration
+ */
+ public $records = array(
+ 'Plugin' => array(
+ //日本語
+ array(
+ 'language_id' => '2',
+ 'is_origin' => true,
+ 'is_translation' => true,
+ 'key' => 'links',
+ 'namespace' => 'netcommons/links',
+ 'name' => 'リンクリスト',
+ 'type' => 1,
+ 'default_action' => 'links/index',
+ 'default_setting_action' => 'link_blocks/index',
+ 'display_topics' => 1,
+ 'display_search' => 1,
+ ),
+ //英語
+ array(
+ 'language_id' => '1',
+ 'is_origin' => false,
+ 'is_translation' => true,
+ 'key' => 'links',
+ 'namespace' => 'netcommons/links',
+ 'name' => 'Bookmark List',
+ 'type' => 1,
+ 'default_action' => 'links/index',
+ 'default_setting_action' => 'link_blocks/index',
+ 'display_topics' => 1,
+ 'display_search' => 1,
+ ),
+ ),
+ 'PluginsRole' => array(
+ array(
+ 'role_key' => 'room_administrator',
+ 'plugin_key' => 'links'
+ ),
+ ),
+ //PluginsRoomは、beforeでセットする
+ );
+
+/**
+ * Before migration callback
+ *
+ * @param string $direction Direction of migration process (up or down)
+ * @return bool Should process continue
+ */
+ public function before($direction) {
+ $pluginName = $this->records['Plugin'][0]['key'];
+ $this->records['PluginsRoom'] = array(
+ //サイト全体
+ array(
+ 'room_id' => Space::getRoomIdRoot(Space::WHOLE_SITE_ID, 'Room'),
+ 'plugin_key' => $pluginName
+ ),
+ //パブリックスペース
+ array(
+ 'room_id' => Space::getRoomIdRoot(Space::PUBLIC_SPACE_ID, 'Room'),
+ 'plugin_key' => $pluginName
+ ),
+ //プライベートスペース
+ array(
+ 'room_id' => Space::getRoomIdRoot(Space::PRIVATE_SPACE_ID, 'Room'),
+ 'plugin_key' => $pluginName
+ ),
+ //グループスペース
+ array(
+ 'room_id' => Space::getRoomIdRoot(Space::COMMUNITY_SPACE_ID, 'Room'),
+ 'plugin_key' => $pluginName
+ ),
+ );
+ return true;
+ }
+
+/**
+ * After migration callback
+ *
+ * @param string $direction Direction of migration process (up or down)
+ * @return bool Should process continue
+ */
+ public function after($direction) {
+ $this->loadModels([
+ 'Plugin' => 'PluginManager.Plugin',
+ ]);
+
+ if ($direction === 'down') {
+ $this->Plugin->uninstallPlugin($this->records['Plugin'][0]['key']);
+ return true;
+ }
+
+ foreach ($this->records as $model => $records) {
+ if (!$this->updateRecords($model, $records)) {
+ return false;
+ }
+ }
+ return true;
+ }
+}
diff --git a/Config/Migration/002_mail_setting_records.php b/Config/Migration/002_mail_setting_records.php
new file mode 100644
index 0000000..05f8544
--- /dev/null
+++ b/Config/Migration/002_mail_setting_records.php
@@ -0,0 +1,125 @@
+
+ * @link http://www.netcommons.org NetCommons Project
+ * @license http://www.netcommons.org/license.txt NetCommons License
+ * @copyright Copyright 2014, NetCommons Project
+ */
+
+App::uses('MailsMigration', 'Mails.Config/Migration');
+
+/**
+ * メール設定データのMigration
+ *
+ * @package NetCommons\Mails\Config\Migration
+ */
+class LinkMailSettingRecords extends MailsMigration {
+
+/**
+ * プラグインキー
+ *
+ * @var string
+ */
+ const PLUGIN_KEY = 'links';
+
+/**
+ * Migration description
+ *
+ * @var string
+ */
+ public $description = 'mail_setting_records';
+
+/**
+ * Actions to be performed
+ *
+ * @var array $migration
+ */
+ public $migration = array(
+ 'up' => array(),
+ 'down' => array(),
+ );
+
+/**
+ * plugin data
+ *
+ * @var array $migration
+ */
+ public $records = array(
+ 'MailSetting' => array(
+ //コンテンツ通知 - 設定
+ array(
+ 'plugin_key' => self::PLUGIN_KEY,
+ 'block_key' => null,
+ 'is_mail_send' => false,
+ 'is_mail_send_approval' => true,
+ ),
+ ),
+ 'MailSettingFixedPhrase' => array(
+ //コンテンツ通知 - 定型文
+ // * 英語
+ array(
+ 'language_id' => '1',
+ 'plugin_key' => self::PLUGIN_KEY,
+ 'block_key' => null,
+ 'type_key' => 'contents',
+ 'mail_fixed_phrase_subject' => '', //デフォルト(__d('mails', 'MailSetting.mail_fixed_phrase_subject'))
+ 'mail_fixed_phrase_body' => '{X-PLUGIN_NAME}にリンクが追加されたのでお知らせします。
+ルーム名: {X-ROOM}
+リンクリスト名: {X-BLOCK_NAME}
+リンク先: {X-LINK_URL}
+タイトル: {X-TITLE}
+カテゴリ: {X-CATEGORY_NAME}
+登録者: {X-USER}
+登録日時: {X-TO_DATE}
+説明:
+{X-DESCRIPTION}
+
+このリンクを確認するには、下記アドレスへ
+{X-URL}',
+ ),
+ // * 日本語
+ array(
+ 'language_id' => '2',
+ 'plugin_key' => self::PLUGIN_KEY,
+ 'block_key' => null,
+ 'type_key' => 'contents',
+ 'mail_fixed_phrase_subject' => '',
+ 'mail_fixed_phrase_body' => '{X-PLUGIN_NAME}にリンクが追加されたのでお知らせします。
+ルーム名: {X-ROOM}
+リンクリスト名: {X-BLOCK_NAME}
+リンク先: {X-LINK_URL}
+タイトル: {X-TITLE}
+カテゴリ: {X-CATEGORY_NAME}
+登録者: {X-USER}
+登録日時: {X-TO_DATE}
+説明:
+{X-DESCRIPTION}
+
+このリンクについて確認するには、下記アドレスへ
+{X-URL}',
+ ),
+ ),
+ );
+
+/**
+ * Before migration callback
+ *
+ * @param string $direction Direction of migration process (up or down)
+ * @return bool Should process continue
+ */
+ public function before($direction) {
+ return true;
+ }
+
+/**
+ * After migration callback
+ *
+ * @param string $direction Direction of migration process (up or down)
+ * @return bool Should process continue
+ */
+ public function after($direction) {
+ return parent::updateAndDelete($direction, self::PLUGIN_KEY);
+ }
+}
diff --git a/Config/Migration/1430464483_initial.php b/Config/Migration/1430464483_initial.php
new file mode 100644
index 0000000..92eb280
--- /dev/null
+++ b/Config/Migration/1430464483_initial.php
@@ -0,0 +1,130 @@
+
+ * @author Shohei Nakajima
+ * @link http://www.netcommons.org NetCommons Project
+ * @license http://www.netcommons.org/license.txt NetCommons License
+ * @copyright Copyright 2014, NetCommons Project
+ */
+
+/**
+ * Migration file
+ *
+ * @author Shohei Nakajima
+ * @package NetCommons\Faqs\Config\Migration
+ */
+class Initial extends CakeMigration {
+
+/**
+ * Migration description
+ *
+ * @var string
+ */
+ public $description = 'initial';
+
+/**
+ * Actions to be performed
+ *
+ * @var array $migration
+ */
+ public $migration = array(
+ 'up' => array(
+ 'create_table' => array(
+ 'link_frame_settings' => array(
+ 'id' => array('type' => 'integer', 'null' => false, 'default' => null, 'key' => 'primary', 'comment' => 'ID'),
+ 'frame_key' => array('type' => 'string', 'null' => false, 'default' => null, 'collate' => 'utf8_general_ci', 'comment' => 'フレームKey', 'charset' => 'utf8'),
+ 'display_type' => array('type' => 'integer', 'null' => false, 'default' => '1', 'length' => 4, 'comment' => '表示方法種別 1: ドロップダウン型、2:リスト型(説明なし)、3:リスト型(説明あり)'),
+ 'open_new_tab' => array('type' => 'boolean', 'null' => false, 'default' => '1', 'comment' => 'リンクの開き方 0:同じウィンドウ内、1:新しいタブ'),
+ 'display_click_count' => array('type' => 'boolean', 'null' => false, 'default' => '1', 'comment' => 'リンクのクリック数の表示 0:表示しない、1:表示する'),
+ 'category_separator_line' => array('type' => 'string', 'null' => true, 'default' => null, 'collate' => 'utf8_general_ci', 'comment' => 'カテゴリ間の区切り線', 'charset' => 'utf8'),
+ 'list_style' => array('type' => 'string', 'null' => true, 'default' => null, 'collate' => 'utf8_general_ci', 'comment' => 'リストマーク', 'charset' => 'utf8'),
+ 'created_user' => array('type' => 'integer', 'null' => true, 'default' => null, 'comment' => '作成者'),
+ 'created' => array('type' => 'datetime', 'null' => true, 'default' => null, 'comment' => '作成日時'),
+ 'modified_user' => array('type' => 'integer', 'null' => true, 'default' => null, 'comment' => '更新者'),
+ 'modified' => array('type' => 'datetime', 'null' => true, 'default' => null, 'comment' => '更新日時'),
+ 'indexes' => array(
+ 'PRIMARY' => array('column' => 'id', 'unique' => 1),
+ ),
+ 'tableParameters' => array('charset' => 'utf8', 'collate' => 'utf8_general_ci', 'engine' => 'InnoDB'),
+ ),
+ 'link_orders' => array(
+ 'id' => array('type' => 'integer', 'null' => false, 'default' => null, 'key' => 'primary', 'comment' => 'ID'),
+ 'block_key' => array('type' => 'string', 'null' => false, 'default' => null, 'collate' => 'utf8_general_ci', 'comment' => 'ブロックKey', 'charset' => 'utf8'),
+ 'category_key' => array('type' => 'string', 'null' => true, 'default' => null, 'collate' => 'utf8_general_ci', 'comment' => 'カテゴリKey', 'charset' => 'utf8'),
+ 'link_key' => array('type' => 'string', 'null' => false, 'default' => null, 'collate' => 'utf8_general_ci', 'comment' => 'リンクKey', 'charset' => 'utf8'),
+ 'weight' => array('type' => 'integer', 'null' => false, 'default' => '0', 'comment' => '表示の重み(表示順序)'),
+ 'created_user' => array('type' => 'integer', 'null' => true, 'default' => '0', 'comment' => '作成者'),
+ 'created' => array('type' => 'datetime', 'null' => true, 'default' => null, 'comment' => '作成日時'),
+ 'modified_user' => array('type' => 'integer', 'null' => true, 'default' => '0', 'comment' => '更新者'),
+ 'modified' => array('type' => 'datetime', 'null' => true, 'default' => null, 'comment' => '更新日時'),
+ 'indexes' => array(
+ 'PRIMARY' => array('column' => 'id', 'unique' => 1),
+ ),
+ 'tableParameters' => array('charset' => 'utf8', 'collate' => 'utf8_general_ci', 'engine' => 'InnoDB'),
+ ),
+ 'link_settings' => array(
+ 'id' => array('type' => 'integer', 'null' => false, 'default' => null, 'key' => 'primary', 'comment' => 'ID'),
+ 'block_key' => array('type' => 'string', 'null' => false, 'default' => null, 'collate' => 'utf8_general_ci', 'comment' => 'Block key | ブロックキー | Hash値 | ', 'charset' => 'utf8'),
+ 'use_workflow' => array('type' => 'boolean', 'null' => false, 'default' => '1', 'comment' => 'Use workflow, 0:Unused 1:Use | コンテンツの承認機能 0:使わない 1:使う | | '),
+ 'created_user' => array('type' => 'integer', 'null' => true, 'default' => '0', 'comment' => '作成者'),
+ 'created' => array('type' => 'datetime', 'null' => true, 'default' => null, 'comment' => '作成日時'),
+ 'modified_user' => array('type' => 'integer', 'null' => true, 'default' => '0', 'comment' => '更新者'),
+ 'modified' => array('type' => 'datetime', 'null' => true, 'default' => null, 'comment' => '更新日時'),
+ 'indexes' => array(
+ 'PRIMARY' => array('column' => 'id', 'unique' => 1),
+ ),
+ 'tableParameters' => array('charset' => 'utf8', 'collate' => 'utf8_general_ci', 'engine' => 'InnoDB'),
+ ),
+ 'links' => array(
+ 'id' => array('type' => 'integer', 'null' => false, 'default' => null, 'key' => 'primary', 'comment' => 'ID'),
+ 'block_id' => array('type' => 'integer', 'null' => false, 'default' => null, 'comment' => 'ブロックID'),
+ 'category_id' => array('type' => 'integer', 'null' => true, 'default' => null, 'comment' => 'カテゴリーID'),
+ 'language_id' => array('type' => 'integer', 'null' => false, 'default' => '0', 'length' => 6, 'comment' => '言語ID'),
+ 'key' => array('type' => 'string', 'null' => false, 'default' => null, 'collate' => 'utf8_general_ci', 'comment' => 'リンクキー', 'charset' => 'utf8'),
+ 'status' => array('type' => 'integer', 'null' => false, 'default' => null, 'length' => 4, 'comment' => '公開状況 1:公開中、2:公開申請中、3:下書き中、4:差し戻し'),
+ 'is_active' => array('type' => 'boolean', 'null' => false, 'default' => '0', 'comment' => 'アクティブなコンテンツかどうか 0:アクティブでない 1:アクティブ'),
+ 'is_latest' => array('type' => 'boolean', 'null' => false, 'default' => '0', 'comment' => '最新コンテンツかどうか 0:最新でない 1:最新'),
+ 'url' => array('type' => 'text', 'null' => true, 'default' => null, 'collate' => 'utf8_general_ci', 'comment' => 'リンク先URL', 'charset' => 'utf8'),
+ 'title' => array('type' => 'string', 'null' => true, 'default' => null, 'collate' => 'utf8_general_ci', 'comment' => 'タイトル', 'charset' => 'utf8'),
+ 'description' => array('type' => 'text', 'null' => true, 'default' => null, 'collate' => 'utf8_general_ci', 'comment' => '説明', 'charset' => 'utf8'),
+ 'click_count' => array('type' => 'integer', 'null' => false, 'default' => '0', 'comment' => 'クリック数'),
+ 'created_user' => array('type' => 'integer', 'null' => true, 'default' => null, 'comment' => '作成者'),
+ 'created' => array('type' => 'datetime', 'null' => true, 'default' => null, 'comment' => '作成日時'),
+ 'modified_user' => array('type' => 'integer', 'null' => true, 'default' => null, 'comment' => '更新者'),
+ 'modified' => array('type' => 'datetime', 'null' => true, 'default' => null, 'comment' => '更新日時'),
+ 'indexes' => array(
+ 'PRIMARY' => array('column' => 'id', 'unique' => 1),
+ ),
+ 'tableParameters' => array('charset' => 'utf8', 'collate' => 'utf8_general_ci', 'engine' => 'InnoDB'),
+ ),
+ ),
+ ),
+ 'down' => array(
+ 'drop_table' => array(
+ 'link_frame_settings', 'link_orders', 'link_settings', 'links'
+ ),
+ ),
+ );
+
+/**
+ * Before migration callback
+ *
+ * @param string $direction Direction of migration process (up or down)
+ * @return bool Should process continue
+ */
+ public function before($direction) {
+ return true;
+ }
+
+/**
+ * After migration callback
+ *
+ * @param string $direction Direction of migration process (up or down)
+ * @return bool Should process continue
+ */
+ public function after($direction) {
+ return true;
+ }
+}
diff --git a/Config/Migration/1468972227_delete_link_settings.php b/Config/Migration/1468972227_delete_link_settings.php
new file mode 100644
index 0000000..f05ca77
--- /dev/null
+++ b/Config/Migration/1468972227_delete_link_settings.php
@@ -0,0 +1,76 @@
+
+ * @author Mitsuru Mutaguchi
+ * @link http://www.netcommons.org NetCommons Project
+ * @license http://www.netcommons.org/license.txt NetCommons License
+ * @copyright Copyright 2014, NetCommons Project
+ */
+
+/**
+ * Migration file
+ *
+ * @author Mitsuru Mutaguchi
+ * @package NetCommons\Links\Config\Migration
+ */
+class DeleteLinkSettings extends CakeMigration {
+
+/**
+ * Migration description
+ *
+ * @var string
+ */
+ public $description = 'delete_link_settings';
+
+/**
+ * Actions to be performed
+ *
+ * @var array $migration
+ */
+ public $migration = array(
+ 'up' => array(
+ 'drop_table' => array(
+ 'link_settings'
+ ),
+ ),
+ 'down' => array(
+ 'create_table' => array(
+ 'link_settings' => array(
+ 'id' => array('type' => 'integer', 'null' => false, 'default' => null, 'key' => 'primary', 'comment' => 'ID'),
+ 'block_key' => array('type' => 'string', 'null' => false, 'default' => null, 'collate' => 'utf8_general_ci', 'comment' => 'Block key | ブロックキー | Hash値 | ', 'charset' => 'utf8'),
+ 'use_workflow' => array('type' => 'boolean', 'null' => false, 'default' => '1', 'comment' => 'Use workflow, 0:Unused 1:Use | コンテンツの承認機能 0:使わない 1:使う | | '),
+ 'created_user' => array('type' => 'integer', 'null' => true, 'default' => '0', 'comment' => '作成者'),
+ 'created' => array('type' => 'datetime', 'null' => true, 'default' => null, 'comment' => '作成日時'),
+ 'modified_user' => array('type' => 'integer', 'null' => true, 'default' => '0', 'comment' => '更新者'),
+ 'modified' => array('type' => 'datetime', 'null' => true, 'default' => null, 'comment' => '更新日時'),
+ 'indexes' => array(
+ 'PRIMARY' => array('column' => 'id', 'unique' => 1),
+ ),
+ 'tableParameters' => array('charset' => 'utf8', 'collate' => 'utf8_general_ci', 'engine' => 'InnoDB'),
+ ),
+ ),
+ ),
+ );
+
+/**
+ * Before migration callback
+ *
+ * @param string $direction Direction of migration process (up or down)
+ * @return bool Should process continue
+ */
+ public function before($direction) {
+ return true;
+ }
+
+/**
+ * After migration callback
+ *
+ * @param string $direction Direction of migration process (up or down)
+ * @return bool Should process continue
+ */
+ public function after($direction) {
+ return true;
+ }
+}
diff --git a/Config/Migration/1469438065_add_index.php b/Config/Migration/1469438065_add_index.php
new file mode 100644
index 0000000..3d3b890
--- /dev/null
+++ b/Config/Migration/1469438065_add_index.php
@@ -0,0 +1,132 @@
+
+ * @author Mitsuru Mutaguchi
+ * @link http://www.netcommons.org NetCommons Project
+ * @license http://www.netcommons.org/license.txt NetCommons License
+ * @copyright Copyright 2014, NetCommons Project
+ */
+
+/**
+ * Migration file
+ *
+ * @author Mitsuru Mutaguchi
+ * @package NetCommons\Links\Config\Migration
+ */
+class AddIndex extends CakeMigration {
+
+/**
+ * Migration description
+ *
+ * @var string
+ */
+ public $description = 'add_index';
+
+/**
+ * Actions to be performed
+ *
+ * @var array $migration
+ */
+ public $migration = array(
+ 'up' => array(
+ 'alter_field' => array(
+ 'link_frame_settings' => array(
+ 'id' => array('type' => 'integer', 'null' => false, 'default' => null, 'unsigned' => false, 'key' => 'primary', 'comment' => 'ID'),
+ 'frame_key' => array('type' => 'string', 'null' => false, 'default' => null, 'key' => 'index', 'collate' => 'utf8_general_ci', 'comment' => 'フレームKey', 'charset' => 'utf8'),
+ 'display_type' => array('type' => 'integer', 'null' => false, 'default' => '1', 'length' => 4, 'unsigned' => false, 'comment' => '表示方法種別 1: ドロップダウン型、2:リスト型(説明なし)、3:リスト型(説明あり)'),
+ 'created_user' => array('type' => 'integer', 'null' => true, 'default' => null, 'unsigned' => false, 'comment' => '作成者'),
+ 'modified_user' => array('type' => 'integer', 'null' => true, 'default' => null, 'unsigned' => false, 'comment' => '更新者'),
+ ),
+ 'link_orders' => array(
+ 'id' => array('type' => 'integer', 'null' => false, 'default' => null, 'unsigned' => false, 'key' => 'primary', 'comment' => 'ID'),
+ 'link_key' => array('type' => 'string', 'null' => false, 'default' => null, 'key' => 'index', 'collate' => 'utf8_general_ci', 'comment' => 'リンクKey', 'charset' => 'utf8'),
+ 'weight' => array('type' => 'integer', 'null' => false, 'default' => '0', 'unsigned' => false, 'comment' => '表示の重み(表示順序)'),
+ 'created_user' => array('type' => 'integer', 'null' => true, 'default' => '0', 'unsigned' => false, 'comment' => '作成者'),
+ 'modified_user' => array('type' => 'integer', 'null' => true, 'default' => '0', 'unsigned' => false, 'comment' => '更新者'),
+ ),
+ 'links' => array(
+ 'id' => array('type' => 'integer', 'null' => false, 'default' => null, 'unsigned' => false, 'key' => 'primary', 'comment' => 'ID'),
+ 'block_id' => array('type' => 'integer', 'null' => false, 'default' => null, 'unsigned' => false, 'key' => 'index', 'comment' => 'ブロックID'),
+ 'category_id' => array('type' => 'integer', 'null' => true, 'default' => null, 'unsigned' => false, 'comment' => 'カテゴリーID'),
+ 'language_id' => array('type' => 'integer', 'null' => false, 'default' => '0', 'length' => 6, 'unsigned' => false, 'comment' => '言語ID'),
+ 'status' => array('type' => 'integer', 'null' => false, 'default' => null, 'length' => 4, 'unsigned' => false, 'comment' => '公開状況 1:公開中、2:公開申請中、3:下書き中、4:差し戻し'),
+ 'click_count' => array('type' => 'integer', 'null' => false, 'default' => '0', 'unsigned' => false, 'comment' => 'クリック数'),
+ 'created_user' => array('type' => 'integer', 'null' => true, 'default' => null, 'unsigned' => false, 'comment' => '作成者'),
+ 'modified_user' => array('type' => 'integer', 'null' => true, 'default' => null, 'unsigned' => false, 'comment' => '更新者'),
+ ),
+ ),
+ 'create_field' => array(
+ 'link_frame_settings' => array(
+ 'indexes' => array(
+ 'frame_key' => array('column' => 'frame_key', 'unique' => 0),
+ ),
+ ),
+ 'link_orders' => array(
+ 'indexes' => array(
+ 'link_key' => array('column' => 'link_key', 'unique' => 0),
+ ),
+ ),
+ 'links' => array(
+ 'indexes' => array(
+ 'block_id' => array('column' => array('block_id', 'language_id'), 'unique' => 0),
+ ),
+ ),
+ ),
+ ),
+ 'down' => array(
+ 'alter_field' => array(
+ 'link_frame_settings' => array(
+ 'id' => array('type' => 'integer', 'null' => false, 'default' => null, 'key' => 'primary', 'comment' => 'ID'),
+ 'frame_key' => array('type' => 'string', 'null' => false, 'default' => null, 'collate' => 'utf8_general_ci', 'comment' => 'フレームKey', 'charset' => 'utf8'),
+ 'display_type' => array('type' => 'integer', 'null' => false, 'default' => '0', 'length' => 4, 'comment' => '表示方法種別 1: ドロップダウン型、2:リスト型(説明なし)、3:リスト型(説明あり)'),
+ 'created_user' => array('type' => 'integer', 'null' => true, 'default' => null, 'comment' => '作成者'),
+ 'modified_user' => array('type' => 'integer', 'null' => true, 'default' => null, 'comment' => '更新者'),
+ ),
+ 'link_orders' => array(
+ 'id' => array('type' => 'integer', 'null' => false, 'default' => null, 'key' => 'primary', 'comment' => 'ID'),
+ 'link_key' => array('type' => 'string', 'null' => false, 'default' => null, 'collate' => 'utf8_general_ci', 'comment' => 'リンクKey', 'charset' => 'utf8'),
+ 'weight' => array('type' => 'integer', 'null' => false, 'default' => '0', 'comment' => '表示の重み(表示順序)'),
+ 'created_user' => array('type' => 'integer', 'null' => true, 'default' => '0', 'comment' => '作成者'),
+ 'modified_user' => array('type' => 'integer', 'null' => true, 'default' => '0', 'comment' => '更新者'),
+ ),
+ 'links' => array(
+ 'id' => array('type' => 'integer', 'null' => false, 'default' => null, 'key' => 'primary', 'comment' => 'ID'),
+ 'block_id' => array('type' => 'integer', 'null' => false, 'default' => null, 'comment' => 'ブロックID'),
+ 'category_id' => array('type' => 'integer', 'null' => true, 'default' => null, 'comment' => 'カテゴリーID'),
+ 'language_id' => array('type' => 'integer', 'null' => false, 'default' => '0', 'length' => 6, 'comment' => '言語ID'),
+ 'status' => array('type' => 'integer', 'null' => false, 'default' => null, 'length' => 4, 'comment' => '公開状況 1:公開中、2:公開申請中、3:下書き中、4:差し戻し'),
+ 'click_count' => array('type' => 'integer', 'null' => false, 'default' => '0', 'comment' => 'クリック数'),
+ 'created_user' => array('type' => 'integer', 'null' => true, 'default' => null, 'comment' => '作成者'),
+ 'modified_user' => array('type' => 'integer', 'null' => true, 'default' => null, 'comment' => '更新者'),
+ ),
+ ),
+ 'drop_field' => array(
+ 'link_frame_settings' => array('indexes' => array('frame_key')),
+ 'link_orders' => array('indexes' => array('link_key')),
+ 'links' => array('indexes' => array('block_id')),
+ ),
+ ),
+ );
+
+/**
+ * Before migration callback
+ *
+ * @param string $direction Direction of migration process (up or down)
+ * @return bool Should process continue
+ */
+ public function before($direction) {
+ return true;
+ }
+
+/**
+ * After migration callback
+ *
+ * @param string $direction Direction of migration process (up or down)
+ * @return bool Should process continue
+ */
+ public function after($direction) {
+ return true;
+ }
+}
diff --git a/Config/Migration/1481097090_add_fields_for_m17n.php b/Config/Migration/1481097090_add_fields_for_m17n.php
new file mode 100644
index 0000000..129675c
--- /dev/null
+++ b/Config/Migration/1481097090_add_fields_for_m17n.php
@@ -0,0 +1,68 @@
+
+ * @link http://www.netcommons.org NetCommons Project
+ * @license http://www.netcommons.org/license.txt NetCommons License
+ * @copyright Copyright 2014, NetCommons Project
+ */
+
+App::uses('NetCommonsMigration', 'NetCommons.Config/Migration');
+
+/**
+ * 多言語化対応
+ *
+ * @author Shohei Nakajima
+ * @package NetCommons\Links\Config\Migration
+ */
+class AddFieldsForM17n extends NetCommonsMigration {
+
+/**
+ * Migration description
+ *
+ * @var string
+ */
+ public $description = 'add_fields_for_m17n';
+
+/**
+ * Actions to be performed
+ *
+ * @var array $migration
+ */
+ public $migration = array(
+ 'up' => array(
+ 'create_field' => array(
+ 'links' => array(
+ 'is_origin' => array('type' => 'boolean', 'null' => false, 'default' => '1', 'comment' => 'オリジナルかどうか', 'after' => 'language_id'),
+ 'is_translation' => array('type' => 'boolean', 'null' => false, 'default' => '0', 'comment' => '翻訳したかどうか', 'after' => 'is_origin'),
+ ),
+ ),
+ ),
+ 'down' => array(
+ 'drop_field' => array(
+ 'links' => array('is_origin', 'is_translation'),
+ ),
+ ),
+ );
+
+/**
+ * Before migration callback
+ *
+ * @param string $direction Direction of migration process (up or down)
+ * @return bool Should process continue
+ */
+ public function before($direction) {
+ return true;
+ }
+
+/**
+ * After migration callback
+ *
+ * @param string $direction Direction of migration process (up or down)
+ * @return bool Should process continue
+ */
+ public function after($direction) {
+ return true;
+ }
+}
diff --git a/Config/Migration/1484545481_add_is_original_copy.php b/Config/Migration/1484545481_add_is_original_copy.php
new file mode 100644
index 0000000..1cfd16d
--- /dev/null
+++ b/Config/Migration/1484545481_add_is_original_copy.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('NetCommonsMigration', 'NetCommons.Config/Migration');
+
+/**
+ * 多言語化対応
+ *
+ * @author Shohei Nakajima
+ * @package NetCommons\Links\Config\Migration
+ */
+class AddIsOriginalCopy extends NetCommonsMigration {
+
+/**
+ * Migration description
+ *
+ * @var string
+ */
+ public $description = 'add_is_original_copy';
+
+/**
+ * Actions to be performed
+ *
+ * @var array $migration
+ */
+ public $migration = array(
+ 'up' => array(
+ 'create_field' => array(
+ 'links' => array(
+ 'is_original_copy' => array('type' => 'boolean', 'null' => false, 'default' => '0', 'comment' => 'オリジナルのコピー。言語を新たに追加したときに使用する', 'after' => 'is_translation'),
+ ),
+ ),
+ ),
+ 'down' => array(
+ 'drop_field' => array(
+ 'links' => array('is_original_copy'),
+ ),
+ ),
+ );
+
+/**
+ * Before migration callback
+ *
+ * @param string $direction Direction of migration process (up or down)
+ * @return bool Should process continue
+ */
+ public function before($direction) {
+ return true;
+ }
+
+/**
+ * After migration callback
+ *
+ * @param string $direction Direction of migration process (up or down)
+ * @return bool Should process continue
+ */
+ public function after($direction) {
+ return true;
+ }
+}
diff --git a/Config/Schema/empty b/Config/Schema/empty
deleted file mode 100644
index e69de29..0000000
diff --git a/Config/Schema/schema.php b/Config/Schema/schema.php
new file mode 100644
index 0000000..ae2cd06
--- /dev/null
+++ b/Config/Schema/schema.php
@@ -0,0 +1,126 @@
+
+ * @author Shohei Nakajima
+ * @link http://www.netcommons.org NetCommons Project
+ * @license http://www.netcommons.org/license.txt NetCommons License
+ * @copyright Copyright 2014, NetCommons Project
+ */
+
+/**
+ * Schema file
+ *
+ * @author Noriko Arai
+ * @author Shohei Nakajima
+ * @package NetCommons\Likes\Config\Schema
+ * @SuppressWarnings(PHPMD.LongVariable)
+ */
+class LinksSchema extends CakeSchema {
+
+/**
+ * Database connection
+ *
+ * @var string
+ */
+ public $connection = 'master';
+
+/**
+ * before
+ *
+ * @param array $event event
+ * @return bool
+ */
+ public function before($event = array()) {
+ return true;
+ }
+
+/**
+ * after
+ *
+ * @param array $event event
+ * @return void
+ */
+ public function after($event = array()) {
+ }
+
+/**
+ * link_frame_settings table
+ *
+ * @var array
+ */
+ public $link_frame_settings = array(
+ 'id' => array('type' => 'integer', 'null' => false, 'default' => null, 'unsigned' => false, 'key' => 'primary', 'comment' => 'ID'),
+ 'frame_key' => array('type' => 'string', 'null' => false, 'default' => null, 'key' => 'index', 'collate' => 'utf8_general_ci', 'comment' => 'フレームKey', 'charset' => 'utf8'),
+ 'display_type' => array('type' => 'integer', 'null' => false, 'default' => '1', 'length' => 4, 'unsigned' => false, 'comment' => '表示方法種別 1: ドロップダウン型、2:リスト型(説明なし)、3:リスト型(説明あり)'),
+ 'open_new_tab' => array('type' => 'boolean', 'null' => false, 'default' => '1', 'comment' => 'リンクの開き方 0:同じウィンドウ内、1:新しいタブ'),
+ 'display_click_count' => array('type' => 'boolean', 'null' => false, 'default' => '1', 'comment' => 'リンクのクリック数の表示 0:表示しない、1:表示する'),
+ 'category_separator_line' => array('type' => 'string', 'null' => true, 'default' => null, 'collate' => 'utf8_general_ci', 'comment' => 'カテゴリ間の区切り線', 'charset' => 'utf8'),
+ 'list_style' => array('type' => 'string', 'null' => true, 'default' => null, 'collate' => 'utf8_general_ci', 'comment' => 'リストマーク', 'charset' => 'utf8'),
+ 'created_user' => array('type' => 'integer', 'null' => true, 'default' => null, 'unsigned' => false, 'comment' => '作成者'),
+ 'created' => array('type' => 'datetime', 'null' => true, 'default' => null, 'comment' => '作成日時'),
+ 'modified_user' => array('type' => 'integer', 'null' => true, 'default' => null, 'unsigned' => false, 'comment' => '更新者'),
+ 'modified' => array('type' => 'datetime', 'null' => true, 'default' => null, 'comment' => '更新日時'),
+ 'indexes' => array(
+ 'PRIMARY' => array('column' => 'id', 'unique' => 1),
+ 'frame_key' => array('column' => 'frame_key', 'unique' => 0)
+ ),
+ 'tableParameters' => array('charset' => 'utf8', 'collate' => 'utf8_general_ci', 'engine' => 'InnoDB')
+ );
+
+/**
+ * link_orders table
+ *
+ * @var array
+ */
+ public $link_orders = array(
+ 'id' => array('type' => 'integer', 'null' => false, 'default' => null, 'unsigned' => false, 'key' => 'primary', 'comment' => 'ID'),
+ 'block_key' => array('type' => 'string', 'null' => false, 'default' => null, 'collate' => 'utf8_general_ci', 'comment' => 'ブロックKey', 'charset' => 'utf8'),
+ 'category_key' => array('type' => 'string', 'null' => true, 'default' => null, 'collate' => 'utf8_general_ci', 'comment' => 'カテゴリKey', 'charset' => 'utf8'),
+ 'link_key' => array('type' => 'string', 'null' => false, 'default' => null, 'key' => 'index', 'collate' => 'utf8_general_ci', 'comment' => 'リンクKey', 'charset' => 'utf8'),
+ 'weight' => array('type' => 'integer', 'null' => false, 'default' => '0', 'unsigned' => false, 'comment' => '表示の重み(表示順序)'),
+ 'created_user' => array('type' => 'integer', 'null' => true, 'default' => '0', 'unsigned' => false, 'comment' => '作成者'),
+ 'created' => array('type' => 'datetime', 'null' => true, 'default' => null, 'comment' => '作成日時'),
+ 'modified_user' => array('type' => 'integer', 'null' => true, 'default' => '0', 'unsigned' => false, 'comment' => '更新者'),
+ 'modified' => array('type' => 'datetime', 'null' => true, 'default' => null, 'comment' => '更新日時'),
+ 'indexes' => array(
+ 'PRIMARY' => array('column' => 'id', 'unique' => 1),
+ 'link_key' => array('column' => 'link_key', 'unique' => 0)
+ ),
+ 'tableParameters' => array('charset' => 'utf8', 'collate' => 'utf8_general_ci', 'engine' => 'InnoDB')
+ );
+
+/**
+ * links table
+ *
+ * @var array
+ */
+ public $links = array(
+ 'id' => array('type' => 'integer', 'null' => false, 'default' => null, 'unsigned' => false, 'key' => 'primary', 'comment' => 'ID'),
+ 'block_id' => array('type' => 'integer', 'null' => false, 'default' => null, 'unsigned' => false, 'key' => 'index', 'comment' => 'ブロックID'),
+ 'category_id' => array('type' => 'integer', 'null' => true, 'default' => null, 'unsigned' => false, 'comment' => 'カテゴリーID'),
+ 'language_id' => array('type' => 'integer', 'null' => false, 'default' => '0', 'length' => 6, 'unsigned' => false, 'comment' => '言語ID'),
+ 'is_origin' => array('type' => 'boolean', 'null' => false, 'default' => '1', 'comment' => 'オリジナルかどうか'),
+ 'is_translation' => array('type' => 'boolean', 'null' => false, 'default' => '0', 'comment' => '翻訳したかどうか'),
+ 'is_original_copy' => array('type' => 'boolean', 'null' => false, 'default' => '0', 'comment' => 'オリジナルのコピー。言語を新たに追加したときに使用する'),
+ 'key' => array('type' => 'string', 'null' => false, 'default' => null, 'collate' => 'utf8_general_ci', 'comment' => 'リンクキー', 'charset' => 'utf8'),
+ 'status' => array('type' => 'integer', 'null' => false, 'default' => null, 'length' => 4, 'unsigned' => false, 'comment' => '公開状況 1:公開中、2:公開申請中、3:下書き中、4:差し戻し'),
+ 'is_active' => array('type' => 'boolean', 'null' => false, 'default' => '0', 'comment' => 'アクティブなコンテンツかどうか 0:アクティブでない 1:アクティブ'),
+ 'is_latest' => array('type' => 'boolean', 'null' => false, 'default' => '0', 'comment' => '最新コンテンツかどうか 0:最新でない 1:最新'),
+ 'url' => array('type' => 'text', 'null' => true, 'default' => null, 'collate' => 'utf8_general_ci', 'comment' => 'リンク先URL', 'charset' => 'utf8'),
+ 'title' => array('type' => 'string', 'null' => true, 'default' => null, 'collate' => 'utf8_general_ci', 'comment' => 'タイトル', 'charset' => 'utf8'),
+ 'description' => array('type' => 'text', 'null' => true, 'default' => null, 'collate' => 'utf8_general_ci', 'comment' => '説明', 'charset' => 'utf8'),
+ 'click_count' => array('type' => 'integer', 'null' => false, 'default' => '0', 'unsigned' => false, 'comment' => 'クリック数'),
+ 'created_user' => array('type' => 'integer', 'null' => true, 'default' => null, 'unsigned' => false, 'comment' => '作成者'),
+ 'created' => array('type' => 'datetime', 'null' => true, 'default' => null, 'comment' => '作成日時'),
+ 'modified_user' => array('type' => 'integer', 'null' => true, 'default' => null, 'unsigned' => false, 'comment' => '更新者'),
+ 'modified' => array('type' => 'datetime', 'null' => true, 'default' => null, 'comment' => '更新日時'),
+ 'indexes' => array(
+ 'PRIMARY' => array('column' => 'id', 'unique' => 1),
+ 'block_id' => array('column' => array('block_id', 'language_id'), 'unique' => 0)
+ ),
+ 'tableParameters' => array('charset' => 'utf8', 'collate' => 'utf8_general_ci', 'engine' => 'InnoDB')
+ );
+
+}
diff --git a/Console/Command/Task/empty b/Console/Command/Task/empty
deleted file mode 100644
index e69de29..0000000
diff --git a/Controller/Component/empty b/Controller/Component/empty
deleted file mode 100644
index e69de29..0000000
diff --git a/Controller/LinkBlockRolePermissionsController.php b/Controller/LinkBlockRolePermissionsController.php
new file mode 100644
index 0000000..701b428
--- /dev/null
+++ b/Controller/LinkBlockRolePermissionsController.php
@@ -0,0 +1,98 @@
+
+ * @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('LinksAppController', 'Links.Controller');
+
+/**
+ * BlockRolePermissions Controller
+ *
+ * @author Shohei Nakajima
+ * @package NetCommons\Links\Controller
+ */
+class LinkBlockRolePermissionsController extends LinksAppController {
+
+/**
+ * layout
+ *
+ * @var array
+ */
+ public $layout = 'NetCommons.setting';
+
+/**
+ * use models
+ *
+ * @var array
+ */
+ public $uses = array(
+ 'Links.LinkBlock',
+ 'Links.LinkSetting',
+ );
+
+/**
+ * use components
+ *
+ * @var array
+ */
+ public $components = array(
+ 'NetCommons.Permission' => array(
+ 'allow' => array(
+ 'edit' => 'block_permission_editable',
+ ),
+ ),
+ );
+
+/**
+ * use helpers
+ *
+ * @var array
+ */
+ public $helpers = array(
+ 'Blocks.BlockRolePermissionForm',
+ 'Blocks.BlockTabs' => array(
+ 'mainTabs' => array('block_index', 'frame_settings'),
+ 'blockTabs' => array('block_settings', 'mail_settings', 'role_permissions'),
+ ),
+ );
+
+/**
+ * edit
+ *
+ * @return void
+ */
+ public function edit() {
+ if (! $linkBlock = $this->LinkBlock->getLinkBlock()) {
+ return $this->throwBadRequest();
+ }
+
+ $permissions = $this->Workflow->getBlockRolePermissions(
+ array('content_creatable', 'content_publishable')
+ );
+ $this->set('roles', $permissions['Roles']);
+
+ if ($this->request->is('post')) {
+ if ($this->LinkSetting->saveLinkSetting($this->request->data)) {
+ $this->redirect(NetCommonsUrl::backToIndexUrl('default_setting_action'));
+ return;
+ }
+ $this->NetCommons->handleValidationError($this->LinkSetting->validationErrors);
+ $this->request->data['BlockRolePermission'] = Hash::merge(
+ $permissions['BlockRolePermissions'],
+ $this->request->data['BlockRolePermission']
+ );
+
+ } else {
+ $this->request->data['LinkSetting'] = $linkBlock['LinkSetting'];
+ $this->request->data['Block'] = $linkBlock['Block'];
+ $this->request->data['BlockRolePermission'] = $permissions['BlockRolePermissions'];
+ $this->request->data['Frame'] = Current::read('Frame');
+ }
+ }
+}
diff --git a/Controller/LinkBlocksController.php b/Controller/LinkBlocksController.php
new file mode 100644
index 0000000..448074f
--- /dev/null
+++ b/Controller/LinkBlocksController.php
@@ -0,0 +1,163 @@
+
+ * @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('LinksAppController', 'Links.Controller');
+
+/**
+ * BlocksController
+ *
+ * @author Shohei Nakajima
+ * @package NetCommons\Links\Controller
+ */
+class LinkBlocksController extends LinksAppController {
+
+/**
+ * layout
+ *
+ * @var array
+ */
+ public $layout = 'NetCommons.setting';
+
+/**
+ * use models
+ *
+ * @var array
+ */
+ public $uses = array(
+ 'Links.LinkBlock',
+ );
+
+/**
+ * use components
+ *
+ * @var array
+ */
+ public $components = array(
+ 'Categories.CategoryEdit',
+ 'NetCommons.Permission' => array(
+ 'allow' => array(
+ 'index,add,edit,delete' => 'block_editable',
+ ),
+ ),
+ 'Paginator',
+ 'Categories.Categories',
+ );
+
+/**
+ * use helpers
+ *
+ * @var array
+ */
+ public $helpers = array(
+ 'Blocks.BlockForm',
+ 'Blocks.BlockIndex',
+ 'Blocks.BlockTabs' => array(
+ 'mainTabs' => array('block_index', 'frame_settings'),
+ 'blockTabs' => array('block_settings', 'mail_settings', 'role_permissions'),
+ ),
+ );
+
+/**
+ * beforeFilter
+ *
+ * @return void
+ */
+ public function beforeFilter() {
+ parent::beforeFilter();
+ $this->Auth->deny('index');
+
+ //CategoryEditComponentの削除
+ if ($this->params['action'] === 'index') {
+ $this->Components->unload('Categories.CategoryEdit');
+ }
+ }
+
+/**
+ * index
+ *
+ * @return void
+ */
+ public function index() {
+ $this->Paginator->settings = array(
+ 'LinkBlock' => $this->LinkBlock->getBlockIndexSettings()
+ );
+
+ $linkBlocks = $this->Paginator->paginate('LinkBlock');
+ if (! $linkBlocks) {
+ $this->view = 'Blocks.Blocks/not_found';
+ return;
+ }
+ $this->set('linkBlocks', $linkBlocks);
+ $this->request->data['Frame'] = Current::read('Frame');
+ }
+
+/**
+ * add
+ *
+ * @return void
+ */
+ public function add() {
+ $this->view = 'edit';
+
+ if ($this->request->is('post')) {
+ //登録処理
+ if ($this->LinkBlock->saveLinkBlock($this->data)) {
+ return $this->redirect(NetCommonsUrl::backToIndexUrl('default_setting_action'));
+ }
+ $this->NetCommons->handleValidationError($this->LinkBlock->validationErrors);
+
+ } else {
+ //表示処理(初期データセット)
+ $this->request->data = $this->LinkBlock->createLinkBlock();
+ $this->request->data['Frame'] = Current::read('Frame');
+ }
+ }
+
+/**
+ * edit
+ *
+ * @return void
+ */
+ public function edit() {
+ if ($this->request->is('put')) {
+ //登録処理
+ if ($this->LinkBlock->saveLinkBlock($this->data)) {
+ return $this->redirect(NetCommonsUrl::backToIndexUrl('default_setting_action'));
+ }
+ $this->NetCommons->handleValidationError($this->LinkBlock->validationErrors);
+
+ } else {
+ //表示処理(初期データセット)
+ $linkBlock = $this->LinkBlock->getLinkBlock();
+ if (! $linkBlock) {
+ return $this->throwBadRequest();
+ }
+ $this->request->data += $linkBlock;
+ $this->request->data['Frame'] = Current::read('Frame');
+ }
+ }
+
+/**
+ * delete
+ *
+ * @return void
+ */
+ public function delete() {
+ if (! $this->request->is('delete')) {
+ return $this->throwBadRequest();
+ }
+ if (! $this->LinkBlock->deleteLinkBlock($this->data)) {
+ return $this->throwBadRequest();
+ }
+
+ $this->redirect(NetCommonsUrl::backToIndexUrl('default_setting_action'));
+ }
+}
diff --git a/Controller/LinkFrameSettingsController.php b/Controller/LinkFrameSettingsController.php
new file mode 100644
index 0000000..9b216de
--- /dev/null
+++ b/Controller/LinkFrameSettingsController.php
@@ -0,0 +1,95 @@
+
+ * @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('LinksAppController', 'Links.Controller');
+
+/**
+ * LinkFrameSettingsController Controller
+ *
+ * @author Shohei Nakajima
+ * @package NetCommons\Links\Controller
+ */
+class LinkFrameSettingsController extends LinksAppController {
+
+/**
+ * layout
+ *
+ * @var array
+ */
+ public $layout = 'NetCommons.setting';
+
+/**
+ * use models
+ *
+ * @var array
+ */
+ public $uses = array(
+ 'Links.LinkFrameSetting'
+ );
+
+/**
+ * use components
+ *
+ * @var array
+ */
+ public $components = array(
+ 'NetCommons.Permission' => array(
+ 'allow' => array(
+ 'edit' => 'page_editable',
+ ),
+ ),
+ );
+
+/**
+ * use helpers
+ *
+ * @var array
+ */
+ public $helpers = array(
+ 'Blocks.BlockForm',
+ 'Blocks.BlockTabs' => array(
+ 'mainTabs' => array('block_index', 'frame_settings'),
+ 'blockTabs' => array('block_settings', 'role_permissions'),
+ ),
+ );
+
+/**
+ * edit
+ *
+ * @return void
+ */
+ public function edit() {
+ if ($this->request->is('put') || $this->request->is('post')) {
+ if (isset($this->request->data['LinkFrameSetting']['has_description']) &&
+ $this->request->data['LinkFrameSetting']['has_description']) {
+ $this->request->data['LinkFrameSetting']['display_type']
+ = LinkFrameSetting::TYPE_LIST_WITH_DESCRIPTION;
+ }
+
+ if ($this->LinkFrameSetting->saveLinkFrameSetting($this->request->data)) {
+ return $this->redirect(NetCommonsUrl::backToPageUrl(true));
+ } else {
+ return $this->throwBadRequest();
+ }
+
+ } else {
+ $this->request->data = $this->LinkFrameSetting->getLinkFrameSetting(true);
+ $displayType = $this->request->data['LinkFrameSetting']['display_type'];
+ if ($displayType === LinkFrameSetting::TYPE_LIST_WITH_DESCRIPTION) {
+ $this->request->data['LinkFrameSetting']['has_description'] = true;
+ $this->request->data['LinkFrameSetting']['display_type']
+ = LinkFrameSetting::TYPE_LIST_ONLY_TITLE;
+ }
+
+ $this->request->data['Frame'] = Current::read('Frame');
+ }
+ }
+}
diff --git a/Controller/LinkListsAppController.php b/Controller/LinkListsAppController.php
deleted file mode 100644
index 1a01fb3..0000000
--- a/Controller/LinkListsAppController.php
+++ /dev/null
@@ -1,7 +0,0 @@
-
-* @link http://www.netcommons.org NetCommons Project
-* @license http://www.netcommons.org/license.txt NetCommons License
- */
-class LinkListsCategoriesController extends LinkListsAppController {
-
-/**
- * Components
- *
- * @var array
- */
- public $components = array('Paginator');
-
-/**
- * index method
- *
- * @return void
- */
- public function index() {
- $this->LinkListsCategory->recursive = 0;
- $this->set('linkListsCategories', $this->Paginator->paginate());
- }
-
-/**
- * view method
- *
- * @throws NotFoundException
- * @param string $id
- * @return void
- */
- public function view($id = null) {
- if (!$this->LinkListsCategory->exists($id)) {
- throw new NotFoundException(__('Invalid link lists category'));
- }
- $options = array('conditions' => array('LinkListsCategory.' . $this->LinkListsCategory->primaryKey => $id));
- $this->set('linkListsCategory', $this->LinkListsCategory->find('first', $options));
- }
-
-/**
- * add method
- *
- * @return void
- */
- public function add() {
- if ($this->request->is('post')) {
- $this->LinkListsCategory->create();
- if ($this->LinkListsCategory->save($this->request->data)) {
- $this->Session->setFlash(__('The link lists category has been saved.'));
- return $this->redirect(array('action' => 'index'));
- } else {
- $this->Session->setFlash(__('The link lists category could not be saved. Please, try again.'));
- }
- }
- $linklistsBlocks = $this->LinkListsCategory->LinklistsBlock->find('list');
- $languages = $this->LinkListsCategory->Language->find('list');
- $this->set(compact('linklistsBlocks', 'languages'));
- }
-
-/**
- * edit method
- *
- * @throws NotFoundException
- * @param string $id
- * @return void
- */
- public function edit($id = null) {
- if (!$this->LinkListsCategory->exists($id)) {
- throw new NotFoundException(__('Invalid link lists category'));
- }
- if ($this->request->is(array('post', 'put'))) {
- if ($this->LinkListsCategory->save($this->request->data)) {
- $this->Session->setFlash(__('The link lists category has been saved.'));
- return $this->redirect(array('action' => 'index'));
- } else {
- $this->Session->setFlash(__('The link lists category could not be saved. Please, try again.'));
- }
- } else {
- $options = array('conditions' => array('LinkListsCategory.' . $this->LinkListsCategory->primaryKey => $id));
- $this->request->data = $this->LinkListsCategory->find('first', $options);
- }
- $linklistsBlocks = $this->LinkListsCategory->LinklistsBlock->find('list');
- $languages = $this->LinkListsCategory->Language->find('list');
- $this->set(compact('linklistsBlocks', 'languages'));
- }
-
-/**
- * delete method
- *
- * @throws NotFoundException
- * @param string $id
- * @return void
- */
- public function delete($id = null) {
- $this->LinkListsCategory->id = $id;
- if (!$this->LinkListsCategory->exists()) {
- throw new NotFoundException(__('Invalid link lists category'));
- }
- $this->request->onlyAllow('post', 'delete');
- if ($this->LinkListsCategory->delete()) {
- $this->Session->setFlash(__('The link lists category has been deleted.'));
- } else {
- $this->Session->setFlash(__('The link lists category could not be deleted. Please, try again.'));
- }
- return $this->redirect(array('action' => 'index'));
- }}
diff --git a/Controller/LinkListsController.php b/Controller/LinkListsController.php
deleted file mode 100644
index fc5b237..0000000
--- a/Controller/LinkListsController.php
+++ /dev/null
@@ -1,117 +0,0 @@
-
-* @link http://www.netcommons.org NetCommons Project
-* @license http://www.netcommons.org/license.txt NetCommons License
- */
-class LinkListsController extends LinkListsAppController {
-
-/**
- * Components
- *
- * @var array
- */
- public $components = array('Paginator');
-
-/**
- * index method
- *
- * @return void
- */
- public function index() {
- $this->LinkList->recursive = 0;
- $this->set('linkLists', $this->Paginator->paginate());
- }
-
-/**
- * view method
- *
- * @throws NotFoundException
- * @param string $id
- * @return void
- */
- public function view($id = null) {
- if (!$this->LinkList->exists($id)) {
- throw new NotFoundException(__('Invalid link list'));
- }
- $options = array('conditions' => array('LinkList.' . $this->LinkList->primaryKey => $id));
- $this->set('linkList', $this->LinkList->find('first', $options));
- }
-
-/**
- * add method
- *
- * @return void
- */
- public function add() {
- if ($this->request->is('post')) {
- $this->LinkList->create();
- if ($this->LinkList->save($this->request->data)) {
- $this->Session->setFlash(__('The link list has been saved.'));
- return $this->redirect(array('action' => 'index'));
- } else {
- $this->Session->setFlash(__('The link list could not be saved. Please, try again.'));
- }
- }
- $linklistsBlocks = $this->LinkList->LinklistsBlock->find('list');
- $languages = $this->LinkList->Language->find('list');
- $linklistsCategories = $this->LinkList->LinklistsCategory->find('list');
- $blocks = $this->LinkList->Block->find('list');
- $this->set(compact('linklistsBlocks', 'languages', 'linklistsCategories', 'blocks'));
- }
-
-/**
- * edit method
- *
- * @throws NotFoundException
- * @param string $id
- * @return void
- */
- public function edit($id = null) {
- if (!$this->LinkList->exists($id)) {
- throw new NotFoundException(__('Invalid link list'));
- }
- if ($this->request->is(array('post', 'put'))) {
- if ($this->LinkList->save($this->request->data)) {
- $this->Session->setFlash(__('The link list has been saved.'));
- return $this->redirect(array('action' => 'index'));
- } else {
- $this->Session->setFlash(__('The link list could not be saved. Please, try again.'));
- }
- } else {
- $options = array('conditions' => array('LinkList.' . $this->LinkList->primaryKey => $id));
- $this->request->data = $this->LinkList->find('first', $options);
- }
- $linklistsBlocks = $this->LinkList->LinklistsBlock->find('list');
- $languages = $this->LinkList->Language->find('list');
- $linklistsCategories = $this->LinkList->LinklistsCategory->find('list');
- $blocks = $this->LinkList->Block->find('list');
- $this->set(compact('linklistsBlocks', 'languages', 'linklistsCategories', 'blocks'));
- }
-
-/**
- * delete method
- *
- * @throws NotFoundException
- * @param string $id
- * @return void
- */
- public function delete($id = null) {
- $this->LinkList->id = $id;
- if (!$this->LinkList->exists()) {
- throw new NotFoundException(__('Invalid link list'));
- }
- $this->request->onlyAllow('post', 'delete');
- if ($this->LinkList->delete()) {
- $this->Session->setFlash(__('The link list has been deleted.'));
- } else {
- $this->Session->setFlash(__('The link list could not be deleted. Please, try again.'));
- }
- return $this->redirect(array('action' => 'index'));
- }}
diff --git a/Controller/LinkMailSettingsController.php b/Controller/LinkMailSettingsController.php
new file mode 100644
index 0000000..b0b7705
--- /dev/null
+++ b/Controller/LinkMailSettingsController.php
@@ -0,0 +1,36 @@
+
+ * @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('MailSettingsController', 'Mails.Controller');
+
+/**
+ * メール設定Controller
+ *
+ * @author Shohei Nakajima
+ * @package NetCommons\Links\Controller
+ */
+class LinkMailSettingsController extends MailSettingsController {
+
+/**
+ * use helpers
+ *
+ * @var array
+ */
+ public $helpers = array(
+ 'Blocks.BlockRolePermissionForm',
+ 'Blocks.BlockTabs' => array(
+ 'mainTabs' => array('block_index', 'frame_settings'),
+ 'blockTabs' => array('block_settings', 'mail_settings', 'role_permissions'),
+ ),
+ 'Mails.MailForm',
+ );
+
+}
diff --git a/Controller/LinkOrdersController.php b/Controller/LinkOrdersController.php
new file mode 100644
index 0000000..88ebe4b
--- /dev/null
+++ b/Controller/LinkOrdersController.php
@@ -0,0 +1,103 @@
+
+ * @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('LinksAppController', 'Links.Controller');
+
+/**
+ * LinkOrders Controller
+ *
+ * @author Shohei Nakajima
+ * @package NetCommons\Links\Controller
+ */
+class LinkOrdersController extends LinksAppController {
+
+/**
+ * use models
+ *
+ * @var array
+ */
+ public $uses = array(
+ 'Links.Link',
+ 'Links.LinkBlock',
+ 'Links.LinkOrder',
+ 'Categories.Category',
+ 'Categories.CategoriesLanguage',
+ );
+
+/**
+ * use component
+ *
+ * @var array
+ */
+ public $components = array(
+ 'NetCommons.Permission' => array(
+ 'allow' => array(
+ 'edit' => 'content_editable',
+ ),
+ ),
+ 'Categories.Categories',
+ );
+
+/**
+ * edit
+ *
+ * @return void
+ */
+ public function edit() {
+ $linkBlock = $this->LinkBlock->getLinkBlock();
+ if (! $linkBlock) {
+ return $this->throwBadRequest();
+ }
+
+ if ($this->request->is('put')) {
+ if ($this->LinkOrder->saveLinkOrders($this->data)) {
+ return $this->redirect(NetCommonsUrl::backToPageUrl());
+ }
+ $this->NetCommons->handleValidationError($this->LinkOrder->validationErrors);
+
+ } else {
+ //カテゴリ
+ array_unshift($this->viewVars['categories'], (
+ $this->Category->create(['id' => 0])
+ + $this->CategoriesLanguage->create(['name' => __d('links', 'No Category')])
+ ));
+
+ $this->request->data['Frame'] = Current::read('Frame');
+ $this->request->data['Block'] = Current::read('Block');
+ }
+
+ //リンクデータ取得
+ $results = $this->Link->find('all', array(
+ 'recursive' => 0,
+ 'conditions' => array(
+ 'Link.block_id' => Current::read('Block.id'),
+ 'Link.is_latest' => true,
+ ),
+ 'order' => array(
+ 'CategoryOrder.weight' => 'asc',
+ 'LinkOrder.weight' => 'asc',
+ ),
+ ));
+
+ $links = [];
+ $linkOrders = [];
+ foreach ($results as $result) {
+ $categoryId = (int)$result['Link']['category_id'];
+ $linkOrder = $result['LinkOrder'];
+ $links[$categoryId][] = $result;
+ $linkOrders[$linkOrder['id']] = $result;
+ }
+ $this->request->data['LinkOrders'] = $linkOrders;
+ $this->set('links', $links);
+ $this->set('linkBlock', $linkBlock['LinkBlock']);
+ }
+
+}
diff --git a/Controller/LinksAppController.php b/Controller/LinksAppController.php
new file mode 100644
index 0000000..fa171ce
--- /dev/null
+++ b/Controller/LinksAppController.php
@@ -0,0 +1,32 @@
+
+ * @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('AppController', 'Controller');
+App::uses('LinkFrameSetting', 'Links.Model');
+
+/**
+ * LinksApp Controller
+ *
+ * @author Shohei Nakajima
+ * @package NetCommons\Links\Controller
+ */
+class LinksAppController extends AppController {
+
+/**
+ * use component
+ *
+ * @var array
+ */
+ public $components = array(
+ 'Pages.PageLayout',
+ 'Security',
+ );
+}
diff --git a/Controller/LinksController.php b/Controller/LinksController.php
new file mode 100644
index 0000000..72aa6e1
--- /dev/null
+++ b/Controller/LinksController.php
@@ -0,0 +1,394 @@
+
+ * @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('LinksAppController', 'Links.Controller');
+App::uses('HttpSocket', 'Network/Http');
+
+/**
+ * Links Controller
+ *
+ * @author Shohei Nakajima
+ * @package NetCommons\Links\Controller
+ */
+class LinksController extends LinksAppController {
+
+/**
+ * use model
+ *
+ * @var array
+ */
+ public $uses = array(
+ 'Links.Link',
+ 'Links.LinkBlock',
+ 'Links.LinkOrder',
+ 'Links.LinkFrameSetting',
+ 'Categories.Category',
+ 'Categories.CategoriesLanguage',
+ );
+
+/**
+ * use component
+ *
+ * @var array
+ */
+ public $components = array(
+ 'NetCommons.Permission' => array(
+ 'allow' => array(
+ 'get,add,edit,delete' => 'content_creatable',
+ ),
+ ),
+ 'Categories.Categories',
+ );
+
+/**
+ * use helpers
+ *
+ * @var array
+ */
+ public $helpers = array(
+ 'NetCommons.Token',
+ 'Workflow.Workflow',
+ );
+
+/**
+ * beforeFilter
+ *
+ * @return void
+ */
+ public function beforeFilter() {
+ parent::beforeFilter();
+ $this->Auth->allow('link');
+
+ if (! Current::read('Block.id')) {
+ return $this->setAction('emptyRender');
+ }
+ $this->LinkBlock->unbindModel(['belongsTo' => ['TrackableCreator', 'TrackableUpdater']], true);
+ $linkBlock = $this->LinkBlock->getLinkBlock([
+ 'LinkBlock.id',
+ 'LinkBlock.room_id',
+ 'LinkBlock.plugin_key',
+ 'LinkBlock.key',
+ 'LinkBlock.public_type',
+ 'LinkBlock.publish_start',
+ 'LinkBlock.publish_end',
+ 'LinkBlock.content_count',
+ 'name'
+ ]);
+ if (! $linkBlock) {
+ return $this->setAction('throwBadRequest');
+ }
+ $this->set('linkBlock', $linkBlock['LinkBlock']);
+ }
+
+/**
+ * index
+ *
+ * @return void
+ */
+ public function index() {
+ $linkFrameSetting = $this->LinkFrameSetting->getLinkFrameSetting(true);
+ if (! $linkFrameSetting) {
+ return $this->throwBadRequest();
+ }
+ $this->set('linkFrameSetting', $linkFrameSetting['LinkFrameSetting']);
+
+ //カテゴリ
+ array_unshift($this->viewVars['categories'], (
+ $this->Category->create(['id' => 0])
+ + $this->CategoriesLanguage->create(['name' => ''])
+ ));
+
+ //取得
+ $this->Link->unbindModel(['belongsTo' => ['TrackableCreator', 'TrackableUpdater']], true);
+ $results = $this->Link->getWorkflowContents('all', array(
+ 'recursive' => 0,
+ 'fields' => [
+ 'Link.id',
+ 'Link.block_id',
+ 'Link.category_id',
+ 'Link.language_id',
+ 'Link.key',
+ 'Link.status',
+ 'Link.url',
+ 'Link.title',
+ 'Link.description',
+ 'Link.click_count',
+ ],
+ 'conditions' => array(
+ 'Link.block_id' => Current::read('Block.id'),
+ ),
+ 'order' => array(
+ 'CategoryOrder.weight' => 'asc',
+ 'LinkOrder.weight' => 'asc',
+ ),
+ ));
+ $links = [];
+ foreach ($results as $link) {
+ $categoryId = (int)$link['Link']['category_id'];
+ $linkId = $link['Link']['id'];
+ $links[$categoryId][$linkId] = $link;
+ }
+ $this->set('links', $links);
+ }
+
+/**
+ * view
+ *
+ * @return void
+ */
+ public function view() {
+ $linkFrameSetting = $this->LinkFrameSetting->getLinkFrameSetting(true);
+ $this->set('linkFrameSetting', $linkFrameSetting['LinkFrameSetting']);
+
+ $link = $this->Link->getWorkflowContents('first', array(
+ 'recursive' => 0,
+ 'conditions' => array(
+ $this->Link->alias . '.block_id' => Current::read('Block.id'),
+ $this->Link->alias . '.key' => $this->params['key']
+ )
+ ));
+ if (! $link) {
+ return $this->throwBadRequest();
+ }
+ $this->set('link', $link);
+
+ $categoryId = isset($link['Link']['category_id'])
+ ? $link['Link']['category_id']
+ : null;
+ $category = Hash::extract(
+ $this->viewVars['categories'],
+ '{n}.Category[id=' . $categoryId . ']'
+ );
+ $category = isset($category[0])
+ ? $category[0]
+ : [];
+ $this->set('category', $category);
+
+ //if (! $this->Link->updateCount($link['Link']['id'])) {
+ // return $this->throwBadRequest();
+ //}
+
+ //新着データを既読にする
+ $this->Link->saveTopicUserStatus($link);
+ }
+
+/**
+ * Get url
+ *
+ * @return void
+ * @throws SocketException
+ */
+ public function get() {
+ $url = isset($this->request->query['url'])
+ ? $this->request->query['url']
+ : null;
+ if (! $url || $url === 'http://') {
+ return $this->throwBadRequest(
+ sprintf(__d('net_commons', 'Please input %s.'), __d('links', 'URL'))
+ );
+ }
+ try {
+ $socket = new HttpSocket(array('request' => array('redirect' => 10)));
+ $response = $socket->get($url);
+ if (! $response->isOk()) {
+ throw new SocketException(__d('links', 'Failed to obtain the title for this page.'));
+ }
+ } catch (SocketException $ex) {
+ CakeLog::error($ex);
+ return $this->throwBadRequest(__d('links', 'Failed to obtain the title for this page.'));
+ }
+
+ $results = array(
+ 'title' => null,
+ 'description' => null,
+ );
+
+ $body = $response->body;
+ $pattern = '/(.*)<\/title>/i';
+ $matches = array();
+ if (preg_match($pattern, $body, $matches)) {
+ $results['title'] = mb_convert_encoding($matches[1], 'utf-8', 'auto');
+ }
+ $pattern = '\]]*' .
+ 'name=([\'"]?)' .
+ 'description\\1[^"\'<>\]]*' .
+ 'content=([\'"]?)([^"\'<>\]]*)\\2[^"\'<>\]]*>';
+ $matches = array();
+ if (preg_match('/' . $pattern . '/i', $body, $matches)) {
+ $results['description'] = mb_convert_encoding($matches[3], 'utf-8', 'auto');
+ } else {
+ $results['description'] = '';
+ }
+
+ if ($results['title']) {
+ $this->NetCommons->renderJson($results);
+ } else {
+ return $this->throwBadRequest(__d('links', 'Failed to obtain the title for this page.'));
+ }
+ }
+
+/**
+ * add
+ *
+ * @return void
+ */
+ public function add() {
+ $this->view = 'edit';
+
+ if ($this->request->is('post')) {
+ //登録処理
+ $data = $this->data;
+ $data['Link']['status'] = $this->Workflow->parseStatus();
+ $categoryId = isset($data['Link']['category_id'])
+ ? $data['Link']['category_id']
+ : null;
+ $category = Hash::extract(
+ $this->viewVars['categories'],
+ '{n}.Category[id=' . $categoryId . ']'
+ );
+ $data['LinkOrder']['category_key'] = isset($category[0]['key'])
+ ? $category[0]['key']
+ : '';
+ unset($data['Link']['id'], $data['LinkOrder']['weight']);
+
+ if ($this->Link->saveLink($data)) {
+ return $this->redirect(NetCommonsUrl::backToPageUrl());
+ }
+ $this->NetCommons->handleValidationError($this->Link->validationErrors);
+
+ } else {
+ $this->request->data += $this->Link->create(array(
+ 'url' => 'http://'
+ ));
+ $this->request->data += $this->LinkOrder->create();
+ $this->request->data['Frame'] = Current::read('Frame');
+ $this->request->data['Block'] = Current::read('Block');
+ }
+ }
+
+/**
+ * edit
+ *
+ * @return void
+ */
+ public function edit() {
+ //データ取得
+ $linkKey = $this->params['key'];
+ if ($this->request->is('put')) {
+ $linkKey = $this->data['Link']['key'];
+ }
+ $link = $this->Link->getWorkflowContents('first', array(
+ 'recursive' => 0,
+ 'conditions' => array(
+ $this->Link->alias . '.block_id' => Current::read('Block.id'),
+ $this->Link->alias . '.key' => $linkKey
+ )
+ ));
+ if (empty($link)) {
+ return $this->throwBadRequest();
+ }
+
+ //編集権限チェック
+ if (! $this->Link->canEditWorkflowContent($link)) {
+ return $this->throwBadRequest();
+ }
+
+ if ($this->request->is('put')) {
+ //登録処理
+ $data = $this->data;
+ $data['Link']['status'] = $this->Workflow->parseStatus();
+ $categoryId = isset($data['Link']['category_id'])
+ ? $data['Link']['category_id']
+ : null;
+ $category = Hash::extract(
+ $this->viewVars['categories'],
+ '{n}.Category[id=' . $categoryId . ']'
+ );
+ $data['LinkOrder']['category_key'] = isset($category[0]['key'])
+ ? $category[0]['key']
+ : '';
+ unset($data['Link']['id']);
+
+ if ($this->Link->saveLink($data)) {
+ return $this->redirect(NetCommonsUrl::backToPageUrl());
+ }
+ $this->NetCommons->handleValidationError($this->Link->validationErrors);
+
+ } else {
+ $this->request->data = $link;
+ $this->request->data['Frame'] = Current::read('Frame');
+ $this->request->data['Block'] = Current::read('Block');
+ }
+
+ //コメント取得
+ $comments = $this->Link->getCommentsByContentKey($linkKey);
+ $this->set('comments', $comments);
+ }
+
+/**
+ * delete
+ *
+ * @return void
+ */
+ public function delete() {
+ if (! $this->request->is('delete')) {
+ return $this->throwBadRequest();
+ }
+
+ //データ取得
+ $link = $this->Link->getWorkflowContents('first', array(
+ 'recursive' => -1,
+ 'conditions' => array(
+ $this->Link->alias . '.block_id' => Current::read('Block.id'),
+ $this->Link->alias . '.key' => $this->data['Link']['key']
+ )
+ ));
+
+ //削除権限チェック
+ if (! $this->Link->canDeleteWorkflowContent($link)) {
+ return $this->throwBadRequest();
+ }
+
+ if (! $this->Link->deleteLink($this->data)) {
+ return $this->throwBadRequest();
+ }
+
+ $this->redirect(NetCommonsUrl::backToPageUrl());
+ }
+
+/**
+ * link
+ *
+ * @return void
+ */
+ public function link() {
+ if (! $this->request->is('put')) {
+ return $this->throwBadRequest();
+ }
+
+ $link = $this->Link->getWorkflowContents('first', array(
+ 'recursive' => -1,
+ 'conditions' => array(
+ $this->Link->alias . '.block_id' => Current::read('Block.id'),
+ $this->Link->alias . '.id' => Hash::get($this->data, 'Link.id')
+ )
+ ));
+ if (! $link) {
+ return $this->throwBadRequest();
+ }
+
+ if (! $this->Link->updateCount($this->data['Link']['id'])) {
+ return $this->throwBadRequest();
+ }
+
+ $this->NetCommons->renderJson();
+ }
+}
diff --git a/Lib/empty b/Lib/empty
deleted file mode 100644
index e69de29..0000000
diff --git a/Locale/eng/LC_MESSAGES/links.po b/Locale/eng/LC_MESSAGES/links.po
new file mode 100644
index 0000000..bc71d7e
--- /dev/null
+++ b/Locale/eng/LC_MESSAGES/links.po
@@ -0,0 +1,133 @@
+# LANGUAGE translation of CakePHP Application
+# Copyright YEAR NAME
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: PROJECT VERSION\n"
+"PO-Revision-Date: YYYY-mm-DD HH:MM+ZZZZ\n"
+"Last-Translator: NAME \n"
+"Language-Team: LANGUAGE \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=utf-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n"
+
+#: Links/Controller/LinkOrdersController.php:66
+msgid "No Category"
+msgstr ""
+
+#: Links/Controller/LinksController.php:154
+#: Links/Model/Link.php:149;157;158
+#: Links/Test/Case/Controller/LinksController/AddTest.php:229
+#: Links/Test/Case/Controller/LinksController/EditTest.php:339
+#: Links/Test/Case/Controller/LinksController/GetTest.php:120
+#: Links/Test/Case/Model/Link/ValidateTest.php:85;87
+#: Links/View/Elements/Links/edit_form.ctp:29
+msgid "URL"
+msgstr ""
+
+#: Links/Controller/LinksController.php:161;165;191
+#: Links/Test/Case/Controller/LinksController/GetTest.php:141
+msgid "Failed to obtain the title for this page."
+msgstr ""
+
+#: Links/Model/Link.php:167
+#: Links/Test/Case/Controller/LinksController/AddTest.php:236
+#: Links/Test/Case/Controller/LinksController/EditTest.php:346
+#: Links/Test/Case/Model/Link/ValidateTest.php:89
+#: Links/View/Elements/Links/edit_form.ctp:50
+msgid "Title"
+msgstr ""
+
+#: Links/Model/LinkBlock.php:184
+#: Links/Test/Case/Controller/LinkBlocksController/EditTest.php:128;157
+#: Links/Test/Case/Model/LinkBlock/ValidateTest.php:79
+#: Links/View/Elements/LinkBlocks/edit_form.ctp:22
+#: Links/View/LinkBlocks/index.ctp:30
+msgid "Link list Title"
+msgstr ""
+
+#: Links/Model/LinkBlock.php:233
+#: Links/Test/Case/Model/LinkBlock/CreateLinkBlockTest.php:74
+msgid "New Bookmark List %s"
+msgstr ""
+
+#: Links/Model/LinkFrameSetting.php:94
+msgid "(no line)"
+msgstr ""
+
+#: Links/View/Elements/LinkBlockRolePermissions/edit_form.ctp:19
+msgid "Link creatable roles"
+msgstr ""
+
+#: Links/View/Elements/LinkBlocks/delete_form.ctp:14;22
+msgid "Link List"
+msgstr ""
+
+#: Links/View/Elements/LinkFrameSettings/edit_form.ctp:27
+msgid "Display method"
+msgstr ""
+
+#: Links/View/Elements/LinkFrameSettings/edit_form.ctp:31
+msgid "Show by dropdown"
+msgstr ""
+
+#: Links/View/Elements/LinkFrameSettings/edit_form.ctp:32
+msgid "Show list"
+msgstr ""
+
+#: Links/View/Elements/LinkFrameSettings/edit_form.ctp:41
+msgid "Show description"
+msgstr ""
+
+#: Links/View/Elements/LinkFrameSettings/edit_form.ctp:51
+msgid "Line"
+msgstr ""
+
+#: Links/View/Elements/LinkFrameSettings/edit_form.ctp:94
+msgid "Marker"
+msgstr ""
+
+#: Links/View/Elements/LinkFrameSettings/edit_form.ctp:111;131
+msgid "Sample"
+msgstr ""
+
+#: Links/View/Elements/LinkFrameSettings/edit_form.ctp:142
+msgid "Open as a new tab"
+msgstr ""
+
+#: Links/View/Elements/LinkFrameSettings/edit_form.ctp:147
+msgid "Count view"
+msgstr ""
+
+#: Links/View/Elements/Links/delete_form.ctp:22
+msgid "Link"
+msgstr ""
+
+#: Links/View/Elements/Links/edit_form.ctp:43
+msgid "GO!"
+msgstr ""
+
+#: Links/View/Elements/Links/edit_form.ctp:58
+msgid "Description"
+msgstr ""
+
+#: Links/View/Elements/Links/index_dropdown.ctp:17
+msgid "Select link to show"
+msgstr ""
+
+#: Links/View/Elements/Links/index_dropdown.ctp:52
+#: Links/View/LinkOrders/edit.ctp:38
+#: Links/View/Links/index.ctp:65;72
+msgid "No link found."
+msgstr ""
+
+#: Links/View/LinkMailSettings/edit.ctp:24
+msgid "MailSetting.mail_fixed_phrase_body.popover"
+msgstr ""
+
+#: Links/View/Links/index.ctp:54
+msgid "Create link"
+msgstr ""
+
diff --git a/Locale/jpn/LC_MESSAGES/links.po b/Locale/jpn/LC_MESSAGES/links.po
new file mode 100644
index 0000000..f834613
--- /dev/null
+++ b/Locale/jpn/LC_MESSAGES/links.po
@@ -0,0 +1,135 @@
+# LANGUAGE translation of CakePHP Application
+# Copyright YEAR NAME
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: PROJECT VERSION\n"
+"PO-Revision-Date: 2015-06-01 18:05+0900\n"
+"Last-Translator: NAME \n"
+"Language-Team: LANGUAGE \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=utf-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n"
+"POT-Creation-Date: \n"
+"Language: ja\n"
+"X-Generator: Poedit 1.8.1\n"
+
+#: Links/Controller/LinkOrdersController.php:66
+msgid "No Category"
+msgstr "カテゴリーなし"
+
+#: Links/Controller/LinksController.php:154
+#: Links/Model/Link.php:149;157;158
+#: Links/Test/Case/Controller/LinksController/AddTest.php:229
+#: Links/Test/Case/Controller/LinksController/EditTest.php:339
+#: Links/Test/Case/Controller/LinksController/GetTest.php:120
+#: Links/Test/Case/Model/Link/ValidateTest.php:85;87
+#: Links/View/Elements/Links/edit_form.ctp:29
+msgid "URL"
+msgstr ""
+
+#: Links/Controller/LinksController.php:161;165;191
+#: Links/Test/Case/Controller/LinksController/GetTest.php:141
+msgid "Failed to obtain the title for this page."
+msgstr "入力したURLからタイトルと説明を取得できませんでした"
+
+#: Links/Model/Link.php:167
+#: Links/Test/Case/Controller/LinksController/AddTest.php:236
+#: Links/Test/Case/Controller/LinksController/EditTest.php:346
+#: Links/Test/Case/Model/Link/ValidateTest.php:89
+#: Links/View/Elements/Links/edit_form.ctp:50
+msgid "Title"
+msgstr "タイトル"
+
+#: Links/Model/LinkBlock.php:184
+#: Links/Test/Case/Controller/LinkBlocksController/EditTest.php:128;157
+#: Links/Test/Case/Model/LinkBlock/ValidateTest.php:79
+#: Links/View/Elements/LinkBlocks/edit_form.ctp:22
+#: Links/View/LinkBlocks/index.ctp:30
+msgid "Link list Title"
+msgstr "リンクリスト名"
+
+#: Links/Model/LinkBlock.php:233
+#: Links/Test/Case/Model/LinkBlock/CreateLinkBlockTest.php:74
+msgid "New Bookmark List %s"
+msgstr "新規リンクリスト%s"
+
+#: Links/Model/LinkFrameSetting.php:94
+msgid "(no line)"
+msgstr "(線なし)"
+
+#: Links/View/Elements/LinkBlockRolePermissions/edit_form.ctp:19
+msgid "Link creatable roles"
+msgstr "リンクを追加できる権限"
+
+#: Links/View/Elements/LinkBlocks/delete_form.ctp:14;22
+msgid "Link List"
+msgstr "リンクリスト"
+
+#: Links/View/Elements/LinkFrameSettings/edit_form.ctp:27
+msgid "Display method"
+msgstr "表示方法選択"
+
+#: Links/View/Elements/LinkFrameSettings/edit_form.ctp:31
+msgid "Show by dropdown"
+msgstr "ドロップダウン"
+
+#: Links/View/Elements/LinkFrameSettings/edit_form.ctp:32
+msgid "Show list"
+msgstr "一覧表示"
+
+#: Links/View/Elements/LinkFrameSettings/edit_form.ctp:41
+msgid "Show description"
+msgstr "説明付き"
+
+#: Links/View/Elements/LinkFrameSettings/edit_form.ctp:51
+msgid "Line"
+msgstr "カテゴリ間の区切り線"
+
+#: Links/View/Elements/LinkFrameSettings/edit_form.ctp:94
+msgid "Marker"
+msgstr "リストマーカー"
+
+#: Links/View/Elements/LinkFrameSettings/edit_form.ctp:111;131
+msgid "Sample"
+msgstr "サンプル"
+
+#: Links/View/Elements/LinkFrameSettings/edit_form.ctp:142
+msgid "Open as a new tab"
+msgstr "新しいタブで開く"
+
+#: Links/View/Elements/LinkFrameSettings/edit_form.ctp:147
+msgid "Count view"
+msgstr "クリック回数の表示"
+
+#: Links/View/Elements/Links/delete_form.ctp:22
+msgid "Link"
+msgstr "リンク"
+
+#: Links/View/Elements/Links/edit_form.ctp:43
+msgid "GO!"
+msgstr "取得"
+
+#: Links/View/Elements/Links/edit_form.ctp:58
+msgid "Description"
+msgstr "説明"
+
+#: Links/View/Elements/Links/index_dropdown.ctp:17
+msgid "Select link to show"
+msgstr "リンクを選択してください"
+
+#: Links/View/Elements/Links/index_dropdown.ctp:52
+#: Links/View/LinkOrders/edit.ctp:38
+#: Links/View/Links/index.ctp:65;72
+msgid "No link found."
+msgstr "リンクがありません。"
+
+# メール関連
+#: Links/View/LinkMailSettings/edit.ctp:24
+msgid "MailSetting.mail_fixed_phrase_body.popover"
+msgstr "{X-SITE_NAME} : サイト名
{X-PLUGIN_NAME} : プラグイン名
{X-ROOM} : ルーム名
{X-BLOCK_NAME} : リンクリスト名
{X-LINK_URL} : リンク先
{X-TITLE} : タイトル
{X-CATEGORY_NAME} : カテゴリ
{X-DESCRIPTION} : 説明
{X-USER} : 登録者
{X-TO_DATE} : 登録日時
{X-URL} : 登録内容のURL"
+
+#: Links/View/Links/index.ctp:54
+msgid "Create link"
+msgstr "リンクの作成"
diff --git a/Locale/links.pot b/Locale/links.pot
new file mode 100644
index 0000000..bc71d7e
--- /dev/null
+++ b/Locale/links.pot
@@ -0,0 +1,133 @@
+# LANGUAGE translation of CakePHP Application
+# Copyright YEAR NAME
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: PROJECT VERSION\n"
+"PO-Revision-Date: YYYY-mm-DD HH:MM+ZZZZ\n"
+"Last-Translator: NAME \n"
+"Language-Team: LANGUAGE \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=utf-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n"
+
+#: Links/Controller/LinkOrdersController.php:66
+msgid "No Category"
+msgstr ""
+
+#: Links/Controller/LinksController.php:154
+#: Links/Model/Link.php:149;157;158
+#: Links/Test/Case/Controller/LinksController/AddTest.php:229
+#: Links/Test/Case/Controller/LinksController/EditTest.php:339
+#: Links/Test/Case/Controller/LinksController/GetTest.php:120
+#: Links/Test/Case/Model/Link/ValidateTest.php:85;87
+#: Links/View/Elements/Links/edit_form.ctp:29
+msgid "URL"
+msgstr ""
+
+#: Links/Controller/LinksController.php:161;165;191
+#: Links/Test/Case/Controller/LinksController/GetTest.php:141
+msgid "Failed to obtain the title for this page."
+msgstr ""
+
+#: Links/Model/Link.php:167
+#: Links/Test/Case/Controller/LinksController/AddTest.php:236
+#: Links/Test/Case/Controller/LinksController/EditTest.php:346
+#: Links/Test/Case/Model/Link/ValidateTest.php:89
+#: Links/View/Elements/Links/edit_form.ctp:50
+msgid "Title"
+msgstr ""
+
+#: Links/Model/LinkBlock.php:184
+#: Links/Test/Case/Controller/LinkBlocksController/EditTest.php:128;157
+#: Links/Test/Case/Model/LinkBlock/ValidateTest.php:79
+#: Links/View/Elements/LinkBlocks/edit_form.ctp:22
+#: Links/View/LinkBlocks/index.ctp:30
+msgid "Link list Title"
+msgstr ""
+
+#: Links/Model/LinkBlock.php:233
+#: Links/Test/Case/Model/LinkBlock/CreateLinkBlockTest.php:74
+msgid "New Bookmark List %s"
+msgstr ""
+
+#: Links/Model/LinkFrameSetting.php:94
+msgid "(no line)"
+msgstr ""
+
+#: Links/View/Elements/LinkBlockRolePermissions/edit_form.ctp:19
+msgid "Link creatable roles"
+msgstr ""
+
+#: Links/View/Elements/LinkBlocks/delete_form.ctp:14;22
+msgid "Link List"
+msgstr ""
+
+#: Links/View/Elements/LinkFrameSettings/edit_form.ctp:27
+msgid "Display method"
+msgstr ""
+
+#: Links/View/Elements/LinkFrameSettings/edit_form.ctp:31
+msgid "Show by dropdown"
+msgstr ""
+
+#: Links/View/Elements/LinkFrameSettings/edit_form.ctp:32
+msgid "Show list"
+msgstr ""
+
+#: Links/View/Elements/LinkFrameSettings/edit_form.ctp:41
+msgid "Show description"
+msgstr ""
+
+#: Links/View/Elements/LinkFrameSettings/edit_form.ctp:51
+msgid "Line"
+msgstr ""
+
+#: Links/View/Elements/LinkFrameSettings/edit_form.ctp:94
+msgid "Marker"
+msgstr ""
+
+#: Links/View/Elements/LinkFrameSettings/edit_form.ctp:111;131
+msgid "Sample"
+msgstr ""
+
+#: Links/View/Elements/LinkFrameSettings/edit_form.ctp:142
+msgid "Open as a new tab"
+msgstr ""
+
+#: Links/View/Elements/LinkFrameSettings/edit_form.ctp:147
+msgid "Count view"
+msgstr ""
+
+#: Links/View/Elements/Links/delete_form.ctp:22
+msgid "Link"
+msgstr ""
+
+#: Links/View/Elements/Links/edit_form.ctp:43
+msgid "GO!"
+msgstr ""
+
+#: Links/View/Elements/Links/edit_form.ctp:58
+msgid "Description"
+msgstr ""
+
+#: Links/View/Elements/Links/index_dropdown.ctp:17
+msgid "Select link to show"
+msgstr ""
+
+#: Links/View/Elements/Links/index_dropdown.ctp:52
+#: Links/View/LinkOrders/edit.ctp:38
+#: Links/View/Links/index.ctp:65;72
+msgid "No link found."
+msgstr ""
+
+#: Links/View/LinkMailSettings/edit.ctp:24
+msgid "MailSetting.mail_fixed_phrase_body.popover"
+msgstr ""
+
+#: Links/View/Links/index.ctp:54
+msgid "Create link"
+msgstr ""
+
diff --git a/Model/Behavior/empty b/Model/Behavior/empty
deleted file mode 100644
index e69de29..0000000
diff --git a/Model/Datasource/empty b/Model/Datasource/empty
deleted file mode 100644
index e69de29..0000000
diff --git a/Model/Link.php b/Model/Link.php
new file mode 100644
index 0000000..5efd24a
--- /dev/null
+++ b/Model/Link.php
@@ -0,0 +1,360 @@
+
+ * @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('LinksAppModel', 'Links.Model');
+
+/**
+ * Link Model
+ *
+ * @author Shohei Nakajima
+ * @package NetCommons\Links\Model
+ */
+class Link extends LinksAppModel {
+
+/**
+ * use behaviors
+ *
+ * @var array
+ */
+ public $actsAs = array(
+ 'NetCommons.OriginalKey',
+ 'Workflow.WorkflowComment',
+ 'Workflow.Workflow',
+ 'Mails.MailQueue' => array(
+ 'embedTags' => array(
+ 'X-TITLE' => 'Link.title',
+ 'X-LINK_URL' => 'Link.url',
+ 'X-DESCRIPTION' => 'Link.description',
+ 'X-CATEGORY_NAME' => 'CategoriesLanguage.name',
+ ),
+ ),
+ 'Topics.Topics' => array(
+ 'fields' => array(
+ 'title' => 'Link.title',
+ 'summary' => 'Link.description',
+ 'path' => '/:plugin_key/:plugin_key/view/:block_id/:content_key',
+ ),
+ 'search_contents' => array('url')
+ ),
+ //多言語
+ 'M17n.M17n' => array(
+ 'commonFields' => array('category_id')
+ ),
+ );
+
+/**
+ * Validation rules
+ *
+ * @var array
+ */
+ public $validate = array();
+
+ //The Associations below have been created with all possible keys, those that are not needed can be removed
+
+/**
+ * belongsTo associations
+ *
+ * @var array
+ */
+ public $belongsTo = array(
+ 'LinkOrder' => array(
+ 'className' => 'Links.LinkOrder',
+ 'foreignKey' => false,
+ 'conditions' => 'LinkOrder.link_key=Link.key',
+ 'fields' => '',
+ //'order' => array('LinkOrder.weight' => 'asc')
+ ),
+ 'Category' => array(
+ 'className' => 'Categories.Category',
+ 'foreignKey' => 'category_id',
+ 'conditions' => '',
+ 'fields' => '',
+ 'order' => ''
+ ),
+ 'CategoryOrder' => array(
+ 'className' => 'Categories.CategoryOrder',
+ 'foreignKey' => false,
+ 'conditions' => 'CategoryOrder.category_key=Category.key',
+ 'fields' => '',
+ //'order' => array('CategoryOrder.weight' => 'asc')
+ ),
+ 'Block' => array(
+ 'className' => 'Blocks.Block',
+ 'foreignKey' => 'block_id',
+ 'conditions' => '',
+ 'fields' => '',
+ 'order' => '',
+ 'counterCache' => array(
+ 'content_count' => array(
+ 'Link.is_origin' => true,
+ 'Link.is_latest' => true
+ ),
+ ),
+ ),
+ );
+
+/**
+ * Called before each find operation. Return false if you want to halt the find
+ * call, otherwise return the (modified) query data.
+ *
+ * @param array $query Data used to execute this query, i.e. conditions, order, etc.
+ * @return mixed true if the operation should continue, false if it should abort; or, modified
+ * $query to continue with new $query
+ * @link http://book.cakephp.org/2.0/en/models/callback-methods.html#beforefind
+ */
+ public function beforeFind($query) {
+ //$this->idがある場合、登録処理として判断する
+ $recursive = isset($query['recursive'])
+ ? $query['recursive']
+ : null;
+ if ($recursive > -1 && ! $this->id) {
+ $belongsTo = $this->Category->bindModelCategoryLang('Link.category_id');
+ $this->bindModel($belongsTo, true);
+ }
+ return parent::beforeFind($query);
+ }
+
+/**
+ * Called during validation operations, before validation. Please note that custom
+ * validation rules can be defined in $validate.
+ *
+ * @param array $options Options passed from Model::save().
+ * @return bool True if validate operation should continue, false to abort
+ * @link http://book.cakephp.org/2.0/en/models/callback-methods.html#beforevalidate
+ * @see Model::save()
+ */
+ public function beforeValidate($options = array()) {
+ $this->validate = array_merge($this->validate, array(
+ 'block_id' => array(
+ 'numeric' => array(
+ 'rule' => array('numeric'),
+ 'message' => __d('net_commons', 'Invalid request.'),
+ 'allowEmpty' => false,
+ 'required' => true,
+ 'on' => 'update', // Limit validation to 'create' or 'update' operations
+ ),
+ ),
+ 'key' => array(
+ 'notBlank' => array(
+ 'rule' => array('notBlank'),
+ 'message' => __d('net_commons', 'Invalid request.'),
+ 'allowEmpty' => false,
+ 'required' => true,
+ 'on' => 'update', // Limit validation to 'create' or 'update' operations
+ ),
+ ),
+ 'language_id' => array(
+ 'numeric' => array(
+ 'rule' => array('numeric'),
+ 'message' => __d('net_commons', 'Invalid request.'),
+ 'required' => true,
+ ),
+ ),
+ 'click_count' => array(
+ 'numeric' => array(
+ 'rule' => array('numeric'),
+ 'message' => __d('net_commons', 'Invalid request.'),
+ 'allowEmpty' => true,
+ ),
+ ),
+
+ //status to set in PublishableBehavior.
+
+ 'url' => array(
+ 'notBlank' => array(
+ 'rule' => array('notBlank'),
+ 'message' => sprintf(__d('net_commons', 'Please input %s.'), __d('links', 'URL')),
+ 'allowEmpty' => false,
+ 'required' => true,
+ ),
+ 'url' => array(
+ 'rule' => array('url'),
+ 'message' => sprintf(
+ __d('net_commons', 'Unauthorized pattern for %s. Please input the data in %s format.'),
+ __d('links', 'URL'),
+ __d('links', 'URL')
+ ),
+ 'allowEmpty' => false,
+ 'required' => true,
+ ),
+ ),
+ 'title' => array(
+ 'notBlank' => array(
+ 'rule' => array('notBlank'),
+ 'message' => sprintf(__d('net_commons', 'Please input %s.'), __d('links', 'Title')),
+ 'allowEmpty' => false,
+ 'required' => true,
+ ),
+ ),
+ ));
+
+ if ($this->data['Link']['url'] === 'http://') {
+ $this->data['Link']['url'] = '';
+ }
+
+ if (isset($this->data['LinkOrder'])) {
+ $this->LinkOrder->set($this->data['LinkOrder']);
+ if (! $this->LinkOrder->validates()) {
+ $this->validationErrors = array_merge(
+ $this->validationErrors, $this->LinkOrder->validationErrors
+ );
+ return false;
+ }
+ }
+
+ return parent::beforeValidate($options);
+ }
+
+/**
+ * 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
+ * @link http://book.cakephp.org/2.0/en/models/callback-methods.html#aftersave
+ * @see Model::save()
+ * @throws InternalErrorException
+ */
+ public function afterSave($created, $options = array()) {
+ //LinkOrder登録
+ if (isset($this->LinkOrder->data['LinkOrder'])) {
+ $this->data['LinkOrder']['link_key'] = $this->data[$this->alias]['key'];
+ $result = $this->LinkOrder->save($this->data['LinkOrder'], false);
+ if (! $result) {
+ throw new InternalErrorException(__d('net_commons', 'Internal Server Error'));
+ }
+ $this->data['LinkOrder'] = $result['LinkOrder'];
+ }
+ }
+
+/**
+ * Save Link
+ *
+ * @param array $data received post data
+ * @return bool True on success, false on validation errors
+ * @throws InternalErrorException
+ */
+ public function saveLink($data) {
+ $this->loadModels([
+ 'Category' => 'Categories.Category',
+ 'LinkOrder' => 'Links.LinkOrder',
+ ]);
+
+ //カテゴリ名をメールに含める
+ if (! empty($data['Link']['category_id'])) {
+ $data += $this->Category->getCategory($data['Link']['category_id']);
+ }
+
+ //トランザクションBegin
+ $this->begin();
+
+ //バリデーション
+ $this->set($data);
+ if (! $this->validates()) {
+ return false;
+ }
+
+ try {
+ //Link登録
+ $link = $this->save(null, false);
+ if (! $link) {
+ throw new InternalErrorException(__d('net_commons', 'Internal Server Error'));
+ }
+
+ //トランザクションCommit
+ $this->commit();
+
+ } catch (Exception $ex) {
+ //トランザクションRollback
+ $this->rollback($ex);
+ }
+
+ return $link;
+ }
+
+/**
+ * Delete Link
+ *
+ * @param array $data received post data
+ * @return mixed On success Model::$data if its not empty or true, false on failure
+ * @throws InternalErrorException
+ */
+ public function deleteLink($data) {
+ $this->loadModels([
+ 'LinkOrder' => 'Links.LinkOrder',
+ ]);
+
+ //トランザクションBegin
+ $this->begin();
+
+ try {
+ $this->contentKey = $data['Link']['key'];
+ if (! $this->deleteAll(array($this->alias . '.key' => $data['Link']['key']), false, true)) {
+ throw new InternalErrorException(__d('net_commons', 'Internal Server Error'));
+ }
+
+ if (! $this->LinkOrder->delete($data['LinkOrder']['id'])) {
+ throw new InternalErrorException(__d('net_commons', 'Internal Server Error'));
+ }
+
+ //トランザクションCommit
+ $this->commit();
+
+ } catch (Exception $ex) {
+ //トランザクションRollback
+ $this->rollback($ex);
+ }
+
+ return true;
+ }
+
+/**
+ * クリック数の更新
+ *
+ * @param int $id links.id
+ * @return bool True on success, false on validation errors
+ * @throws InternalErrorException
+ */
+ public function updateCount($id) {
+ //トランザクションBegin
+ $this->begin();
+
+ try {
+ $result = $this->updateAll(
+ array(
+ $this->alias . '.click_count' => $this->alias . '.click_count + 1'
+ ),
+ array(
+ $this->alias . '.id' => $id,
+ $this->alias . '.block_id' => Current::read('Block.id'),
+ )
+ );
+ if (! $result) {
+ throw new InternalErrorException(__d('net_commons', 'Internal Server Error'));
+ }
+
+ //トランザクションCommit
+ $this->commit();
+
+ } catch (Exception $ex) {
+ //トランザクションRollback
+ $this->rollback($ex);
+ }
+
+ $this->setSlaveDataSource();
+
+ return true;
+ }
+
+}
diff --git a/Model/LinkBlock.php b/Model/LinkBlock.php
new file mode 100644
index 0000000..28dbb07
--- /dev/null
+++ b/Model/LinkBlock.php
@@ -0,0 +1,343 @@
+
+ * @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('BlockBaseModel', 'Blocks.Model');
+
+/**
+ * LinkBlock Model
+ *
+ * @author Shohei Nakajima
+ * @package NetCommons\Links\Model
+ */
+class LinkBlock extends BlockBaseModel {
+
+/**
+ * Custom database table name
+ *
+ * @var string
+ */
+ public $useTable = 'blocks';
+
+/**
+ * Validation rules
+ *
+ * @var array
+ */
+ public $validate = array();
+
+ //The Associations below have been created with all possible keys, those that are not needed can be removed
+
+/**
+ * belongsTo associations
+ *
+ * @var array
+ */
+ public $belongsTo = array(
+ 'Block' => array(
+ 'className' => 'Blocks.Block',
+ 'foreignKey' => 'id',
+ 'type' => 'INNER',
+ 'conditions' => '',
+ 'fields' => '',
+ 'order' => ''
+ )
+ );
+
+/**
+ * use behaviors
+ *
+ * @var array
+ */
+ public $actsAs = array(
+ 'Blocks.Block' => array(
+ 'name' => 'LinkBlock.name',
+ 'loadModels' => array(
+ 'BlockSetting' => 'Blocks.BlockSetting',
+ 'Category' => 'Categories.Category',
+ 'CategoryOrder' => 'Categories.CategoryOrder',
+ )
+ ),
+ 'Categories.Category',
+ 'NetCommons.OriginalKey',
+ //多言語
+ 'M17n.M17n',
+ );
+
+/**
+ * Array of virtual fields this model has. Virtual fields are aliased
+ * SQL expressions. Fields added to this property will be read as other fields in a model
+ * but will not be saveable.
+ *
+ * `public $virtualFields = array('two' => '1 + 1');`
+ *
+ * Is a simplistic example of how to set virtualFields
+ *
+ * @var array
+ * @link http://book.cakephp.org/2.0/ja/models/model-attributes.html#virtualfields
+ */
+ public $virtualFields = array(
+ 'language_id' => 'LinkBlocksLanguage.language_id',
+ 'name' => 'LinkBlocksLanguage.name',
+ 'block_id' => 'LinkBlock.id',
+ 'is_origin' => 'LinkBlocksLanguage.is_origin',
+ 'is_translation' => 'LinkBlocksLanguage.is_translation',
+ );
+
+/**
+ * Constructor
+ *
+ * @param bool|int|string|array $id Set this ID for this model on startup,
+ * can also be an array of options, see above.
+ * @param string $table Name of database table to use.
+ * @param string $ds DataSource connection name.
+ * @return void
+ * @SuppressWarnings(PHPMD.BooleanArgumentFlag)
+ */
+ public function __construct($id = false, $table = null, $ds = null) {
+ parent::__construct($id, $table, $ds);
+
+ $this->loadModels([
+ 'Link' => 'Links.Link',
+ 'LinkSetting' => 'Links.LinkSetting',
+ 'LinkOrder' => 'Links.LinkOrder',
+ ]);
+ }
+
+/**
+ * Called before each find operation. Return false if you want to halt the find
+ * call, otherwise return the (modified) query data.
+ *
+ * @param array $query Data used to execute this query, i.e. conditions, order, etc.
+ * @return mixed true if the operation should continue, false if it should abort; or, modified
+ * $query to continue with new $query
+ * @link http://book.cakephp.org/2.0/en/models/callback-methods.html#beforefind
+ */
+ public function beforeFind($query) {
+ if (! isset($this->belongsTo['BlocksLanguage'])) {
+ $belongsTo = $this->Block->bindModelBlockLang('LinkBlock.id');
+ $this->bindModel($belongsTo, true);
+ }
+
+ $this->bindModel(array(
+ 'belongsTo' => array(
+ 'LinkBlocksLanguage' => array(
+ 'className' => 'Blocks.BlocksLanguage',
+ 'foreignKey' => false,
+ 'type' => 'INNER',
+ 'conditions' => array(
+ 'LinkBlocksLanguage.id = BlocksLanguage.id',
+ //'LinkBlocksLanguage.language_id' => Current::read('Language.id', '0')
+ ),
+ 'fields' => array('LinkBlocksLanguage.language_id', 'LinkBlocksLanguage.name'),
+ 'order' => ''
+ ),
+ )
+ ), true);
+ return true;
+ }
+
+/**
+ * Called during validation operations, before validation. Please note that custom
+ * validation rules can be defined in $validate.
+ *
+ * @param array $options Options passed from Model::save().
+ * @return bool True if validate operation should continue, false to abort
+ * @link http://book.cakephp.org/2.0/en/models/callback-methods.html#beforevalidate
+ * @see Model::save()
+ */
+ public function beforeValidate($options = array()) {
+ $this->validate = array_merge($this->validate, array(
+ 'language_id' => array(
+ 'numeric' => array(
+ 'rule' => array('numeric'),
+ 'message' => __d('net_commons', 'Invalid request.'),
+ 'required' => false,
+ ),
+ ),
+ 'room_id' => array(
+ 'numeric' => array(
+ 'rule' => array('numeric'),
+ 'message' => __d('net_commons', 'Invalid request.'),
+ 'required' => false,
+ ),
+ ),
+ 'name' => array(
+ 'notBlank' => array(
+ 'rule' => array('notBlank'),
+ 'message' => sprintf(
+ __d('net_commons', 'Please input %s.'), __d('links', 'Link list Title')
+ ),
+ 'required' => true,
+ )
+ )
+ ));
+
+ if (isset($this->data['LinkSetting'])) {
+ $this->LinkSetting->set($this->data['LinkSetting']);
+ if (! $this->LinkSetting->validates()) {
+ $this->validationErrors = array_merge(
+ $this->validationErrors, $this->LinkSetting->validationErrors
+ );
+ return false;
+ }
+ }
+
+ return parent::beforeValidate($options);
+ }
+
+/**
+ * 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
+ * @link http://book.cakephp.org/2.0/en/models/callback-methods.html#aftersave
+ * @see Model::save()
+ * @throws InternalErrorException
+ */
+ public function afterSave($created, $options = array()) {
+ //LinkSetting登録
+ if (isset($this->data['LinkSetting'])) {
+ $this->LinkSetting->set($this->data['LinkSetting']);
+ $this->LinkSetting->save(null, false);
+ }
+ parent::afterSave($created, $options);
+ }
+
+/**
+ * LinkBlockデータ生成
+ *
+ * @return array LinkBlockデータ配列
+ */
+ public function createLinkBlock() {
+ $linkBlock = $this->createAll(array(
+ 'LinkBlock' => array(
+ 'language_id' => Current::read('Language.id'),
+ 'room_id' => Current::read('Room.id'),
+ 'name' => __d('links', 'New Bookmark List %s', date('YmdHis')),
+ ),
+ 'BlocksLanguage' => array(
+ 'language_id' => Current::read('Language.id'),
+ ),
+ ));
+ return ($linkBlock + $this->LinkSetting->createBlockSetting());
+ }
+
+/**
+ * LinkBlockデータ取得
+ *
+ * @param array $fields 取得するカラムリスト
+ * @return array LinkBlockデータ配列
+ */
+ public function getLinkBlock($fields = null) {
+ $linkBlock = $this->find('first', array(
+ 'fields' => $fields,
+ 'recursive' => 0,
+ 'conditions' => $this->getBlockConditionById(),
+ ));
+
+ if (! $linkBlock) {
+ return false;
+ }
+ return ($linkBlock + $this->LinkSetting->getLinkSetting());
+ }
+
+/**
+ * LinkBlock登録処理
+ *
+ * @param array $data received post data
+ * @return bool True on success, false on validation errors
+ * @throws InternalErrorException
+ */
+ public function saveLinkBlock($data) {
+ //トランザクションBegin
+ $this->begin();
+
+ //バリデーション
+ $this->set($data);
+ if (! $this->validates()) {
+ return false;
+ }
+
+ try {
+ //登録処理
+ if (isset($data[$this->alias]['id'])) {
+ if (! $this->save(null, false)) {
+ throw new InternalErrorException(__d('net_commons', 'Internal Server Error'));
+ }
+ } else {
+ //BlockBehaviorで登録するため、useTableをfalseにする
+ $this->useTable = false;
+ $this->save(null, false);
+ }
+
+ //トランザクションCommit
+ $this->commit();
+
+ } catch (Exception $ex) {
+ //トランザクションRollback
+ $this->rollback($ex);
+ }
+
+ return true;
+ }
+
+/**
+ * LinkBlockの削除処理
+ *
+ * @param array $data received post data
+ * @return mixed On success Model::$data if its not empty or true, false on failure
+ * @throws InternalErrorException
+ */
+ public function deleteLinkBlock($data) {
+ //トランザクションBegin
+ $this->begin();
+
+ $conditions = array(
+ $this->alias . '.key' => $data[$this->alias]['key']
+ );
+ $blocks = $this->find('list', array(
+ 'recursive' => -1,
+ 'conditions' => $conditions,
+ ));
+ $blocks = array_keys($blocks);
+
+ try {
+ $this->Link->blockKey = $data[$this->alias]['key'];
+ $conditions = array($this->Link->alias . '.block_id' => $blocks);
+ if (! $this->Link->deleteAll($conditions, false, true)) {
+ throw new InternalErrorException(__d('net_commons', 'Internal Server Error'));
+ }
+
+ $conditions = array($this->LinkOrder->alias . '.block_key' => $data[$this->alias]['key']);
+ if (! $this->LinkOrder->deleteAll($conditions, false)) {
+ throw new InternalErrorException(__d('net_commons', 'Internal Server Error'));
+ }
+
+ //Blockデータ削除
+ $this->deleteBlock($data[$this->alias]['key']);
+
+ //トランザクションCommit
+ $this->commit();
+
+ } catch (Exception $ex) {
+ //トランザクションRollback
+ $this->rollback($ex);
+ }
+
+ return true;
+ }
+
+}
diff --git a/Model/LinkFrameSetting.php b/Model/LinkFrameSetting.php
new file mode 100644
index 0000000..3ceb853
--- /dev/null
+++ b/Model/LinkFrameSetting.php
@@ -0,0 +1,313 @@
+
+ * @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('LinksAppModel', 'Links.Model');
+App::uses('Folder', 'Utility');
+
+/**
+ * LinkFrameSetting Model
+ *
+ * @author Shohei Nakajima
+ * @package NetCommons\Links\Model
+ */
+class LinkFrameSetting extends LinksAppModel {
+
+/**
+ * Type
+ *
+ * @var string
+ */
+ const
+ TYPE_DROPDOWN = '1',
+ TYPE_LIST_ONLY_TITLE = '2',
+ TYPE_LIST_WITH_DESCRIPTION = '3';
+
+/**
+ * categorySeparatorLine
+ *
+ * @var array
+ */
+ public $categorySeparators = array();
+
+/**
+ * categorySeparatorLine default
+ *
+ * @var string
+ */
+ const CATEGORY_SEPARATOR_DEFAULT = 'default';
+
+/**
+ * categorySeparatorLine default
+ *
+ * @var string
+ */
+ const LINE_STYLE_NONE = 'none',
+ LINE_STYLE_DISC = 'disc',
+ LINE_STYLE_CIRCLE = 'circle',
+ LINE_STYLE_LOWER_ALPHA = 'lower-alpha',
+ LINE_STYLE_UPPER_ALPHA = 'upper-alpha';
+
+/**
+ * listStyle
+ *
+ * @var array
+ */
+ public $listStyles = array();
+
+/**
+ * Validation rules
+ *
+ * @var array
+ */
+ public $validate = array();
+
+/**
+ * Constructor. Binds the model's database table to the object.
+ *
+ * @param bool|int|string|array $id Set this ID for this model on startup,
+ * can also be an array of options, see above.
+ * @param string $table Name of database table to use.
+ * @param string $ds DataSource connection name.
+ * @see Model::__construct()
+ * @SuppressWarnings(PHPMD.BooleanArgumentFlag)
+ */
+ public function __construct($id = false, $table = null, $ds = null) {
+ parent::__construct($id, $table, $ds);
+ $pluginDir = APP . 'Plugin' . DS . $this->plugin . DS . WEBROOT_DIR . DS . 'img' . DS;
+
+ //カテゴリ間の区切り線
+ $dir = new Folder($pluginDir . 'line');
+ $files = $dir->find('.*\..*');
+ $files = Hash::sort($files, '{n}', 'asc');
+
+ $this->categorySeparators = array(
+ null => array(
+ 'key' => null,
+ 'name' => __d('links', '(no line)'),
+ 'style' => null
+ ),
+ self::CATEGORY_SEPARATOR_DEFAULT => array(
+ 'key' => self::CATEGORY_SEPARATOR_DEFAULT,
+ 'name' => '',
+ 'style' => ''
+ )
+ );
+ foreach ($files as $file) {
+ $info = getimagesize($dir->pwd() . DS . $file);
+ $img = Router::url('/') . Inflector::underscore($this->plugin) . '/img/line/' . $file;
+ $this->categorySeparators[$file] = array(
+ 'key' => $file,
+ 'name' => '',
+ 'style' => 'background-image: url(' . $img . '); ' .
+ 'border-image: url(' . $img . '); ' . 'height: ' . $info[1] . 'px;',
+ );
+ }
+ unset($dir);
+
+ //線スタイル
+ $dir = new Folder($pluginDir . 'mark');
+ $files = $dir->find('.*\..*');
+ $files = Hash::sort($files, '{n}', 'asc');
+ $this->listStyles = array(
+ null => array(
+ 'key' => null,
+ 'name' => '',
+ 'style' => 'list-style-type: ' . self::LINE_STYLE_NONE . ';'
+ ),
+ self::LINE_STYLE_DISC => array(
+ 'key' => self::LINE_STYLE_DISC,
+ 'name' => '',
+ 'style' => 'list-style-type: ' . self::LINE_STYLE_DISC . ';'
+ ),
+ self::LINE_STYLE_CIRCLE => array(
+ 'key' => self::LINE_STYLE_CIRCLE,
+ 'name' => '',
+ 'style' => 'list-style-type: ' . self::LINE_STYLE_CIRCLE . ';'
+ ),
+ self::LINE_STYLE_LOWER_ALPHA => array(
+ 'key' => self::LINE_STYLE_LOWER_ALPHA,
+ 'name' => '',
+ 'style' => 'list-style-type: ' . self::LINE_STYLE_LOWER_ALPHA . ';'
+ ),
+ self::LINE_STYLE_UPPER_ALPHA => array(
+ 'key' => self::LINE_STYLE_UPPER_ALPHA,
+ 'name' => '',
+ 'style' => 'list-style-type: ' . self::LINE_STYLE_UPPER_ALPHA . ';'
+ ),
+ );
+
+ foreach ($files as $file) {
+ $info = getimagesize($dir->pwd() . DS . $file);
+ $img = Router::url('/') . Inflector::underscore($this->plugin) . '/img/mark/' . $file;
+ $this->listStyles[$file] = array(
+ 'key' => $file,
+ 'name' => '',
+ 'style' => 'list-style-type: none; ' . 'list-style-image: url(' . $img . '); '
+ );
+ }
+ unset($dir);
+ }
+
+/**
+ * Called during validation operations, before validation. Please note that custom
+ * validation rules can be defined in $validate.
+ *
+ * @param array $options Options passed from Model::save().
+ * @return bool True if validate operation should continue, false to abort
+ * @link http://book.cakephp.org/2.0/en/models/callback-methods.html#beforevalidate
+ * @see Model::save()
+ */
+ public function beforeValidate($options = array()) {
+ $this->validate = array_merge($this->validate, array(
+ 'frame_key' => array(
+ 'notBlank' => array(
+ 'rule' => array('notBlank'),
+ 'message' => __d('net_commons', 'Invalid request.'),
+ 'allowEmpty' => false,
+ 'required' => true,
+ 'on' => 'update', // Limit validation to 'create' or 'update' operations
+ ),
+ ),
+ 'display_type' => array(
+ 'numeric' => array(
+ 'rule' => array('numeric'),
+ 'message' => __d('net_commons', 'Invalid request.'),
+ 'allowEmpty' => false,
+ 'required' => true,
+ ),
+ 'inList' => array(
+ 'rule' => array('inList', array(
+ self::TYPE_DROPDOWN,
+ self::TYPE_LIST_ONLY_TITLE,
+ self::TYPE_LIST_WITH_DESCRIPTION
+ )),
+ 'message' => __d('net_commons', 'Invalid request.'),
+ )
+ ),
+ 'open_new_tab' => array(
+ 'boolean' => array(
+ 'rule' => array('boolean'),
+ 'message' => __d('net_commons', 'Invalid request.'),
+ ),
+ ),
+ 'display_click_count' => array(
+ 'boolean' => array(
+ 'rule' => array('boolean'),
+ 'message' => __d('net_commons', 'Invalid request.'),
+ ),
+ ),
+ 'category_separator_line' => array(
+ 'inList' => array(
+ 'rule' => array('inList',
+ array_keys($this->categorySeparators)
+ ),
+ 'message' => __d('net_commons', 'Invalid request.'),
+ 'allowEmpty' => true,
+ )
+ ),
+ 'list_style' => array(
+ 'inList' => array(
+ 'rule' => array('inList',
+ array_keys($this->listStyles)
+ ),
+ 'message' => __d('net_commons', 'Invalid request.'),
+ 'allowEmpty' => true,
+ )
+ ),
+ ));
+
+ return parent::beforeValidate($options);
+ }
+
+/**
+ * LinkFrameSettingデータ取得
+ *
+ * @param bool $created 作成フラグ
+ * @return array LinkFrameSettingデータ配列
+ */
+ public function getLinkFrameSetting($created) {
+ $conditions = array(
+ 'frame_key' => Current::read('Frame.key')
+ );
+
+ $linkFrameSetting = $this->find('first', array(
+ 'recursive' => -1,
+ 'conditions' => $conditions,
+ ));
+
+ if (! $linkFrameSetting) {
+ if ($created) {
+ $linkFrameSetting = $this->create(array(
+ 'category_separator_line' => self::CATEGORY_SEPARATOR_DEFAULT
+ ));
+ } else {
+ return $linkFrameSetting;
+ }
+ }
+
+ //カテゴリ間の区切り線
+ $separatorLine = $linkFrameSetting['LinkFrameSetting']['category_separator_line'];
+ if (isset($this->categorySeparators[$separatorLine])) {
+ $style = $this->categorySeparators[$separatorLine]['style'];
+ } else {
+ $style = null;
+ }
+ $linkFrameSetting['LinkFrameSetting']['category_separator_line_css'] = $style;
+
+ //リストマーク
+ $listStyle = $linkFrameSetting['LinkFrameSetting']['list_style'];
+ if (isset($this->listStyles[$listStyle])) {
+ $style = $this->listStyles[$listStyle]['style'];
+ } else {
+ $style = null;
+ }
+ $linkFrameSetting['LinkFrameSetting']['list_style_css'] = $style;
+
+ return $linkFrameSetting;
+ }
+
+/**
+ * LinkFrameSettingデータ登録処理
+ *
+ * @param array $data received post data
+ * @return bool True on success, false on failure
+ * @throws InternalErrorException
+ */
+ public function saveLinkFrameSetting($data) {
+ $this->loadModels([
+ 'LinkFrameSetting' => 'Links.LinkFrameSetting',
+ ]);
+
+ //トランザクションBegin
+ $this->begin();
+
+ //バリデーション
+ $this->set($data);
+ if (! $this->validates()) {
+ return false;
+ }
+
+ try {
+ if (! $this->save(null, false)) {
+ throw new InternalErrorException(__d('net_commons', 'Internal Server Error'));
+ }
+
+ //トランザクションCommit
+ $this->commit();
+
+ } catch (Exception $ex) {
+ //トランザクションRollback
+ $this->rollback($ex);
+ }
+
+ return true;
+ }
+}
diff --git a/Model/LinkListsAppModel.php b/Model/LinkListsAppModel.php
deleted file mode 100644
index d3679d3..0000000
--- a/Model/LinkListsAppModel.php
+++ /dev/null
@@ -1,7 +0,0 @@
-
+ * @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('LinksAppModel', 'Links.Model');
+
+/**
+ * LinkOrder Model
+ *
+ * @author Shohei Nakajima
+ * @package NetCommons\Links\Model
+ */
+class LinkOrder extends LinksAppModel {
+
+/**
+ * Validation rules
+ *
+ * @var array
+ */
+ public $validate = array();
+
+/**
+ * Called during validation operations, before validation. Please note that custom
+ * validation rules can be defined in $validate.
+ *
+ * @param array $options Options passed from Model::save().
+ * @return bool True if validate operation should continue, false to abort
+ * @link http://book.cakephp.org/2.0/en/models/callback-methods.html#beforevalidate
+ * @see Model::save()
+ */
+ public function beforeValidate($options = array()) {
+ $this->validate = array_merge($this->validate, array(
+ 'block_key' => array(
+ 'notBlank' => array(
+ 'rule' => array('notBlank'),
+ 'message' => __d('net_commons', 'Invalid request.'),
+ 'allowEmpty' => false,
+ 'required' => true,
+ 'on' => 'update', // Limit validation to 'create' or 'update' operations
+ ),
+ ),
+ 'link_key' => array(
+ 'notBlank' => array(
+ 'rule' => array('notBlank'),
+ 'message' => __d('net_commons', 'Invalid request.'),
+ 'allowEmpty' => false,
+ 'required' => true,
+ 'on' => 'update', // Limit validation to 'create' or 'update' operations
+ ),
+ ),
+ 'weight' => array(
+ 'numeric' => array(
+ 'rule' => array('numeric'),
+ 'message' => __d('net_commons', 'Invalid request.'),
+ 'allowEmpty' => false,
+ ),
+ ),
+ ));
+
+ return parent::beforeValidate($options);
+ }
+
+/**
+ * Called before each save operation, after validation. Return a non-true result
+ * to halt the save.
+ *
+ * @param array $options Options passed from Model::save().
+ * @return bool True if the operation should continue, false if it should abort
+ * @link http://book.cakephp.org/2.0/en/models/callback-methods.html#beforesave
+ * @see Model::save()
+ */
+ public function beforeSave($options = array()) {
+ if (isset($this->data[$this->alias]['link_key']) &&
+ ! isset($this->data[$this->alias]['weight']) &&
+ array_key_exists('category_key', $this->data[$this->alias])) {
+
+ $before = $this->find('first', array(
+ 'recursive' => -1,
+ 'fields' => array('category_key', 'weight'),
+ 'conditions' => array('link_key' => $this->data[$this->alias]['link_key']),
+ ));
+
+ if ($before) {
+ if ($before[$this->alias]['category_key'] !== $this->data[$this->alias]['category_key']) {
+ $this->updateAll(
+ array($this->alias . '.weight' => $this->alias . '.weight - 1'),
+ array(
+ $this->alias . '.weight > ' => $before[$this->alias]['weight'],
+ $this->alias . '.block_key' => Current::read('Block.key'),
+ $this->alias . '.category_key' => $before[$this->alias]['category_key'],
+ )
+ );
+ $this->data[$this->alias]['weight'] = $this->getMaxWeight(
+ $this->data[$this->alias]['category_key']) + 1;
+ }
+ } elseif (! $this->id) {
+ $this->data[$this->alias]['weight'] = $this->getMaxWeight(
+ $this->data[$this->alias]['category_key']) + 1;
+ }
+ }
+
+ return true;
+ }
+
+/**
+ * Called before every deletion operation.
+ *
+ * @param bool $cascade If true records that depend on this record will also be deleted
+ * @return bool True if the operation should continue, false if it should abort
+ * @link http://book.cakephp.org/2.0/en/models/callback-methods.html#beforedelete
+ * @SuppressWarnings(PHPMD.BooleanArgumentFlag)
+ */
+ public function beforeDelete($cascade = true) {
+ if ($this->id) {
+ $before = $this->find('first', array(
+ 'recursive' => -1,
+ 'fields' => array('block_key', 'category_key', 'weight'),
+ 'conditions' => array('id' => $this->id),
+ ));
+
+ $this->updateAll(
+ array($this->alias . '.weight' => $this->alias . '.weight - 1'),
+ array(
+ $this->alias . '.weight > ' => $before[$this->alias]['weight'],
+ $this->alias . '.block_key' => $before[$this->alias]['block_key'],
+ $this->alias . '.category_key' => $before[$this->alias]['category_key'],
+ )
+ );
+ }
+ return true;
+ }
+
+/**
+ * Category毎の表示順序
+ *
+ * @param string $categoryKey Category.key
+ * @return int $weight LinkOrders.weight
+ */
+ public function getMaxWeight($categoryKey) {
+ $order = $this->find('first', array(
+ 'recursive' => -1,
+ 'fields' => array('weight'),
+ 'conditions' => array(
+ 'block_key' => Current::read('Block.key'),
+ 'category_key' => $categoryKey
+ ),
+ 'order' => array('weight' => 'DESC')
+ ));
+
+ if (isset($order[$this->alias]['weight'])) {
+ $weight = (int)$order[$this->alias]['weight'];
+ } else {
+ $weight = 0;
+ }
+ return $weight;
+ }
+
+/**
+ * Save LinkOrder
+ *
+ * @param array $data received post data
+ * @return bool True on success, false on validation errors
+ * @throws InternalErrorException
+ */
+ public function saveLinkOrders($data) {
+ //トランザクションBegin
+ $this->begin();
+
+ //バリデーション
+ if (! $this->validateMany($data['LinkOrders'])) {
+ return false;
+ }
+
+ try {
+ //登録処理
+ if (! $this->saveMany($data['LinkOrders'], ['validate' => false])) {
+ throw new InternalErrorException(__d('net_commons', 'Internal Server Error'));
+ }
+
+ //トランザクションCommit
+ $this->commit();
+
+ } catch (Exception $ex) {
+ //トランザクションRollback
+ $this->rollback($ex);
+ }
+
+ return true;
+ }
+}
diff --git a/Model/LinkSetting.php b/Model/LinkSetting.php
new file mode 100644
index 0000000..448b34e
--- /dev/null
+++ b/Model/LinkSetting.php
@@ -0,0 +1,93 @@
+
+ * @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('BlockSettingBehavior', 'Blocks.Model/Behavior');
+App::uses('BlockBaseModel', 'Blocks.Model');
+
+/**
+ * LinkSetting Model
+ *
+ * @author Shohei Nakajima
+ * @package NetCommons\Links\Model
+ */
+class LinkSetting extends BlockBaseModel {
+
+/**
+ * Custom database table name
+ *
+ * @var string
+ */
+ public $useTable = false;
+
+/**
+ * Validation rules
+ *
+ * @var array
+ */
+ public $validate = array();
+
+/**
+ * use behaviors
+ *
+ * @var array
+ */
+ public $actsAs = array(
+ 'Blocks.BlockRolePermission',
+ 'Blocks.BlockSetting' => array(
+ BlockSettingBehavior::FIELD_USE_WORKFLOW,
+ ),
+ );
+
+/**
+ * LinkSettingデータ取得
+ *
+ * @return array
+ * @see BlockSettingBehavior::getBlockSetting() 取得
+ */
+ public function getLinkSetting() {
+ return $this->getBlockSetting();
+ }
+
+/**
+ * Save link settings
+ *
+ * @param array $data received post data
+ * @return bool True on success, false on failure
+ * @throws InternalErrorException
+ */
+ public function saveLinkSetting($data) {
+ //トランザクションBegin
+ $this->begin();
+
+ //バリデーション
+ $this->set($data);
+ if (! $this->validates()) {
+ return false;
+ }
+
+ try {
+ // useTable = falseでsaveすると必ずfalseになるので、throwさせない
+ // BlockBaseModel継承によりuseTable = falseでも beforeSave(), afterSave()が実行されるため、
+ // behaviorsのbeforeSave(), afterSave()も実行される
+ $this->save(null, false);
+
+ //トランザクションCommit
+ $this->commit();
+
+ } catch (Exception $ex) {
+ //トランザクションRollback
+ $this->rollback($ex);
+ }
+
+ return true;
+ }
+
+}
diff --git a/Model/Linklist.php b/Model/Linklist.php
deleted file mode 100644
index 37e50b9..0000000
--- a/Model/Linklist.php
+++ /dev/null
@@ -1,139 +0,0 @@
-
-* @link http://www.netcommons.org NetCommons Project
-* @license http://www.netcommons.org/license.txt NetCommons License
- */
-
-App::uses('LinkListsAppModel', 'LinkLists.Model');
-
-/**
- * Summary for Linklist Model
- */
-class Linklist extends LinkListsAppModel {
-
-/**
- * Use database config
- *
- * @var string
- */
- public $useDbConfig = 'master';
-
-/**
- * Validation rules
- *
- * @var array
- */
- public $validate = array(
- 'linklists_block_id' => array(
- 'numeric' => array(
- 'rule' => array('numeric'),
- //'message' => 'Your custom message here',
- //'allowEmpty' => false,
- //'required' => false,
- //'last' => false, // Stop validation after this rule
- //'on' => 'create', // Limit validation to 'create' or 'update' operations
- ),
- ),
- 'status' => array(
- 'numeric' => array(
- 'rule' => array('numeric'),
- //'message' => 'Your custom message here',
- //'allowEmpty' => false,
- //'required' => false,
- //'last' => false, // Stop validation after this rule
- //'on' => 'create', // Limit validation to 'create' or 'update' operations
- ),
- ),
- 'language_id' => array(
- 'numeric' => array(
- 'rule' => array('numeric'),
- //'message' => 'Your custom message here',
- //'allowEmpty' => false,
- //'required' => false,
- //'last' => false, // Stop validation after this rule
- //'on' => 'create', // Limit validation to 'create' or 'update' operations
- ),
- ),
- 'is_auto_translated' => array(
- 'boolean' => array(
- 'rule' => array('boolean'),
- //'message' => 'Your custom message here',
- //'allowEmpty' => false,
- //'required' => false,
- //'last' => false, // Stop validation after this rule
- //'on' => 'create', // Limit validation to 'create' or 'update' operations
- ),
- ),
- 'url' => array(
- 'notEmpty' => array(
- 'rule' => array('notEmpty'),
- //'message' => 'Your custom message here',
- //'allowEmpty' => false,
- //'required' => false,
- //'last' => false, // Stop validation after this rule
- //'on' => 'create', // Limit validation to 'create' or 'update' operations
- ),
- ),
- );
-
- //The Associations below have been created with all possible keys, those that are not needed can be removed
-
-/**
- * belongsTo associations
- *
- * @var array
- */
- public $belongsTo = array(
- 'LinklistsBlock' => array(
- 'className' => 'LinklistsBlock',
- 'foreignKey' => 'linklists_block_id',
- 'conditions' => '',
- 'fields' => '',
- 'order' => ''
- ),
- 'Language' => array(
- 'className' => 'Language',
- 'foreignKey' => 'language_id',
- 'conditions' => '',
- 'fields' => '',
- 'order' => ''
- ),
- 'LinklistsCategory' => array(
- 'className' => 'LinklistsCategory',
- 'foreignKey' => 'linklists_category_id',
- 'conditions' => '',
- 'fields' => '',
- 'order' => ''
- )
- );
-
-/**
- * hasAndBelongsToMany associations
- *
- * @var array
- */
- public $hasAndBelongsToMany = array(
- 'Block' => array(
- 'className' => 'Block',
- 'joinTable' => 'linklists_blocks',
- 'foreignKey' => 'linklist_id',
- 'associationForeignKey' => 'block_id',
- 'unique' => 'keepExisting',
- 'conditions' => '',
- 'fields' => '',
- 'order' => '',
- 'limit' => '',
- 'offset' => '',
- 'finderQuery' => '',
- )
- );
-
-}
diff --git a/Model/LinklistPartSetting.php b/Model/LinklistPartSetting.php
deleted file mode 100644
index 870aacc..0000000
--- a/Model/LinklistPartSetting.php
+++ /dev/null
@@ -1,118 +0,0 @@
-
-* @link http://www.netcommons.org NetCommons Project
-* @license http://www.netcommons.org/license.txt NetCommons License
- */
-
-App::uses('LinkListsAppModel', 'LinkLists.Model');
-
-/**
- * Summary for LinklistPartSetting Model
- */
-class LinklistPartSetting extends LinkListsAppModel {
-
-/**
- * Use database config
- *
- * @var string
- */
- public $useDbConfig = 'master';
-
-/**
- * Validation rules
- *
- * @var array
- */
- public $validate = array(
- 'linklist_block_id' => array(
- 'numeric' => array(
- 'rule' => array('numeric'),
- //'message' => 'Your custom message here',
- //'allowEmpty' => false,
- //'required' => false,
- //'last' => false, // Stop validation after this rule
- //'on' => 'create', // Limit validation to 'create' or 'update' operations
- ),
- ),
- 'part_id' => array(
- 'numeric' => array(
- 'rule' => array('numeric'),
- //'message' => 'Your custom message here',
- //'allowEmpty' => false,
- //'required' => false,
- //'last' => false, // Stop validation after this rule
- //'on' => 'create', // Limit validation to 'create' or 'update' operations
- ),
- ),
- 'readable_content' => array(
- 'boolean' => array(
- 'rule' => array('boolean'),
- //'message' => 'Your custom message here',
- //'allowEmpty' => false,
- //'required' => false,
- //'last' => false, // Stop validation after this rule
- //'on' => 'create', // Limit validation to 'create' or 'update' operations
- ),
- ),
- 'editable_content' => array(
- 'boolean' => array(
- 'rule' => array('boolean'),
- //'message' => 'Your custom message here',
- //'allowEmpty' => false,
- //'required' => false,
- //'last' => false, // Stop validation after this rule
- //'on' => 'create', // Limit validation to 'create' or 'update' operations
- ),
- ),
- 'creatable_content' => array(
- 'boolean' => array(
- 'rule' => array('boolean'),
- //'message' => 'Your custom message here',
- //'allowEmpty' => false,
- //'required' => false,
- //'last' => false, // Stop validation after this rule
- //'on' => 'create', // Limit validation to 'create' or 'update' operations
- ),
- ),
- 'publishable_content' => array(
- 'boolean' => array(
- 'rule' => array('boolean'),
- //'message' => 'Your custom message here',
- //'allowEmpty' => false,
- //'required' => false,
- //'last' => false, // Stop validation after this rule
- //'on' => 'create', // Limit validation to 'create' or 'update' operations
- ),
- ),
- );
-
- //The Associations below have been created with all possible keys, those that are not needed can be removed
-
-/**
- * belongsTo associations
- *
- * @var array
- */
- public $belongsTo = array(
- 'LinklistBlock' => array(
- 'className' => 'LinklistBlock',
- 'foreignKey' => 'linklist_block_id',
- 'conditions' => '',
- 'fields' => '',
- 'order' => ''
- ),
- 'Part' => array(
- 'className' => 'Part',
- 'foreignKey' => 'part_id',
- 'conditions' => '',
- 'fields' => '',
- 'order' => ''
- )
- );
-}
diff --git a/Model/LinklistSetting.php b/Model/LinklistSetting.php
deleted file mode 100644
index e44285c..0000000
--- a/Model/LinklistSetting.php
+++ /dev/null
@@ -1,60 +0,0 @@
-
-* @link http://www.netcommons.org NetCommons Project
-* @license http://www.netcommons.org/license.txt NetCommons License
- */
-
-App::uses('LinkListsAppModel', 'LinkLists.Model');
-
-/**
- * Summary for LinklistSetting Model
- */
-class LinklistSetting extends LinkListsAppModel {
-
-/**
- * Use database config
- *
- * @var string
- */
- public $useDbConfig = 'master';
-
-/**
- * Validation rules
- *
- * @var array
- */
- public $validate = array(
- 'linklist_block_id' => array(
- 'numeric' => array(
- 'rule' => array('numeric'),
- //'message' => 'Your custom message here',
- //'allowEmpty' => false,
- //'required' => false,
- //'last' => false, // Stop validation after this rule
- //'on' => 'create', // Limit validation to 'create' or 'update' operations
- ),
- ),
- );
-
- //The Associations below have been created with all possible keys, those that are not needed can be removed
-
-/**
- * belongsTo associations
- *
- * @var array
- */
- public $belongsTo = array(
- 'LinklistBlock' => array(
- 'className' => 'LinklistBlock',
- 'foreignKey' => 'linklist_block_id',
- 'conditions' => '',
- 'fields' => '',
- 'order' => ''
- )
- );
-}
diff --git a/Model/LinklistsBlock.php b/Model/LinklistsBlock.php
deleted file mode 100644
index f047f9b..0000000
--- a/Model/LinklistsBlock.php
+++ /dev/null
@@ -1,97 +0,0 @@
-
-* @link http://www.netcommons.org NetCommons Project
-* @license http://www.netcommons.org/license.txt NetCommons License
- */
-
-App::uses('LinkListsAppModel', 'LinkLists.Model');
-
-/**
- * Summary for LinklistsBlock Model
- */
-class LinklistsBlock extends LinkListsAppModel {
-
-/**
- * Use database config
- *
- * @var string
- */
- public $useDbConfig = 'master';
-
-/**
- * Validation rules
- *
- * @var array
- */
- public $validate = array(
- 'block_id' => array(
- 'numeric' => array(
- 'rule' => array('numeric'),
- //'message' => 'Your custom message here',
- //'allowEmpty' => false,
- //'required' => false,
- //'last' => false, // Stop validation after this rule
- //'on' => 'create', // Limit validation to 'create' or 'update' operations
- ),
- ),
- );
-
- //The Associations below have been created with all possible keys, those that are not needed can be removed
-
-/**
- * belongsTo associations
- *
- * @var array
- */
- public $belongsTo = array(
- 'Block' => array(
- 'className' => 'Block',
- 'foreignKey' => 'block_id',
- 'conditions' => '',
- 'fields' => '',
- 'order' => ''
- )
- );
-
-/**
- * hasMany associations
- *
- * @var array
- */
- public $hasMany = array(
- 'Linklist' => array(
- 'className' => 'Linklist',
- 'foreignKey' => 'linklists_block_id',
- 'dependent' => false,
- 'conditions' => '',
- 'fields' => '',
- 'order' => '',
- 'limit' => '',
- 'offset' => '',
- 'exclusive' => '',
- 'finderQuery' => '',
- 'counterQuery' => ''
- ),
- 'LinklistsCategory' => array(
- 'className' => 'LinklistsCategory',
- 'foreignKey' => 'linklists_block_id',
- 'dependent' => false,
- 'conditions' => '',
- 'fields' => '',
- 'order' => '',
- 'limit' => '',
- 'offset' => '',
- 'exclusive' => '',
- 'finderQuery' => '',
- 'counterQuery' => ''
- )
- );
-
-}
diff --git a/Model/LinklistsCategory.php b/Model/LinklistsCategory.php
deleted file mode 100644
index 9405527..0000000
--- a/Model/LinklistsCategory.php
+++ /dev/null
@@ -1,121 +0,0 @@
-
-* @link http://www.netcommons.org NetCommons Project
-* @license http://www.netcommons.org/license.txt NetCommons License
- */
-
-App::uses('LinkListsAppModel', 'LinkLists.Model');
-
-/**
- * Summary for LinklistsCategory Model
- */
-class LinklistsCategory extends LinkListsAppModel {
-
-/**
- * Use database config
- *
- * @var string
- */
- public $useDbConfig = 'master';
-
-/**
- * Validation rules
- *
- * @var array
- */
- public $validate = array(
- 'linklists_block_id' => array(
- 'numeric' => array(
- 'rule' => array('numeric'),
- //'message' => 'Your custom message here',
- //'allowEmpty' => false,
- //'required' => false,
- //'last' => false, // Stop validation after this rule
- //'on' => 'create', // Limit validation to 'create' or 'update' operations
- ),
- ),
- 'status' => array(
- 'numeric' => array(
- 'rule' => array('numeric'),
- //'message' => 'Your custom message here',
- //'allowEmpty' => false,
- //'required' => false,
- //'last' => false, // Stop validation after this rule
- //'on' => 'create', // Limit validation to 'create' or 'update' operations
- ),
- ),
- 'language_id' => array(
- 'numeric' => array(
- 'rule' => array('numeric'),
- //'message' => 'Your custom message here',
- //'allowEmpty' => false,
- //'required' => false,
- //'last' => false, // Stop validation after this rule
- //'on' => 'create', // Limit validation to 'create' or 'update' operations
- ),
- ),
- 'is_auto_translated' => array(
- 'boolean' => array(
- 'rule' => array('boolean'),
- //'message' => 'Your custom message here',
- //'allowEmpty' => false,
- //'required' => false,
- //'last' => false, // Stop validation after this rule
- //'on' => 'create', // Limit validation to 'create' or 'update' operations
- ),
- ),
- );
-
- //The Associations below have been created with all possible keys, those that are not needed can be removed
-
-/**
- * belongsTo associations
- *
- * @var array
- */
- public $belongsTo = array(
- 'LinklistsBlock' => array(
- 'className' => 'LinklistsBlock',
- 'foreignKey' => 'linklists_block_id',
- 'conditions' => '',
- 'fields' => '',
- 'order' => ''
- ),
- 'Language' => array(
- 'className' => 'Language',
- 'foreignKey' => 'language_id',
- 'conditions' => '',
- 'fields' => '',
- 'order' => ''
- )
- );
-
-/**
- * hasMany associations
- *
- * @var array
- */
- public $hasMany = array(
- 'Linklist' => array(
- 'className' => 'Linklist',
- 'foreignKey' => 'linklists_category_id',
- 'dependent' => false,
- 'conditions' => '',
- 'fields' => '',
- 'order' => '',
- 'limit' => '',
- 'offset' => '',
- 'exclusive' => '',
- 'finderQuery' => '',
- 'counterQuery' => ''
- )
- );
-
-}
diff --git a/Model/LinksAppModel.php b/Model/LinksAppModel.php
new file mode 100644
index 0000000..565806f
--- /dev/null
+++ b/Model/LinksAppModel.php
@@ -0,0 +1,22 @@
+
+ * @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('AppModel', 'Model');
+
+/**
+ * LinkApp Model
+ *
+ * @author Shohei Nakajima
+ * @package NetCommons\Links\Model
+ */
+class LinksAppModel extends AppModel {
+
+}
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..c94eec2
--- /dev/null
+++ b/README.md
@@ -0,0 +1,6 @@
+Links
+==============
+
+[](https://github.com/NetCommons3/Links/actions/workflows/tests.yml)
+[](https://coveralls.io/r/NetCommons3/Links?branch=master)
+[](https://packagist.org/packages/netcommons/links)
diff --git a/Test/Case/AllLinksTest.php b/Test/Case/AllLinksTest.php
new file mode 100644
index 0000000..96a353a
--- /dev/null
+++ b/Test/Case/AllLinksTest.php
@@ -0,0 +1,33 @@
+
+ * @link http://www.netcommons.org NetCommons Project
+ * @license http://www.netcommons.org/license.txt NetCommons License
+ * @copyright Copyright 2014, NetCommons Project
+ */
+
+App::uses('NetCommonsTestSuite', 'NetCommons.TestSuite');
+
+/**
+ * Links All Test Suite
+ *
+ * @author Shohei Nakajima
+ * @package NetCommons\Links\Test\Case
+ * @codeCoverageIgnore
+ */
+class AllLinksTest extends NetCommonsTestSuite {
+
+/**
+ * All test suite
+ *
+ * @return NetCommonsTestSuite
+ */
+ public static function suite() {
+ $plugin = preg_replace('/^All([\w]+)Test$/', '$1', __CLASS__);
+ $suite = new NetCommonsTestSuite(sprintf('All %s Plugin tests', $plugin));
+ $suite->addTestDirectoryRecursive(CakePlugin::path($plugin) . 'Test' . DS . 'Case');
+ return $suite;
+ }
+}
diff --git a/Test/Case/Controller/Component/empty b/Test/Case/Controller/Component/empty
deleted file mode 100644
index e69de29..0000000
diff --git a/Test/Case/Controller/LinkBlockRolePermissionsController/EditTest.php b/Test/Case/Controller/LinkBlockRolePermissionsController/EditTest.php
new file mode 100644
index 0000000..cc49d93
--- /dev/null
+++ b/Test/Case/Controller/LinkBlockRolePermissionsController/EditTest.php
@@ -0,0 +1,154 @@
+
+ * @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('BlockRolePermissionsControllerEditTest', 'Blocks.TestSuite');
+
+/**
+ * LinkBlockRolePermissionsController::edit()のテスト
+ *
+ * @author Shohei Nakajima
+ * @package NetCommons\Links\Test\Case\Controller\LinkBlockRolePermissionsController
+ */
+class LinkBlockRolePermissionsControllerEditTest extends BlockRolePermissionsControllerEditTest {
+
+/**
+ * Fixtures
+ *
+ * @var array
+ */
+ public $fixtures = array(
+ 'plugin.categories.category',
+ 'plugin.categories.category_order',
+ 'plugin.categories.categories_language',
+ 'plugin.links.link',
+ 'plugin.links.link_frame_setting',
+ 'plugin.links.link_order',
+ 'plugin.links.block_setting_for_link',
+ 'plugin.workflow.workflow_comment',
+ );
+
+/**
+ * Plugin name
+ *
+ * @var string
+ */
+ public $plugin = 'links';
+
+/**
+ * Controller name
+ *
+ * @var string
+ */
+ protected $_controller = 'link_block_role_permissions';
+
+/**
+ * 権限設定で使用するFieldsの取得
+ *
+ * @return array
+ */
+ private function __approvalFields() {
+ $data = array(
+ 'LinkSetting' => array(
+ 'use_workflow',
+ 'approval_type',
+ )
+ );
+
+ return $data;
+ }
+
+/**
+ * テストDataの取得
+ *
+ * @return array
+ */
+ private function __data() {
+ $data = array(
+ 'LinkSetting' => array(
+ 'id' => 2,
+ 'block_key' => 'block_2',
+ 'use_workflow' => '1',
+ 'approval_type' => '1',
+ )
+ );
+
+ return $data;
+ }
+
+/**
+ * edit()アクションDataProvider
+ *
+ * ### 戻り値
+ * - approvalFields コンテンツ承認の利用有無のフィールド
+ * - exception Exception
+ * - return testActionの実行後の結果
+ *
+ * @return array
+ */
+ public function dataProviderEditGet() {
+ return array(
+ array('approvalFields' => $this->__approvalFields())
+ );
+ }
+
+/**
+ * editアクションのGETテスト(Exceptionエラー)
+ *
+ * @param array $approvalFields コンテンツ承認の利用有無のフィールド
+ * @param string|null $exception Exception
+ * @param string $return testActionの実行後の結果
+ * @dataProvider dataProviderEditGet
+ * @return void
+ */
+
+ public function testEditGetExceptionError($approvalFields, $exception = null, $return = 'view') {
+ $this->_mockForReturnFalse('Links.LinkBlock', 'getLinkBlock');
+
+ $exception = 'BadRequestException';
+ $this->testEditGet($approvalFields, $exception, $return);
+ }
+
+/**
+ * edit()アクションDataProvider
+ *
+ * ### 戻り値
+ * - data POSTデータ
+ * - exception Exception
+ * - return testActionの実行後の結果
+ *
+ * @return array
+ */
+ public function dataProviderEditPost() {
+ return array(
+ array('data' => $this->__data())
+ );
+ }
+
+/**
+ * editアクションのPOSTテスト(Saveエラー)
+ *
+ * @param array $data POSTデータ
+ * @param string|null $exception Exception
+ * @param string $return testActionの実行後の結果
+ * @dataProvider dataProviderEditPost
+ * @return void
+ */
+ public function testEditPostSaveError($data, $exception = null, $return = 'view') {
+ $data['BlockRolePermission']['content_creatable'][Role::ROOM_ROLE_KEY_GENERAL_USER]['roles_room_id'] = 'aaaa';
+
+ //テスト実施
+ $result = $this->testEditPost($data, false, $return);
+
+ $approvalFields = $this->__approvalFields();
+ $this->_assertEditGetPermission($approvalFields, $result);
+ }
+
+}
diff --git a/Test/Case/Controller/LinkBlocksController/BeforeFilterTest.php b/Test/Case/Controller/LinkBlocksController/BeforeFilterTest.php
new file mode 100644
index 0000000..c64f7ae
--- /dev/null
+++ b/Test/Case/Controller/LinkBlocksController/BeforeFilterTest.php
@@ -0,0 +1,94 @@
+
+ * @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('NetCommonsControllerTestCase', 'NetCommons.TestSuite');
+
+/**
+ * LinkBlocksController::beforeFilter()のテスト
+ *
+ * @author Shohei Nakajima
+ * @package NetCommons\Links\Test\Case\Controller\LinkBlocksController
+ */
+class LinkBlocksControllerBeforeFilterTest extends NetCommonsControllerTestCase {
+
+/**
+ * Fixtures
+ *
+ * @var array
+ */
+ public $fixtures = array(
+ 'plugin.categories.category',
+ 'plugin.categories.category_order',
+ 'plugin.categories.categories_language',
+ 'plugin.links.link',
+ 'plugin.links.link_frame_setting',
+ 'plugin.links.link_order',
+ 'plugin.links.block_setting_for_link',
+ 'plugin.workflow.workflow_comment',
+ );
+
+/**
+ * Plugin name
+ *
+ * @var string
+ */
+ public $plugin = 'links';
+
+/**
+ * Controller name
+ *
+ * @var string
+ */
+ protected $_controller = 'link_blocks';
+
+/**
+ * index()アクションのテスト
+ *
+ * @return void
+ */
+ public function testBeforeFilterIndex() {
+ //ログイン
+ TestAuthGeneral::login($this);
+
+ //テスト実行
+ $this->_testGetAction(array('action' => 'index', 'block_id' => '2', 'frame_id' => '6'),
+ array('method' => 'assertNotEmpty'), null, 'view');
+
+ //チェック
+ $this->assertFalse($this->controller->Components->loaded('Categories.CategoryEdit'));
+ $this->assertNotEmpty($this->view);
+
+ //ログアウト
+ TestAuthGeneral::logout($this);
+ }
+
+/**
+ * index()アクションのテスト
+ *
+ * @return void
+ */
+ public function testBeforeFilterEdit() {
+ //ログイン
+ TestAuthGeneral::login($this);
+
+ //テスト実行
+ $this->_testGetAction(array('action' => 'edit', 'block_id' => '2', 'frame_id' => '6'),
+ array('method' => 'assertNotEmpty'), null, 'view');
+
+ //チェック
+ $this->assertTrue($this->controller->Components->loaded('Categories.CategoryEdit'));
+ $this->assertNotEmpty($this->view);
+
+ //ログアウト
+ TestAuthGeneral::logout($this);
+ }
+
+}
diff --git a/Test/Case/Controller/LinkBlocksController/EditTest.php b/Test/Case/Controller/LinkBlocksController/EditTest.php
new file mode 100644
index 0000000..4e49383
--- /dev/null
+++ b/Test/Case/Controller/LinkBlocksController/EditTest.php
@@ -0,0 +1,230 @@
+
+ * @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('BlocksControllerEditTest', 'Blocks.TestSuite');
+
+/**
+ * LinkBlocksController::edit()のテスト
+ *
+ * @author Shohei Nakajima
+ * @package NetCommons\Links\Test\Case\Controller\LinkBlocksController
+ */
+class LinkBlocksControllerEditTest extends BlocksControllerEditTest {
+
+/**
+ * Fixtures
+ *
+ * @var array
+ */
+ public $fixtures = array(
+ 'plugin.categories.category',
+ 'plugin.categories.category_order',
+ 'plugin.categories.categories_language',
+ 'plugin.links.link',
+ 'plugin.links.link_frame_setting',
+ 'plugin.links.link_order',
+ 'plugin.links.block_setting_for_link',
+ 'plugin.workflow.workflow_comment',
+ );
+
+/**
+ * Plugin name
+ *
+ * @var string
+ */
+ public $plugin = 'links';
+
+/**
+ * Controller name
+ *
+ * @var string
+ */
+ protected $_controller = 'link_blocks';
+
+/**
+ * Edit controller name
+ *
+ * @var string
+ */
+ protected $_editController = 'link_blocks';
+
+/**
+ * テストDataの取得
+ *
+ * @param bool $isEdit 編集かどうか
+ * @return array
+ */
+ private function __data($isEdit) {
+ $frameId = '6';
+ if ($isEdit) {
+ $blockId = '2';
+ $blockKey = 'block_2';
+ $linkId = '3';
+ $linkKey = $blockKey;
+ } else {
+ $blockId = null;
+ $blockKey = null;
+ $linkId = null;
+ $linkKey = $blockKey;
+ }
+
+ $data = array(
+ 'Frame' => array(
+ 'id' => $frameId
+ ),
+ 'Block' => array(
+ 'id' => $blockId,
+ 'key' => $blockKey,
+ 'language_id' => '2',
+ 'room_id' => '2',
+ 'plugin_key' => $this->plugin,
+ 'public_type' => '1',
+ 'from' => null,
+ 'to' => null,
+ ),
+ 'LinkSetting' => array(
+ 'id' => $linkId,
+ 'block_key' => $linkKey,
+ ),
+ 'LinkBlock' => array(
+ 'id' => $blockId,
+ 'key' => $blockKey,
+ 'name' => 'Link name',
+ ),
+ );
+
+ return $data;
+ }
+
+/**
+ * add()アクションDataProvider
+ *
+ * ### 戻り値
+ * - method: リクエストメソッド(get or post or put)
+ * - data: 登録データ
+ * - validationError: バリデーションエラー
+ *
+ * @return array
+ */
+ public function dataProviderAdd() {
+ $data = $this->__data(false);
+
+ //テストデータ
+ $results = array();
+ $results[0] = array('method' => 'get');
+ $results[1] = array('method' => 'put');
+ $results[2] = array('method' => 'post', 'data' => $data, 'validationError' => false);
+ $results[3] = array('method' => 'post', 'data' => $data,
+ 'validationError' => array(
+ 'field' => 'LinkBlock.name',
+ 'value' => '',
+ 'message' => sprintf(__d('net_commons', 'Please input %s.'), __d('links', 'Link list Title')),
+ )
+ );
+
+ return $results;
+ }
+
+/**
+ * edit()アクションDataProvider
+ *
+ * ### 戻り値
+ * - method: リクエストメソッド(get or post or put)
+ * - data: 登録データ
+ * - validationError: バリデーションエラー
+ *
+ * @return array
+ */
+ public function dataProviderEdit() {
+ $data = $this->__data(true);
+
+ //テストデータ
+ $results = array();
+ $results[0] = array('method' => 'get');
+ $results[1] = array('method' => 'post');
+ $results[2] = array('method' => 'put', 'data' => $data, 'validationError' => false);
+ $results[3] = array('method' => 'put', 'data' => $data,
+ 'validationError' => array(
+ 'field' => 'LinkBlock.name',
+ 'value' => '',
+ 'message' => sprintf(__d('net_commons', 'Please input %s.'), __d('links', 'Link list Title')),
+ )
+ );
+
+ return $results;
+ }
+
+/**
+ * edit()アクションのExceptionErrorテスト
+ *
+ * @return void
+ */
+ public function testEditGetOnExceptionError() {
+ //ログイン
+ TestAuthGeneral::login($this);
+
+ //テストデータ
+ $this->_mockForReturnFalse('Links.LinkBlock', 'getLinkBlock');
+
+ //テスト実行
+ $this->_testGetAction(array('action' => 'edit', 'block_id' => '2', 'frame_id' => '6'), null, 'BadRequestException');
+
+ //ログアウト
+ TestAuthGeneral::logout($this);
+ }
+
+/**
+ * delete()アクションDataProvider
+ *
+ * ### 戻り値
+ * - data 削除データ
+ *
+ * @return array
+ */
+ public function dataProviderDelete() {
+ $data = array(
+ 'Block' => array(
+ 'id' => '4',
+ 'key' => 'block_2',
+ ),
+ 'LinkBlock' => array(
+ 'key' => 'block_2',
+ ),
+ );
+
+ //テストデータ
+ $results = array();
+ $results[0] = array('data' => $data);
+
+ return $results;
+ }
+
+/**
+ * delete()アクションのExceptionErrorテスト
+ *
+ * @return void
+ */
+ public function testDeleteOnExceptionError() {
+ //ログイン
+ TestAuthGeneral::login($this);
+
+ //テストデータ
+ $this->_mockForReturnFalse('Links.LinkBlock', 'deleteLinkBlock');
+
+ //テスト実行
+ $data = $this->dataProviderDelete()[0]['data'];
+ $this->_testPostAction('delete', $data, array('action' => 'delete', 'block_id' => '2', 'frame_id' => '6'), 'BadRequestException');
+
+ //ログアウト
+ TestAuthGeneral::logout($this);
+ }
+
+}
diff --git a/Test/Case/Controller/LinkBlocksController/IndexPaginatorTest.php b/Test/Case/Controller/LinkBlocksController/IndexPaginatorTest.php
new file mode 100644
index 0000000..5596f34
--- /dev/null
+++ b/Test/Case/Controller/LinkBlocksController/IndexPaginatorTest.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('BlocksControllerPaginatorTest', 'Blocks.TestSuite');
+
+/**
+ * LinkBlocksController::index()のPaginatorテスト
+ *
+ * @author Shohei Nakajima
+ * @package NetCommons\Links\Test\Case\Controller\LinkBlocksController
+ */
+class LinkBlocksControllerIndexPaginatorTest extends BlocksControllerPaginatorTest {
+
+/**
+ * Fixtures
+ *
+ * @var array
+ */
+ public $fixtures = array(
+ 'plugin.categories.category',
+ 'plugin.categories.category_order',
+ 'plugin.categories.categories_language',
+ 'plugin.links.link',
+ 'plugin.links.link_frame_setting',
+ 'plugin.links.link_order',
+ 'plugin.links.block_setting_for_link',
+ 'plugin.workflow.workflow_comment',
+ );
+
+/**
+ * Plugin name
+ *
+ * @var string
+ */
+ public $plugin = 'links';
+
+/**
+ * Controller name
+ *
+ * @var string
+ */
+ protected $_controller = 'link_blocks';
+
+/**
+ * Edit controller name
+ *
+ * @var string
+ */
+ protected $_editController = 'link_blocks';
+
+}
diff --git a/Test/Case/Controller/LinkBlocksController/IndexTest.php b/Test/Case/Controller/LinkBlocksController/IndexTest.php
new file mode 100644
index 0000000..c14f6a8
--- /dev/null
+++ b/Test/Case/Controller/LinkBlocksController/IndexTest.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('BlocksControllerTest', 'Blocks.TestSuite');
+
+/**
+ * LinkBlocksController::index()のテスト
+ *
+ * @author Shohei Nakajima
+ * @package NetCommons\Links\Test\Case\Controller\LinkBlocksController
+ */
+class LinkBlocksControllerIndexTest extends BlocksControllerTest {
+
+/**
+ * Fixtures
+ *
+ * @var array
+ */
+ public $fixtures = array(
+ 'plugin.categories.category',
+ 'plugin.categories.category_order',
+ 'plugin.categories.categories_language',
+ 'plugin.links.link',
+ 'plugin.links.link_frame_setting',
+ 'plugin.links.link_order',
+ 'plugin.links.block_setting_for_link',
+ 'plugin.workflow.workflow_comment',
+ );
+
+/**
+ * Plugin name
+ *
+ * @var string
+ */
+ public $plugin = 'links';
+
+/**
+ * Controller name
+ *
+ * @var string
+ */
+ protected $_controller = 'link_blocks';
+
+/**
+ * Edit controller name
+ *
+ * @var string
+ */
+ protected $_editController = 'link_blocks';
+
+}
diff --git a/Test/Case/Controller/LinkFrameSettingsController/EditTest.php b/Test/Case/Controller/LinkFrameSettingsController/EditTest.php
new file mode 100644
index 0000000..de99a90
--- /dev/null
+++ b/Test/Case/Controller/LinkFrameSettingsController/EditTest.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('FrameSettingsControllerTest', 'Frames.TestSuite');
+
+/**
+ * LinkFrameSettingsController::edit()のテスト
+ *
+ * @author Shohei Nakajima
+ * @package NetCommons\Links\Test\Case\Controller\LinkFrameSettingsController
+ */
+class LinkFrameSettingsControllerEditTest extends FrameSettingsControllerTest {
+
+/**
+ * Fixtures
+ *
+ * @var array
+ */
+ public $fixtures = array(
+ 'plugin.links.link',
+ 'plugin.links.link_frame_setting',
+ 'plugin.links.link_order',
+ 'plugin.links.block_setting_for_link',
+ );
+
+/**
+ * Plugin name
+ *
+ * @var string
+ */
+ public $plugin = 'links';
+
+/**
+ * Controller name
+ *
+ * @var string
+ */
+ protected $_controller = 'link_frame_settings';
+
+/**
+ * テストDataの取得
+ *
+ * @return array
+ */
+ private function __data() {
+ $frameId = '6';
+ $frameKey = 'frame_3';
+ $linkFrameId = '6';
+
+ $data = array(
+ 'Frame' => array(
+ 'id' => $frameId,
+ 'key' => $frameKey,
+ ),
+ 'LinkFrameSetting' => array(
+ 'id' => $linkFrameId,
+ 'frame_key' => $frameKey,
+ 'display_type' => '1',
+ 'category_separator_line' => '',
+ 'list_style' => '',
+ ),
+ );
+
+ return $data;
+ }
+
+/**
+ * edit()アクションDataProvider
+ *
+ * ### 戻り値
+ * - method: リクエストメソッド(get or post or put)
+ * - data: 登録データ
+ * - validationError: バリデーションエラー(省略可)
+ * - exception: Exception Error(省略可)
+ *
+ * @return array
+ */
+ public function dataProviderEdit() {
+ $data = $this->__data();
+
+ //テストデータ
+ $results = array();
+ $results[0] = array('method' => 'get');
+ $results[1] = array('method' => 'post', 'data' => $data, 'validationError' => false);
+ $results[2] = array('method' => 'put', 'data' => $data, 'validationError' => false);
+ $results[3] = array('method' => 'put', 'data' => $data,
+ 'validationError' => array(
+ 'field' => 'LinkFrameSetting.frame_key',
+ 'value' => null,
+ ),
+ 'BadRequestException'
+ );
+
+ return $results;
+ }
+
+}
diff --git a/Test/Case/Controller/LinkListsCategoriesControllerTest.php b/Test/Case/Controller/LinkListsCategoriesControllerTest.php
deleted file mode 100644
index 2e7b1c3..0000000
--- a/Test/Case/Controller/LinkListsCategoriesControllerTest.php
+++ /dev/null
@@ -1,71 +0,0 @@
-
-* @link http://www.netcommons.org NetCommons Project
-* @license http://www.netcommons.org/license.txt NetCommons License
- */
-
-App::uses('LinkListsCategoriesController', 'LinkLists.Controller');
-
-/**
- * Summary for LinkListsCategoriesController Test Case
- */
-class LinkListsCategoriesControllerTest extends ControllerTestCase {
-
-/**
- * Fixtures
- *
- * @var array
- */
- public $fixtures = array(
- 'plugin.link_lists.linklists_category',
- 'plugin.link_lists.linklists_block',
- 'plugin.link_lists.language',
- 'plugin.link_lists.linklist',
- 'plugin.link_lists.site_setting',
- 'plugin.link_lists.site_setting_value'
- );
-
-/**
- * testIndex method
- *
- * @return void
- */
- public function testIndex() {
- }
-
-/**
- * testView method
- *
- * @return void
- */
- public function testView() {
- }
-
-/**
- * testAdd method
- *
- * @return void
- */
- public function testAdd() {
- }
-
-/**
- * testEdit method
- *
- * @return void
- */
- public function testEdit() {
- }
-
-/**
- * testDelete method
- *
- * @return void
- */
- public function testDelete() {
- }
-
-}
diff --git a/Test/Case/Controller/LinkListsControllerTest.php b/Test/Case/Controller/LinkListsControllerTest.php
deleted file mode 100644
index 5c62fb0..0000000
--- a/Test/Case/Controller/LinkListsControllerTest.php
+++ /dev/null
@@ -1,73 +0,0 @@
-
-* @link http://www.netcommons.org NetCommons Project
-* @license http://www.netcommons.org/license.txt NetCommons License
- */
-
-App::uses('LinkListsController', 'LinkLists.Controller');
-
-/**
- * Summary for LinkListsController Test Case
- */
-class LinkListsControllerTest extends ControllerTestCase {
-
-/**
- * Fixtures
- *
- * @var array
- */
- public $fixtures = array(
- 'plugin.link_lists.linklist',
- 'plugin.link_lists.linklists_block',
- 'plugin.link_lists.language',
- 'plugin.link_lists.linklists_category',
- 'plugin.link_lists.block',
- 'plugin.link_lists.blocks_language',
- 'plugin.link_lists.site_setting',
- 'plugin.link_lists.site_setting_value'
- );
-
-/**
- * testIndex method
- *
- * @return void
- */
- public function testIndex() {
- }
-
-/**
- * testView method
- *
- * @return void
- */
- public function testView() {
- }
-
-/**
- * testAdd method
- *
- * @return void
- */
- public function testAdd() {
- }
-
-/**
- * testEdit method
- *
- * @return void
- */
- public function testEdit() {
- }
-
-/**
- * testDelete method
- *
- * @return void
- */
- public function testDelete() {
- }
-
-}
diff --git a/Test/Case/Controller/LinkMailSettingsController/EditTest.php b/Test/Case/Controller/LinkMailSettingsController/EditTest.php
new file mode 100644
index 0000000..f4ba6f6
--- /dev/null
+++ b/Test/Case/Controller/LinkMailSettingsController/EditTest.php
@@ -0,0 +1,95 @@
+
+ * @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('NetCommonsControllerTestCase', 'NetCommons.TestSuite');
+
+/**
+ * LinkMailSettingsController::edit()のテスト
+ *
+ * @author Shohei Nakajima
+ * @package NetCommons\Links\Test\Case\Controller\LinkMailSettingsController
+ */
+class LinkMailSettingsControllerEditTest extends NetCommonsControllerTestCase {
+
+/**
+ * Fixtures
+ *
+ * @var array
+ */
+ public $fixtures = array(
+ 'plugin.categories.category',
+ 'plugin.categories.category_order',
+ 'plugin.categories.categories_language',
+ 'plugin.links.link',
+ 'plugin.links.link_frame_setting',
+ 'plugin.links.link_order',
+ 'plugin.links.block_setting_for_link',
+ 'plugin.mails.mail_setting_fixed_phrase',
+ 'plugin.workflow.workflow_comment',
+ );
+
+/**
+ * Plugin name
+ *
+ * @var string
+ */
+ public $plugin = 'links';
+
+/**
+ * Controller name
+ *
+ * @var string
+ */
+ protected $_controller = 'link_mail_settings';
+
+/**
+ * setUp method
+ *
+ * @return void
+ */
+ public function setUp() {
+ parent::setUp();
+
+ //ログイン
+ TestAuthGeneral::login($this);
+ }
+
+/**
+ * tearDown method
+ *
+ * @return void
+ */
+ public function tearDown() {
+ //ログアウト
+ TestAuthGeneral::logout($this);
+
+ parent::tearDown();
+ }
+
+/**
+ * edit()アクションのGetリクエストテスト
+ *
+ * @return void
+ */
+ public function testEditGet() {
+ //テストデータ
+ $frameId = '6';
+ $blockId = '2';
+
+ //テスト実行
+ $this->_testGetAction(array('action' => 'edit', 'block_id' => $blockId, 'frame_id' => $frameId),
+ array('method' => 'assertNotEmpty'), null, 'view');
+
+ //チェック
+ $this->assertInput('form', null, 'links/link_mail_settings/edit/' . $blockId, $this->view);
+ }
+
+}
diff --git a/Test/Case/Controller/LinkOrdersController/EditTest.php b/Test/Case/Controller/LinkOrdersController/EditTest.php
new file mode 100644
index 0000000..26463c4
--- /dev/null
+++ b/Test/Case/Controller/LinkOrdersController/EditTest.php
@@ -0,0 +1,291 @@
+
+ * @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('NetCommonsControllerTestCase', 'NetCommons.TestSuite');
+App::uses('LinkOrderFixture', 'Links.Test/Fixture');
+
+/**
+ * LinkOrdersController::edit()のテスト
+ *
+ * @author Shohei Nakajima
+ * @package NetCommons\Links\Test\Case\Controller\LinkOrdersController
+ */
+class LinkOrdersControllerEditTest extends NetCommonsControllerTestCase {
+
+/**
+ * Fixtures
+ *
+ * @var array
+ */
+ public $fixtures = array(
+ 'plugin.categories.category',
+ 'plugin.categories.category_order',
+ 'plugin.categories.categories_language',
+ 'plugin.links.link',
+ 'plugin.links.link_frame_setting',
+ 'plugin.links.link_order',
+ 'plugin.links.block_setting_for_link',
+ 'plugin.workflow.workflow_comment',
+ );
+
+/**
+ * Plugin name
+ *
+ * @var string
+ */
+ public $plugin = 'links';
+
+/**
+ * Controller name
+ *
+ * @var string
+ */
+ protected $_controller = 'link_orders';
+
+/**
+ * setUp method
+ *
+ * @return void
+ */
+ public function setUp() {
+ parent::setUp();
+
+ //ログイン
+ TestAuthGeneral::login($this);
+ }
+
+/**
+ * tearDown method
+ *
+ * @return void
+ */
+ public function tearDown() {
+ //ログアウト
+ TestAuthGeneral::logout($this);
+
+ parent::tearDown();
+ }
+
+/**
+ * edit()アクションのGetリクエストテスト
+ *
+ * @return void
+ */
+ public function testEditGet() {
+ //テストデータ
+ $frameId = '6';
+ $blockId = '2';
+ $blockKey = 'block_1';
+
+ //テスト実行
+ $this->_testGetAction(array('action' => 'edit', 'block_id' => $blockId, 'frame_id' => $frameId),
+ array('method' => 'assertNotEmpty'), null, 'view');
+
+ //チェック
+ $this->__assertEditGet($frameId, $blockId, $blockKey);
+ }
+
+/**
+ * edit()のチェック
+ *
+ * @param int $frameId フレームID
+ * @param int $blockId ブロックID
+ * @param string $blockKey ブロックKey
+ * @return void
+ */
+ private function __assertEditGet($frameId, $blockId, $blockKey) {
+ $this->assertInput('form', null, 'links/link_orders/edit/' . $blockId, $this->view);
+ $this->assertInput('input', '_method', 'PUT', $this->view);
+ $this->assertInput('input', 'data[Frame][id]', $frameId, $this->view);
+ $this->assertInput('input', 'data[Block][id]', $blockId, $this->view);
+ $this->assertInput('input', 'data[Block][key]', $blockKey, $this->view);
+
+ $this->assertEquals($frameId, Hash::get($this->controller->request->data, 'Frame.id'));
+ $this->assertEquals($blockId, Hash::get($this->controller->request->data, 'Block.id'));
+ $this->assertEquals($blockKey, Hash::get($this->controller->request->data, 'Block.key'));
+ $this->assertCount(5, Hash::get($this->controller->request->data, 'LinkOrders'));
+
+ $this->__assertRequestData($blockId, $blockKey, array(
+ 'Link' => array('id' => '5', 'key' => 'content_key_3'),
+ 'LinkOrder' => array('id' => '3', 'weight' => '1'),
+ 'Category' => array('id' => null, 'key' => null),
+ 'CategoryOrder' => array('id' => null, 'weight' => null),
+ ));
+ $this->__assertRequestData($blockId, $blockKey, array(
+ 'Link' => array('id' => '2', 'key' => 'content_key_1'),
+ 'LinkOrder' => array('id' => '1', 'weight' => '1'),
+ 'Category' => array('id' => '1', 'key' => 'category_1'),
+ 'CategoryOrder' => array('id' => '1', 'weight' => '1'),
+ ));
+ $this->__assertRequestData($blockId, $blockKey, array(
+ 'Link' => array('id' => '3', 'key' => 'content_key_2'),
+ 'LinkOrder' => array('id' => '2', 'weight' => '2'),
+ 'Category' => array('id' => '1', 'key' => 'category_1'),
+ 'CategoryOrder' => array('id' => '1', 'weight' => '1'),
+ ));
+ $this->__assertRequestData($blockId, $blockKey, array(
+ 'Link' => array('id' => '7', 'key' => 'content_key_4'),
+ 'LinkOrder' => array('id' => '4', 'weight' => '3'),
+ 'Category' => array('id' => '1', 'key' => 'category_1'),
+ 'CategoryOrder' => array('id' => '1', 'weight' => '1'),
+ ));
+ $this->__assertRequestData($blockId, $blockKey, array(
+ 'Link' => array('id' => '8', 'key' => 'content_key_5'),
+ 'LinkOrder' => array('id' => '5', 'weight' => '4'),
+ 'Category' => array('id' => '1', 'key' => 'category_1'),
+ 'CategoryOrder' => array('id' => '1', 'weight' => '1'),
+ ));
+ }
+
+/**
+ * edit()アクションの評価
+ *
+ * @param int $blockId ブロックID
+ * @param string $blockKey ブロックKey
+ * @param array $expected 期待値
+ * @return void
+ */
+ private function __assertRequestData($blockId, $blockKey, $expected) {
+ $actual = $this->controller->request->data;
+ $linkOrderId = Hash::get($expected, 'LinkOrder.id');
+
+ $pathKey = 'LinkOrders.' . $linkOrderId . '.Link.id';
+ $this->assertEquals(Hash::get($expected, 'Link.id'), Hash::get($actual, $pathKey));
+
+ $pathKey = 'LinkOrders.' . $linkOrderId . '.Link.key';
+ $this->assertEquals(Hash::get($expected, 'Link.key'), Hash::get($actual, $pathKey));
+
+ $pathKey = 'LinkOrders.' . $linkOrderId . '.Link.category_id';
+ $this->assertEquals(Hash::get($expected, 'Category.id'), Hash::get($actual, $pathKey));
+
+ $pathKey = 'LinkOrders.' . $linkOrderId . '.Link.block_id';
+ $this->assertEquals($blockId, Hash::get($actual, $pathKey));
+
+ $pathKey = 'LinkOrders.' . $linkOrderId . '.LinkOrder.id';
+ $this->assertEquals($linkOrderId, Hash::get($actual, $pathKey));
+
+ $pathKey = 'LinkOrders.' . $linkOrderId . '.LinkOrder.block_key';
+ $this->assertEquals($blockKey, Hash::get($actual, $pathKey));
+
+ $pathKey = 'LinkOrders.' . $linkOrderId . '.LinkOrder.category_key';
+ $this->assertEquals(Hash::get($expected, 'Category.key'), Hash::get($actual, $pathKey));
+
+ $pathKey = 'LinkOrders.' . $linkOrderId . '.LinkOrder.link_key';
+ $this->assertEquals(Hash::get($expected, 'Link.key'), Hash::get($actual, $pathKey));
+
+ $pathKey = 'LinkOrders.' . $linkOrderId . '.LinkOrder.weight';
+ $this->assertEquals(Hash::get($expected, 'LinkOrder.weight'), Hash::get($actual, $pathKey));
+
+ $pathKey = 'LinkOrders.' . $linkOrderId . '.Category.id';
+ $this->assertEquals(Hash::get($expected, 'Category.id'), Hash::get($actual, $pathKey));
+
+ $pathKey = 'LinkOrders.' . $linkOrderId . '.Category.key';
+ $this->assertEquals(Hash::get($expected, 'Category.key'), Hash::get($actual, $pathKey));
+
+ $pathKey = 'LinkOrders.' . $linkOrderId . '.CategoryOrder.id';
+ $this->assertEquals(Hash::get($expected, 'CategoryOrder.id'), Hash::get($actual, $pathKey));
+
+ $pathKey = 'LinkOrders.' . $linkOrderId . '.CategoryOrder.category_key';
+ $this->assertEquals(Hash::get($expected, 'Category.key'), Hash::get($actual, $pathKey));
+
+ $pathKey = 'LinkOrders.' . $linkOrderId . '.CategoryOrder.weight';
+ $this->assertEquals(Hash::get($expected, 'CategoryOrder.weight'), Hash::get($actual, $pathKey));
+ }
+
+/**
+ * POSTリクエストデータ生成
+ *
+ * @return array リクエストデータ
+ */
+ private function __data() {
+ $data = array(
+ 'Frame' => array(
+ 'id' => '6'
+ ),
+ 'Block' => array(
+ 'id' => '2', 'key' => 'block_1'
+ ),
+ );
+ $data['LinkOrders'] = array();
+ $data['LinkOrders'][] = array('LinkOrder' => Hash::insert((new LinkOrderFixture())->records[2], 'weight', '1'));
+ $data['LinkOrders'][] = array('LinkOrder' => Hash::insert((new LinkOrderFixture())->records[4], 'weight', '1'));
+ $data['LinkOrders'][] = array('LinkOrder' => Hash::insert((new LinkOrderFixture())->records[3], 'weight', '2'));
+ $data['LinkOrders'][] = array('LinkOrder' => Hash::insert((new LinkOrderFixture())->records[1], 'weight', '3'));
+ $data['LinkOrders'][] = array('LinkOrder' => Hash::insert((new LinkOrderFixture())->records[0], 'weight', '4'));
+ $data['LinkOrders'] = Hash::combine($data['LinkOrders'], '{n}.LinkOrder.id', '{n}');
+
+ return $data;
+ }
+
+/**
+ * edit()アクションのPOSTリクエストテスト
+ *
+ * @return void
+ */
+ public function testEditPost() {
+ //テストデータ
+ $frameId = '6';
+ $blockId = '2';
+
+ //テスト実行
+ $this->_testPostAction('put', $this->__data(),
+ array('action' => 'edit', 'block_id' => $blockId, 'frame_id' => $frameId), null, 'view');
+
+ //チェック
+ $header = $this->controller->response->header();
+ $pattern = '/' . preg_quote('/', '/') . '/';
+ $this->assertRegExp($pattern, $header['Location']);
+ }
+
+/**
+ * ValidationErrorテスト
+ *
+ * @return void
+ */
+ public function testEditPostValidationError() {
+ $this->generateNc(Inflector::camelize($this->_controller), array('components' => array(
+ 'Flash' => array('set')
+ )));
+
+ //ログイン
+ TestAuthGeneral::login($this);
+
+ //テストデータ
+ $frameId = '6';
+ $blockId = '2';
+
+ //テスト実行
+ $this->controller->Flash->expects($this->once())
+ ->method('set')
+ ->will($this->returnValue(null));
+
+ $this->_testPostAction('put', Hash::insert($this->__data(), 'LinkOrders.{n}.LinkOrder.weight', 'aaaa'),
+ array('action' => 'edit', 'block_id' => $blockId, 'frame_id' => $frameId), null, 'view');
+ }
+
+/**
+ * ExceptionErrorテスト
+ *
+ * @return void
+ */
+ public function testEditPostOnExceptionError() {
+ $this->_mockForReturnFalse('Links.LinkBlock', 'getLinkBlock');
+
+ //テストデータ
+ $frameId = '6';
+ $blockId = '2';
+
+ //テスト実行
+ $this->_testPostAction('put', $this->__data(),
+ array('action' => 'edit', 'block_id' => $blockId, 'frame_id' => $frameId), 'BadRequestException', 'view');
+ }
+
+}
diff --git a/Test/Case/Controller/LinksController/AddTest.php b/Test/Case/Controller/LinksController/AddTest.php
new file mode 100644
index 0000000..87bc0c7
--- /dev/null
+++ b/Test/Case/Controller/LinksController/AddTest.php
@@ -0,0 +1,336 @@
+
+ * @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('WorkflowControllerAddTest', 'Workflow.TestSuite');
+
+/**
+ * LinksController::add()のテスト
+ *
+ * @author Shohei Nakajima
+ * @package NetCommons\Links\Test\Case\Controller\LinksController
+ */
+class LinksControllerAddTest extends WorkflowControllerAddTest {
+
+/**
+ * Fixtures
+ *
+ * @var array
+ */
+ public $fixtures = array(
+ 'plugin.categories.category',
+ 'plugin.categories.category_order',
+ 'plugin.categories.categories_language',
+ 'plugin.links.link',
+ 'plugin.links.link_frame_setting',
+ 'plugin.links.link_order',
+ 'plugin.links.block_setting_for_link',
+ 'plugin.workflow.workflow_comment',
+ );
+
+/**
+ * Plugin name
+ *
+ * @var string
+ */
+ public $plugin = 'links';
+
+/**
+ * Controller name
+ *
+ * @var string
+ */
+ protected $_controller = 'links';
+
+/**
+ * テストDataの取得
+ *
+ * @return array
+ */
+ private function __data() {
+ $frameId = '6';
+ $blockId = '2';
+ $blockKey = 'block_1';
+
+ $data = array(
+ 'save_' . WorkflowComponent::STATUS_IN_DRAFT => null,
+ 'Frame' => array(
+ 'id' => $frameId,
+ ),
+ 'Block' => array(
+ 'id' => $blockId,
+ 'key' => $blockKey,
+ 'language_id' => '2',
+ 'room_id' => '2',
+ 'plugin_key' => $this->plugin,
+ ),
+ 'Link' => array(
+ 'id' => null,
+ 'key' => null,
+ 'language_id' => '2',
+ 'status' => null,
+ 'url' => 'http://www.netcommons.org',
+ 'title' => 'Lorem ipsum dolor sit amet',
+ 'description' => 'Lorem ipsum dolor sit amet, aliquet feugiat. Convallis morbi fringilla gravida, phasellus feugiat dapibus velit nunc, pulvinar eget sollicitudin venenatis cum nullam, vivamus ut a sed, mollitia lectus. Nulla vestibulum massa neque ut et, id hendrerit sit, feugiat in taciti enim proin nibh, tempor dignissim, rhoncus duis vestibulum nunc mattis convallis.',
+ ),
+ 'LinkOrder' => array(
+ 'id' => null,
+ 'block_key' => 'block_1',
+ 'category_key' => 'category_1',
+ 'link_key' => null,
+ ),
+ 'WorkflowComment' => array(
+ 'comment' => 'WorkflowComment save test',
+ ),
+ );
+
+ return $data;
+ }
+
+/**
+ * addアクションのGETテスト(ログインなし)用DataProvider
+ *
+ * ### 戻り値
+ * - urlOptions: URLオプション
+ * - assert: テストの期待値
+ * - exception: Exception
+ * - return: testActionの実行後の結果
+ *
+ * @return array
+ */
+ public function dataProviderAddGet() {
+ $data = $this->__data();
+
+ //テストデータ
+ $results = array();
+ // * ログインなし
+ $results[0] = array(
+ 'urlOptions' => array(
+ 'frame_id' => $data['Frame']['id'],
+ 'block_id' => $data['Block']['id']
+ ),
+ 'assert' => null, 'exception' => 'ForbiddenException',
+ );
+
+ return $results;
+ }
+
+/**
+ * addアクションのGETテスト(作成権限あり)用DataProvider
+ *
+ * ### 戻り値
+ * - urlOptions: URLオプション
+ * - assert: テストの期待値
+ * - exception: Exception
+ * - return: testActionの実行後の結果
+ *
+ * @return array
+ */
+ public function dataProviderAddGetByCreatable() {
+ $data = $this->__data();
+
+ //テストデータ
+ $results = array();
+ $results[0] = array(
+ 'urlOptions' => array(
+ 'frame_id' => $data['Frame']['id'],
+ 'block_id' => $data['Block']['id'],
+ ),
+ 'assert' => array('method' => 'assertNotEmpty'),
+ );
+
+ // * フレームID指定なしテスト
+ array_push($results, Hash::merge($results[0], array(
+ 'urlOptions' => array('frame_id' => null, 'block_id' => $data['Block']['id']),
+ 'assert' => array('method' => 'assertNotEmpty'),
+ )));
+
+ return $results;
+ }
+
+/**
+ * addアクションのPOSTテスト用DataProvider
+ *
+ * ### 戻り値
+ * - data: 登録データ
+ * - role: ロール
+ * - urlOptions: URLオプション
+ * - exception: Exception
+ * - return: testActionの実行後の結果
+ *
+ * @return array
+ */
+ public function dataProviderAddPost() {
+ $data = $this->__data();
+
+ //テストデータ
+ $results = array();
+ // * ログインなし
+ $results[0] = array(
+ 'data' => $data, 'role' => null,
+ 'urlOptions' => array(
+ 'frame_id' => $data['Frame']['id'],
+ 'block_id' => $data['Block']['id']
+ ),
+ 'exception' => 'ForbiddenException'
+ );
+ // * 作成権限あり
+ $results[1] = array(
+ 'data' => $data, 'role' => Role::ROOM_ROLE_KEY_GENERAL_USER,
+ 'urlOptions' => array(
+ 'frame_id' => $data['Frame']['id'],
+ 'block_id' => $data['Block']['id']
+ ),
+ );
+ // * フレームID指定なしテスト
+ $results[2] = array(
+ 'data' => $data, 'role' => Role::ROOM_ROLE_KEY_ROOM_ADMINISTRATOR,
+ 'urlOptions' => array(
+ 'frame_id' => null,
+ 'block_id' => $data['Block']['id']),
+ );
+
+ return $results;
+ }
+
+/**
+ * addアクションのValidationErrorテスト用DataProvider
+ *
+ * ### 戻り値
+ * - data: 登録データ
+ * - urlOptions: URLオプション
+ * - validationError: バリデーションエラー
+ *
+ * @return array
+ */
+ public function dataProviderAddValidationError() {
+ $data = $this->__data();
+ $result = array(
+ 'data' => $data,
+ 'urlOptions' => array(
+ 'frame_id' => $data['Frame']['id'],
+ 'block_id' => $data['Block']['id']
+ ),
+ 'validationError' => array(),
+ );
+
+ //テストデータ
+ $results = array();
+ array_push($results, Hash::merge($result, array(
+ 'validationError' => array(
+ 'field' => 'Link.url',
+ 'value' => 'aaaa',
+ 'message' => sprintf(__d('net_commons', 'Unauthorized pattern for %s. Please input the data in %s format.'), __d('links', 'URL'), __d('links', 'URL')),
+ )
+ )));
+ array_push($results, Hash::merge($result, array(
+ 'validationError' => array(
+ 'field' => 'Link.title',
+ 'value' => '',
+ 'message' => sprintf(__d('net_commons', 'Please input %s.'), __d('links', 'Title')),
+ )
+ )));
+
+ return $results;
+ }
+
+/**
+ * Viewのアサーション
+ *
+ * @param array $data テストデータ
+ * @return void
+ */
+ private function __assertAddGet($data) {
+ $this->assertInput(
+ 'input', 'data[Frame][id]', $data['Frame']['id'], $this->view
+ );
+ $this->assertInput(
+ 'input', 'data[Block][id]', $data['Block']['id'], $this->view
+ );
+ $this->assertInput(
+ 'input', 'data[Link][id]', null, $this->view
+ );
+ $this->assertInput(
+ 'input', 'data[Link][key]', null, $this->view
+ );
+ $this->assertInput(
+ 'input', 'data[Link][url]', null, $this->view
+ );
+ $this->assertInput(
+ 'input', 'data[Link][title]', null, $this->view
+ );
+ $this->assertInput(
+ 'input', 'data[Link][description]', null, $this->view
+ );
+ $this->assertInput(
+ 'input', 'data[LinkOrder][id]', null, $this->view
+ );
+ $this->assertInput(
+ 'input', 'data[LinkOrder][link_key]', null, $this->view
+ );
+ }
+
+/**
+ * view(ctp)ファイルのテスト(公開権限なし)
+ *
+ * @return void
+ */
+ public function testViewFileByCreatable() {
+ TestAuthGeneral::login($this, Role::ROOM_ROLE_KEY_GENERAL_USER);
+
+ //テスト実行
+ $data = $this->__data();
+ $this->_testGetAction(
+ array(
+ 'action' => 'add',
+ 'frame_id' => $data['Frame']['id'],
+ 'block_id' => $data['Block']['id'],
+ ),
+ array('method' => 'assertNotEmpty')
+ );
+
+ //チェック
+ $this->__assertAddGet($data);
+ $this->assertInput('button', 'save_' . WorkflowComponent::STATUS_IN_DRAFT, null, $this->view);
+ $this->assertInput('button', 'save_' . WorkflowComponent::STATUS_APPROVAL_WAITING, null, $this->view);
+
+ TestAuthGeneral::logout($this);
+ }
+
+/**
+ * view(ctp)ファイルのテスト(公開権限あり)
+ *
+ * @return void
+ */
+ public function testViewFileByPublishable() {
+ //ログイン
+ TestAuthGeneral::login($this);
+
+ //テスト実行
+ $data = $this->__data();
+ $this->_testGetAction(
+ array(
+ 'action' => 'add',
+ 'frame_id' => $data['Frame']['id'],
+ 'block_id' => $data['Block']['id'],
+ ),
+ array('method' => 'assertNotEmpty')
+ );
+
+ //チェック
+ $this->__assertAddGet($data);
+ $this->assertInput('button', 'save_' . WorkflowComponent::STATUS_IN_DRAFT, null, $this->view);
+ $this->assertInput('button', 'save_' . WorkflowComponent::STATUS_PUBLISHED, null, $this->view);
+
+ //ログアウト
+ TestAuthGeneral::logout($this);
+ }
+
+}
diff --git a/Test/Case/Controller/LinksController/BeforeFilterTest.php b/Test/Case/Controller/LinksController/BeforeFilterTest.php
new file mode 100644
index 0000000..8fdd356
--- /dev/null
+++ b/Test/Case/Controller/LinksController/BeforeFilterTest.php
@@ -0,0 +1,109 @@
+
+ * @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('NetCommonsControllerTestCase', 'NetCommons.TestSuite');
+
+/**
+ * LinksController::beforeFilter()のテスト
+ *
+ * @author Shohei Nakajima
+ * @package NetCommons\Links\Test\Case\Controller\LinksController
+ */
+class LinksControllerBeforeFilterTest extends NetCommonsControllerTestCase {
+
+/**
+ * Fixtures
+ *
+ * @var array
+ */
+ public $fixtures = array(
+ 'plugin.categories.category',
+ 'plugin.categories.category_order',
+ 'plugin.categories.categories_language',
+ 'plugin.links.link',
+ 'plugin.links.link_frame_setting',
+ 'plugin.links.link_order',
+ 'plugin.links.block_setting_for_link',
+ 'plugin.workflow.workflow_comment',
+ );
+
+/**
+ * Plugin name
+ *
+ * @var string
+ */
+ public $plugin = 'links';
+
+/**
+ * Controller name
+ *
+ * @var string
+ */
+ protected $_controller = 'links';
+
+/**
+ * setUp method
+ *
+ * @return void
+ */
+ public function setUp() {
+ parent::setUp();
+ //ログイン
+ TestAuthGeneral::login($this);
+ }
+
+/**
+ * tearDown method
+ *
+ * @return void
+ */
+ public function tearDown() {
+ //ログアウト
+ TestAuthGeneral::logout($this);
+ parent::tearDown();
+ }
+
+/**
+ * index()アクションのテスト
+ *
+ * @return void
+ */
+ public function testBeforeFilter() {
+ //テスト実行
+ $this->_testGetAction(array('action' => 'index', 'frame_id' => '6'),
+ array('method' => 'assertNotEmpty'), null, 'view');
+ }
+
+/**
+ * index()アクションのテスト(ブロックIDなし)
+ *
+ * @return void
+ */
+ public function testBeforeFilterWOBlockId() {
+ //テスト実行
+ $this->_testGetAction(array('action' => 'index', 'frame_id' => '13'),
+ array('method' => 'assertEmpty'), null, 'view');
+ }
+
+/**
+ * index()アクションのテスト(ブロックデータなし)
+ *
+ * @return void
+ */
+ public function testBeforeFilterWOBlockData() {
+ $this->_mockForReturnFalse('Links.LinkBlock', 'getLinkBlock');
+
+ //テスト実行
+ $this->_testGetAction(array('action' => 'index', 'frame_id' => '6'),
+ null, 'BadRequestException', 'view');
+ }
+
+}
diff --git a/Test/Case/Controller/LinksController/DeleteTest.php b/Test/Case/Controller/LinksController/DeleteTest.php
new file mode 100644
index 0000000..1cbe350
--- /dev/null
+++ b/Test/Case/Controller/LinksController/DeleteTest.php
@@ -0,0 +1,279 @@
+
+ * @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('WorkflowControllerDeleteTest', 'Workflow.TestSuite');
+
+/**
+ * LinksController::delete()のテスト
+ *
+ * @author Shohei Nakajima
+ * @package NetCommons\Links\Test\Case\Controller\LinksController
+ */
+class LinksControllerDeleteTest extends WorkflowControllerDeleteTest {
+
+/**
+ * Fixtures
+ *
+ * @var array
+ */
+ public $fixtures = array(
+ 'plugin.categories.category',
+ 'plugin.categories.category_order',
+ 'plugin.categories.categories_language',
+ 'plugin.links.link',
+ 'plugin.links.link_frame_setting',
+ 'plugin.links.link_order',
+ 'plugin.links.block_setting_for_link',
+ 'plugin.workflow.workflow_comment',
+ );
+
+/**
+ * Plugin name
+ *
+ * @var string
+ */
+ public $plugin = 'links';
+
+/**
+ * Controller name
+ *
+ * @var string
+ */
+ protected $_controller = 'links';
+
+/**
+ * テストDataの取得
+ *
+ * @param string $contentKey キー
+ * @return array
+ */
+ private function __data($contentKey = null) {
+ $frameId = '6';
+ $blockId = '2';
+ $blockKey = 'block_1';
+ if ($contentKey === 'content_key_2') {
+ $contentId = '3';
+ $contentOrderId = '2';
+ } elseif ($contentKey === 'content_key_4') {
+ $contentId = '5';
+ $contentOrderId = '4';
+ } else {
+ $contentId = '2';
+ $contentOrderId = '1';
+ }
+
+ $data = array(
+ 'delete' => null,
+ 'Frame' => array(
+ 'id' => $frameId,
+ ),
+ 'Block' => array(
+ 'id' => $blockId,
+ 'key' => $blockKey,
+ ),
+ 'Link' => array(
+ 'id' => $contentId,
+ 'key' => $contentKey,
+ ),
+ 'LinkOrder' => array(
+ 'id' => $contentOrderId,
+ ),
+ );
+
+ return $data;
+ }
+
+/**
+ * deleteアクションのGETテスト用DataProvider
+ *
+ * ### 戻り値
+ * - role: ロール
+ * - urlOptions: URLオプション
+ * - assert: テストの期待値
+ * - exception: Exception
+ * - return: testActionの実行後の結果
+ *
+ * @return array
+ */
+ public function dataProviderDeleteGet() {
+ $data = $this->__data();
+
+ //テストデータ
+ $results = array();
+ // * ログインなし
+ $results[0] = array('role' => null,
+ 'urlOptions' => array(
+ 'frame_id' => $data['Frame']['id'],
+ 'block_id' => $data['Block']['id'],
+ 'key' => 'content_key_1',
+ ),
+ 'assert' => null, 'exception' => 'ForbiddenException'
+ );
+ // * 作成権限のみ(自分自身)
+ array_push($results, Hash::merge($results[0], array(
+ 'role' => Role::ROOM_ROLE_KEY_GENERAL_USER,
+ 'urlOptions' => array(
+ 'frame_id' => $data['Frame']['id'],
+ 'block_id' => $data['Block']['id'],
+ 'key' => 'content_key_2',
+ ),
+ 'assert' => null, 'exception' => 'BadRequestException'
+ )));
+ // * 編集権限、公開権限なし
+ array_push($results, Hash::merge($results[0], array(
+ 'role' => Role::ROOM_ROLE_KEY_EDITOR,
+ 'assert' => null, 'exception' => 'BadRequestException'
+ )));
+ // * 公開権限あり
+ array_push($results, Hash::merge($results[0], array(
+ 'role' => Role::ROOM_ROLE_KEY_ROOM_ADMINISTRATOR,
+ 'assert' => null, 'exception' => 'BadRequestException'
+ )));
+
+ return $results;
+ }
+
+/**
+ * deleteアクションのPOSTテスト用DataProvider
+ *
+ * ### 戻り値
+ * - data: 登録データ
+ * - role: ロール
+ * - urlOptions: URLオプション
+ * - exception: Exception
+ * - return: testActionの実行後の結果
+ *
+ * @return array
+ */
+ public function dataProviderDeletePost() {
+ $data = $this->__data();
+ $contentKey1 = 'content_key_1';
+ $contentKey2 = 'content_key_2';
+ $contentKey4 = 'content_key_4';
+
+ //テストデータ
+ $results = array();
+ // * ログインなし
+ array_push($results, array(
+ 'data' => $this->__data($contentKey1),
+ 'role' => null,
+ 'urlOptions' => array(
+ 'frame_id' => $data['Frame']['id'],
+ 'block_id' => $data['Block']['id'],
+ 'key' => $contentKey1
+ ),
+ 'exception' => 'ForbiddenException'
+ ));
+ // * 作成権限のみ
+ // ** 他人の記事
+ array_push($results, array(
+ 'data' => $this->__data($contentKey1),
+ 'role' => Role::ROOM_ROLE_KEY_GENERAL_USER,
+ 'urlOptions' => array(
+ 'frame_id' => $data['Frame']['id'],
+ 'block_id' => $data['Block']['id'],
+ 'key' => $contentKey1
+ ),
+ 'exception' => 'BadRequestException'
+ ));
+ // ** 自分の記事&一度も公開されていない
+ array_push($results, array(
+ 'data' => $this->__data($contentKey2),
+ 'role' => Role::ROOM_ROLE_KEY_GENERAL_USER,
+ 'urlOptions' => array(
+ 'frame_id' => $data['Frame']['id'],
+ 'block_id' => $data['Block']['id'],
+ 'key' => $contentKey2
+ ),
+ ));
+ // ** 自分の記事&一度公開している
+ array_push($results, array(
+ 'data' => $this->__data($contentKey4),
+ 'role' => Role::ROOM_ROLE_KEY_GENERAL_USER,
+ 'urlOptions' => array(
+ 'frame_id' => $data['Frame']['id'],
+ 'block_id' => $data['Block']['id'],
+ 'key' => $contentKey4
+ ),
+ 'exception' => 'BadRequestException'
+ ));
+ // * 編集権限あり
+ // ** 公開していない
+ array_push($results, array(
+ 'data' => $this->__data($contentKey2),
+ 'role' => Role::ROOM_ROLE_KEY_EDITOR,
+ 'urlOptions' => array(
+ 'frame_id' => $data['Frame']['id'],
+ 'block_id' => $data['Block']['id'],
+ 'key' => $contentKey2
+ ),
+ ));
+ // ** 公開している
+ array_push($results, array(
+ 'data' => $this->__data($contentKey4),
+ 'role' => Role::ROOM_ROLE_KEY_EDITOR,
+ 'urlOptions' => array(
+ 'frame_id' => $data['Frame']['id'],
+ 'block_id' => $data['Block']['id'],
+ 'key' => $contentKey4
+ ),
+ 'exception' => 'BadRequestException'
+ ));
+ // * 公開権限あり
+ // ** フレームID指定なしテスト
+ array_push($results, array(
+ 'data' => $this->__data($contentKey1),
+ 'role' => Role::ROOM_ROLE_KEY_ROOM_ADMINISTRATOR,
+ 'urlOptions' => array(
+ 'frame_id' => null,
+ 'block_id' => $data['Block']['id'],
+ 'key' => $contentKey1
+ ),
+ ));
+
+ return $results;
+ }
+
+/**
+ * deleteアクションのExceptionErrorテスト用DataProvider
+ *
+ * ### 戻り値
+ * - mockModel: Mockのモデル
+ * - mockMethod: Mockのメソッド
+ * - data: 登録データ
+ * - urlOptions: URLオプション
+ * - exception: Exception
+ * - return: testActionの実行後の結果
+ *
+ * @return array
+ */
+ public function dataProviderDeleteExceptionError() {
+ $data = $this->__data();
+
+ //テストデータ
+ $results = array();
+ $results[0] = array(
+ 'mockModel' => 'Links.Link',
+ 'mockMethod' => 'deleteLink',
+ 'data' => $data,
+ 'urlOptions' => array(
+ 'frame_id' => $data['Frame']['id'],
+ 'block_id' => $data['Block']['id'],
+ 'key' => 'content_key_1',
+ ),
+ 'exception' => 'BadRequestException',
+ 'return' => 'view'
+ );
+
+ return $results;
+ }
+
+}
diff --git a/Test/Case/Controller/LinksController/EditTest.php b/Test/Case/Controller/LinksController/EditTest.php
new file mode 100644
index 0000000..b5f0db6
--- /dev/null
+++ b/Test/Case/Controller/LinksController/EditTest.php
@@ -0,0 +1,448 @@
+
+ * @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('WorkflowControllerEditTest', 'Workflow.TestSuite');
+App::uses('LinkFixture', 'Links.Test/Fixture');
+App::uses('LinkOrderFixture', 'Links.Test/Fixture');
+
+/**
+ * LinksController::edit()のテスト
+ *
+ * @author Shohei Nakajima
+ * @package NetCommons\Links\Test\Case\Controller\LinksController
+ */
+class LinksControllerEditTest extends WorkflowControllerEditTest {
+
+/**
+ * Fixtures
+ *
+ * @var array
+ */
+ public $fixtures = array(
+ 'plugin.categories.category',
+ 'plugin.categories.category_order',
+ 'plugin.categories.categories_language',
+ 'plugin.links.link',
+ 'plugin.links.link_frame_setting',
+ 'plugin.links.link_order',
+ 'plugin.links.block_setting_for_link',
+ 'plugin.workflow.workflow_comment',
+ );
+
+/**
+ * Plugin name
+ *
+ * @var string
+ */
+ public $plugin = 'links';
+
+/**
+ * Controller name
+ *
+ * @var string
+ */
+ protected $_controller = 'links';
+
+/**
+ * テストDataの取得
+ *
+ * @param string $role ロール
+ * @return array
+ */
+ private function __data($role = null) {
+ $frameId = '6';
+ $blockId = '2';
+ $blockKey = 'block_1';
+ if ($role === Role::ROOM_ROLE_KEY_GENERAL_USER) {
+ $contentId = '3';
+ $contentKey = 'content_key_2';
+ } else {
+ $contentId = '2';
+ $contentKey = 'content_key_1';
+ }
+
+ $data = array(
+ 'save_' . WorkflowComponent::STATUS_IN_DRAFT => null,
+ 'Frame' => array(
+ 'id' => $frameId,
+ ),
+ 'Block' => array(
+ 'id' => $blockId,
+ 'key' => $blockKey,
+ 'language_id' => '2',
+ 'room_id' => '2',
+ 'plugin_key' => $this->plugin,
+ ),
+ 'Link' => Hash::get(Hash::extract((new LinkFixture())->records, '{n}[id=' . $contentId . ']'), '0'),
+ 'LinkOrder' => Hash::get(Hash::extract((new LinkOrderFixture())->records, '{n}[link_key=' . $contentKey . ']'), '0'),
+ 'WorkflowComment' => array(
+ 'comment' => 'WorkflowComment save test',
+ ),
+ );
+
+ return $data;
+ }
+
+/**
+ * editアクションのGETテスト(ログインなし)用DataProvider
+ *
+ * ### 戻り値
+ * - urlOptions: URLオプション
+ * - assert: テストの期待値
+ * - exception: Exception
+ * - return: testActionの実行後の結果
+ *
+ * @return array
+ */
+ public function dataProviderEditGet() {
+ $data = $this->__data();
+
+ //テストデータ
+ $results = array();
+ // * ログインなし
+ $results[0] = array(
+ 'urlOptions' => array(
+ 'frame_id' => $data['Frame']['id'],
+ 'block_id' => $data['Block']['id'],
+ 'key' => 'content_key_1'
+ ),
+ 'assert' => null, 'exception' => 'ForbiddenException'
+ );
+
+ return $results;
+ }
+
+/**
+ * editアクションのGETテスト(作成権限のみ)用DataProvider
+ *
+ * ### 戻り値
+ * - urlOptions: URLオプション
+ * - assert: テストの期待値
+ * - exception: Exception
+ * - return: testActionの実行後の結果
+ *
+ * @return array
+ */
+ public function dataProviderEditGetByCreatable() {
+ $data = $this->__data();
+
+ //テストデータ
+ // * 作成権限のみ
+ $results = array();
+ // ** 他人の記事
+ $results[0] = array(
+ 'urlOptions' => array(
+ 'frame_id' => $data['Frame']['id'],
+ 'block_id' => $data['Block']['id'],
+ 'key' => 'content_key_1'
+ ),
+ 'assert' => null, 'exception' => 'BadRequestException'
+ );
+ // ** 自分の記事
+ $results[1] = array(
+ 'urlOptions' => array(
+ 'frame_id' => $data['Frame']['id'],
+ 'block_id' => $data['Block']['id'],
+ 'key' => 'content_key_2'
+ ),
+ 'assert' => array('method' => 'assertNotEmpty'),
+ );
+
+ return $results;
+ }
+
+/**
+ * editアクションのGETテスト(編集権限あり、公開権限なし)用DataProvider
+ *
+ * ### 戻り値
+ * - urlOptions: URLオプション
+ * - assert: テストの期待値
+ * - exception: Exception
+ * - return: testActionの実行後の結果
+ *
+ * @return array
+ */
+ public function dataProviderEditGetByEditable() {
+ $data = $this->__data();
+
+ //テストデータ
+ // * 編集権限あり
+ $results = array();
+ // ** コンテンツあり
+ $results[0] = array(
+ 'urlOptions' => array(
+ 'frame_id' => $data['Frame']['id'],
+ 'block_id' => $data['Block']['id'],
+ 'key' => 'content_key_1'
+ ),
+ 'assert' => array('method' => 'assertNotEmpty'),
+ );
+
+ // ** コンテンツなし
+ $results[count($results)] = array(
+ 'urlOptions' => array(
+ 'frame_id' => '14',
+ 'block_id' => null,
+ 'key' => null
+ ),
+ 'assert' => array('method' => 'assertEquals', 'expected' => 'emptyRender'),
+ 'exception' => null, 'return' => 'viewFile'
+ );
+
+ return $results;
+ }
+
+/**
+ * editアクションのGETテスト(公開権限あり)用DataProvider
+ *
+ * ### 戻り値
+ * - urlOptions: URLオプション
+ * - assert: テストの期待値
+ * - exception: Exception
+ * - return: testActionの実行後の結果
+ *
+ * @return array
+ */
+ public function dataProviderEditGetByPublishable() {
+ $data = $this->__data();
+
+ //テストデータ
+ // * フレームID指定なしテスト
+ $results = array();
+ $results[0] = array(
+ 'urlOptions' => array(
+ 'frame_id' => null,
+ 'block_id' => $data['Block']['id'],
+ 'key' => 'content_key_1'
+ ),
+ 'assert' => array('method' => 'assertNotEmpty'),
+ );
+
+ return $results;
+ }
+
+/**
+ * editアクションのPOSTテスト用DataProvider
+ *
+ * ### 戻り値
+ * - data: 登録データ
+ * - role: ロール
+ * - urlOptions: URLオプション
+ * - exception: Exception
+ * - return: testActionの実行後の結果
+ *
+ * @return array
+ */
+ public function dataProviderEditPost() {
+ $data = $this->__data();
+
+ //テストデータ
+ $results = array();
+ // * ログインなし
+ $contentKey = 'content_key_1';
+ array_push($results, array(
+ 'data' => $data,
+ 'role' => null,
+ 'urlOptions' => array(
+ 'frame_id' => $data['Frame']['id'],
+ 'block_id' => $data['Block']['id'],
+ 'key' => $contentKey,
+ ),
+ 'exception' => 'ForbiddenException'
+ ));
+ // * 作成権限のみ
+ // ** 他人の記事
+ $contentKey = 'content_key_1';
+ array_push($results, array(
+ 'data' => $data,
+ 'role' => Role::ROOM_ROLE_KEY_GENERAL_USER,
+ 'urlOptions' => array(
+ 'frame_id' => $data['Frame']['id'],
+ 'block_id' => $data['Block']['id'],
+ 'key' => $contentKey,
+ ),
+ 'exception' => 'BadRequestException'
+ ));
+ // ** 自分の記事
+ $contentKey = 'content_key_2';
+ array_push($results, array(
+ 'data' => $this->__data(Role::ROOM_ROLE_KEY_GENERAL_USER),
+ 'role' => Role::ROOM_ROLE_KEY_GENERAL_USER,
+ 'urlOptions' => array(
+ 'frame_id' => $data['Frame']['id'],
+ 'block_id' => $data['Block']['id'],
+ 'key' => $contentKey,
+ ),
+ ));
+ // * 編集権限あり
+ // ** コンテンツあり
+ $contentKey = 'content_key_1';
+ array_push($results, array(
+ 'data' => $data,
+ 'role' => Role::ROOM_ROLE_KEY_EDITOR,
+ 'urlOptions' => array(
+ 'frame_id' => $data['Frame']['id'],
+ 'block_id' => $data['Block']['id'],
+ 'key' => $contentKey,
+ ),
+ ));
+ // ** フレームID指定なしテスト
+ $contentKey = 'content_key_1';
+ array_push($results, array(
+ 'data' => $data,
+ 'role' => Role::ROOM_ROLE_KEY_ROOM_ADMINISTRATOR,
+ 'urlOptions' => array(
+ 'frame_id' => null,
+ 'block_id' => $data['Block']['id'],
+ 'key' => $contentKey,
+ ),
+ ));
+
+ return $results;
+ }
+
+/**
+ * editアクションのValidationErrorテスト用DataProvider
+ *
+ * ### 戻り値
+ * - data: 登録データ
+ * - urlOptions: URLオプション
+ * - validationError: バリデーションエラー
+ *
+ * @return array
+ */
+ public function dataProviderEditValidationError() {
+ $data = $this->__data();
+ $result = array(
+ 'data' => $data,
+ 'urlOptions' => array(
+ 'frame_id' => $data['Frame']['id'],
+ 'block_id' => $data['Block']['id'],
+ 'key' => 'content_key_1',
+ ),
+ 'validationError' => array(),
+ );
+
+ //テストデータ
+ $results = array();
+ array_push($results, Hash::merge($result, array(
+ 'validationError' => array(
+ 'field' => 'Link.url',
+ 'value' => 'aaaa',
+ 'message' => sprintf(__d('net_commons', 'Unauthorized pattern for %s. Please input the data in %s format.'), __d('links', 'URL'), __d('links', 'URL')),
+ )
+ )));
+ array_push($results, Hash::merge($result, array(
+ 'validationError' => array(
+ 'field' => 'Link.title',
+ 'value' => '',
+ 'message' => sprintf(__d('net_commons', 'Please input %s.'), __d('links', 'Title')),
+ )
+ )));
+
+ return $results;
+ }
+
+/**
+ * Viewのアサーション
+ *
+ * @param array $data テストデータ
+ * @return void
+ */
+ private function __assertEditGet($data) {
+ $this->assertInput(
+ 'input', 'data[Frame][id]', $data['Frame']['id'], $this->view
+ );
+ $this->assertInput(
+ 'input', 'data[Block][id]', $data['Block']['id'], $this->view
+ );
+ $this->assertInput(
+ 'input', 'data[Link][id]', $data['Link']['id'], $this->view
+ );
+ $this->assertInput(
+ 'input', 'data[Link][key]', $data['Link']['key'], $this->view
+ );
+ $this->assertInput(
+ 'input', 'data[Link][url]', null, $this->view
+ );
+ $this->assertInput(
+ 'input', 'data[Link][title]', null, $this->view
+ );
+ $this->assertInput(
+ 'input', 'data[Link][description]', null, $this->view
+ );
+ $this->assertInput(
+ 'input', 'data[LinkOrder][id]', $data['LinkOrder']['id'], $this->view
+ );
+ $this->assertInput(
+ 'input', 'data[LinkOrder][link_key]', $data['LinkOrder']['link_key'], $this->view
+ );
+ }
+
+/**
+ * view(ctp)ファイルのテスト(公開権限なし)
+ *
+ * @return void
+ */
+ public function testViewFileByEditable() {
+ TestAuthGeneral::login($this, Role::ROOM_ROLE_KEY_EDITOR);
+
+ //テスト実行
+ $data = $this->__data();
+ $this->_testGetAction(
+ array(
+ 'action' => 'edit',
+ 'block_id' => $data['Block']['id'],
+ 'frame_id' => $data['Frame']['id'],
+ 'key' => 'content_key_1',
+ ),
+ array('method' => 'assertNotEmpty')
+ );
+
+ //チェック
+ $this->__assertEditGet($data);
+ $this->assertInput('button', 'save_' . WorkflowComponent::STATUS_IN_DRAFT, null, $this->view);
+ $this->assertInput('button', 'save_' . WorkflowComponent::STATUS_APPROVAL_WAITING, null, $this->view);
+ $this->assertNotRegExp('//', $this->view);
+
+ TestAuthGeneral::logout($this);
+ }
+
+/**
+ * view(ctp)ファイルのテスト(公開権限あり)
+ *
+ * @return void
+ */
+ public function testViewFileByPublishable() {
+ //ログイン
+ TestAuthGeneral::login($this);
+
+ //テスト実行
+ $data = $this->__data();
+ $urlOptions = array(
+ 'action' => 'edit',
+ 'block_id' => $data['Block']['id'],
+ 'frame_id' => $data['Frame']['id'],
+ 'key' => 'content_key_1',
+ );
+ $this->_testGetAction($urlOptions, array('method' => 'assertNotEmpty'));
+
+ //チェック
+ $this->__assertEditGet($data);
+ $this->assertInput('button', 'save_' . WorkflowComponent::STATUS_IN_DRAFT, null, $this->view);
+ $this->assertInput('button', 'save_' . WorkflowComponent::STATUS_PUBLISHED, null, $this->view);
+ $this->assertInput('input', '_method', 'DELETE', $this->view);
+
+ //ログアウト
+ TestAuthGeneral::logout($this);
+ }
+
+}
diff --git a/Test/Case/Controller/LinksController/GetTest.php b/Test/Case/Controller/LinksController/GetTest.php
new file mode 100644
index 0000000..8d85673
--- /dev/null
+++ b/Test/Case/Controller/LinksController/GetTest.php
@@ -0,0 +1,145 @@
+
+ * @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('NetCommonsControllerTestCase', 'NetCommons.TestSuite');
+
+/**
+ * LinksController::get()のテスト
+ *
+ * @author Shohei Nakajima
+ * @package NetCommons\Links\Test\Case\Controller\LinksController
+ */
+class LinksControllerGetTest extends NetCommonsControllerTestCase {
+
+/**
+ * Fixtures
+ *
+ * @var array
+ */
+ public $fixtures = array(
+ 'plugin.categories.category',
+ 'plugin.categories.category_order',
+ 'plugin.categories.categories_language',
+ 'plugin.links.link',
+ 'plugin.links.link_frame_setting',
+ 'plugin.links.link_order',
+ 'plugin.links.block_setting_for_link',
+ 'plugin.workflow.workflow_comment',
+ );
+
+/**
+ * Plugin name
+ *
+ * @var string
+ */
+ public $plugin = 'links';
+
+/**
+ * Controller name
+ *
+ * @var string
+ */
+ protected $_controller = 'links';
+
+/**
+ * setUp method
+ *
+ * @return void
+ */
+ public function setUp() {
+ parent::setUp();
+
+ //テストプラグインのロード
+ NetCommonsCakeTestCase::loadTestPlugin($this, 'Links', 'TestLinks');
+ //テストコントローラ生成
+ $this->generateNc('TestLinks.TestControllerLinksControllerGet');
+ //ログイン
+ TestAuthGeneral::login($this);
+ }
+
+/**
+ * tearDown method
+ *
+ * @return void
+ */
+ public function tearDown() {
+ //ログアウト
+ TestAuthGeneral::logout($this);
+
+ parent::tearDown();
+ }
+
+/**
+ * get()アクションのテスト
+ *
+ * @return void
+ */
+ public function testGet() {
+ //テスト実行
+ $actionUrl = array(
+ 'plugin' => 'test_links', 'controller' => 'test_controller_links_controller_get',
+ 'action' => 'get', 'frame_id' => '6'
+ );
+ $paramUrl = 'success';
+
+ $result = $this->_testGetAction(NetCommonsUrl::actionUrl($actionUrl) . '&url=' . $paramUrl,
+ array('method' => 'assertNotEmpty'), null, 'json');
+
+ //チェック
+ $this->assertEquals('OK', $result['name']);
+ $this->assertEquals(200, $result['code']);
+ $this->assertNotEmpty($result['title']);
+ $this->assertNotEmpty($result['description']);
+ }
+
+/**
+ * get()アクションのテスト(URLが空値)
+ *
+ * @return void
+ */
+ public function testGetWOUrl() {
+ //テスト実行
+ $actionUrl = array(
+ 'plugin' => 'test_links', 'controller' => 'test_controller_links_controller_get',
+ 'action' => 'get', 'frame_id' => '6'
+ );
+ $paramUrl = '';
+
+ $result = $this->_testGetAction(NetCommonsUrl::actionUrl($actionUrl) . '&url=' . $paramUrl,
+ null, 'BadRequestException', 'json');
+
+ //チェック
+ $this->assertEquals('Bad Request', $result['name']);
+ $this->assertEquals(sprintf(__d('net_commons', 'Please input %s.'), __d('links', 'URL')), $result['error']);
+ }
+
+/**
+ * get()アクションのテスト(URLが不正)
+ *
+ * @return void
+ */
+ public function testGetOnBadUrl() {
+ //テスト実行
+ $actionUrl = array(
+ 'plugin' => 'test_links', 'controller' => 'test_controller_links_controller_get',
+ 'action' => 'get', 'frame_id' => '6'
+ );
+ $paramUrl = 'failure';
+
+ $result = $this->_testGetAction(NetCommonsUrl::actionUrl($actionUrl) . '&url=' . $paramUrl,
+ null, 'BadRequestException', 'json');
+
+ //チェック
+ $this->assertEquals('Bad Request', $result['name']);
+ $this->assertEquals(__d('links', 'Failed to obtain the title for this page.'), $result['error']);
+ }
+
+}
diff --git a/Test/Case/Controller/LinksController/IndexTest.php b/Test/Case/Controller/LinksController/IndexTest.php
new file mode 100644
index 0000000..181227f
--- /dev/null
+++ b/Test/Case/Controller/LinksController/IndexTest.php
@@ -0,0 +1,220 @@
+
+ * @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('WorkflowControllerIndexTest', 'Workflow.TestSuite');
+
+/**
+ * LinksController::index()のテスト
+ *
+ * @author Shohei Nakajima
+ * @package NetCommons\Links\Test\Case\Controller\LinksController
+ */
+class LinksControllerIndexTest extends WorkflowControllerIndexTest {
+
+/**
+ * Fixtures
+ *
+ * @var array
+ */
+ public $fixtures = array(
+ 'plugin.categories.category',
+ 'plugin.categories.category_order',
+ 'plugin.categories.categories_language',
+ 'plugin.links.frame4link',
+ 'plugin.links.frame_public_language4link',
+ 'plugin.links.frames_language4link',
+ 'plugin.links.link',
+ 'plugin.links.link_frame_setting',
+ 'plugin.links.link_order',
+ 'plugin.links.block_setting_for_link',
+ 'plugin.workflow.workflow_comment',
+ );
+
+/**
+ * Plugin name
+ *
+ * @var string
+ */
+ public $plugin = 'links';
+
+/**
+ * Controller name
+ *
+ * @var string
+ */
+ protected $_controller = 'links';
+
+/**
+ * テストDataの取得
+ *
+ * @param int $frameId フレームID
+ * @return array
+ */
+ private function __data($frameId) {
+ $blockId = '2';
+
+ $data = array(
+ 'action' => 'index',
+ 'frame_id' => $frameId,
+ 'block_id' => $blockId,
+ );
+
+ return $data;
+ }
+
+/**
+ * indexアクションのテスト(ログインなし)用DataProvider
+ *
+ * ### 戻り値
+ * - urlOptions: URLオプション
+ * - assert: テストの期待値
+ * - exception: Exception
+ * - return: testActionの実行後の結果
+ *
+ * @return array
+ */
+ public function dataProviderIndex() {
+ //テストデータ
+ $results = array();
+ $results[0] = array(
+ 'urlOptions' => $this->__data('6'),
+ 'assert' => array(
+ array('method' => 'assertTextContains', 'assert' => ' 'assertTextNotContains', 'assert' => 'Description 1'),
+ ),
+ );
+ $results[2] = array(
+ 'urlOptions' => $this->__data('8'),
+ 'assert' => array(
+ array('method' => 'assertTextContains', 'assert' => '