PageRenderTime 33ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 1ms

/concrete/core/models/page.php

https://bitbucket.org/selfeky/xclusivescardwebsite
PHP | 2211 lines | 1534 code | 322 blank | 355 comment | 269 complexity | 2311583a62869f705a4b9e2dbb4d6f1c MD5 | raw file
  1. <?php
  2. defined('C5_EXECUTE') or die("Access Denied.");
  3. /**
  4. *
  5. * The page object in Concrete encapsulates all the functionality used by a typical page and their contents
  6. * including blocks, page metadata, page permissions.
  7. * @package Pages
  8. *
  9. */
  10. class Concrete5_Model_Page extends Collection {
  11. protected $blocksAliasedFromMasterCollection = null;
  12. /**
  13. * @param string $path /path/to/page
  14. * @param string $version ACTIVE or RECENT
  15. * @return Page
  16. */
  17. public static function getByPath($path, $version = 'RECENT') {
  18. $path = rtrim($path, '/'); // if the path ends in a / remove it.
  19. $cID = CacheLocal::getEntry('page_id_from_path', $path);
  20. if ($cID == false) {
  21. $db = Loader::db();
  22. $cID = $db->GetOne("select cID from PagePaths where cPath = ?", array($path));
  23. CacheLocal::set("page_id_from_path", $path, $cID);
  24. }
  25. return Page::getByID($cID, $version);
  26. }
  27. /**
  28. * @param int $cID Collection ID of a page
  29. * @param string $versionOrig ACTIVE or RECENT
  30. * @param string $class
  31. * @return Page
  32. */
  33. public static function getByID($cID, $version = 'RECENT', $class = 'Page') {
  34. $c = CacheLocal::getEntry('page', $cID . ':' . $version);
  35. if ($c instanceof $class) {
  36. return $c;
  37. }
  38. $where = "where Pages.cID = ?";
  39. $c = new $class;
  40. $c->populatePage($cID, $where, $version);
  41. // must use cID instead of c->getCollectionID() because cID may be the pointer to another page
  42. CacheLocal::set('page', $cID . ':' . $version, $c);
  43. return $c;
  44. }
  45. /**
  46. * @access private
  47. */
  48. protected function populatePage($cInfo, $where, $cvID) {
  49. $db = Loader::db();
  50. $q0 = "select Pages.cID, Pages.pkgID, Pages.cPointerID, Pages.cPointerExternalLink, Pages.cIsActive, Pages.cIsSystemPage, Pages.cPointerExternalLinkNewWindow, Pages.cFilename, Collections.cDateAdded, Pages.cDisplayOrder, Collections.cDateModified, cInheritPermissionsFromCID, cInheritPermissionsFrom, cOverrideTemplatePermissions, cCheckedOutUID, cIsTemplate, uID, cPath, cParentID, cChildren, cCacheFullPageContent, cCacheFullPageContentOverrideLifetime, cCacheFullPageContentLifetimeCustom from Pages inner join Collections on Pages.cID = Collections.cID left join PagePaths on (Pages.cID = PagePaths.cID and PagePaths.ppIsCanonical = 1) ";
  51. //$q2 = "select cParentID, cPointerID, cPath, Pages.cID from Pages left join PagePaths on (Pages.cID = PagePaths.cID and PagePaths.ppIsCanonical = 1) ";
  52. $v = array($cInfo);
  53. $r = $db->query($q0 . $where, $v);
  54. $row = $r->fetchRow();
  55. if ($row['cPointerID'] > 0) {
  56. $q1 = $q0 . "where Pages.cID = ?";
  57. $cPointerOriginalID = $row['cID'];
  58. $v = array($row['cPointerID']);
  59. $cParentIDOverride = $row['cParentID'];
  60. $cPathOverride = $row['cPath'];
  61. $cPointerID = $row['cPointerID'];
  62. $cDisplayOrderOverride = $row['cDisplayOrder'];
  63. $r = $db->query($q1, $v);
  64. $row = $r->fetchRow();
  65. }
  66. if ($r) {
  67. if ($row) {
  68. foreach ($row as $key => $value) {
  69. $this->{$key} = $value;
  70. }
  71. if (isset($cParentIDOverride)) {
  72. $this->cPointerID = $cPointerID;
  73. $this->cPointerOriginalID = $cPointerOriginalID;
  74. $this->cPath = $cPathOverride;
  75. $this->cParentID = $cParentIDOverride;
  76. }
  77. $this->isMasterCollection = $row['cIsTemplate'];
  78. } else {
  79. if ($cInfo == 1) {
  80. $this->cID = '1';
  81. $this->loadError(COLLECTION_INIT);
  82. } else {
  83. // there was no record of this particular collection in the database
  84. $this->loadError(COLLECTION_NOT_FOUND);
  85. }
  86. }
  87. $r->free();
  88. } else {
  89. $this->loadError(COLLECTION_NOT_FOUND);
  90. }
  91. if ($cvID != false && !$this->isError()) {
  92. $this->loadVersionObject($cvID);
  93. }
  94. unset($r);
  95. }
  96. public function getPermissionObjectIdentifier() {
  97. // this is a hack but it's a really good one for performance
  98. // if the permission access entity for page owner exists in the database, then we return the collection ID. Otherwise, we just return the permission collection id
  99. // this is because page owner is the ONLY thing that makes it so we can't use getPermissionsCollectionID, and for most sites that will DRAMATICALLY reduce the number of queries.
  100. if (PAGE_PERMISSION_IDENTIFIER_USE_PERMISSION_COLLECTION_ID) {
  101. return $this->getPermissionsCollectionID();
  102. } else {
  103. return $this->getCollectionID();
  104. }
  105. }
  106. /**
  107. * Returns 1 if the page is in edit mode
  108. * @return bool
  109. */
  110. public function isEditMode() {
  111. $v = View::getInstance();
  112. return ($this->isCheckedOutByMe() && ($v->editingEnabled()));
  113. }
  114. /**
  115. * Get the package ID for a page (page thats added by a package) (returns 0 if its not in a package)
  116. * @return int
  117. */
  118. public function getPackageID() {return $this->pkgID;}
  119. /**
  120. * Get the package handle for a page (page thats added by a package)
  121. * @return string
  122. */
  123. public function getPackageHandle() {
  124. return PackageList::getHandle($this->pkgID);
  125. }
  126. /**
  127. * Returns 1 if the page is in arrange mode
  128. * @return bool
  129. */
  130. public function isArrangeMode() {return ($this->isCheckedOutByMe() && ($_REQUEST['btask'] == 'arrange'));}
  131. /**
  132. * Forces the page to be checked in if its checked out
  133. */
  134. public function forceCheckIn() {
  135. // This function forces checkin to take place
  136. $db = Loader::db();
  137. $q = "update Pages set cIsCheckedOut = 0, cCheckedOutUID = null, cCheckedOutDatetime = null, cCheckedOutDatetimeLastEdit = null where cID = '{$this->cID}'";
  138. $r = $db->query($q);
  139. }
  140. /**
  141. * Checks if the page is a dashboard page, returns true if it is
  142. * @return bool
  143. */
  144. public function isAdminArea() {
  145. if ($this->isGeneratedCollection()) {
  146. $pos = strpos($this->getCollectionFilename(), "/" . DIRNAME_DASHBOARD);
  147. return ($pos > -1);
  148. }
  149. return false;
  150. }
  151. /**
  152. * Takes an array of area/block values and makes that the arrangement for this page's version
  153. * Format is like: $area[10][0] = 2, $area[10][1] = 8, $area[15][0] = 27, with the area ID being the
  154. * key and the block IDs being 1-n values inside it
  155. * @param array $areas
  156. */
  157. public function processArrangement($areas) {
  158. // this function is called via ajax, so it's a bit wonky, but the format is generally
  159. // a{areaID} = array(b1, b2, b3) (where b1, etc... are blocks with ids appended.)
  160. $db = Loader::db();
  161. $db->Execute('delete from CollectionVersionBlockStyles where cID = ? and cvID = ?', array($this->getCollectionID(), $this->getVersionID()));
  162. foreach($areas as $arID => $blocks) {
  163. if (intval($arID) > 0) {
  164. // this is a serialized area;
  165. $arHandle = $db->getOne("select arHandle from Areas where arID = ?", array($arID));
  166. $startDO = 0;
  167. foreach($blocks as $bIdentifier) {
  168. $bID = 0;
  169. $csrID = 0;
  170. $bd2 = explode('-', $bIdentifier);
  171. $bID = $bd2[0];
  172. $csrID = $bd2[1];
  173. if (intval($bID) > 0) {
  174. $v = array($startDO, $arHandle, $bID, $this->getCollectionID(), $this->getVersionID());
  175. try {
  176. $db->query("update CollectionVersionBlocks set cbDisplayOrder = ?, arHandle = ? where bID = ? and cID = ? and (cvID = ? or cbIncludeAll = 1)", $v);
  177. if ($csrID > 0) {
  178. $db->query("insert into CollectionVersionBlockStyles (csrID, arHandle, bID, cID, cvID) values (?, ?, ?, ?, ?)", array(
  179. $csrID, $arHandle, $bID, $this->getCollectionID(), $this->getVersionID()
  180. ));
  181. }
  182. // update the style for any of these blocks
  183. } catch(Exception $e) {}
  184. $startDO++;
  185. }
  186. }
  187. }
  188. }
  189. }
  190. /**
  191. * checks if the page is checked out, if it is return true
  192. * @return bool
  193. */
  194. function isCheckedOut() {
  195. // function to inform us as to whether the current collection is checked out
  196. $db = Loader::db();
  197. if (isset($this->isCheckedOutCache)) {
  198. return $this->isCheckedOutCache;
  199. }
  200. $dh = Loader::helper('date');
  201. $q = "select cIsCheckedOut, UNIX_TIMESTAMP('" . $dh->getSystemDateTime() . "') - UNIX_TIMESTAMP(cCheckedOutDatetimeLastEdit) as timeout from Pages where cID = '{$this->cID}'";
  202. $r = $db->query($q);
  203. if ($r) {
  204. $row = $r->fetchRow();
  205. if ($row['cIsCheckedOut'] == 0) {
  206. return false;
  207. } else {
  208. if ($row['timeout'] > CHECKOUT_TIMEOUT) {
  209. $this->forceCheckIn();
  210. $this->isCheckedOutCache = false;
  211. return false;
  212. } else {
  213. $this->isCheckedOutCache = true;
  214. return true;
  215. }
  216. }
  217. }
  218. }
  219. /**
  220. * Gets the user that is editing the current page.
  221. * $return string $name
  222. */
  223. public function getCollectionCheckedOutUserName() {
  224. $db = Loader::db();
  225. $query = "select cCheckedOutUID from Pages where cID = ?";
  226. $vals=array($this->cID);
  227. $checkedOutId = $db->getOne($query, $vals);
  228. if(is_object(UserInfo::getByID($checkedOutId))){
  229. $ui = UserInfo::getByID($checkedOutId);
  230. $name=$ui->getUserName();
  231. }else{
  232. $name= t('Unknown User');
  233. }
  234. return $name;
  235. }
  236. /**
  237. * Checks if the page is checked out by the current user
  238. * @return bool
  239. */
  240. function isCheckedOutByMe() {
  241. $u = new User();
  242. return ($this->getCollectionCheckedOutUserID() > 0 && $this->getCollectionCheckedOutUserID() == $u->getUserID());
  243. }
  244. /**
  245. * Checks if the page is a single page
  246. * @return bool
  247. */
  248. function isGeneratedCollection() {
  249. // generated collections are collections without types, that have special cFilename attributes
  250. return $this->cFilename != null && $this->vObj->ctID == 0;
  251. }
  252. public function assignPermissions($userOrGroup, $permissions = array(), $accessType = PagePermissionKey::ACCESS_TYPE_INCLUDE) {
  253. if ($this->cInheritPermissionsFrom != 'OVERRIDE') {
  254. $this->setPermissionsToManualOverride();
  255. $this->clearPagePermissions();
  256. }
  257. if (is_array($userOrGroup)) {
  258. $pe = GroupCombinationPermissionAccessEntity::getOrCreate($userOrGroup);
  259. // group combination
  260. } else if ($userOrGroup instanceof User || $userOrGroup instanceof UserInfo) {
  261. $pe = UserPermissionAccessEntity::getOrCreate($userOrGroup);
  262. } else {
  263. // group;
  264. $pe = GroupPermissionAccessEntity::getOrCreate($userOrGroup);
  265. }
  266. foreach($permissions as $pkHandle) {
  267. $pk = PagePermissionKey::getByHandle($pkHandle);
  268. $pk->setPermissionObject($this);
  269. $pa = $pk->getPermissionAccessObject();
  270. if (!is_object($pa)) {
  271. $pa = PermissionAccess::create($pk);
  272. } else if ($pa->isPermissionAccessInUse()) {
  273. $pa = $pa->duplicate();
  274. }
  275. $pa->addListItem($pe, false, $accessType);
  276. $pt = $pk->getPermissionAssignmentObject();
  277. $pt->assignPermissionAccess($pa);
  278. }
  279. }
  280. private static function translatePermissionsXMLToKeys($node) {
  281. $pkHandles = array();
  282. if ($node['canRead'] == '1') {
  283. $pkHandles[] = 'view_page';
  284. $pkHandles[] = 'view_page_in_sitemap';
  285. }
  286. if ($node['canWrite'] == '1') {
  287. $pkHandles[] = 'view_page_versions';
  288. $pkHandles[] = 'edit_page_properties';
  289. $pkHandles[] = 'edit_page_contents';
  290. $pkHandles[] = 'approve_page_versions';
  291. $pkHandles[] = 'move_or_copy_page';
  292. $pkHandles[] = 'preview_page_as_user';
  293. $pkHandles[] = 'add_subpage';
  294. }
  295. if ($node['canAdmin'] == '1') {
  296. $pkHandles[] = 'edit_page_speed_settings';
  297. $pkHandles[] = 'edit_page_permissions';
  298. $pkHandles[] = 'edit_page_theme';
  299. $pkHandles[] = 'schedule_page_contents_guest_access';
  300. $pkHandles[] = 'edit_page_type';
  301. $pkHandles[] = 'delete_page';
  302. $pkHandles[] = 'delete_page_versions';
  303. }
  304. return $pkHandles;
  305. }
  306. /**
  307. * @private
  308. */
  309. public function assignPermissionSet($px) {
  310. // this is the legacy function that is called just by xml. We pass these values in as though they were the old ones.
  311. if (isset($px->guests)) {
  312. $pkHandles = self::translatePermissionsXMLToKeys($px->guests);
  313. $this->assignPermissions(Group::getByID(GUEST_GROUP_ID), $pkHandles);
  314. }
  315. if (isset($px->registered)) {
  316. $pkHandles = self::translatePermissionsXMLToKeys($px->registered);
  317. $this->assignPermissions(Group::getByID(REGISTERED_GROUP_ID), $pkHandles);
  318. }
  319. if (isset($px->administrators)) {
  320. $pkHandles = self::translatePermissionsXMLToKeys($px->administrators);
  321. $this->assignPermissions(Group::getByID(ADMIN_GROUP_ID), $pkHandles);
  322. }
  323. if (isset($px->group)) {
  324. foreach($px->group as $g) {
  325. $pkHandles = self::translatePermissionsXMLToKeys($px->administrators);
  326. $this->assignPermissions(Group::getByID($g['gID']), $pkHandles);
  327. }
  328. }
  329. if (isset($px->user)) {
  330. foreach($px->user as $u) {
  331. $pkHandles = self::translatePermissionsXMLToKeys($px->administrators);
  332. $this->assignPermissions(UserInfo::getByID($u['uID']), $pkHandles);
  333. }
  334. }
  335. }
  336. /**
  337. * Make an alias to a page
  338. * @param Collection $c
  339. * @return int $newCID
  340. */
  341. function addCollectionAlias($c) {
  342. $db = Loader::db();
  343. // the passed collection is the parent collection
  344. $cParentID = $c->getCollectionID();
  345. $u = new User();
  346. $uID = $u->getUserID();
  347. $ctID = 0;
  348. $dh = Loader::helper('date');
  349. $cDate = $dh->getSystemDateTime();
  350. $cDatePublic = $dh->getSystemDateTime();
  351. $handle = $this->getCollectionHandle();
  352. $_cParentID = $c->getCollectionID();
  353. $q = "select PagePaths.cPath from PagePaths where cID = '{$_cParentID}'";
  354. if ($_cParentID > 1) {
  355. $q .= " and ppIsCanonical = 1";
  356. }
  357. $cPath = $db->getOne($q);
  358. $data['handle'] = $this->getCollectionHandle();
  359. $data['name'] = $this->getCollectionName();
  360. $cobj = parent::add($data);
  361. $newCID = $cobj->getCollectionID();
  362. $v = array($newCID, $cParentID, $uID, $this->getCollectionID());
  363. $q = "insert into Pages (cID, cParentID, uID, cPointerID) values (?, ?, ?, ?)";
  364. $r = $db->prepare($q);
  365. $res = $db->execute($r, $v);
  366. $newCID = $db->Insert_ID();
  367. Loader::model('page_statistics');
  368. PageStatistics::incrementParents($newCID);
  369. $q2 = "insert into PagePaths (cID, cPath) values (?, ?)";
  370. $v2 = array($newCID, $cPath . '/' . $handle);
  371. $db->query($q2, $v2);
  372. return $newCID;
  373. }
  374. /**
  375. * Update the name, link, and to open in a new window for an external link
  376. * @param string $cName
  377. * @param string $cLink
  378. * @param bool $newWindow
  379. */
  380. function updateCollectionAliasExternal($cName, $cLink, $newWindow = 0) {
  381. if ($this->cPointerExternalLink != '') {
  382. $db = Loader::db();
  383. $this->markModified();
  384. if ($newWindow) {
  385. $newWindow = 1;
  386. } else {
  387. $newWindow = 0;
  388. }
  389. $db->query("update CollectionVersions set cvName = ? where cID = ?", array($cName, $this->cID));
  390. $db->query("update Pages set cPointerExternalLink = ?, cPointerExternalLinkNewWindow = ? where cID = ?", array($cLink, $newWindow, $this->cID));
  391. }
  392. }
  393. /**
  394. * Add a new external link
  395. * @param string $cName
  396. * @param string $cLink
  397. * @param bool $newWindow
  398. * @return int $newCID
  399. */
  400. function addCollectionAliasExternal($cName, $cLink, $newWindow = 0) {
  401. $db = Loader::db();
  402. $dh = Loader::helper('date');
  403. $dt = Loader::helper('text');
  404. $u = new User();
  405. $cParentID = $this->getCollectionID();
  406. $uID = $u->getUserID();
  407. $cDate = $dh->getSystemDateTime();
  408. $cDatePublic = $dh->getSystemDateTime();
  409. $handle = $this->getCollectionHandle();
  410. // make the handle out of the title
  411. $handle = $dt->urlify($cLink);
  412. $data['handle'] = $handle;
  413. $data['name'] = $cName;
  414. $cobj = parent::add($data);
  415. $newCID = $cobj->getCollectionID();
  416. if ($newWindow) {
  417. $newWindow = 1;
  418. } else {
  419. $newWindow = 0;
  420. }
  421. $v = array($newCID, $cParentID, $uID, $cLink, $newWindow);
  422. $q = "insert into Pages (cID, cParentID, uID, cPointerExternalLink, cPointerExternalLinkNewWindow) values (?, ?, ?, ?, ?)";
  423. $r = $db->prepare($q);
  424. $res = $db->execute($r, $v);
  425. $newCID = $db->Insert_ID();
  426. Loader::model('page_statistics');
  427. PageStatistics::incrementParents($newCID);
  428. Page::getByID($newCID)->movePageDisplayOrderToBottom();
  429. return $newCID;
  430. }
  431. /**
  432. * Check if a page is a single page that is in the core (/concrete directory)
  433. * @return bool
  434. */
  435. public function isSystemPage() {
  436. return $this->cIsSystemPage;
  437. }
  438. /**
  439. * Gets the icon for a page (also fires the on_page_get_icon event)
  440. * @return string $icon Path to the icon
  441. */
  442. public function getCollectionIcon() {
  443. // returns a fully qualified image link for this page's icon, either based on its collection type or if icon.png appears in its view directory
  444. $icon = '';
  445. $icon = Events::fire('on_page_get_icon', $this);
  446. if ($icon) {
  447. return $icon;
  448. }
  449. if ($this->isGeneratedCollection()) {
  450. if ($this->getPackageID() > 0) {
  451. if (is_dir(DIR_PACKAGES . '/' . $this->getPackageHandle())) {
  452. $dirp = DIR_PACKAGES;
  453. $url = BASE_URL . DIR_REL;
  454. } else {
  455. $dirp = DIR_PACKAGES_CORE;
  456. $url = ASSETS_URL;
  457. }
  458. $file = $dirp . '/' . $this->getPackageHandle() . '/' . DIRNAME_PAGES . $this->getCollectionPath() . '/' . FILENAME_PAGE_ICON;
  459. if (file_exists($file)) {
  460. $icon = $url . '/' . DIRNAME_PACKAGES . '/' . $this->getPackageHandle() . '/' . DIRNAME_PAGES . $this->getCollectionPath() . '/' . FILENAME_PAGE_ICON;
  461. }
  462. } else if (file_exists(DIR_FILES_CONTENT . $this->getCollectionPath() . '/' . FILENAME_PAGE_ICON)) {
  463. $icon = BASE_URL . DIR_REL . '/' . DIRNAME_PAGES . $this->getCollectionPath() . '/' . FILENAME_PAGE_ICON;
  464. } else if (file_exists(DIR_FILES_CONTENT_REQUIRED . $this->getCollectionPath() . '/' . FILENAME_PAGE_ICON)) {
  465. $icon = ASSETS_URL . '/' . DIRNAME_PAGES . $this->getCollectionPath() . '/' . FILENAME_PAGE_ICON;
  466. }
  467. } else {
  468. }
  469. return $icon;
  470. }
  471. /**
  472. * Remove an external link/alias
  473. * @return int $cIDRedir cID for the original page if the page was an alias
  474. */
  475. function removeThisAlias() {
  476. $cIDRedir = $this->getCollectionPointerID();
  477. $cPointerExternalLink = $this->getCollectionPointerExternalLink();
  478. if ($cPointerExternalLink != '') {
  479. $this->delete();
  480. } else if ($cIDRedir > 0) {
  481. $db = Loader::db();
  482. Loader::model('page_statistics');
  483. PageStatistics::decrementParents($this->getCollectionPointerOriginalID());
  484. $args = array($this->getCollectionPointerOriginalID());
  485. $q = "delete from Pages where cID = ?";
  486. $r = $db->query($q, $args);
  487. $q = "delete from Collections where cID = ?";
  488. $r = $db->query($q, $args);
  489. $q = "delete from CollectionVersions where cID = ?";
  490. $r = $db->query($q, $args);
  491. $q = "delete from PagePaths where cID = ?";
  492. $r = $db->query($q, $args);
  493. return $cIDRedir;
  494. }
  495. }
  496. public function populateRecursivePages($pages, $pageRow, $cParentID, $level, $includeThisPage = true) {
  497. $db = Loader::db();
  498. $children = $db->GetAll('select cID, cDisplayOrder from Pages where cParentID = ? order by cDisplayOrder asc', array($pageRow['cID']));
  499. if ($includeThisPage) {
  500. $pages[] = array(
  501. 'cID' => $pageRow['cID'],
  502. 'cDisplayOrder' => $pageRow['cDisplayOrder'],
  503. 'cParentID' => $cParentID,
  504. 'level' => $level,
  505. 'total' => count($children)
  506. );
  507. }
  508. $level++;
  509. $cParentID = $pageRow['cID'];
  510. if (count($children) > 0) {
  511. foreach($children as $pageRow) {
  512. $pages = $this->populateRecursivePages($pages, $pageRow, $cParentID, $level);
  513. }
  514. }
  515. return $pages;
  516. }
  517. public function queueForDeletionSort($a, $b) {
  518. if ($a['level'] > $b['level']) {
  519. return -1;
  520. }
  521. if ($a['level'] < $b['level']) {
  522. return 1;
  523. }
  524. return 0;
  525. }
  526. public function queueForDuplicationSort($a, $b) {
  527. if ($a['level'] > $b['level']) {
  528. return 1;
  529. }
  530. if ($a['level'] < $b['level']) {
  531. return -1;
  532. }
  533. if ($a['cDisplayOrder'] > $b['cDisplayOrder']) {
  534. return 1;
  535. }
  536. if ($a['cDisplayOrder'] < $b['cDisplayOrder']) {
  537. return -1;
  538. }
  539. if ($a['cID'] > $b['cID']) {
  540. return 1;
  541. }
  542. if ($a['cID'] < $b['cID']) {
  543. return -1;
  544. }
  545. return 0;
  546. }
  547. public function queueForDeletion() {
  548. $pages = array();
  549. $includeThisPage = true;
  550. if ($this->getCollectionPath() == TRASH_PAGE_PATH) {
  551. // we're in the trash. we can't delete the trash. we're skipping over the trash node.
  552. $includeThisPage = false;
  553. }
  554. $pages = $this->populateRecursivePages($pages, array('cID' => $this->getCollectionID()), $this->getCollectionParentID(), 0, $includeThisPage);
  555. // now, since this is deletion, we want to order the pages by level, which
  556. // should get us no funny business if the queue dies.
  557. usort($pages, array('Page', 'queueForDeletionSort'));
  558. $q = Queue::get('delete_page');
  559. foreach($pages as $page) {
  560. $q->send(serialize($page));
  561. }
  562. }
  563. public function queueForDeletionRequest() {
  564. $pages = array();
  565. $includeThisPage = true;
  566. $pages = $this->populateRecursivePages($pages, array('cID' => $this->getCollectionID()), $this->getCollectionParentID(), 0, $includeThisPage);
  567. // now, since this is deletion, we want to order the pages by level, which
  568. // should get us no funny business if the queue dies.
  569. usort($pages, array('Page', 'queueForDeletionSort'));
  570. $q = Queue::get('delete_page_request');
  571. foreach($pages as $page) {
  572. $q->send(serialize($page));
  573. }
  574. }
  575. public function queueForDuplication($destination, $includeParent = true) {
  576. $pages = array();
  577. $pages = $this->populateRecursivePages($pages, array('cID' => $this->getCollectionID()), $this->getCollectionParentID(), 0, $includeParent);
  578. // now, since this is deletion, we want to order the pages by level, which
  579. // should get us no funny business if the queue dies.
  580. usort($pages, array('Page', 'queueForDuplicationSort'));
  581. $q = Queue::get('copy_page');
  582. foreach($pages as $page) {
  583. $page['destination'] = $destination->getCollectionID();
  584. $q->send(serialize($page));
  585. }
  586. }
  587. public function export($pageNode) {
  588. $p = $pageNode->addChild('page');
  589. $p->addAttribute('name', Loader::helper('text')->entities($this->getCollectionName()));
  590. $p->addAttribute('path', $this->getCollectionPath());
  591. $p->addAttribute('filename', $this->getCollectionFilename());
  592. $p->addAttribute('pagetype', $this->getCollectionTypeHandle());
  593. $p->addAttribute('description', Loader::helper('text')->entities($this->getCollectionDescription()));
  594. $p->addAttribute('package', $this->getPackageHandle());
  595. if ($this->getCollectionParentID() == 0 && $this->isSystemPage()) {
  596. $p->addAttribute('root', 'true');
  597. }
  598. $attribs = $this->getSetCollectionAttributes();
  599. if (count($attribs) > 0) {
  600. $attributes = $p->addChild('attributes');
  601. foreach($attribs as $ak) {
  602. $av = $this->getAttributeValueObject($ak);
  603. $cnt = $ak->getController();
  604. $cnt->setAttributeValue($av);
  605. $akx = $attributes->addChild('attributekey');
  606. $akx->addAttribute('handle', $ak->getAttributeKeyHandle());
  607. $cnt->exportValue($akx);
  608. }
  609. }
  610. $db = Loader::db();
  611. $r = $db->Execute('select arHandle from Areas where cID = ? and arIsGlobal = 0', array($this->getCollectionID()));
  612. while ($row = $r->FetchRow()) {
  613. $ax = Area::get($this, $row['arHandle']);
  614. $ax->export($p, $this);
  615. }
  616. }
  617. /**
  618. * Returns the uID for a page that is checked out
  619. * @return int
  620. */
  621. function getCollectionCheckedOutUserID() {
  622. return $this->cCheckedOutUID;
  623. }
  624. /**
  625. * Returns the path for the current page
  626. * @return string
  627. */
  628. function getCollectionPath() {
  629. return $this->cPath;
  630. }
  631. /**
  632. * Returns the path for a page from its cID
  633. * @param int cID
  634. * @return string $path
  635. */
  636. public static function getCollectionPathFromID($cID) {
  637. $db = Loader::db();
  638. $path = $db->GetOne("select cPath from PagePaths inner join CollectionVersions on (PagePaths.cID = CollectionVersions.cID and CollectionVersions.cvIsApproved = 1) where PagePaths.cID = ?", array($cID));
  639. return $path;
  640. }
  641. /**
  642. * Returns the uID for a page ownder
  643. * @return int
  644. */
  645. function getCollectionUserID() {
  646. return $this->uID;
  647. }
  648. /**
  649. * Returns the page's handle
  650. * @return string
  651. */
  652. function getCollectionHandle() {
  653. return $this->vObj->cvHandle;
  654. }
  655. /**
  656. * Returns the page's name
  657. * @return string
  658. */
  659. function getCollectionTypeName() {
  660. return $this->vObj->ctName;
  661. }
  662. /**
  663. * Returns the Collection Type ID
  664. * @return int
  665. */
  666. function getCollectionTypeID() {
  667. return $this->vObj->ctID;
  668. }
  669. /**
  670. * Returns the Collection Type handle
  671. * @return string
  672. */
  673. function getCollectionTypeHandle() {
  674. return $this->vObj->ctHandle;
  675. }
  676. /**
  677. * Returns theme id for the collection
  678. * @return int
  679. */
  680. function getCollectionThemeID() {
  681. if ($this->vObj->ptID < 1 && $this->cID != HOME_CID) {
  682. $c = Page::getByID(HOME_CID);
  683. return $c->getCollectionThemeID();
  684. } else {
  685. return $this->vObj->ptID;
  686. }
  687. }
  688. /**
  689. * Check if a block is an alias from a page default
  690. * @param array $b
  691. * @return bool
  692. */
  693. function isBlockAliasedFromMasterCollection(&$b) {
  694. //Retrieve info for all of this page's blocks at once (and "cache" it)
  695. // so we don't have to query the database separately for every block on the page.
  696. if (is_null($this->blocksAliasedFromMasterCollection)) {
  697. $db = Loader::db();
  698. $q = 'SELECT bID FROM CollectionVersionBlocks WHERE cID = ? AND isOriginal = 0 AND cvID = ? AND bID IN (SELECT bID FROM CollectionVersionBlocks AS cvb2 WHERE cvb2.cid = ?)';
  699. $v = array($this->getCollectionID(), $this->getVersionObject()->getVersionID(), $this->getMasterCollectionID());
  700. $r = $db->execute($q, $v);
  701. $this->blocksAliasedFromMasterCollection = $db->GetCol($q, $v);
  702. }
  703. return ($b->isAlias() && in_array($b->getBlockID(), $this->blocksAliasedFromMasterCollection));
  704. }
  705. /**
  706. * Returns Collection's theme object
  707. * @return PageTheme
  708. */
  709. function getCollectionThemeObject() {
  710. if ($this->vObj->ptID < 1) {
  711. return PageTheme::getSiteTheme();
  712. } else {
  713. $pl = PageTheme::getByID($this->vObj->ptID);
  714. return $pl;
  715. }
  716. }
  717. /**
  718. * Returns the page's name
  719. * @return string
  720. */
  721. function getCollectionName() {
  722. if (isset($this->vObj)) {
  723. return $this->vObj->cvName;
  724. }
  725. return $this->cvName;
  726. }
  727. /**
  728. * Returns the collection ID for the aliased page (returns 0 unless used on an actual alias)
  729. * @return int
  730. */
  731. function getCollectionPointerID() {
  732. return $this->cPointerID;
  733. }
  734. /**
  735. * Returns link for the aliased page
  736. * @return string
  737. */
  738. function getCollectionPointerExternalLink() {
  739. return $this->cPointerExternalLink;
  740. }
  741. /**
  742. * Returns if the alias opens in a new window
  743. * @return bool
  744. */
  745. function openCollectionPointerExternalLinkInNewWindow() {
  746. return $this->cPointerExternalLinkNewWindow;
  747. }
  748. /**
  749. * Checks to see if the page is an alias
  750. * @return bool
  751. */
  752. function isAlias() {
  753. return $this->cPointerID > 0 || $this->cPointerExternalLink != null;
  754. }
  755. /**
  756. * Checks if a page is an external link
  757. * @return bool
  758. */
  759. function isExternalLink() {
  760. return ($this->cPointerExternalLink != null);
  761. }
  762. /**
  763. * Get the original cID of a page
  764. * @return int
  765. */
  766. function getCollectionPointerOriginalID() {
  767. return $this->cPointerOriginalID;
  768. }
  769. /**
  770. * Get the file name of a page (single pages)
  771. * @return string
  772. */
  773. function getCollectionFilename() {
  774. return $this->cFilename;
  775. }
  776. /**
  777. * Gets the date a the current version was made public,
  778. * if user is specified, returns in the current user's timezone
  779. * @param string $dateFormat
  780. * @param string $type (system || user)
  781. * @return string date formated like: 2009-01-01 00:00:00
  782. */
  783. function getCollectionDatePublic($dateFormat = null, $type='system') {
  784. if(!$dateFormat) {
  785. $dateFormat = 'Y-m-d H:i:s';
  786. }
  787. $dh = Loader::helper('date');
  788. if(ENABLE_USER_TIMEZONES && $type == 'user') {
  789. $dh = Loader::helper('date');
  790. return $dh->getLocalDateTime($this->vObj->cvDatePublic, $dateFormat);
  791. } else {
  792. return $dh->date($dateFormat, strtotime($this->vObj->cvDatePublic));
  793. }
  794. }
  795. /**
  796. * Get the description of a page
  797. * @return string
  798. */
  799. function getCollectionDescription() {
  800. return $this->vObj->cvDescription;
  801. }
  802. /**
  803. * Gets the cID of the page's parent
  804. * @return int
  805. */
  806. function getCollectionParentID() {
  807. return $this->cParentID;
  808. }
  809. /**
  810. * Get the Parent cID from a page by using a cID
  811. * @param int $cID
  812. * @return int
  813. */
  814. function getCollectionParentIDFromChildID($cID) {
  815. $db = Loader::db();
  816. $q = "select cParentID from Pages where cID = ?";
  817. $cParentID = $db->GetOne($q, array($cID));
  818. return $cParentID;
  819. }
  820. /**
  821. * Returns an array of this cParentID and aliased parentIDs
  822. * @return array $cID
  823. */
  824. function getCollectionParentIDs(){
  825. $cIDs=array($this->cParentID);
  826. $db = Loader::db();
  827. $aliasedParents=$db->getAll('SELECT cParentID FROM Pages WHERE cPointerID='.intval($this->cID).' ');
  828. foreach($aliasedParents as $aliasedParent)
  829. $cIDs[]=$aliasedParent['cParentID'];
  830. return $cIDs;
  831. }
  832. /**
  833. * Checks if a page is a page default
  834. * @return bool
  835. */
  836. function isMasterCollection() {
  837. return $this->isMasterCollection;
  838. }
  839. /**
  840. * Gets the template permissions
  841. * @return string
  842. */
  843. function overrideTemplatePermissions() {
  844. return $this->cOverrideTemplatePermissions;
  845. }
  846. /**
  847. * Gets the position of the page in the sitemap
  848. * @return int
  849. */
  850. function getCollectionDisplayOrder() {
  851. return $this->cDisplayOrder;
  852. }
  853. /**
  854. * Set the theme for a page using the page object
  855. * @param PageTheme $pl
  856. */
  857. public function setTheme($pl) {
  858. $db = Loader::db();
  859. $db->query('update CollectionVersions set ptID = ? where cID = ? and cvID = ?', array($pl->getThemeID(), $this->cID, $this->vObj->getVersionID()));
  860. }
  861. /**
  862. * Set the permissions of sub-collections added beneath this permissions to inherit from the template
  863. */
  864. function setPermissionsInheritanceToTemplate() {
  865. $db = Loader::db();
  866. if ($this->cID) {
  867. $db->query("update Pages set cOverrideTemplatePermissions = 0 where cID = {$this->cID}");
  868. }
  869. }
  870. /**
  871. * Set the permissions of sub-collections added beneath this permissions to inherit from the parent
  872. */
  873. function setPermissionsInheritanceToOverride() {
  874. $db = Loader::db();
  875. if ($this->cID) {
  876. $db->query("update Pages set cOverrideTemplatePermissions = 1 where cID = {$this->cID}");
  877. }
  878. }
  879. function getPermissionsCollectionID() {
  880. return $this->cInheritPermissionsFromCID;
  881. }
  882. function getCollectionInheritance() {
  883. return $this->cInheritPermissionsFrom;
  884. }
  885. function getParentPermissionsCollectionID() {
  886. $db = Loader::db();
  887. $v = array($this->cParentID);
  888. $q = "select cInheritPermissionsFromCID from Pages where cID = ?";
  889. $ppID = $db->getOne($q, $v);
  890. return $ppID;
  891. }
  892. function getPermissionsCollectionObject() {
  893. return Page::getByID($this->cInheritPermissionsFromCID, "RECENT");
  894. }
  895. function getMasterCollectionID() {
  896. $db = Loader::db();
  897. $q = "select p.cID from Pages p inner join CollectionVersions on p.cID = CollectionVersions.cID where CollectionVersions.ctID = '{$this->vObj->ctID}' and cIsTemplate = 1";
  898. $cID = $db->getOne($q);
  899. if ($cID) {
  900. return $cID;
  901. }
  902. }
  903. function getOriginalCollectionID() {
  904. // this is a bit weird...basically, when editing a master collection, we store the
  905. // master collection ID in session, along with the collection ID we were looking at before
  906. // moving to the master collection. This allows us to get back to that original collection
  907. return $_SESSION['ocID'];
  908. }
  909. function getNumChildren() {
  910. return $this->cChildren;
  911. }
  912. function getNumChildrenDirect() {
  913. // direct children only
  914. $db = Loader::db();
  915. $v = array($this->cID);
  916. $num = $db->getOne('select count(cID) as total from Pages where cParentID = ?', $v);
  917. if ($num) {
  918. return $num;
  919. }
  920. return 0;
  921. }
  922. /**
  923. * Returns the first child of the current page, or null if there is no child
  924. * @param string $sortColumn
  925. * @return Page
  926. */
  927. public function getFirstChild($sortColumn = 'cDisplayOrder asc', $excludeSystemPages = false) {
  928. if ($excludeSystemPages) {
  929. $systemPages = ' and cIsSystemPage = 0';
  930. } else {
  931. $systemPages = '';
  932. }
  933. $db = Loader::db();
  934. $cID = $db->GetOne("select Pages.cID from Pages inner join CollectionVersions on Pages.cID = CollectionVersions.cID where cvIsApproved = 1 and cParentID = ? " . $systemPages . " order by {$sortColumn}", array($this->cID));
  935. if ($cID > 1) {
  936. return Page::getByID($cID, "ACTIVE");
  937. }
  938. return false;
  939. }
  940. function getCollectionChildrenArray( $oneLevelOnly=0 ) {
  941. $this->childrenCIDArray = array();
  942. $this->_getNumChildren($this->cID,$oneLevelOnly);
  943. return $this->childrenCIDArray;
  944. }
  945. function _getNumChildren($cID,$oneLevelOnly=0, $sortColumn = 'cDisplayOrder asc') {
  946. $db = Loader::db();
  947. $q = "select cID from Pages where cParentID = {$cID} and cIsTemplate = 0 order by {$sortColumn}";
  948. $r = $db->query($q);
  949. if ($r) {
  950. while ($row = $r->fetchRow()) {
  951. if ($row['cID'] > 0) {
  952. $this->childrenCIDArray[] = $row['cID'];
  953. if( !$oneLevelOnly ) $this->_getNumChildren($row['cID']);
  954. }
  955. }
  956. }
  957. }
  958. function canMoveCopyTo($cobj) {
  959. // ensures that we're not moving or copying to a collection inside our part of the tree
  960. $children = $this->getCollectionChildrenArray();
  961. $children[] = $this->getCollectionID();
  962. return (!in_array($cobj->getCollectionID(), $children));
  963. }
  964. function update($data) {
  965. $db = Loader::db();
  966. $vo = $this->getVersionObject();
  967. $cvID = $vo->getVersionID();
  968. $this->markModified();
  969. $cName = $this->getCollectionName();
  970. $cDescription = $this->getCollectionDescription();
  971. $cDatePublic = $this->getCollectionDatePublic();
  972. $ctID = $this->getCollectionTypeID();
  973. $uID = $this->getCollectionUserID();
  974. $pkgID = $this->getPackageID();
  975. $cFilename = $this->getCollectionFilename();
  976. $rescanTemplatePermissions = false;
  977. $cCacheFullPageContent = $this->cCacheFullPageContent;
  978. $cCacheFullPageContentLifetimeCustom = $this->cCacheFullPageContentLifetimeCustom;
  979. $cCacheFullPageContentOverrideLifetime = $this->cCacheFullPageContentOverrideLifetime;
  980. if (isset($data['cName'])) {
  981. $cName = $data['cName'];
  982. }
  983. if (isset($data['cCacheFullPageContent'])) {
  984. $cCacheFullPageContent = $data['cCacheFullPageContent'];
  985. }
  986. if (isset($data['cCacheFullPageContentLifetimeCustom'])) {
  987. $cCacheFullPageContentLifetimeCustom = $data['cCacheFullPageContentLifetimeCustom'];
  988. }
  989. if (isset($data['cCacheFullPageContentOverrideLifetime'])) {
  990. $cCacheFullPageContentOverrideLifetime = $data['cCacheFullPageContentOverrideLifetime'];
  991. }
  992. if (isset($data['cDescription'])) {
  993. $cDescription = $data['cDescription'];
  994. }
  995. if (isset($data['cDatePublic'])) {
  996. $cDatePublic = $data['cDatePublic'];
  997. }
  998. if (isset($data['uID'])) {
  999. $uID = $data['uID'];
  1000. }
  1001. if (isset($data['ctID'])) {
  1002. $ctID = $data['ctID'];
  1003. // we grab the package that this ct belongs to
  1004. $pkgID = $db->GetOne("select pkgID from PageTypes where ctID = ?", array($data['ctID']));
  1005. $rescanTemplatePermissions = true;
  1006. }
  1007. $txt = Loader::helper('text');
  1008. if (!isset($data['cHandle']) && ($this->getCollectionHandle() != '')) {
  1009. $cHandle = $this->getCollectionHandle();
  1010. } else if (!$data['cHandle']) {
  1011. // make the handle out of the title
  1012. $cHandle = $txt->urlify($cName);
  1013. $cHandle = str_replace('-', PAGE_PATH_SEPARATOR, $cHandle);
  1014. } else {
  1015. $cHandle = $txt->urlify($data['cHandle']);
  1016. $cHandle = str_replace('-', PAGE_PATH_SEPARATOR, $cHandle);
  1017. }
  1018. $cName = $txt->sanitize($cName);
  1019. // Update the non-canonical page paths
  1020. if (isset($data['ppURL']))
  1021. $this->rescanPagePaths($data['ppURL']);
  1022. if ($this->isGeneratedCollection()) {
  1023. if (isset($data['cFilename'])) {
  1024. $cFilename = $data['cFilename'];
  1025. }
  1026. // we only update a subset
  1027. $v = array($cName, $cHandle, $cDescription, $cDatePublic, $cvID, $this->cID);
  1028. $q = "update CollectionVersions set cvName = ?, cvHandle = ?, cvDescription = ?, cvDatePublic = ? where cvID = ? and cID = ?";
  1029. $r = $db->prepare($q);
  1030. $res = $db->execute($r, $v);
  1031. } else {
  1032. $v = array($cName, $cHandle, $ctID, $cDescription, $cDatePublic, $cvID, $this->cID);
  1033. $q = "update CollectionVersions set cvName = ?, cvHandle = ?, ctID = ?, cvDescription = ?, cvDatePublic = ? where cvID = ? and cID = ?";
  1034. $r = $db->prepare($q);
  1035. $res = $db->execute($r, $v);
  1036. }
  1037. $db->query("update Pages set uID = ?, pkgID = ?, cFilename = ?, cCacheFullPageContent = ?, cCacheFullPageContentLifetimeCustom = ?, cCacheFullPageContentOverrideLifetime = ? where cID = ?", array($uID, $pkgID, $cFilename, $cCacheFullPageContent, $cCacheFullPageContentLifetimeCustom, $cCacheFullPageContentOverrideLifetime, $this->cID));
  1038. $cache = PageCache::getLibrary();
  1039. $cache->purge($this);
  1040. $this->refreshCache();
  1041. $ret = Events::fire('on_page_update', $this);
  1042. }
  1043. public function uniquifyPagePath($origPath) {
  1044. $db = Loader::db();
  1045. $proceed = false;
  1046. $suffix = 0;
  1047. while ($proceed != true) {
  1048. $newPath = ($suffix == 0) ? $origPath : $origPath . $suffix;
  1049. $v = array($newPath, $this->cID);
  1050. $q = "select cID from PagePaths where cPath = ? and cID <> ?";
  1051. $r = $db->query($q, $v);
  1052. if ($r->numRows() == 0) {
  1053. $proceed = true;
  1054. } else {
  1055. $suffix++;
  1056. }
  1057. }
  1058. return $newPath;
  1059. }
  1060. public function rescanPagePaths($newPaths) {
  1061. $db = Loader::db();
  1062. $txt = Loader::helper('text');
  1063. // First, get the list of page paths from the DB.
  1064. $ppaths = $this->getPagePaths();
  1065. // Second, reset all of their cPath values to null.
  1066. $paths = array();
  1067. foreach ($ppaths as $ppath) {
  1068. if (!$ppath['ppIsCanonical']) {
  1069. $paths[$ppath['ppID']] = null;
  1070. }
  1071. }
  1072. // Third, fill in the cPath values from the user updated data.
  1073. Loader::library('3rdparty/urlify');
  1074. foreach ($newPaths as $key=>$val) {
  1075. if (!empty($val)) {
  1076. // Auto-prepend a slash if one is missing.
  1077. $val = trim($val, '/');
  1078. $pathSegments = explode('/', $val);
  1079. $newVal = '/';
  1080. foreach($pathSegments as $pathSegment) {
  1081. $newVal .= $pathSegment . '/';
  1082. }
  1083. $newVal = substr($newVal, 0, strlen($newVal) - 1);
  1084. $newVal = str_replace('-', PAGE_PATH_SEPARATOR, $newVal);
  1085. $paths[$key] = $newVal;
  1086. }
  1087. }
  1088. // Fourth, delete, update, or insert page paths as necessary.
  1089. foreach ($paths as $key=>$val) {
  1090. if (empty($val)) {
  1091. $v = array($this->cID, $key);
  1092. $q = "delete from PagePaths where cID = ? and ppID = ?";
  1093. } else if (is_numeric($key)) {
  1094. $val = $this->uniquifyPagePath($val);
  1095. $v = array($val, $this->cID, $key);
  1096. $q = "update PagePaths set cPath = ?, ppIsCanonical = 0 where cID = ? and ppID = ?";
  1097. } else {
  1098. $val = $this->uniquifyPagePath($val);
  1099. $v = array($this->cID, $val);
  1100. $q = "insert into PagePaths (cID, cPath, ppIsCanonical) values (?, ?, 0)";
  1101. }
  1102. $r = $db->query($q, $v);
  1103. }
  1104. }
  1105. function clearPagePermissions() {
  1106. $db = Loader::db();
  1107. $db->Execute("delete from PagePermissionAssignments where cID = '{$this->cID}'");
  1108. $this->permissionAssignments = array();
  1109. }
  1110. public function inheritPermissionsFromParent() {
  1111. $db = Loader::db();
  1112. $cpID = $this->getParentPermissionsCollectionID();
  1113. $this->updatePermissionsCollectionID($this->cID, $cpID);
  1114. $v = array('PARENT', $cpID, $this->cID);
  1115. $q = "update Pages set cInheritPermissionsFrom = ?, cInheritPermissionsFromCID = ? where cID = ?";
  1116. $r = $db->query($q, $v);
  1117. $this->cInheritPermissionsFrom = 'PARENT';
  1118. $this->cInheritPermissionsFromCID = $cpID;
  1119. $this->clearPagePermissions();
  1120. $this->rescanAreaPermissions();
  1121. }
  1122. public function inheritPermissionsFromDefaults() {
  1123. $db = Loader::db();
  1124. $cpID = $this->getMasterCollectionID();
  1125. $this->updatePermissionsCollectionID($this->cID, $cpID);
  1126. $v = array('TEMPLATE', $cpID, $this->cID);
  1127. $q = "update Pages set cInheritPermissionsFrom = ?, cInheritPermissionsFromCID = ? where cID = ?";
  1128. $r = $db->query($q, $v);
  1129. $this->cInheritPermissionsFrom = 'TEMPLATE';
  1130. $this->cInheritPermissionsFromCID = $cpID;
  1131. $this->clearPagePermissions();
  1132. $this->rescanAreaPermissions();
  1133. }
  1134. public function setPermissionsToManualOverride() {
  1135. if ($this->cInheritPermissionsFrom != 'OVERRIDE') {
  1136. $db = Loader::db();
  1137. $this->acquirePagePermissions($this->getPermissionsCollectionID());
  1138. $this->acquireAreaPermissions($this->getPermissionsCollectionID());
  1139. $cpID = $this->cID;
  1140. $this->updatePermissionsCollectionID($this->cID, $cpID);
  1141. $v = array('OVERRIDE', $cpID, $this->cID);
  1142. $q = "update Pages set cInheritPermissionsFrom = ?, cInheritPermissionsFromCID = ? where cID = ?";
  1143. $r = $db->query($q, $v);
  1144. $this->cInheritPermissionsFrom = 'OVERRIDE';
  1145. $this->cInheritPermissionsFromCID = $cpID;
  1146. $this->rescanAreaPermissions();
  1147. }
  1148. }
  1149. public function rescanAreaPermissions() {
  1150. $db = Loader::db();
  1151. $r = $db->Execute('select arHandle, arIsGlobal from Areas where cID = ?', $this->getCollectionID());
  1152. while ($row = $r->FetchRow()) {
  1153. $a = Area::getOrCreate($this, $row['arHandle'], $row['arIsGlobal']);
  1154. $a->rescanAreaPermissionsChain();
  1155. }
  1156. }
  1157. public function setOverrideTemplatePermissions($cOverrideTemplatePermissions) {
  1158. $db = Loader::db();
  1159. $v = array($cOverrideTemplatePermissions, $this->cID);
  1160. $q = "update Pages set cOverrideTemplatePermissions = ? where cID = ?";
  1161. $db->Execute($q, $v);
  1162. $this->cOverrideTemplatePermissions = $cOverrideTemplatePermissions;
  1163. }
  1164. function updatePermissionsCollectionID($cParentIDString, $npID) {
  1165. // now we iterate through
  1166. $db = Loader::db();
  1167. $pcID = $this->getPermissionsCollectionID();
  1168. $q = "select cID from Pages where cParentID in ({$cParentIDString}) and cInheritPermissionsFromCID = {$pcID}";
  1169. $r = $db->query($q);
  1170. $cList = array();
  1171. while ($row = $r->fetchRow()) {
  1172. $cList[] = $row['cID'];
  1173. }
  1174. if (count($cList) > 0) {
  1175. $cParentIDString = implode(',', $cList);
  1176. $q2 = "update Pages set cInheritPermissionsFromCID = {$npID} where cID in ({$cParentIDString})";
  1177. $r2 = $db->query($q2);
  1178. $this->updatePermissionsCollectionID($cParentIDString, $npID);
  1179. }
  1180. }
  1181. function acquireAreaPermissions($permissionsCollectionID) {
  1182. $v = array($this->cID);
  1183. $db = Loader::db();
  1184. $q = "delete from AreaPermissionAssignments where cID = ?";
  1185. $db->query($q, $v);
  1186. // ack - we need to copy area permissions from that page as well
  1187. $v = array($permissionsCollectionID);
  1188. $q = "select cID, arHandle, paID, pkID from AreaPermissionAssignments where cID = ?";
  1189. $r = $db->query($q, $v);
  1190. while($row = $r->fetchRow()) {
  1191. $v = array($this->cID, $row['arHandle'], $row['paID'], $row['pkID']);
  1192. $q = "insert into AreaPermissionAssignments (cID, arHandle, paID, pkID) values (?, ?, ?, ?)";
  1193. $db->query($q, $v);
  1194. }
  1195. // any areas that were overriding permissions on the current page need to be overriding permissions
  1196. // on the NEW page as well.
  1197. $v = array($permissionsCollectionID);
  1198. $q = "select * from Areas where cID = ?";
  1199. $r = $db->query($q, $v);
  1200. while($row = $r->fetchRow()) {
  1201. $v = array($this->cID, $row['arHandle'], $row['arOverrideCollectionPermissions'], $row['arInheritPermissionsFromAreaOnCID'], $row['arIsGlobal']);
  1202. $q = "insert into Areas (cID, arHandle, arOverrideCollectionPermissions, arInheritPermissionsFromAreaOnCID, arIsGlobal) values (?, ?, ?, ?, ?)";
  1203. $db->query($q, $v);
  1204. }
  1205. }
  1206. function acquirePagePermissions($permissionsCollectionID) {
  1207. $v = array($this->cID);
  1208. $db = Loader::db();
  1209. $q = "delete from PagePermissionAssignments where cID = ?";
  1210. $db->query($q, $v);
  1211. $v = array($permissionsCollectionID);
  1212. $q = "select cID, paID, pkID from PagePermissionAssignments where cID = ?";
  1213. $r = $db->query($q, $v);
  1214. while($row = $r->fetchRow()) {
  1215. $v = array($this->cID, $row['paID'], $row['pkID']);
  1216. $q = "insert into PagePermissionAssignments (cID, paID, pkID) values (?, ?, ?)";
  1217. $db->query($q, $v);
  1218. }
  1219. }
  1220. public function __destruct() {
  1221. parent::__destruct();
  1222. }
  1223. function updateGroupsSubCollection($cParentIDString) {
  1224. // now we iterate through
  1225. $db = Loader::db();
  1226. $pcID = $this->getPermissionsCollectionID();
  1227. $q = "select cID from Pages where cParentID in ({$cParentIDString}) and cInheritPermissionsFrom = 'PARENT'";
  1228. $r = $db->query($q);
  1229. $cList = array();
  1230. while ($row = $r->fetchRow()) {
  1231. $cList[] = $row['cID'];
  1232. }
  1233. if (count($cList) > 0) {
  1234. $cParentIDString = implode(',', $cList);
  1235. $q2 = "update Pages set cInheritPermissionsFromCID = {$this->cID} where cID in ({$cParentIDString})";
  1236. $r2 = $db->query($q2);
  1237. $this->updateGroupsSubCollection($cParentIDString);
  1238. }
  1239. }
  1240. function move($nc, $retainOldPagePath = false) {
  1241. $db = Loader::db();
  1242. $newCParentID = $nc->getCollectionID();
  1243. $dh = Loader::helper('date');
  1244. Loader::model('page_statistics');
  1245. $cID = ($this->getCollectionPointerOriginalID() > 0) ? $this->getCollectionPointerOriginalID() : $this->cID;
  1246. PageStatistics::decrementParents($cID);
  1247. $cDateModified = $dh->getSystemDateTime();
  1248. if ($this->getPermissionsCollectionID() != $this->getCollectionID() && $this->getPermissionsCollectionID() != $this->getMasterCollectionID()) {
  1249. // implicitly, we're set to inherit the permissions of wherever we are in the site.
  1250. // as such, we'll change to inherit whatever permissions our new parent has
  1251. $npID = $nc->getPermissionsCollectionID();
  1252. if ($npID != $this->getPermissionsCollectionID()) {
  1253. //we have to update the existing collection with the info for the new
  1254. //as well as all collections beneath it that are set to inherit from this parent
  1255. // first we do this one
  1256. $q = "update Pages set cInheritPermissionsFromCID = {$npID} where cID = {$this->cID}";
  1257. $r = $db->query($q);
  1258. $this->updatePermissionsCollectionID($this->getCollectionID(), $npID);
  1259. }
  1260. }
  1261. $db->query("update Collections set cDateModified = ? where cID = ?", array($cDateModified, $cID));
  1262. $v = array($newCParentID, $cID);
  1263. $q = "update Pages set cParentID = ? where cID = ?";
  1264. $r = $db->prepare($q);
  1265. $res = $db->execute($r, $v);
  1266. PageStatistics::incrementParents($cID);
  1267. if (!$this->isActive()) {
  1268. $this->activate();
  1269. // if we're moving from the trash, we have to activate recursively
  1270. if ($this->isInTrash()) {
  1271. $pages = array();
  1272. $pages = $this->populateRecursivePages($pages, array('cID' => $this->getCollectionID()), $this->getCollectionParentID(), 0, false);
  1273. foreach($pages as $page) {
  1274. $db->Execute('update Pages set cIsActive = 1 where cID = ?', array($page['cID']));
  1275. }
  1276. }
  1277. }
  1278. $this->rescanSystemPageStatus();
  1279. $this->cParentID = $newCParentID;
  1280. $this->movePageDisplayOrderToBottom();
  1281. // run any event we have for page move. Arguments are
  1282. // 1. current page being moved
  1283. // 2. former parent
  1284. // 3. new parent
  1285. $oldParent = Page::getByID($this->getCollectionParentID(), 'RECENT');
  1286. $newParent = Page::getByID($newCParentID, 'RECENT');
  1287. $ret = Events::fire('on_page_move', $this, $oldParent, $newParent);
  1288. // now that we've moved the collection, we rescan its path
  1289. $this->rescanCollectionPath($retainOldPagePath);
  1290. }
  1291. function duplicateAll($nc, $preserveUserID = false) {
  1292. $db = Loader::db();
  1293. $nc2 = $this->duplicate($nc);
  1294. Page::_duplicateAll($this, $nc2, $preserveUserID);
  1295. return $nc2;
  1296. }
  1297. /**
  1298. * @access private
  1299. **/
  1300. function _duplicateAll($cParent, $cNewParent, $preserveUserID = false) {
  1301. $db = Loader::db();
  1302. $cID = $cParent->getCollectionID();
  1303. $q = "select cID from Pages where cParentID = '{$cID}' order by cDisplayOrder asc";
  1304. $r = $db->query($q);
  1305. if ($r) {
  1306. while ($row = $r->fetchRow()) {
  1307. $tc = Page::getByID($row['cID']);
  1308. $nc = $tc->duplicate($cNewParent, $preserveUserID);
  1309. $tc->_duplicateAll($tc, $nc, $preserveUserID);
  1310. }
  1311. }
  1312. }
  1313. function duplicate($nc, $preserveUserID = false) {
  1314. $db = Loader::db();
  1315. // the passed collection is the parent collection
  1316. $cParentID = $nc->getCollectionID();
  1317. $u = new User();
  1318. $uID = $u->getUserID();
  1319. if ($preserveUserID) {
  1320. $uID = $this->getCollectionUserID();
  1321. }
  1322. $dh = Loader::helper('date');
  1323. $cDate = $dh->getSystemDateTime();
  1324. $cobj = parent::getByID($this->cID);
  1325. // create new name
  1326. $newCollectionName = $this->getCollectionName();
  1327. $index = 1;
  1328. $nameCount = 1;
  1329. while ($nameCount > 0) {
  1330. // if we have a node at the new level with the same name, we keep incrementing til we don't
  1331. $nameCount = $db->GetOne('select count(Pages.cID) from CollectionVersions inner join Pages on (CollectionVersions.cID = Pages.cID and CollectionVersions.cvIsApproved = 1) where Pages.cParentID = ? and CollectionVersions.cvName = ?',
  1332. array($cParentID, $newCollectionName)
  1333. );
  1334. if ($nameCount > 0) {
  1335. $index++;
  1336. $newCollectionName = $this->getCollectionName() . ' ' . $index;
  1337. }
  1338. }
  1339. $newC = $cobj->duplicate();
  1340. $newCID = $newC->getCollectionID();
  1341. $v = array($newCID, $cParentID, $uID, $this->overrideTemplatePermissions(), $this->getPermissionsCollectionID(), $this->getCollectionInheritance(), $this->cFilename, $this->cPointerID, $this->cPointerExternalLink, $this->cPointerExternalLinkNewWindow, $this->cDisplayOrder, $this->pkgID);
  1342. $q = "insert into Pages (cID, cParentID, uID, cOverrideTemplatePermissions, cInheritPermissionsFromCID, cInheritPermissionsFrom, cFilename, cPointerID, cPointerExternalLink, cPointerExternalLinkNewWindow, cDisplayOrder, pkgID) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
  1343. $res = $db->query($q, $v);
  1344. Loader::model('page_statistics');
  1345. PageStatistics::incrementParents($newCID);
  1346. if ($res) {
  1347. // rescan the collection path
  1348. $nc2 = Page::getByID($newCID);
  1349. // now with any specific permissions - but only if this collection is set to override
  1350. if ($this->getCollectionInheritance() == 'OVERRIDE') {
  1351. $nc2->acquirePagePermissions($this->getPermissionsCollectionID());
  1352. $nc2->acquireAreaPermissions($this->getPermissionsCollectionID());
  1353. // make sure we update the proper permissions pointer to the new page ID
  1354. $q = "update Pages set cInheritPermissionsFromCID = ? where cID = ?";
  1355. $v = array($newCID, $newCID);
  1356. $r = $db->query($q, $v);
  1357. } else if ($this->getCollectionInheritance() == "PARENT") {
  1358. // we need to clear out any lingering permissions groups (just in case), and set this collection to inherit from the parent
  1359. $npID = $nc->getPermissionsCollectionID();
  1360. $q = "update Pages set cInheritPermissionsFromCID = {$npID} where cID = {$newCID}";
  1361. $r = $db->query($q);
  1362. }
  1363. if ($index > 1) {
  1364. $args['cName'] = $newCollectionName;
  1365. $args['cHandle'] = $nc2->getCollectionHandle() . '-' . $index;
  1366. }
  1367. $nc2->update($args);
  1368. // arguments for event
  1369. // 1. new page
  1370. // 2. old page
  1371. $ret = Events::fire('on_page_duplicate', $nc2, $this);
  1372. $nc2->rescanCollectionPath();
  1373. return $nc2;
  1374. }
  1375. }
  1376. function delete() {
  1377. Loader::model('page_statistics');
  1378. $cID = $this->getCollectionID();
  1379. if ($cID <= 1) {
  1380. return false;
  1381. }
  1382. $db = Loader::db();
  1383. // run any internal event we have for page deletion
  1384. $ret = Events::fire('on_page_delete', $this);
  1385. if ($ret < 0) {
  1386. return false;
  1387. }
  1388. Log::addEntry(t('Page "%s" at path "%s" deleted', $this->getCollectionName(), $this->getCollectionPath()),t('Page Action'));
  1389. parent::delete();
  1390. $cID = $this->getCollectionID();
  1391. $cParentID = $this->getCollectionParentID();
  1392. // Now that all versions are gone, we can delete the collection information
  1393. $q = "delete from PagePaths where cID = '{$cID}'";
  1394. $r = $db->query($q);
  1395. // remove all pages where the pointer is this cID
  1396. $r = $db->query("select cID from Pages where cPointerID = ?", array($cID));
  1397. while ($row = $r->fetchRow()) {
  1398. PageStatistics::decrementParents($row['cID']);
  1399. $db->Execute('DELETE FROM PagePaths WHERE cID=?', array($row['cID']));
  1400. }
  1401. // Update cChildren for cParentID
  1402. PageStatistics::decrementParents($cID);
  1403. $q = "delete from PagePermissionAssignments where cID = '{$cID}'";
  1404. $r = $db->query($q);
  1405. $q = "delete from Pages where cID = '{$cID}'";
  1406. $r = $db->query($q);
  1407. $q = "delete from Pages where cPointerID = '{$cID}'";
  1408. $r = $db->query($q);
  1409. $q = "delete from Areas WHERE cID = '{$cID}'";
  1410. $r = $db->query($q);
  1411. $q = "delete from ComposerDrafts WHERE cID = '{$cID}'";
  1412. $r = $db->query($q);
  1413. $db->query('delete from PageSearchIndex where cID = ?', array($cID));
  1414. $q = "select cID from Pages where cParentID = '{$cID}'";
  1415. $r = $db->query($q);
  1416. if ($r) {
  1417. while ($row = $r->fetchRow()) {
  1418. if ($row['cID'] > 0) {
  1419. $nc = Page::getByID($row['cID']);
  1420. if( $nc->isAlias() )
  1421. $nc->removeThisAlias();
  1422. else $nc->delete();
  1423. }
  1424. }
  1425. }
  1426. $cache = PageCache::getLibrary();
  1427. $cache->purge($this);
  1428. }
  1429. public function moveToTrash() {
  1430. $trash = Page::getByPath(TRASH_PAGE_PATH);
  1431. Log::addEntry(t('Page "%s" at path "%s" Moved to trash', $this->getCollectionName(), $this->getCollectionPath()),t('Page Action'));
  1432. $this->move($trash);
  1433. $this->deactivate();
  1434. $pages = array();
  1435. $pages = $this->populateRecursivePages($pages, array('cID' => $this->getCollectionID()), $this->getCollectionParentID(), 0, false);
  1436. $db = Loader::db();
  1437. foreach($pages as $page) {
  1438. $db->Execute('update Pages set cIsActive = 0 where cID = ?', array($page['cID']));
  1439. }
  1440. }
  1441. function rescanChildrenDisplayOrder() {
  1442. $db = Loader::db();
  1443. // this should be re-run every time a new page is added, but i don't think it is yet - AE
  1444. //$oneLevelOnly=1;
  1445. //$children_array = $this->getCollectionChildrenArray( $oneLevelOnly );
  1446. $q = "SELECT cID FROM Pages WHERE cParentID=".intval($this->getCollectionID()).' ORDER BY cDisplayOrder';
  1447. $children_array = $db->getCol($q);
  1448. $current_count=0;
  1449. foreach($children_array as $newcID) {
  1450. $q = "update Pages set cDisplayOrder='$current_count' where cID='$newcID'";
  1451. $r = $db->query($q);
  1452. $current_count++;
  1453. }
  1454. }
  1455. function getNextSubPageDisplayOrder() {
  1456. $db = Loader::db();
  1457. $max = $db->getOne("select max(cDisplayOrder) from Pages where cParentID = " . $this->getCollectionID());
  1458. if ($max == "" || $max == null) {
  1459. return 0;
  1460. } else if (!$max) {
  1461. return 1;
  1462. } else {
  1463. return $max + 1;
  1464. }
  1465. }
  1466. function rescanCollectionPath($retainOldPagePath = false) {
  1467. if ($this->cParentID > 0) {
  1468. $db = Loader::db();
  1469. // first, we grab the path of the parent, if such a thing exists, for our prefix
  1470. $q = "select PagePaths.cPath as cPathParent from PagePaths left join Pages on (Pages.cParentID = PagePaths.cID and PagePaths.ppIsCanonical = 1) where Pages.cID = '{$this->cID}'";
  1471. $cPath = $db->getOne($q);
  1472. // Now we perform the collection path function on the current cID
  1473. $np = $this->rescanCollectionPathIndividual($this->cID, $cPath, $retainOldPagePath);
  1474. $this->cPath = $np;
  1475. // Now we start with the recursive collection path scanning, armed with our prefix (from the level above what we're scanning)
  1476. if ($np) {
  1477. $this->rescanCollectionPathChildren($this->cID, $np);
  1478. }
  1479. }
  1480. }
  1481. function updateDisplayOrder($do,$cID=0) {
  1482. //this line was added to allow changing the display order of aliases
  1483. if(!intval($cID)) $cID=$this->getCollectionID();
  1484. $db = Loader::db();
  1485. $db->query("update Pages set cDisplayOrder = ? where cID = ?", array($do, $cID));
  1486. }
  1487. public function movePageDisplayOrderToTop() {
  1488. // first, we take the current collection, stick it at the beginning of an array, then get all other items from the current level that aren't that cID, order by display order, and then update
  1489. $db = Loader::db();
  1490. $nodes = array();
  1491. $nodes[] = $this->getCollectionID();
  1492. $r = $db->GetCol('select cID from Pages where cParentID = ? and cID <> ? order by cDisplayOrder asc', array($this->getCollectionParentID(), $this->getCollectionID()));
  1493. $nodes = array_merge($nodes, $r);
  1494. $displayOrder = 0;
  1495. foreach($nodes as $do) {
  1496. $co = Page::getByID($do);
  1497. $co->updateDisplayOrder($displayOrder);
  1498. $displayOrder++;
  1499. }
  1500. }
  1501. public function movePageDisplayOrderToBottom() {
  1502. // first, we take the current collection, stick it at the beginning of an array, then get all other items from the current level that aren't that cID, order by display order, and then update
  1503. $db = Loader::db();
  1504. $nodes = $db->GetCol('select cID from Pages where cParentID = ? and cID <> ? order by cDisplayOrder asc', array($this->getCollectionParentID(), $this->getCollectionID()));
  1505. $displayOrder = 0;
  1506. $nodes[] = $this->getCollectionID();
  1507. foreach($nodes as $do) {
  1508. $co = Page::getByID($do);
  1509. $co->updateDisplayOrder($displayOrder);
  1510. $displayOrder++;
  1511. }
  1512. }
  1513. function rescanCollectionPathIndividual($cID, $cPath, $retainOldPagePath = false) {
  1514. $db = Loader::db();
  1515. $q = "select CollectionVersions.cID, CollectionVersions.cvHandle, CollectionVersions.cvID, PagePaths.cID as cpcID from CollectionVersions left join PagePaths on (PagePaths.cID = CollectionVersions.cID) where CollectionVersions.cID = '{$cID}' and CollectionVersions.cvIsApproved = 1";
  1516. $r = $db->query($q);
  1517. if (!$r) return;
  1518. $row = $r->fetchRow();
  1519. if (!$row['cvHandle']) {
  1520. $row['cvHandle'] = $row['cID'];
  1521. }
  1522. if ($row['cvHandle']) {
  1523. $origPath = $cPath . '/' . $row['cvHandle'];
  1524. // first, we check to see if this path already exists
  1525. $proceed = false;
  1526. $suffix = 0;
  1527. while ($proceed != true) {
  1528. $newPath = ($suffix == 0) ? $origPath : $origPath . $suffix;
  1529. $v2 = array($newPath);
  1530. $q2 = "select cID from PagePaths where cPath = ? and cID <> {$cID}";
  1531. $r2 = $db->query($q2, $v2);
  1532. if ($r2->numRows() == 0) {
  1533. $proceed = true;
  1534. } else {
  1535. $suffix++;
  1536. }
  1537. }
  1538. if ($row['cpcID']) {
  1539. if ($retainOldPagePath) {
  1540. $db->query("update PagePaths set ppIsCanonical = 0 where cID = {$cID}");
  1541. } else {
  1542. $db->query('delete from PagePaths where ppIsCanonical = 1 and cID = ?', array($row['cpcID']));
  1543. }
  1544. }
  1545. // Check to see if a non-canonical page path already exists for the new location.
  1546. $v = array($cID, $newPath);
  1547. $rc = $db->query("select cID from PagePaths where cID = ? and cPath = ?", $v);
  1548. if ($rc->numRows() > 0) {
  1549. // Update the non-canonical path to be canonical.
  1550. $q3 = "update PagePaths set ppIsCanonical = 1 where cID = ? and cPath = ?";
  1551. } else {
  1552. // Create a new page path for the new location.
  1553. $q3 = "insert into PagePaths (cID, cPath) values (?, ?)";
  1554. }
  1555. $rc->free();
  1556. $r3 = $db->prepare($q3);
  1557. $res3 = $db->execute($r3, $v);
  1558. if ($res3) {
  1559. $np = Page::getByID($cID, $row['cvID']);
  1560. $np->rescanSystemPageStatus();
  1561. return $newPath;
  1562. }
  1563. }
  1564. $r->free();
  1565. }
  1566. public function rescanSystemPageStatus() {
  1567. $cID = $this->getCollectionID();
  1568. $db = Loader::db();
  1569. $newPath = $db->GetOne('select cPath from PagePaths where cID = ? and ppIsCanonical = 1', array($cID));
  1570. // now we mark the page as a system page based on this path:
  1571. $systemPages=array('/login', '/register', '/!trash', '/!stacks', '/!drafts', '/!trash/*', '/!stacks/*', '/!drafts/*', '/download_file', '/profile', '/dashboard', '/profile/*', '/dashboard/*','/page_forbidden','/page_not_found','/members');
  1572. $th = Loader::helper('text');
  1573. $db->Execute('update Pages set cIsSystemPage = 0 where cID = ?', array($cID));
  1574. foreach($systemPages as $sp) {
  1575. if ($th->fnmatch($sp, $newPath)) {
  1576. $db->Execute('update Pages set cIsSystemPage = 1 where cID = ?', array($cID));
  1577. }
  1578. }
  1579. }
  1580. public function isInTrash() {
  1581. return $this->getCollectionPath() != TRASH_PAGE_PATH && strpos($this->getCollectionPath(), TRASH_PAGE_PATH) === 0;
  1582. }
  1583. public function moveToRoot() {
  1584. $db = Loader::db();
  1585. $db->Execute('update Pages set cParentID = 0 where cID = ?', array($this->getCollectionID()));
  1586. }
  1587. public function rescanSystemPages() {
  1588. $db = Loader::db();
  1589. $systemPages=array('/login', '/register', '/!trash/%', '/!drafts/%', '/!stacks/%', '/!trash', '/!stacks', '/!drafts', '/download_file', '/profile', '/dashboard', '/profile/%', '/dashboard/%','/page_forbidden','/page_not_found','/members');
  1590. foreach($systemPages as $sp) {
  1591. $r = $db->Execute('select cID from PagePaths where cPath like "' . $sp . '"');
  1592. while ($row = $r->Fetchrow()) {
  1593. $db->Execute('update Pages set cIsSystemPage = 1 where cID = ?', array($row['cID']));
  1594. }
  1595. }
  1596. }
  1597. public function deactivate() {
  1598. $db = Loader::db();
  1599. $db->Execute('update Pages set cIsActive = 0 where cID = ?', array($this->getCollectionID()));
  1600. }
  1601. public function activate() {
  1602. $db = Loader::db();
  1603. $db->Execute('update Pages set cIsActive = 1 where cID = ?', array($this->getCollectionID()));
  1604. }
  1605. public function isActive() {
  1606. return $this->cIsActive;
  1607. }
  1608. public function setPageIndexScore($score) {
  1609. $this->cIndexScore = $score;
  1610. }
  1611. public function getPageIndexScore() {
  1612. return round($this->cIndexScore, 2);
  1613. }
  1614. public function getPageIndexContent() {
  1615. $db = Loader::db();
  1616. return $db->GetOne('select content from PageSearchIndex where cID = ?', array($this->cID));
  1617. }
  1618. function rescanCollectionPathChildren($cID, $cPath) {
  1619. $db = Loader::db();
  1620. $q = "select cID from Pages where cParentID = $cID";
  1621. $r = $db->query($q);
  1622. if ($r) {
  1623. while ($row = $r->fetchRow()) {
  1624. $np = $this->rescanCollectionPathIndividual($row['cID'], $cPath);
  1625. $this->rescanCollectionPathChildren($row['cID'], $np);
  1626. }
  1627. $r->free();
  1628. }
  1629. }
  1630. function getCollectionAction() {
  1631. $cID = $this->cID;
  1632. $valt = Loader::helper('validation/token');
  1633. $token = $valt->getParameter();
  1634. if(isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on' && defined('BASE_URL_SSL')) {
  1635. $str = BASE_URL_SSL . DIR_REL . "/" . DISPATCHER_FILENAME . "?cID={$cID}&" . $token;
  1636. } else {
  1637. $str = BASE_URL . DIR_REL . "/" . DISPATCHER_FILENAME . "?cID={$cID}&" . $token;
  1638. }
  1639. return $str;
  1640. }
  1641. function _associateMasterCollectionBlocks($newCID, $masterCID) {
  1642. $mc = Page::getByID($masterCID, 'ACTIVE');
  1643. $nc = Page::getByID($newCID, 'RECENT');
  1644. $db = Loader::db();
  1645. $mcID = $mc->getCollectionID();
  1646. $mcvID = $mc->getVersionID();
  1647. $q = "select CollectionVersionBlocks.arHandle, BlockTypes.btCopyWhenPropagate, CollectionVersionBlocks.cbOverrideAreaPermissions, CollectionVersionBlocks.bID from CollectionVersionBlocks inner join Blocks on Blocks.bID = CollectionVersionBlocks.bID inner join BlockTypes on Blocks.btID = BlockTypes.btID where CollectionVersionBlocks.cID = '$mcID' and CollectionVersionBlocks.cvID = '{$mcvID}' order by CollectionVersionBlocks.cbDisplayOrder asc";
  1648. // ok. This function takes two IDs, the ID of the newly created virgin collection, and the ID of the crusty master collection
  1649. // who will impart his wisdom to the his young learner, by duplicating his various blocks, as well as their permissions, for the
  1650. // new collection
  1651. //$q = "select CollectionBlocks.cbAreaName, Blocks.bID, Blocks.bName, Blocks.bFilename, Blocks.btID, Blocks.uID, BlockTypes.btClassname, BlockTypes.btTablename from CollectionBlocks left join BlockTypes on (Blocks.btID = BlockTypes.btID) inner join Blocks on (CollectionBlocks.bID = Blocks.bID) where CollectionBlocks.cID = '$masterCID' order by CollectionBlocks.cbDisplayOrder asc";
  1652. //$q = "select CollectionVersionBlocks.cbAreaName, Blocks.bID, Blocks.bName, Blocks.bFilename, Blocks.btID, Blocks.uID, BlockTypes.btClassname, BlockTypes.btTablename from CollectionBlocks left join BlockTypes on (Blocks.btID = BlockTypes.btID) inner join Blocks on (CollectionBlocks.bID = Blocks.bID) where CollectionBlocks.cID = '$masterCID' order by CollectionBlocks.cbDisplayOrder asc";
  1653. $r = $db->query($q);
  1654. if ($r) {
  1655. while ($row = $r->fetchRow()) {
  1656. $b = Block::getByID($row['bID'], $mc, $row['arHandle']);
  1657. if ($row['btCopyWhenPropagate']) {
  1658. $b->duplicate($nc);
  1659. } else {
  1660. $b->alias($nc);
  1661. }
  1662. }
  1663. $r->free();
  1664. }
  1665. }
  1666. function _associateMasterCollectionAttributes($newCID, $masterCID) {
  1667. $mc = Page::getByID($masterCID, 'ACTIVE');
  1668. $nc = Page::getByID($newCID, 'RECENT');
  1669. $db = Loader::db();
  1670. $mcID = $mc->getCollectionID();
  1671. $mcvID = $mc->getVersionID();
  1672. $q = "select * from CollectionAttributeValues where cID = ?";
  1673. $r = $db->query($q, array($mcID));
  1674. if ($r) {
  1675. while ($row = $r->fetchRow()) {
  1676. $db->Execute('insert into CollectionAttributeValues (cID, cvID, akID, avID) values (?, ?, ?, ?)', array(
  1677. $nc->getCollectionID(), $nc->getVersionID(), $row['akID'], $row['avID']
  1678. ));
  1679. }
  1680. $r->free();
  1681. }
  1682. }
  1683. /**
  1684. * Adds the home page to the system. Typically used only by the installation program.
  1685. * @return page
  1686. **/
  1687. public static function addHomePage() {
  1688. // creates the home page of the site
  1689. Loader::model('collection_types');
  1690. $dh = Loader::helper('date');
  1691. $db = Loader::db();
  1692. // we use to hard code the home page page type into the system
  1693. // but now we're not going to do that
  1694. //$db->query("insert into PageTypes (ctID, ctHandle, ctName) values (?, ?, ?)", array(HOME_CTID, HOME_HANDLE, HOME_NAME));
  1695. $cParentID = 0;
  1696. $handle = HOME_HANDLE;
  1697. $uID = HOME_UID;
  1698. $name = HOME_NAME;
  1699. $data['name'] = HOME_NAME;
  1700. $data['handle'] = $handle;
  1701. $data['uID'] = $uID;
  1702. $data['cID'] = HOME_CID;
  1703. $cobj = parent::add($data);
  1704. $cID = $cobj->getCollectionID();
  1705. //$ctID = HOME_CTID;
  1706. $ctID = 0;
  1707. $cDate = $dh->getSystemDateTime();
  1708. $cDatePublic = $dh->getSystemDateTime();
  1709. $v = array($cID, $cParentID, $uID, 'OVERRIDE', 1, 1, 0);
  1710. $q = "insert into Pages (cID, cParentID, uID, cInheritPermissionsFrom, cOverrideTemplatePermissions, cInheritPermissionsFromCID, cDisplayOrder) values (?, ?, ?, ?, ?, ?, ?)";
  1711. $r = $db->prepare($q);
  1712. $res = $db->execute($r, $v);
  1713. $pc = Page::getByID($cID, 'RECENT');
  1714. return $pc;
  1715. }
  1716. /**
  1717. * Adds a new page of a certain type, using a passed associate array to setup value. $data may contain any or all of the following:
  1718. * "uID": User ID of the page's owner
  1719. * "pkgID": Package ID the page belongs to
  1720. * "cName": The name of the page
  1721. * "cHandle": The handle of the page as used in the path
  1722. * "cDatePublic": The date assigned to the page
  1723. * @param collectiontype $ct
  1724. * @param array $data
  1725. * @return page
  1726. **/
  1727. public function add(CollectionType $ct, $data) {
  1728. $db = Loader::db();
  1729. $txt = Loader::helper('text');
  1730. // the passed collection is the parent collection
  1731. $cParentID = $this->getCollectionID();
  1732. $u = new User();
  1733. if (isset($data['uID'])) {
  1734. $uID = $data['uID'];
  1735. } else {
  1736. $uID = $u->getUserID();
  1737. $data['uID'] = $uID;
  1738. }
  1739. if (isset($data['pkgID'])) {
  1740. $pkgID = $data['pkgID'];
  1741. } else if ($ct->getPackageID() > 0) {
  1742. $pkgID = $ct->getPackageID();
  1743. } else {
  1744. $pkgID = 0;
  1745. }
  1746. if (isset($data['cName'])) {
  1747. $data['name'] = $data['cName'];
  1748. }
  1749. if (!$data['cHandle']) {
  1750. // make the handle out of the title
  1751. $handle = $txt->urlify($data['name']);
  1752. } else {
  1753. $handle = $txt->urlify($data['cHandle']);
  1754. }
  1755. $handle = str_replace('-', PAGE_PATH_SEPARATOR, $handle);
  1756. $data['handle'] = $handle;
  1757. $dh = Loader::helper('date');
  1758. $cDate = $dh->getSystemDateTime();
  1759. $cDatePublic = ($data['cDatePublic']) ? $data['cDatePublic'] : null;
  1760. $data['ctID'] = $ct->getCollectionTypeID();
  1761. if ($ct->getCollectionTypeHandle() == STACKS_PAGE_TYPE) {
  1762. $data['cvIsNew'] = 0;
  1763. }
  1764. $cobj = parent::add($data);
  1765. $cID = $cobj->getCollectionID();
  1766. $ctID = $ct->getCollectionTypeID();
  1767. $q = "select p.cID from Pages p inner join CollectionVersions cv on p.cID = cv.cID where cv.ctID = '$ctID' and cIsTemplate = '1'";
  1768. $masterCID = $db->getOne($q);
  1769. //$this->rescanChildrenDisplayOrder();
  1770. $cDisplayOrder = $this->getNextSubPageDisplayOrder();
  1771. $cInheritPermissionsFromCID = ($this->overrideTemplatePermissions()) ? $this->getPermissionsCollectionID() : $masterCID;
  1772. $cInheritPermissionsFrom = ($this->overrideTemplatePermissions()) ? "PARENT" : "TEMPLATE";
  1773. $ptID = $this->getCollectionThemeID();
  1774. $v = array($cID, $cParentID, $uID, $cInheritPermissionsFrom, $this->overrideTemplatePermissions(), $cInheritPermissionsFromCID, $cDisplayOrder, $pkgID);
  1775. $q = "insert into Pages (cID, cParentID, uID, cInheritPermissionsFrom, cOverrideTemplatePermissions, cInheritPermissionsFromCID, cDisplayOrder, pkgID) values (?, ?, ?, ?, ?, ?, ?, ?)";
  1776. $r = $db->prepare($q);
  1777. $res = $db->execute($r, $v);
  1778. $newCID = $cID;
  1779. if ($res) {
  1780. // Collection added with no problem -- update cChildren on parrent
  1781. Loader::model('page_statistics');
  1782. PageStatistics::incrementParents($newCID);
  1783. if ($r) {
  1784. // now that we know the insert operation was a success, we need to see if the collection type we're adding has a master collection associated with it
  1785. if ($masterCID) {
  1786. $this->_associateMasterCollectionBlocks($newCID, $masterCID);
  1787. $this->_associateMasterCollectionAttributes($newCID, $masterCID);
  1788. }
  1789. }
  1790. $pc = Page::getByID($newCID, 'RECENT');
  1791. // run any internal event we have for page addition
  1792. Events::fire('on_page_add', $pc);
  1793. $pc->rescanCollectionPath();
  1794. }
  1795. return $pc;
  1796. }
  1797. public function getCollectionFullPageCaching() {
  1798. return $this->cCacheFullPageContent;
  1799. }
  1800. public function getCollectionFullPageCachingLifetime() {
  1801. return $this->cCacheFullPageContentOverrideLifetime;
  1802. }
  1803. public function getCollectionFullPageCachingLifetimeCustomValue() {
  1804. return $this->cCacheFullPageContentLifetimeCustom;
  1805. }
  1806. public function getCollectionFullPageCachingLifetimeValue() {
  1807. if ($this->cCacheFullPageContentOverrideLifetime == 'default') {
  1808. $lifetime = CACHE_LIFETIME;
  1809. } else if ($this->cCacheFullPageContentOverrideLifetime == 'custom') {
  1810. $lifetime = $this->cCacheFullPageContentLifetimeCustom * 60;
  1811. } else if ($this->cCacheFullPageContentOverrideLifetime == 'forever') {
  1812. $lifetime = 31536000; // 1 year
  1813. } else {
  1814. if (FULL_PAGE_CACHE_LIFETIME == 'custom') {
  1815. $lifetime = Config::get('FULL_PAGE_CACHE_LIFETIME_CUSTOM') * 60;
  1816. } else if (FULL_PAGE_CACHE_LIFETIME == 'forever') {
  1817. $lifetime = 31536000; // 1 year
  1818. } else {
  1819. $lifetime = CACHE_LIFETIME;
  1820. }
  1821. }
  1822. if (!$lifetime) {
  1823. // we have no value, which means forever, but we need a numerical value for page caching
  1824. $lifetime = 31536000;
  1825. }
  1826. return $lifetime;
  1827. }
  1828. public function addStatic($data) {
  1829. $db = Loader::db();
  1830. $cParentID = $this->getCollectionID();
  1831. if (isset($data['pkgID'])) {
  1832. $pkgID = $data['pkgID'];
  1833. } else {
  1834. $pkgID = 0;
  1835. }
  1836. $handle = $data['handle'];
  1837. $cName = $data['name'];
  1838. $cFilename = $data['filename'];
  1839. $uID = USER_SUPER_ID;
  1840. $data['uID'] = $uID;
  1841. $cIsSystemPage = 0;
  1842. $cobj = parent::add($data);
  1843. $cID = $cobj->getCollectionID();
  1844. $this->rescanChildrenDisplayOrder();
  1845. $cDisplayOrder = $this->getNextSubPageDisplayOrder();
  1846. // These get set to parent by default here, but they can be overridden later
  1847. $cInheritPermissionsFromCID = $this->getPermissionsCollectionID();
  1848. $cInheritPermissionsFrom = 'PARENT';
  1849. $v = array($cID, $cFilename, $cParentID, $cInheritPermissionsFrom, $this->overrideTemplatePermissions(), $cInheritPermissionsFromCID, $cDisplayOrder, $cIsSystemPage, $uID, $pkgID);
  1850. $q = "insert into Pages (cID, cFilename, cParentID, cInheritPermissionsFrom, cOverrideTemplatePermissions, cInheritPermissionsFromCID, cDisplayOrder, cIsSystemPage, uID, pkgID) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
  1851. $r = $db->prepare($q);
  1852. $res = $db->execute($r, $v);
  1853. if ($res) {
  1854. // Collection added with no problem -- update cChildren on parrent
  1855. Loader::model('page_statistics');
  1856. PageStatistics::incrementParents($cID);
  1857. }
  1858. $pc = Page::getByID($cID);
  1859. $pc->rescanCollectionPath();
  1860. return $pc;
  1861. }
  1862. function getPagePaths() {
  1863. $db = Loader::db();
  1864. $q = "select ppID, cPath, ppIsCanonical from PagePaths where cID = {$this->cID}";
  1865. $r = $db->query($q, $v);
  1866. $paths = array();
  1867. if ($r) {
  1868. while ($row = $r->fetchRow()) {
  1869. $paths[] = $row;
  1870. }
  1871. $r->free();
  1872. }
  1873. return $paths;
  1874. }
  1875. /*
  1876. * returns an instance of the current page object
  1877. *
  1878. */
  1879. public static function getCurrentPage() {
  1880. $req = Request::get();
  1881. $current = $req->getCurrentPage();
  1882. if (is_object($current)) {
  1883. return $current;
  1884. } else {
  1885. global $c;
  1886. return $c;
  1887. }
  1888. }
  1889. }