PageRenderTime 80ms CodeModel.GetById 26ms RepoModel.GetById 1ms app.codeStats 0ms

/baser/models/page_category.php

https://github.com/hashing/basercms
PHP | 652 lines | 381 code | 60 blank | 211 comment | 69 complexity | 52ea20a190275c3bda98abae1a95ab03 MD5 | raw file
Possible License(s): MIT
  1. <?php
  2. /* SVN FILE: $Id$ */
  3. /**
  4. * ページカテゴリーモデル
  5. *
  6. * PHP versions 5
  7. *
  8. * baserCMS : Based Website Development Project <http://basercms.net>
  9. * Copyright 2008 - 2012, baserCMS Users Community <http://sites.google.com/site/baserusers/>
  10. *
  11. * @copyright Copyright 2008 - 2012, baserCMS Users Community
  12. * @link http://basercms.net baserCMS Project
  13. * @package baser.models
  14. * @since baserCMS v 0.1.0
  15. * @version $Revision$
  16. * @modifiedby $LastChangedBy$
  17. * @lastmodified $Date$
  18. * @license http://basercms.net/license/index.html
  19. */
  20. /**
  21. * ページカテゴリーモデル
  22. *
  23. * @package baser.models
  24. */
  25. class PageCategory extends AppModel {
  26. /**
  27. * クラス名
  28. *
  29. * @var string
  30. * @access public
  31. */
  32. var $name = 'PageCategory';
  33. /**
  34. * データベース接続
  35. *
  36. * @var string
  37. * @access public
  38. */
  39. var $useDbConfig = 'baser';
  40. /**
  41. * actsAs
  42. *
  43. * @var array
  44. * @access public
  45. */
  46. var $actsAs = array('Tree', 'BcCache');
  47. /**
  48. * hasMany
  49. *
  50. * @var array
  51. * @access @public
  52. */
  53. var $hasMany = array('Page' => array('className'=>'Page',
  54. 'conditions'=>'',
  55. 'order'=>'Page.sort',
  56. 'limit'=>'',
  57. 'foreignKey'=>'page_category_id',
  58. 'dependent'=>false,
  59. 'exclusive'=>false,
  60. 'finderQuery'=>''));
  61. /**
  62. * ページカテゴリフォルダのパスリスト
  63. * キーはカテゴリID
  64. * キャッシュ用
  65. *
  66. * @var mixed
  67. * @access protected
  68. */
  69. var $_pageCategoryPathes = -1;
  70. /**
  71. * エージェントカテゴリのID
  72. *
  73. * @var array
  74. * @access protected
  75. */
  76. var $_agentId = array();
  77. /**
  78. * 保存時に関連ページを更新するかどうか
  79. *
  80. * @var boolean
  81. * @access public
  82. */
  83. var $updateRelatedPage = true;
  84. /**
  85. * バリデーション
  86. *
  87. * @var array
  88. * @access public
  89. */
  90. var $validate = array(
  91. 'name' => array(
  92. array( 'rule' => array('minLength', 1),
  93. 'message' => 'ページカテゴリ名を入力してください。',
  94. 'required' => true),
  95. 'alphaNumericPlus' => array(
  96. 'rule' => 'alphaNumericPlus',
  97. 'message' => 'ページカテゴリ名は半角英数字とハイフン、アンダースコアのみで入力してください。'
  98. ),
  99. array( 'rule' => array('maxLength', 50),
  100. 'message' => 'ページカテゴリ名は50文字以内で入力してください。'),
  101. array( 'rule' => array('duplicatePageCategory'),
  102. 'message' => '入力されたページカテゴリー名は、同一階層に既に登録されています。')
  103. ),
  104. 'title' => array(
  105. array( 'rule' => array('minLength', 1),
  106. 'message' => 'ページカテゴリタイトルを入力してください。',
  107. 'required' => true),
  108. array( 'rule' => array('maxLength', 255),
  109. 'message' => 'ページカテゴリタイトルは255文字以内で入力してください。')
  110. )
  111. );
  112. /**
  113. * コントロールソースを取得する
  114. *
  115. * @param string フィールド名
  116. * @return array コントロールソース
  117. * @access public
  118. */
  119. function getControlSource($field, $options = array()) {
  120. switch ($field) {
  121. case 'parent_id':
  122. $conditions = array();
  123. if(isset($options['conditions'])) {
  124. $conditions = $options['conditions'];
  125. }
  126. if(!empty($options['excludeParentId'])) {
  127. if(!is_array($options['excludeParentId'])) {
  128. $options['excludeParentId'] = array($options['excludeParentId']);
  129. }
  130. $excludeIds = array();
  131. foreach($options['excludeParentId'] as $excludeParentId) {
  132. $children = $this->children($excludeParentId);
  133. if($children) {
  134. $excludeIds = am($excludeIds, Set::extract('/PageCategory/id', $children));
  135. }
  136. $excludeIds[] = $excludeParentId;
  137. }
  138. $conditions['NOT']['PageCategory.id'] = $excludeIds;
  139. }
  140. $parentIds = array();
  141. if(!empty($options['parentId'])) {
  142. if(!is_array($options['parentId'])) {
  143. $options['parentId'] = array($options['parentId']);
  144. }
  145. foreach($options['parentId'] as $parentId) {
  146. $children = $this->children($parentId);
  147. if($children) {
  148. $parentIds = am($parentIds, Set::extract('/PageCategory/id', $children));
  149. } else {
  150. return array();
  151. }
  152. }
  153. }
  154. if($parentIds) {
  155. $conditions['PageCategory.id'] = $parentIds;
  156. }
  157. if(isset($options['ownerId'])) {
  158. $ownerIdConditions = array(
  159. array('PageCategory.owner_id' => null),
  160. array('PageCategory.owner_id' => $options['ownerId']),
  161. );
  162. if(isset($conditions['OR'])) {
  163. $conditions['OR'] = am($conditions['OR'], $ownerIdConditions);
  164. } else {
  165. $conditions['OR'] = $ownerIdConditions;
  166. }
  167. }
  168. $parents = $this->generatetreelist($conditions);
  169. $controlSources['parent_id'] = array();
  170. $excludeIds = array();
  171. if(!Configure::read('BcApp.mobile')) {
  172. $excludeIds = $this->getAgentCategoryIds('mobile');
  173. }
  174. if(!Configure::read('BcApp.smartphone')) {
  175. $excludeIds = $this->getAgentCategoryIds('smartphone');
  176. }
  177. foreach($parents as $key => $parent) {
  178. if($parent && !in_array($key, $excludeIds)) {
  179. if(preg_match("/^([_]+)/i",$parent,$matches)) {
  180. $parent = preg_replace("/^[_]+/i",'',$parent);
  181. $prefix = str_replace('_','&nbsp&nbsp&nbsp',$matches[1]);
  182. $parent = $prefix.'└'.$parent;
  183. }
  184. $controlSources['parent_id'][$key] = $parent;
  185. }
  186. }
  187. break;
  188. case 'owner_id':
  189. $UserGroup = ClassRegistry::init('UserGroup');
  190. $controlSources['owner_id'] = $UserGroup->find('list', array('fields' => array('id', 'title'), 'recursive' => -1));
  191. break;
  192. }
  193. if(isset($controlSources[$field])) {
  194. return $controlSources[$field];
  195. }else {
  196. return false;
  197. }
  198. }
  199. /**
  200. * beforeSave
  201. *
  202. * @return boolean
  203. * @access public
  204. */
  205. function beforeSave() {
  206. // セーフモードの場合はフォルダの自動生成は行わない
  207. if(ini_get('safe_mode')) {
  208. return true;
  209. }
  210. // 新しいページファイルのパスを取得する
  211. $newPath = $this->createPageCategoryFolder($this->data);
  212. if($this->exists()) {
  213. $oldPath = $this->createPageCategoryFolder($this->find('first',array('conditions'=>array('id'=>$this->id))));
  214. if($newPath != $oldPath) {
  215. $dir = new Folder();
  216. $ret = $dir->move(array('to'=>$newPath,'from'=>$oldPath,'chmod'=>0777));
  217. }else {
  218. if(!is_dir($newPath)) {
  219. $dir = new Folder();
  220. $ret = $dir->create($newPath, 0777);
  221. }
  222. $ret = true;
  223. }
  224. }else {
  225. $dir = new Folder();
  226. $ret = $dir->create($newPath, 0777);
  227. }
  228. return $ret;
  229. }
  230. /**
  231. * afterSave
  232. *
  233. * @param boolean $created
  234. * @return void
  235. * @access public
  236. */
  237. function afterSave($created) {
  238. if(!$created && $this->updateRelatedPage) {
  239. $this->updateRelatedPageUrlRecursive($this->data['PageCategory']['id']);
  240. }
  241. }
  242. /**
  243. * ページカテゴリのフォルダを生成してパスを返す
  244. *
  245. * @param array $data ページカテゴリデータ
  246. * @return mixid カテゴリのパス / false
  247. * @access public
  248. */
  249. function createPageCategoryFolder($data) {
  250. $path = $this->getPageCategoryFolderPath($data);
  251. $folder = new Folder();
  252. if($folder->create($path, 0777)){
  253. return $path;
  254. }else{
  255. return false;
  256. }
  257. }
  258. /**
  259. * カテゴリフォルダのパスを取得する
  260. *
  261. * @param array $data ページカテゴリデータ
  262. * @return string $path
  263. * @access public
  264. */
  265. function getPageCategoryFolderPath($data) {
  266. if(isset($data['PageCategory'])) {
  267. $data = $data['PageCategory'];
  268. }
  269. $path = $pagesPath = getViewPath().'pages'.DS;
  270. $categoryName = $data['name'];
  271. $parentId = $data['parent_id'];
  272. if($parentId) {
  273. $categoryPath = $this->getPath($parentId);
  274. if($categoryPath) {
  275. foreach($categoryPath as $category) {
  276. $path .= $category['PageCategory']['name'].DS;
  277. }
  278. }
  279. }
  280. return $path.$categoryName;
  281. }
  282. /**
  283. * 同一階層に同じニックネームのカテゴリがないかチェックする
  284. * 同じテーマが条件
  285. *
  286. * @param array $check
  287. * @return boolean
  288. * @access public
  289. */
  290. function duplicatePageCategory($check) {
  291. $parentId = $this->data['PageCategory']['parent_id'];
  292. if($parentId) {
  293. $conditions['PageCategory.parent_id'] = $parentId;
  294. }else {
  295. $conditions['OR'] = array('PageCategory.parent_id'=>'');
  296. $conditions['OR'] = array('PageCategory.parent_id'=>null);
  297. }
  298. $children = $this->find('all',array('conditions'=>$conditions));
  299. if($children) {
  300. foreach($children as $child) {
  301. if($this->exists()) {
  302. if($this->id == $child['PageCategory']['id']) {
  303. continue;
  304. }
  305. }
  306. if($child['PageCategory']['name'] == $check[key($check)]) {
  307. return false;
  308. }
  309. }
  310. }
  311. return true;
  312. }
  313. /**
  314. * 関連するページデータをカテゴリ無所属に変更し保存する
  315. *
  316. * @param boolean $cascade
  317. * @return boolean
  318. * @access public
  319. */
  320. function beforeDelete($cascade = true) {
  321. parent::beforeDelete($cascade);
  322. $id = $this->data['PageCategory']['id'];
  323. if($this->releaseRelatedPagesRecursive($id)){
  324. $path = $this->createPageCategoryFolder($this->find('first',array('conditions'=>array('id'=>$id))));
  325. $folder = new Folder();
  326. $folder->delete($path);
  327. return true;
  328. }else {
  329. return false;
  330. }
  331. }
  332. /**
  333. * 関連するページのカテゴリを解除する(再帰的)
  334. *
  335. * @param int $categoryId
  336. * @return boolean
  337. * @access public
  338. */
  339. function releaseRelatedPagesRecursive($categoryId) {
  340. if(!$this->releaseRelatedPages($categoryId)){
  341. return false;
  342. }
  343. $children = $this->children($categoryId);
  344. $ret = true;
  345. foreach($children as $child) {
  346. if(!$this->releaseRelatedPages($child['PageCategory']['id'])) {
  347. $ret = false;
  348. }
  349. }
  350. return $ret;
  351. }
  352. /**
  353. * 関連するページのカテゴリを解除する
  354. *
  355. * @param int $categoryId
  356. * @return boolean
  357. * @access public
  358. */
  359. function releaseRelatedPages($categoryId) {
  360. $pages = $this->Page->find('all',array('conditions'=>array('Page.page_category_id'=>$categoryId),'recursive'=>-1));
  361. $ret = true;
  362. if($pages) {
  363. foreach($pages as $page) {
  364. $page['Page']['page_category_id'] = '';
  365. $page['Page']['url'] = $this->Page->getPageUrl($page);
  366. $this->Page->set($page);
  367. if(!$this->Page->save()) {
  368. $ret = false;
  369. }
  370. }
  371. }
  372. return $ret;
  373. }
  374. /**
  375. * 関連するページデータのURLを更新する
  376. *
  377. * @param string $id
  378. * @return void
  379. * @access public
  380. */
  381. function updateRelatedPageUrlRecursive($categoryId) {
  382. if(!$this->updateRelatedPageUrl($categoryId)){
  383. return false;
  384. }
  385. $children = $this->children($categoryId);
  386. $ret = true;
  387. foreach($children as $child) {
  388. if(!$this->updateRelatedPageUrl($child['PageCategory']['id'])) {
  389. $ret = false;
  390. }
  391. }
  392. return $ret;
  393. }
  394. /**
  395. * 関連するページデータのURLを更新する
  396. *
  397. * @param string $id
  398. * @return void
  399. * @access public
  400. */
  401. function updateRelatedPageUrl($id) {
  402. if(!$id) {
  403. return;
  404. }
  405. $pages = $this->Page->find('all',array('conditions'=>array('Page.page_category_id'=>$id),'recursive'=>-1));
  406. $result = true;
  407. // ページデータのURLを更新
  408. if($pages) {
  409. $this->Page->saveFile = false;
  410. foreach($pages as $page) {
  411. $page['Page']['url'] = $this->Page->getPageUrl($page);
  412. $this->Page->set($page);
  413. if(!$this->Page->save()){
  414. $result = false;
  415. }
  416. }
  417. }
  418. return $result;
  419. }
  420. /**
  421. * カテゴリフォルダのパスから対象となるデータが存在するかチェックする
  422. * 存在する場合は id を返す
  423. *
  424. * @param string $path
  425. * @return mixed
  426. * @access public
  427. */
  428. function getIdByPath($path) {
  429. if($this->_pageCategoryPathes == -1) {
  430. $this->_pageCategoryPathes = array();
  431. $pageCategories = $this->find('all');
  432. if($pageCategories) {
  433. foreach($pageCategories as $pageCategory) {
  434. $this->_pageCategoryPathes[$pageCategory['PageCategory']['id']] = $this->getPageCategoryFolderPath($pageCategory);
  435. }
  436. }
  437. }
  438. if(in_array($path, $this->_pageCategoryPathes)) {
  439. return array_search($path,$this->_pageCategoryPathes);
  440. }else{
  441. return false;
  442. }
  443. }
  444. /**
  445. * モバイル用のカテゴリIDをリストで取得する
  446. *
  447. * @param boolean $top
  448. * @return array $ids
  449. * @access public
  450. */
  451. function getAgentCategoryIds($type = 'mobile', $top = true){
  452. $agentId = $this->getAgentId($type);
  453. if(!$agentId){
  454. return array();
  455. }
  456. $ids = array();
  457. if($top) {
  458. $ids[] = $agentId;
  459. }
  460. $children = $this->children($agentId, false, array('PageCategory.id'),array('PageCategory.id'));
  461. if($children){
  462. $children = Set::extract('/PageCategory/id',$children);
  463. $ids = am($ids,$children);
  464. }
  465. return $ids;
  466. }
  467. /**
  468. * エージェントカテゴリのIDを取得する
  469. *
  470. * @param int $targetId
  471. * @return int
  472. * @access public
  473. */
  474. function getAgentId($type = 'mobile') {
  475. if(!isset($this->_agentId[$type])){
  476. $agentId = $this->field('id',array('PageCategory.name'=>$type));
  477. if($agentId) {
  478. $this->_agentId[$type] = $agentId;
  479. } else {
  480. return false;
  481. }
  482. }
  483. return $this->_agentId[$type];
  484. }
  485. /**
  486. * PCのIDを元にモバイル・スマホの相対階層のIDを取得する
  487. * @param type $id
  488. * @return type
  489. */
  490. function getAgentRelativeId($type, $id) {
  491. if(!$id) {
  492. return $this->getAgentId($type);
  493. } else {
  494. $path = $this->getPath($id, array('name'), -1);
  495. $path = Set::extract('/PageCategory/name', $path);
  496. $path = implode(DS, $path);
  497. $path = getViewPath().'pages'.DS.$type.DS.$path;
  498. }
  499. $agentId = $this->getIdByPath($path);
  500. return $agentId;
  501. }
  502. /**
  503. * ツリーリストを取得する
  504. *
  505. * @param array $fields
  506. * @param int $id
  507. * @return array
  508. * @access public
  509. */
  510. function getTreeList($fields,$id){
  511. $this->recursive = -1;
  512. $pageCategories = array();
  513. $pageCategories[] = $pageCategory = $this->read($fields,$id);
  514. if($pageCategory['PageCategory']['parent_id']){
  515. $parents = $this->getTreeList($fields,$pageCategory['PageCategory']['parent_id']);
  516. $pageCategories = am($parents,$pageCategories);
  517. }
  518. return $pageCategories;
  519. }
  520. /**
  521. * 新しいカテゴリが追加できる状態かチェックする
  522. *
  523. * @param int $userGroupId
  524. * @param boolean $rootEditable
  525. * @return boolean
  526. * @access public
  527. */
  528. function checkNewCategoryAddable($userGroupId, $rootEditable) {
  529. $newCatAddable = false;
  530. $ownerCats = $this->find('count', array(
  531. 'conditions' => array(
  532. 'OR' => array(
  533. array('PageCategory.owner_id' => null),
  534. array('PageCategory.owner_id' => $userGroupId)
  535. ),
  536. array('PageCategory.id <>' => $this->getAgentId('mobile')),
  537. array('PageCategory.id <>' => $this->getAgentId('smartphone'))
  538. )));
  539. if($ownerCats || $rootEditable) {
  540. $newCatAddable = true;
  541. }
  542. return $newCatAddable;
  543. }
  544. /**
  545. * ページカテゴリーをコピーする
  546. *
  547. * @param int $id
  548. * @param array $data
  549. * @return mixed page Or false
  550. */
  551. function copy($id = null, $data = array()) {
  552. if($id) {
  553. $data = $this->find('first', array('conditions' => array('PageCategory.id' => $id), 'recursive' => -1));
  554. }
  555. $data['PageCategory']['name'] .= '_copy';
  556. $data['PageCategory']['title'] .= '_copy';
  557. unset($data['PageCategory']['id']);
  558. unset($data['PageCategory']['created']);
  559. unset($data['PageCategory']['modified']);
  560. $this->create($data);
  561. $result = $this->save();
  562. if($result) {
  563. return $result;
  564. } else {
  565. if(isset($this->validationErrors['name'])) {
  566. return $this->copy(null, $data);
  567. } else {
  568. return false;
  569. }
  570. }
  571. }
  572. /**
  573. * ページカテゴリタイプを取得する
  574. * 1:PC / 2:ケータイ / 3:スマフォ
  575. *
  576. * @param int $id
  577. * @return string
  578. * @access public
  579. */
  580. function getType($id) {
  581. $types = array('' => '1', Configure::read('BcAgent.mobile.prefix') => '2', Configure::read('BcAgent.smartphone.prefix') => '3');
  582. $path = $this->getpath($id, array('name'));
  583. unset($path[count($path)-1]);
  584. if(!empty($path[0]['PageCategory']['name'])) {
  585. if(isset($types[$path[0]['PageCategory']['name']])) {
  586. return $types[$path[0]['PageCategory']['name']];
  587. }
  588. }
  589. return 1;
  590. }
  591. }
  592. ?>