* @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('LibAppObject', 'NetCommons.Lib'); App::uses('BlockSettingBehavior', 'Blocks.Model/Behavior'); /** * NetCommonsの機能に必要な情報(ブロック)を取得する内容をまとめたUtility * * @property Controller $_controller コントローラ * @property Language $Language Languageモデル * @property Block $Block Pluginモデル * @property BlocksLanguage $BlocksLanguage BlocksLanguageモデル * @property BlockRolePermission $BlockRolePermission BlockRolePermissionモデル * @property BlockSetting $BlockSetting BlockSettingモデル * * @property CurrentLibLanguage $CurrentLibLanguage CurrentLibLanguageライブラリ * @property CurrentLibRoom $CurrentLibRoom CurrentLibRoomライブラリ * * @author Shohei Nakajima * @package NetCommons\NetCommons\Utility */ class CurrentLibBlock extends LibAppObject { /** * 使用するモデル * * @var array */ public $uses = [ 'Language' => 'M17n.Language', 'Block', 'BlocksLanguage', 'BlockRolePermission', 'BlockSetting', ]; /** * 使用するライブラリ * * @var array */ public $libs = [ 'CurrentLibLanguage' => 'NetCommons.Lib/Current', 'CurrentLibRoom' => 'NetCommons.Lib/Current', ]; /** * 一度取得したブロックデータを保持 * * @var array */ private $__blocks = []; /** * 一度取得したルーム権限パーミッション(block_settingからblock_permissionのフォーマットに変換)データを保持 * * @var array */ private $__rolePermFromSetting = []; /** * 一度取得したルーム権限パーミッション(block_role_permissions)データを保持 * * @var array|null */ private $__rolePermissions = null; /** * インスタンスの取得 * * @return CurrentLibFrame */ public static function getInstance() { return parent::_getInstance(__CLASS__); } /** * インスタンスのクリア * * @return void */ public static function resetInstance() { parent::_resetInstance(__CLASS__); } /** * コントローラのセット * * @param Controller $controller コントローラ * @return void */ public function initialize($controller = null) { parent::initialize($controller); $this->__langId = $this->CurrentLibLanguage->getLangId(); } /** * ブロックIDの取得 * * @return int|null ブロックID(int)。nullの場合、パラメータ等からblock_idが取得できなかった */ public function getCurrentBlockId() { if (empty($this->_controller->request->params['requested']) && !empty($this->_controller->request->data['Block']['id'])) { $blockId = $this->_controller->request->data['Block']['id']; } elseif (isset($this->_controller->request->params['block_id'])) { $blockId = $this->_controller->request->params['block_id']; } else { return null; } return (int)$blockId; } /** * ページブロックキーの取得 * * @return array */ public function getBlockKeysInCurrentPage() { $blockKeys = []; foreach ($this->__blocks as $block) { if (isset($block['Block']['key'])) { $blockKeys[] = $block['Block']['key']; } else { $blockKeys[] = null; } } return array_unique($blockKeys); } /** * リクエストパラメータにブロックIDがあるか * * @return bool */ public function isBlockIdInRequest() { return empty($this->_controller->request->params['requested']) && !empty($this->_controller->request->data['Block']['id']) || !empty($this->_controller->request->params['block_id']); } /** * ブロックデータを取得するカラムの取得 * * CurrentLibFrameで使用する * * @return array */ public function getFindFields() { return $this->__getFields(); } /** * ブロックデータを取得するカラムを生成する * * @return array */ private function __getFields() { $fields = [ 'Block.id', 'Block.room_id', 'Block.plugin_key', 'Block.key', 'Block.public_type', 'Block.publish_start', 'Block.publish_end', 'Block.content_count', 'BlocksLanguage.language_id', 'BlocksLanguage.block_id', 'BlocksLanguage.name', 'BlocksLanguage.is_origin', 'BlocksLanguage.is_translation', 'BlocksLanguage.is_original_copy', ]; return $fields; } /** * 多言語のフレーム取得のためのjoinsを生成する * * @return array */ private function __makeJoinsByMultipleLang() { $joins = [ [ 'type' => 'LEFT', 'table' => $this->BlocksLanguage->table, 'alias' => $this->BlocksLanguage->alias, 'conditions' => [ 'BlocksLanguage.block_id = Block.id', 'OR' => [ 'BlocksLanguage.is_translation' => false, 'BlocksLanguage.language_id' => $this->__langId, ], ], ], ]; return $joins; } /** * 単一言語のフレーム取得のためのjoinsを生成する * * @return array */ private function __makeJoinsBySingleLang() { $joins = [ [ 'type' => 'LEFT', 'table' => $this->BlocksLanguage->table, 'alias' => $this->BlocksLanguage->alias, 'conditions' => [ 'BlocksLanguage.block_id = Block.id', 'BlocksLanguage.language_id' => $this->__langId, ], ], ]; return $joins; } /** * ブロックデータを取得 * * @param string|int $blockId ブロックID * @return array */ public function findBlockById($blockId) { if (isset($this->__blocks[$blockId])) { return $this->__blocks[$blockId]; } $fields = $this->__getFields(); if ($this->Language->isMultipleLang()) { $joins = $this->__makeJoinsByMultipleLang(); } else { $joins = $this->__makeJoinsBySingleLang(); } $block = $this->Block->find('first', [ 'recursive' => -1, 'fields' => $fields, 'joins' => $joins, 'conditions' => [ 'Block.id' => $blockId, ], 'callbacks' => false, ]); $this->setBlock($blockId, $block); return $block; } /** * ブロックデータを変数にセットする * * CurrentLibFrameで使用するため、publicメソッド化 * * @param string|int $blockId ブロックID * @param array $block ブロックデータ * @return void */ public function setBlock($blockId, $block) { if ($block) { $this->__blocks[$blockId] = [ 'Block' => $block['Block'], 'BlocksLanguage' => $block['BlocksLanguage'] ]; } else { $this->__blocks[$blockId] = [ 'Block' => null, 'BlocksLanguage' => null ]; } } /** * ブロックキーからブロックロールパーミッションのデータを取得 * * @param string|int $roomId ルームID * @param string $blockKey ブロックキー * @return array * @throws InternalErrorException */ public function findBlockRolePermissionsByBlockKey($roomId, $blockKey) { if (isset($this->__rolePermissions[$blockKey])) { return $this->__rolePermissions[$blockKey]; } $results = $this->BlockRolePermission->find('all', [ 'recursive' => -1, 'fields' => [ 'id', 'roles_room_id', 'block_key', 'permission', 'value' ], 'conditions' => [ 'block_key' => $blockKey, 'roles_room_id' => $this->CurrentLibRoom->getRoleRoomIdByRoomId($roomId), ], 'callbacks' => false, ]); $this->__rolePermissions[$blockKey] = []; foreach ($results as $permission) { $blockKey = $permission['BlockRolePermission']['block_key']; $key = $permission['BlockRolePermission']['permission']; $this->__rolePermissions[$blockKey][$key] = $permission['BlockRolePermission']; } // content_publishable は BlockRolePermission から無くなったが、あった場合throw Exception しとく // アップデート時にMigrationで削除するのでありえない。 // unsetして継続させた方が良いのか?アップデート時は管理者で操作するので問題なし。 // アップデート時に、ファイル上書きして、プラグイン管理のアップデートを実行するまでの間あり得る if (isset($this->__rolePermissions[$blockKey]['content_publishable'])) { throw new InternalErrorException('BlockRolePermission.content_publishable exists'); } return $this->__rolePermissions[$blockKey]; } /** * ブロックキーからブロックロールパーミッションのデータをローカル変数にセットする * * @param string|int $roomId ルームID * @param array $blockKeys ブロックキーリスト * @return void * @throws InternalErrorException */ public function setBlockRolePermissions($roomId, $blockKeys) { $results = $this->BlockRolePermission->find('all', [ 'recursive' => -1, 'fields' => [ 'id', 'roles_room_id', 'block_key', 'permission', 'value' ], 'conditions' => [ 'block_key' => $blockKeys, 'roles_room_id' => $this->CurrentLibRoom->getRoleRoomIdByRoomId($roomId) ], 'callbacks' => false, ]); //変数の初期化 foreach ($blockKeys as $blockKey) { $this->__rolePermissions[$blockKey] = []; } foreach ($results as $permission) { $blockKey = $permission['BlockRolePermission']['block_key']; $key = $permission['BlockRolePermission']['permission']; $this->__rolePermissions[$blockKey][$key] = $permission['BlockRolePermission']; // content_publishable は BlockRolePermission から無くなったが、あった場合throw Exception しとく // アップデート時にMigrationで削除するのでありえない。 // unsetして継続させた方が良いのか?アップデート時は管理者で操作するので問題なし。 // アップデート時に、ファイル上書きして、プラグイン管理のアップデートを実行するまでの間あり得る if (isset($this->__rolePermissions[$blockKey]['content_publishable'])) { throw new InternalErrorException('BlockRolePermission.content_publishable exists'); } } } /** * ブロックキーからブロック設定データからワークフローの有無を取得 * * ・承認ありのルームの場合、BlockSettingの承認有無は使用せずに、room_role_permissionsを使用する。 * ・承認なしのルームの場合、BlockSettingにデータは、承認なしのデータとする。 *  ただし、実際に利用するpermissionのデータは、room_role_permissionsの設定値を利用する。 *  逆にBlockSettingにデータがない場合、承認ありとする(元のソースktera)。 * * @param string|int $roomId ルームID * @param string $blockKey ブロックキー * @return array */ public function findUseWorkflowPermissionsByBlockKey($roomId, $blockKey) { $room = $this->CurrentLibRoom->findRoomById($roomId); if (! $room || $room['Room']['need_approval']) { return []; } if (! $blockKey) { $permissions = []; $permissions['content_publishable']['value'] = true; $permissions['content_comment_publishable']['value'] = true; return $permissions; } if (isset($this->__rolePermFromSetting[$blockKey])) { return $this->__rolePermFromSetting[$blockKey]; } $results = $this->BlockSetting->find('all', array( 'recursive' => -1, 'fields' => array('field_name', 'value'), 'conditions' => array( 'room_id' => $roomId, 'block_key' => $blockKey, 'field_name' => array( BlockSettingBehavior::FIELD_USE_WORKFLOW, BlockSettingBehavior::FIELD_USE_COMMENT_APPROVAL ), ), 'callbacks' => false, )); $blockSettings = []; foreach ($results as $result) { $key = $result['BlockSetting']['field_name']; $value = $result['BlockSetting']['value']; $blockSettings[$key] = $value; } $this->__setUseWorkflowPermission($blockKey, $blockSettings); return $this->__rolePermFromSetting[$blockKey]; } /** * ブロック設定データのワークフローの有無をローカル変数にセットする * * @param string|int $roomId ルームID * @param array $blockKeys ブロックキーリスト * @return array */ public function setUseWorkflowPermissions($roomId, $blockKeys) { $results = $this->BlockSetting->find('all', array( 'recursive' => -1, 'fields' => array('block_key', 'field_name', 'value'), 'conditions' => array( 'room_id' => $roomId, 'block_key' => $blockKeys, 'field_name' => array( BlockSettingBehavior::FIELD_USE_WORKFLOW, BlockSettingBehavior::FIELD_USE_COMMENT_APPROVAL ), ), 'callbacks' => false, )); $blockSettings = []; foreach ($results as $result) { $blockKey = $result['BlockSetting']['block_key']; $key = $result['BlockSetting']['field_name']; $value = $result['BlockSetting']['value']; $blockSettings[$blockKey][$key] = $value; } foreach ($blockKeys as $blockKey) { if (isset($blockSettings[$blockKey])) { $this->__setUseWorkflowPermission($blockKey, $blockSettings[$blockKey]); } else { $this->__setUseWorkflowPermission($blockKey, []); } } } /** * ブロック設定データのワークフローの有無をローカル変数をセットする * * @param string $blockKey ブロックキー * @param array $blockSettings ブロック設定データリスト * @return array */ private function __setUseWorkflowPermission($blockKey, $blockSettings) { if (!$blockSettings) { $this->__rolePermFromSetting[$blockKey]['content_publishable']['value'] = true; $this->__rolePermFromSetting[$blockKey]['content_comment_publishable']['value'] = true; } else { $this->__rolePermFromSetting[$blockKey] = []; if (empty($blockSettings[BlockSettingBehavior::FIELD_USE_WORKFLOW])) { $this->__rolePermFromSetting[$blockKey]['content_publishable']['value'] = true; } if (empty($blockSettings[BlockSettingBehavior::FIELD_USE_COMMENT_APPROVAL])) { $this->__rolePermFromSetting[$blockKey]['content_comment_publishable']['value'] = true; } } } }