Source for file layout-defs.php

Documentation is available at layout-defs.php

  1. <?php
  2. /* ******************************************************************** */
  3. /* CATALYST PHP Source Code */
  4. /* -------------------------------------------------------------------- */
  5. /* This program is free software; you can redistribute it and/or modify */
  6. /* it under the terms of the GNU General Public License as published by */
  7. /* the Free Software Foundation; either version 2 of the License, or */
  8. /* (at your option) any later version. */
  9. /* */
  10. /* This program is distributed in the hope that it will be useful, */
  11. /* but WITHOUT ANY WARRANTY; without even the implied warranty of */
  12. /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
  13. /* GNU General Public License for more details. */
  14. /* */
  15. /* You should have received a copy of the GNU General Public License */
  16. /* along with this program; if not, write to: */
  17. /* The Free Software Foundation, Inc., 59 Temple Place, Suite 330, */
  18. /* Boston, MA 02111-1307 USA */
  19. /* -------------------------------------------------------------------- */
  20. /* */
  21. /* Filename: layout-defs.php */
  22. /* Author: Paul Waite */
  23. /* Description: Definitions for content layout management in webpages. */
  24. /* */
  25. /* ******************************************************************** */
  26. /** @package cm */
  27. include_once("block-defs.php");
  28.  
  29. // ----------------------------------------------------------------------
  30. /** New layout to be created */
  31. ("NEW_LAYOUT", -1);
  32.  
  33. // ......................................................................
  34. // Anything which is editing and uses layouts might need to save data.
  35.  
  36. $update_delim = "^~";
  37. $RESPONSE->body->add_script(
  38. "function sto(fld, fm) {\n"
  39. . " var datFld = eval('document.forms.' + fm + '._update_data');\n"
  40. . " if (datFld != null) {\n"
  41. . " fname = fld.name;\n"
  42. . " if (datFld.value != '') datFld.value += '$update_delim';\n"
  43. . " datFld.value += fname + '|' + escape(fld.value);\n"
  44. . " }\n"
  45. . "}\n"
  46. );
  47.  
  48. // ......................................................................
  49. /**
  50. * Find content layout tags in a string.
  51. * These are of the format: <!--LAYOUTID="my layout id"--> and there
  52. * may be any number (including zero) of these in the string.
  53. * Returns a string which is the passed-in string with the tags
  54. * replaced by the rendered layout content.
  55. * @param string The string to search for layout definitions
  56. * @return string The string with all layout content rendered into it
  57. */
  58. function render_layouts($s) {
  59. $rs = $s;
  60. if (stristr($rs, "LAYOUTID=")) {
  61. preg_match_all("/<!--LAYOUTID=\"(.+)\"-->/i", $rs, $matches);
  62. for ($i=0; $i< count($matches[0]); $i++) {
  63. $layouttag = $matches[0][$i];
  64. $layoutid = $matches[1][$i];
  65. debugbr("layout: rendering $layoutid", DBG_DEBUG);
  66. $mylayout = new named_layout($layoutid);
  67. $rs = str_replace($layouttag, $mylayout->render(), $rs);
  68. }
  69. }
  70. debug_trace();
  71. return $rs;
  72. } // render_layouts
  73. // ......................................................................
  74.  
  75. /**
  76. * Layout
  77. * A layout can be simply viewed as a table definition. The table cells
  78. * can contain blocks, and so this entity is provided to allow control
  79. * of how blocks of content can be arranged on a webpage.
  80. * @package cm
  81. */
  82. class layout extends RenderableObject {
  83. // Public
  84. /** The unique ID of this layout */
  85.  
  86. var $layoutid = 0;
  87. /** The name of the current layout */
  88.  
  89. var $layout_name = "";
  90. /** The language of the layout (0 = default) */
  91.  
  92. var $language = 0;
  93. /** The language encoding code */
  94.  
  95. var $lang_encoding = "";
  96. /** The language text direction */
  97.  
  98. var $lang_direction = "";
  99. /** True if we should display last modified date */
  100.  
  101. var $show_last_modified = false;
  102. /** The format string for last modified datetime */
  103.  
  104. var $format_last_modified = NICE_DATE;
  105. /** The prefix string for last modified datetime */
  106.  
  107. var $prefix_last_modified = "";
  108. /** The index category of the current layout - used with Lucene indexing */
  109.  
  110. var $index_category = "";
  111. /** Table width specification */
  112.  
  113. var $table_width = "";
  114. /** Table autojustify flag */
  115.  
  116. var $table_autojustify = false;
  117. /** Table rowstriping mode flag */
  118.  
  119. var $table_rowstripes = false;
  120. /** Whether the layout exists in database or not */
  121.  
  122. var $exists = false;
  123.  
  124. // Private
  125. /** The layout table itself
  126. @access private */
  127. var $layout_table;
  128. /** The name of the layout form
  129. @access private */
  130. var $layoutfm = "layoutform";
  131. /** The group privilege settings for this layout, as
  132. read from the database.
  133. @access private */
  134. var $privileges = array();
  135. /** The groups which have privilege settings for this layout, as
  136. read from the database.
  137. @access private */
  138. var $privilege_groups = array();
  139. /** The group membership for Editor privilege
  140. @access private */
  141. var $editor_groups = array(DEFAULT_EDITOR_GROUPS);
  142. /** The group membership for Authoring privilege
  143. @access private */
  144. var $author_groups = array(DEFAULT_AUTHOR_GROUPS);
  145. /** The group membership for Entry privilege
  146. @access private */
  147. var $entry_groups = array(DEFAULT_ENTRY_GROUPS);
  148. /** The layout blocks, keyed on 'row|col'
  149. @access private */
  150. var $layout_blocks = array();
  151. /** Supplemental layout table style
  152. @access private */
  153. var $layout_style = "";
  154. /** Total rows in layout
  155. @access private */
  156. var $tot_rows = 0;
  157. /** Total columns in layout
  158. @access private */
  159. var $tot_cols = 0;
  160. /** Total empty/undefined cells
  161. @access private */
  162. var $tot_empty = 0;
  163. /** Total cells containing a content block
  164. @access private */
  165. var $tot_block = 0;
  166. /** Total plain content cells
  167. @access private */
  168. var $tot_plain = 0;
  169. /** Total wysiwyg content cells
  170. @access private */
  171. var $tot_wysiwyg = 0;
  172. /** Total editable plain content cells
  173. @access private */
  174. var $tot_editable = 0;
  175. /** Total viewable plain content cells
  176. @access private */
  177. var $tot_viewable = 0;
  178. /** Array of layout blocks in edit mode
  179. @access private */
  180. var $edit_blocks = array();
  181. /** Array of layout cells with edit permission
  182. @access private */
  183. var $editable_cells = array();
  184. /** Array of layout cells with view permission
  185. @access private */
  186. var $viewable_cells = array();
  187. /** Last modified date/time string.
  188. Most recently modified block in layout.
  189. @access private */
  190. var $last_modified = "";
  191. /** Table style to apply for plain cells table
  192. @access private */
  193. var $table_style = "";
  194. /** Message to display (optional)
  195. @access private */
  196. var $message = "";
  197. /** Local layouteditor object, only instantiated if the
  198. layout requires editing services.
  199. @access private */
  200. var $layouteditor;
  201. // ....................................................................
  202. /**
  203. * Constructor
  204. * Create a new layout object. To create a new layout then just leave
  205. * leave the argument list empty.
  206. * @param string $id The unique name/identity of the layout.
  207. */
  208. function layout($id=NEW_LAYOUT) {
  209. // Creating new layout..
  210. if ($id == NEW_LAYOUT) {
  211. $id = get_next_sequencevalue("seq_layout_id", "ax_layout", "layout_id");
  212. }
  213.  
  214. // Save block ID..
  215. $this->layoutid = $id;
  216.  
  217. // Define a unique form name..
  218. $this->layoutfm = "layoutfm_$id";
  219.  
  220. // Read it from database
  221. $this->get($id);
  222. } // layout
  223. // ....................................................................
  224. /**
  225. * Provide a layouteditor. This is used to instantiate a layouteditor
  226. * object for when we need to change this layout somewhow. We only
  227. * need one, so we check if it's already been done first.
  228. */
  229. function activate_editing() {
  230. if (!isset($this->layouteditor)) {
  231. global $RESPONSE, $LIBDIR;
  232. include_once("layout-editor-defs.php");
  233. $this->layouteditor = new layouteditor($this);
  234. }
  235. else {
  236. // Give it an up to date set of data..
  237. $this->layouteditor->refresh($this);
  238. }
  239. } // activate_editing
  240. // ....................................................................
  241. /**
  242. * Get the layout.
  243. * Retrieves the specified layout from database.
  244. * @param string $name The name/identity of the layout to get
  245. */
  246. function get($id) {
  247. global $RESPONSE;
  248. debug_trace($this);
  249. $this->exists = false;
  250.  
  251. // Try and find it..
  252. if ($RESPONSE->multilang) {
  253. $q = "SELECT * FROM ax_layout, ax_language";
  254. $q .= " WHERE ax_layout.layout_id=$id";
  255. $q .= " AND ax_language.lang_id=ax_layout.lang_id";
  256. }
  257. else {
  258. $q = "SELECT * FROM ax_layout";
  259. $q .= " WHERE ax_layout.layout_id=$id";
  260. }
  261. // Privilege settings
  262. $this->privileges = array();
  263. $this->privilege_groups = array();
  264. $Lq = dbrecordset($q);
  265. if ($Lq->hasdata) {
  266. $this->layoutid = $id;
  267. // Check for editor & author groups overrides..
  268. $q = "SELECT * FROM ax_layout_set_group lg, ax_group g";
  269. $q .= " WHERE g.group_id=lg.group_id";
  270. $Lsec = dbrecordset($q);
  271. if ($Lsec->hasdata) {
  272. $editor = array();
  273. $author = array();
  274. $entry = array();
  275. do {
  276. $group_id = $Lsec->field("group_id");
  277. $group_desc = $Lsec->field("group_desc");
  278. $group_priv = $Lsec->field("cm_privilege");
  279. $this->privileges["$group_priv|$group_id"] = $group_desc;
  280. $this->privilege_groups[$group_id] = $group_desc;
  281. switch ($group_priv) {
  282. case "editor":
  283. $editor[] = $group_desc;
  284. break;
  285. case "author":
  286. $author[] = $group_desc;
  287. break;
  288. case "entry":
  289. $entry[] = $group_desc;
  290. break;
  291. } // switch
  292. } while ($Lsec->get_next());
  293. debugbr("layout privileges override:", DBG_DEBUG);
  294. if (count($editor) > 0) {
  295. $this->editor_groups = $editor;
  296. debugbr(" --> editor privilege: " . implode(",", $editor), DBG_DEBUG);
  297. }
  298. if (count($author) > 0) {
  299. $this->author_groups = $author;
  300. debugbr(" --> author privilege: " . implode(",", $author), DBG_DEBUG);
  301. }
  302. if (count($entry) > 0) {
  303. $this->entry_groups = $entry;
  304. debugbr(" --> entry privilege: " . implode(",", $entry), DBG_DEBUG);
  305. }
  306. }
  307. else {
  308. debugbr("default privilege settings apply", DBG_DEBUG);
  309. }
  310. // Back-fill with all non-privileged groups
  311. $Gp = dbrecordset("SELECT * FROM ax_group");
  312. if ($Gp->hasdata) {
  313. $unprivileged = array();
  314. do {
  315. $group_id = $Gp->field("group_id");
  316. $group_desc = $Gp->field("group_desc");
  317. if (!isset($this->privilege_groups[$group_id])) {
  318. $this->privileges["none|$group_id"] = $group_desc;
  319. $unprivileged[$group_id] = $group_desc;
  320. }
  321. } while ($Gp->get_next());
  322. foreach($unprivileged as $gid => $gdesc) {
  323. $this->privilege_groups[$gid] = $gdesc;
  324. }
  325. }
  326. // Continue populating layout data..
  327. $this->layout_name = $Lq->field("layout_name");
  328. if ($RESPONSE->multilang) {
  329. $this->language = $Lq->field("lang_id");
  330. $this->lang_encoding = $Lq->field("char_encoding");
  331. $this->lang_direction = $Lq->field("direction");
  332. }
  333. $this->layout_style = $Lq->field("layout_style");
  334. $this->index_category = $Lq->field("index_category");
  335. $sertable = $Lq->field("layout_table");
  336. if ($sertable != "") {
  337. $this->layout_table = unserialize($sertable);
  338. }
  339. $this->format_last_modified = $Lq->field("format_last_modified");
  340. if ($this->format_last_modified == "") {
  341. $this->format_last_modified = NICE_DATE;
  342. }
  343. $this->prefix_last_modified = $Lq->field("prefix_last_modified");
  344. $this->show_last_modified = ($Lq->field("show_last_modified") == "t");
  345. if ($this->show_last_modified) {
  346. $lmts = 0;
  347. $q = "SELECT MAX(last_modified) AS lastmod FROM ax_block";
  348. $q .= " WHERE layout_id=$id";
  349. $Lm = dbrecordset($q);
  350. if ($Lm->hasdata) {
  351. $lmdt = $Lm->field("lastmod");
  352. if ($lmdt != "") {
  353. $lmts = datetime_to_timestamp($lmdt);
  354. }
  355. }
  356. // Table modification time..
  357. if (isset($this->layout_table) && isset($this->layout_table->last_modified)) {
  358. $ts = $this->layout_table->last_modified;
  359. if ($ts > $lmts) $lmts = $ts;
  360. }
  361. // Save modstamp string..
  362. if ($lmts > 0) {
  363. $this->last_modified = timestamp_to_displaydate($this->format_last_modified, $lmts);
  364. if ($this->prefix_last_modified != "") {
  365. $this->last_modified = $this->prefix_last_modified . " " . $this->last_modified;
  366. }
  367. }
  368. }
  369. $this->exists = true;
  370. }
  371. // Ensure we have a table for layout..
  372. if (!isset($this->layout_table) || $this->layout_table->cellcount() == 0) {
  373. $this->layout_table = new matrix(1, 1, "&nbsp;");
  374. $this->layout_table->tablename = "layout:$this->layout_name";
  375. $this->layout_table->setwidth("100%");
  376. }
  377.  
  378. // Get the layout cell information..
  379. $this->tot_empty = 0;
  380. $this->tot_block = 0;
  381. $this->tot_plain = 0;
  382. $this->tot_wysiwyg = 0;
  383. $this->tot_editable = 0;
  384. $this->tot_viewable = 0;
  385. $this->editable_cells = array();
  386. $this->viewable_cells = array();
  387. $this->tot_rows = $this->layout_table->rowcount();
  388. $this->tot_cols = $this->layout_table->cellcount();
  389. if ($this->exists) {
  390. for ($row=0; $row < $this->tot_rows; $row++) {
  391. for ($col=0; $col < $this->tot_cols; $col++) {
  392. if ($this->layout_table->cell_exists($row, $col)) {
  393. $cell = $this->layout_table->get_cell($row, $col);
  394. $this->layout_blocks["$row|$col"] = $cell->blockid;
  395. if (!isset($cell->celltype)) {
  396. $this->tot_empty += 1;
  397. }
  398. else {
  399. switch ($cell->celltype) {
  400. case BLOCK_CONTENT: $this->tot_block += 1; break;
  401. case PLAIN_CELL: $this->tot_plain += 1; break;
  402. case WYSIWYG_EDITOR: $this->tot_wysiwyg += 1; break;
  403. }
  404. if (isset($cell->access) && isset($RESPONSE)) {
  405. if ($RESPONSE->ismemberof_group_in( array_merge($this->editor_groups, $this->author_groups) ) ||
  406. ($RESPONSE->ismemberof_group_in( $this->entry_groups ) && $this->is_pendingver())
  407. ) {
  408. if ($cell->access->anypermitted($RESPONSE->group_names_list(), PERM_UPDATE)) {
  409. $this->tot_editable += 1;
  410. $this->editable_cells["$row|$col"] = true;
  411. }
  412. }
  413. if ($cell->access->anypermitted($RESPONSE->group_names_list(), PERM_READ)) {
  414. $this->tot_viewable += 1;
  415. $this->viewable_cells["$row|$col"] = true;
  416. }
  417. }
  418. }
  419. }
  420. else {
  421. $this->tot_empty += 1;
  422. }
  423. }
  424. }
  425. }
  426. debug_trace();
  427. // Return true if at least the block exists..
  428. return $this->exists;
  429. } // get
  430. // ....................................................................
  431. /**
  432. * Save the layout.
  433. * Save this layout to the database. Create a new one if it
  434. * doesn't already exist.
  435. */
  436. function put() {
  437. debug_trace($this);
  438. // Timestamp the change in the table object itself..
  439. $this->layout_table->last_modified = time();
  440.  
  441. // Deal with brand new layout..
  442. if ($this->exists) {
  443. $Lq = new dbupdate("ax_layout");
  444. $Lq->where("layout_id=" . $this->layoutid);
  445. }
  446. else {
  447. $Lq = new dbinsert("ax_layout");
  448. $Lq->set("layout_id", $this->layoutid);
  449. }
  450. $Lq->set("layout_name", $this->layout_name);
  451. $Lq->set("lang_id", $this->language);
  452. $Lq->set("layout_style", $this->layout_style);
  453. $Lq->set("index_category", $this->index_category);
  454. $Lq->set("layout_table", serialize($this->layout_table));
  455. $Lq->set("show_last_modified", $this->show_last_modified);
  456. $Lq->set("format_last_modified", $this->format_last_modified);
  457. $Lq->set("prefix_last_modified", $this->prefix_last_modified);
  458. $this->exists = $Lq->execute();
  459. debug_trace();
  460. } // put
  461. // ....................................................................
  462. /**
  463. * Replicate the hosted layout as a new layout. Creates a brand new
  464. * layout in the database, with same data as this one. The end result
  465. * is that this current object becomes the new layout, and a duplicate
  466. * set of layout records exist in the database. The layout ID of this
  467. * new layout is, of course, updated to being a brand new one.
  468. * NOTES: The layout name is normally left null, which keeps the layout
  469. * in the same 'family' of layout versions. You can force the layout
  470. * name to be different, and this will create a new 'layout_set'
  471. * record of that name for you, if required.
  472. * @param string $layoutname New layout name. If null, keeps same name.
  473. */
  474. function replicate($layoutname="") {
  475. $this->activate_editing();
  476. $this->layouteditor->replicate($layoutname);
  477. } // replicate
  478. // ....................................................................
  479. /**
  480. * Delete the hosted layout from the database. Afterwards, the current object
  481. * still exists as it was before this method was executed, but the
  482. * $this->layout->exists flag will have been reset to false.
  483. */
  484. function delete() {
  485. $this->activate_editing();
  486. $this->layouteditor->delete();
  487. } // delete
  488. // ....................................................................
  489. /**
  490. * Paste the given layout into this layout, replacing the complete
  491. * definition as it currently stands, with the new one. To do this
  492. * we delete the current layout from the database, get() the new
  493. * layout from the database, and then replicate it, morphing this
  494. * object into the brand new layout. All layout and associated block
  495. * ID's are changed, and are brand new.
  496. */
  497. function paste_layout($layoutid) {
  498. $layoutname = $this->layout_name;
  499. $this->delete();
  500. $this->get($layoutid);
  501. $this->replicate($layoutname);
  502. } // paste_layout
  503. // ....................................................................
  504. /**
  505. * Index all blocks in this layout.
  506. * If Lucene indexing is enabled, then we call the indexer for all of
  507. * the blocks which are in the hosted layout, using the webpage path and title as
  508. * provided in the call to this method.
  509. * @param string $path The relative path to the webpage the hosted layout is in
  510. * @param string $title The title of the webpage the hosted layout is in
  511. */
  512. function index($path, $title) {
  513. global $RESPONSE;
  514. $lcq = dbrecordset("SELECT block_id FROM ax_block WHERE layout_id=" . $this->layoutid);
  515. if ($lcq->hasdata) {
  516. // Include metadata if there is any..
  517. $metadata = false;
  518. if ($RESPONSE->metadata_mode == METADATA_ENABLED) {
  519. include_once("metadata-defs.php");
  520. $metadata = new layout_metadata_elements($this->layoutid, "", true);
  521. }
  522. do {
  523. $blockid = $lcq->field("block_id");
  524. $b = new block($blockid);
  525. $b->index($path, $title, $this->index_category, $metadata);
  526. } while ($lcq->get_next());
  527. }
  528. } // index
  529. // ....................................................................
  530. /**
  531. * Un-Index all blocks in this layout. After calling this method all
  532. * the bloacks in the layout will have been removed from the Lucene
  533. * index.
  534. */
  535. function unindex() {
  536. $lcq = dbrecordset("SELECT block_id FROM ax_block WHERE layout_id=" . $this->layoutid);
  537. if ($lcq->hasdata) {
  538. do {
  539. $blockid = $lcq->field("block_id");
  540. $b = new block($blockid);
  541. $b->unindex();
  542. } while ($lcq->get_next());
  543. }
  544. } // unindex
  545. // ....................................................................
  546. /**
  547. * Return true if the current user is permitted to edit layout details.
  548. * We allow editing only for versions VERSION_PENDING and VERSION_LIVE
  549. * and the latter only for Editors.
  550. * @return boolean True if editing is permitted by current user.
  551. */
  552. function user_can_edit($required_version=VERSION_UNDEFINED) {
  553. global $RESPONSE;
  554. $perm = false;
  555. if ($required_version == VERSION_UNDEFINED ||
  556. $required_version == $this->version) {
  557. // Pending version
  558. if ($this->is_pendingver()) {
  559. if ($RESPONSE->ismemberof_group_in( array_merge($this->editor_groups, $this->author_groups) )) {
  560. $perm = true;
  561. }
  562. }
  563. // Live version
  564. elseif ($this->version == VERSION_LIVE) {
  565. if ($RESPONSE->ismemberof_group_in( $this->editor_groups )) {
  566. $perm = true;
  567. }
  568. }
  569. }
  570. return $perm;
  571. } // user_can_edit
  572. // ....................................................................
  573. /**
  574. * Return PENDING version status.
  575. * @return boolean True if current versin is PENDING, or only one version.
  576. */
  577. function is_pendingver() {
  578. return ($this->version == VERSION_PENDING || $this->version_count == 1);
  579. }
  580. // ....................................................................
  581. /**
  582. * Render the layout editing suite.
  583. * @return string The HTML for the editing suite form etc.
  584. * @access private
  585. */
  586. function editform() {
  587. $this->activate_editing();
  588. return $this->layouteditor->editform();
  589. } // editform
  590. // ....................................................................
  591. /**
  592. * Render the layout content.
  593. * @return string The HTML
  594. * @access private
  595. */
  596. function layoutcontent() {
  597. debug_trace($this);
  598. global $LIBDIR;
  599. global $RESPONSE;
  600.  
  601. $pwidth = "150px";
  602.  
  603. // Create a simple container table to view layout..
  604. $Tvw = new table($this->layout_name);
  605. $Tvw->tr();
  606. $Tvw->td();
  607.  
  608. // Make our layout table and populate it with our blocks..
  609. $Tlay = $this->layout_table;
  610.  
  611. // Apply supplemental style if defined..
  612. if ($this->layout_style != "") {
  613. $Tlay->setstyle($this->layout_style);
  614. }
  615.  
  616. // Ensure any blank cells return "&nbsp;"..
  617. $Tlay->setnbsp();
  618.  
  619. if ($this->tot_plain > 0) {
  620. $edbox = new form_textfield();
  621. $edbox->set_onchange("sto(this,'$this->layoutfm')");
  622. $group_names_list = $RESPONSE->group_names_list();
  623. $profile = $Tlay->get_width_profile();
  624. $tblwdth = $Tlay->width;
  625. }
  626. if ($this->tot_editable > 0) {
  627. $RESPONSE->set_style("input {background-color:#F9F7ED;}");
  628. }
  629. for ($r = 0; $r < $this->tot_rows; $r++) {
  630. for ($c = 0; $c < $this->tot_cols; $c++) {
  631. if (isset($this->layout_blocks["$r|$c"])) {
  632. $blockid = $this->layout_blocks["$r|$c"];
  633. if ($blockid != 0) {
  634. // Render as content block cell..
  635. $block = new block($blockid);
  636. if ($block->mode == "editing") {
  637. $this->edit_blocks[] = $block->blockid;
  638. }
  639. $block->set_layout_info(
  640. $this->version,
  641. $this->version_count,
  642. $this->language,
  643. $this->lang_encoding,
  644. $this->lang_direction,
  645. $this->editor_groups,
  646. $this->author_groups,
  647. $this->entry_groups
  648. );
  649. $cell = $Tlay->get_cell($r, $c);
  650. $cell->setcontent($block->render());
  651. $cell->setalignment($block->justify, $block->valign);
  652. // Apply supplemental style if defined..
  653. if ($this->layout_style != "") {
  654. $cell->setstyle($this->layout_style);
  655. }
  656. $Tlay->set_cell($r, $c, $cell);
  657. }
  658. else {
  659. if ($this->tot_editable > 0 && $this->mode != "previewing") {
  660. // Render as editable textfield, if update is permitted..
  661. $cell = $Tlay->get_cell($r, $c);
  662. if (isset($this->editable_cells["$r|$c"])) {
  663. // Try to ascertain a pixel width..
  664. $edbox->clearstyle();
  665. if (isset($profile[$c])) {
  666. $pwdth = $profile[$c];
  667. if (strstr($pwdth, "%")) {
  668. if ($tblwdth != "" && !strstr($tbldwdth, "%")) {
  669. $w = (int) ($tblwdth * $pwdth / 100);
  670. $edbox->setstyle("width:" . $w . "px;");
  671. }
  672. }
  673. else {
  674. if ($pwdth != "") {
  675. $edbox->setstyle("width:" . $pwdth . "px;");
  676. }
  677. }
  678. }
  679. $edbox->setvalue($cell->content->content);
  680. $cell->content->content = $edbox->render($cell->cellid);
  681. // Apply supplemental style if defined..
  682. if ($this->layout_style != "") {
  683. $cell->setstyle($this->layout_style);
  684. }
  685. $Tlay->set_cell($r, $c, $cell);
  686. }
  687. }
  688. // Overriding read permission blanking here. If it isn't
  689. // a viewable cell then they draw a blank..
  690. if (!isset($this->viewable_cells["$r|$c"])) {
  691. $cell = $Tlay->get_cell($r, $c);
  692. $cell->content->content = "";
  693. // Apply supplemental style if defined..
  694. if ($this->layout_style != "") {
  695. $cell->setstyle($this->layout_style);
  696. }
  697. $Tlay->set_cell($r, $c, $cell);
  698. }
  699. }
  700. }
  701. }
  702. }
  703.  
  704. // Add in editing tools if authorised..
  705. debugbr("layoutcontent: mode is $this->mode", DBG_DEBUG);
  706. if ($this->mode != "previewing") {
  707. $layedit = ($RESPONSE->ismemberof_group_in( array_merge($this->editor_groups, $this->author_groups, $this->entry_groups) ));
  708. $Tvw->td_content("<form name=\"$this->layoutfm\" method=\"post\">\n");
  709. $formcontent = "";
  710.  
  711. if ($layedit) {
  712. $Tvw->setstyle("border-width:1px;border-style:dotted;border-color:#0000ff;");
  713. $Tlay->setborder(1);
  714.  
  715. // Version selector
  716. $verCombo = new form_combofield("layout_version");
  717. $verCombo->setclass("axcombo");
  718. $verCombo->setstyle("width:$pwidth;font-size:85%;");
  719. $verCombo->additem(0, "Pending");
  720. $verCombo->additem(1, "Live");
  721. $verCombo->additem(2, "Previous");
  722. $verCombo->setvalue($this->version);
  723. $verCombo->set_onchange("document.forms.$this->layoutfm.submit()");
  724.  
  725. // Tools for the toolbar
  726. $toolbar = array();
  727. $toolbar[] = $verCombo;
  728.  
  729. // Tools only for edit-enabled users..
  730. if ($this->user_can_edit()) {
  731. if ($RESPONSE->metadata_mode == METADATA_ENABLED) {
  732. $btn = new image_button("_meta", "", "", "", "$LIBDIR/img/_meta.gif", 42, 15, "Edit metadata");
  733. $url = "/axyl-metadata-editor.php?layout_id=" . urlencode($this->layoutid);
  734. $btn->set_onclick("meta_edit('$url')");
  735. $RESPONSE->body->add_popup_script(
  736. "meta_edit",
  737. 600, 650, 50, 50,
  738. "toolbar=no,status=no,scrollbars=yes,resizable=yes"
  739. );
  740. $toolbar[] = $btn;
  741. }
  742. $toolbar[] = new image_button(
  743. "_edit",
  744. "", "", "",
  745. "$LIBDIR/img/_edit.gif",
  746. 42, 15,
  747. "Edit layout"
  748. );
  749. // Paste layout from clipboard button..
  750. $layconf = new configuration("layout", "clipboard");
  751. $copy_layoutid = $layconf->value("copy_layoutid");
  752. if ($copy_layoutid != "" && $copy_layoutid != $this->layoutid) {
  753. $bpaste = new image_button(
  754. "_paste",
  755. "", "", "",
  756. "$LIBDIR/img/_paste.gif",
  757. 57, 15,
  758. "Paste layout"
  759. );
  760. $bpaste->set_confirm_text("Overwrite this layout with the one on the clipboard?");
  761. $toolbar[] = $bpaste;
  762. }
  763. // Copy layout to clipboard button..
  764. $toolbar[] = new image_button(
  765. "_copy",
  766. "", "", "",
  767. "$LIBDIR/img/_copy.gif",
  768. 42, 15,
  769. "Copy layout to clipboard"
  770. );
  771. } // can edit
  772.  
  773. // Toolbar table
  774. $Tbar = new table("toolbar");
  775. $Tbar->tr("axtitle");
  776. if ($this->user_can_edit()) {
  777. //$Tbar->th("[$this->layout_name]", "axtitle");
  778. $Tbar->th("[Layout]", "axtitle");
  779. $Tbar->th_alignment("", "top");
  780. }
  781. else {
  782. $Tbar->th("&nbsp;", "axtitle");
  783. }
  784. $tools = "";
  785. foreach ($toolbar as $tool) {
  786. $tools .= $tool->render();
  787. }
  788. // Render tools, if any..
  789. $Tbar->th($tools, "axtitle");
  790. $Tbar->th_css("text-align:right");
  791. $Tvw->td_content( $Tbar->render(), "axtitle" );
  792.  
  793. // Hidden form fields..
  794. $update_data = new form_hiddenfield("_update_data", "");
  795. $update_flag = new form_hiddenfield("_update_flag", "false");
  796.  
  797. // Put hidden fields into the toolbar form..
  798. $form_content .=
  799. $update_data->render()
  800. . $update_flag->render();
  801.  
  802. } // if layedit
  803.  
  804. $layfm = new form_hiddenfield("edit_layoutform", $this->layoutfm);
  805. $mode = new form_hiddenfield("layoutmode", $this->mode);
  806. $elid = new form_hiddenfield("edit_layoutid", $this->layoutid);
  807. $export_flag = new form_hiddenfield("_export_flag", "false");
  808. $form_content .=
  809. $mode->render()
  810. . $layfm->render()
  811. . $elid->render()
  812. . $export_flag->render();
  813.  
  814. // Put hidden fields into the toolbar form..
  815. $Tvw->td_content( $form_content );
  816. $Tvw->td_content("</form>\n");
  817.  
  818. } // not previewing
  819.  
  820. // Put layout into viewer table..
  821. $Tvw->td_content( $Tlay->render() );
  822. $Tvw->td_alignment("", "top");
  823.  
  824. if ($this->show_last_modified && $this->last_modified != "") {
  825. $Tvw->tr();
  826. $Tvw->td($this->last_modified, "axyl_lastmod");
  827. }
  828.  
  829. $bottoolbar = array();
  830. // If editable content, give them a save button,
  831. // and remember the layout ID and the mode..
  832. if ($this->mode != "previewing"
  833. && $this->tot_editable > 0
  834. && count($this->edit_blocks) == 0
  835. ) {
  836. $bupdate = new form_imagebutton("_update", "", "", "$LIBDIR/img/_save.gif", "Save changes", 57, 15);
  837. $clkstr = "document.forms.$this->layoutfm._update_flag.value='true';";
  838. $clkstr .= "document.forms.$this->layoutfm.submit();";
  839. $bupdate->set_onclick($clkstr);
  840. $bottoolbar[] = $bupdate->render();
  841. }
  842. if ($this->mode != "previewing"
  843. && $this->tot_plain > 0
  844. && $this->tot_blocks == 0
  845. ) {
  846. $bexport = new form_imagebutton("_export", "", "", "$LIBDIR/img/_export.gif", "Export in CSV format", 57, 15);
  847. $clkstr = "document.forms.$this->layoutfm._export_flag.value='true';";
  848. $clkstr .= "document.forms.$this->layoutfm.submit();";
  849. $bexport->set_onclick($clkstr);
  850. $bottoolbar[] = $bexport->render();
  851. }
  852. if (count($bottoolbar > 0)) {
  853. $tools = implode("&nbsp;", $bottoolbar);
  854. $Tvw->tr();
  855. $Tvw->td( $tools );
  856. }
  857.  
  858. // Return the html..
  859. $s = $Tvw->render();
  860. debug_trace();
  861. return $s;
  862. } // layoutcontent
  863. // ....................................................................
  864. /**
  865. * Render the block content according to the mode of operation
  866. * we are in. Possible modes: 'viewing', 'editing', 'saving'.
  867. * @return string The HTML
  868. */
  869. function html() {
  870. debug_trace($this);
  871. global $LIBDIR;
  872. global $RESPONSE;
  873. global $edit_layoutid;
  874.  
  875. $s = "";
  876. if ($this->message != "") {
  877. $s .= "<center><span class=error>$this->message</span></center>";
  878. }
  879.  
  880. switch($this->mode) {
  881. case "editing":
  882. // Make sure edit request is meant for us..
  883. if (!isset($edit_layoutid) || $edit_layoutid != $this->layoutid) {
  884. return "";
  885. }
  886. // Deal with first layout edit. In this case it won't yet
  887. // exist in the database, so we create it here..
  888. if (!$this->exists) {
  889. $this->put();
  890. }
  891. $this->mode = "saving";
  892. $s .= $this->editform();
  893. break;
  894.  
  895. default:
  896. if ($this->mode != "viewing" && $this->mode != "previewing") {
  897. $this->mode = "viewing";
  898. }
  899. // Insert any layout metadata into the page..
  900. if ($RESPONSE->metadata_mode == METADATA_ENABLED) {
  901. include_once("metadata-defs.php");
  902. $laymeta = new layout_metadata_elements($this->layoutid, "", true);
  903. $laymeta->insert_metatags($RESPONSE);
  904. }
  905.  
  906. // Render this layout now..
  907. $s .= $this->layoutcontent();
  908.  
  909. } // switch
  910. return $s;
  911. } // html
  912. // ....................................................................
  913. /**
  914. * Assign the cell IDs to the layout. We iterate across all cells
  915. * assigning the unique ID. This is used when the table shape changes.
  916. * @access private
  917. */
  918. function assign_cellids() {
  919. for ($row=0; $row < $this->tot_rows; $row++) {
  920. for ($col=0; $col < $this->tot_cols; $col++) {
  921. if ($this->layout_table->cell_exists($row, $col)) {
  922. $cell = $this->layout_table->get_cell($row, $col);
  923. $cell->setcellid("_tcell|$row|$col|tbody");
  924. $this->layout_table->set_cell($row, $col, $cell);
  925. }
  926. }
  927. }
  928. } // assign_cellids
  929. // ....................................................................
  930. /**
  931. * Vacate the given layout cell. Removes any defined Plain cell
  932. * or Content Block cell from this cell position. Note: this will
  933. * also delete any defined blocks/blocklets and lose all the content
  934. * in these records.
  935. * @param integer $row The row number of the layout cell
  936. * @param integer $col The column number of the layout cell
  937. * @access private
  938. */
  939. function cell_vacate($row, $col) {
  940. if ($this->layout_table->cell_exists($row, $col)) {
  941. $cell = $this->layout_table->get_cell($row, $col);
  942. if (isset($cell->celltype)) unset($cell->celltype);
  943. if (isset($cell->blockid)) {
  944. if ($cell->blockid != "") {
  945. $b = new block($cell->blockid);
  946. $b->delete();
  947. }
  948. if (isset($cell->celltype)) unset($cell->celltype);
  949. if (isset($cell->blockid)) unset($cell->blockid);
  950. if (isset($cell->access)) unset($cell->access);
  951. }
  952. $this->layout_table->set_cell($row, $col, $cell);
  953. }
  954. } // cell_vacate
  955. // ....................................................................
  956. /**
  957. * Merge the settings of the two cells. We assume that cell1 is
  958. * going to be the surviving cell, having "absorbed" cell2.
  959. * Rules: If cell1 is defined already, then we just vacate cell2
  960. * and leave cell1 as-is. If cell1 is empty, and cell2 is
  961. * defined, then we copy cell2 to cell1 and unset cell2 without
  962. * removing any blocks.
  963. * @param integer $row1 The row number of the absorbing cell
  964. * @param integer $col1 The column number of the absorbing cell
  965. * @param integer $row2 The row number of the absorbed cell
  966. * @param integer $col2 The column number of the absorbed cell
  967. * @access private
  968. */
  969. function cell_merge($row1, $col1, $row2, $col2) {
  970. if ($this->layout_table->cell_exists($row1, $col1) &&
  971. $this->layout_table->cell_exists($row2, $col2)) {
  972. $cell1 = $this->layout_table->get_cell($row1, $col1);
  973. $cell2 = $this->layout_table->get_cell($row2, $col2);
  974. if (isset($cell1->celltype)) {
  975. $this->cell_vacate($row2, $col2);
  976. }
  977. else {
  978. if (isset($cell2->celltype)) {
  979. $cell1->celltype = $cell2->celltype;
  980. unset($cell2->celltype);
  981. if (isset($cell2->blockid)) {
  982. $cell1->blockid = $cell2->blockid;
  983. unset($cell2->blockid);
  984. }
  985. // Put absorbed cell back in place..
  986. $this->layout_table->set_cell($row2, $col2, $cell2);
  987. }
  988. }
  989. // Put resultant cell back in place..
  990. $this->layout_table->set_cell($row1, $col1, $cell1);
  991. }
  992. } //cell_merge
  993. // ....................................................................
  994. /**
  995. * Process a block edit form POST.
  996. * Assume that the fields have been submitted in a form as named
  997. * in the config, and grab the POSTed values. This method is executed
  998. * from the constructor usually, before anything is read in from
  999. * the database. We get first shot to change data here.
  1000. * @param text $id The identity of the set to update from POST
  1001. * @access private
  1002. */
  1003. function POSTprocess() {
  1004. debug_trace($this);
  1005. global $HTTP_POST_VARS, $RESPONSE, $LIBDIR;
  1006. global $edit_layoutform, $edit_layoutid, $layoutmode;
  1007.  
  1008. // Only interested in our own postings..
  1009. if (isset($edit_layoutform) && $edit_layoutform == $this->layoutfm) {
  1010. if (isset($layoutmode) && isset($edit_layoutid)) {
  1011. $this->get($edit_layoutid);
  1012. if ($this->layoutid == $edit_layoutid) {
  1013. // Posted buttons, and hidden fields..
  1014. global $_done_x, $_edit_x, $_update_x, $_copy_x, $_paste_x;
  1015. global $_update_flag, $_update_data, $_export_flag, $update_delim;
  1016. global $layoutmode;
  1017.  
  1018. $this->mode = $layoutmode;
  1019. debugbr("layoutid $this->layoutid mode is $this->mode", DBG_DEBUG);
  1020. switch ($this->mode) {
  1021. case "viewing":
  1022. // Clicked Edit button
  1023. if (isset($_edit_x)) {
  1024. $this->mode = "editing";
  1025. }
  1026. elseif (isset($_copy_x)) {
  1027. $this->get($edit_layoutid);
  1028. $layconf = new configuration("layout", "clipboard");
  1029. if (!$layconf->field_exists("copy_layoutid")) {
  1030. $layconf->field_insert("copy_layoutid", "text");
  1031. }
  1032. $layconf->set_value("copy_layoutid", $this->layoutid);
  1033. $layconf->put();
  1034. }
  1035. elseif (isset($_paste_x) && isset($edit_layoutid)) {
  1036. $layconf = new configuration("layout", "clipboard");
  1037. $copy_layoutid = $layconf->value("copy_layoutid");
  1038. if ($copy_layoutid != "" && $edit_layoutid != "") {
  1039. $this->get($edit_layoutid);
  1040. debugbr("pasting layout $copy_layoutid", DBG_DEBUG);
  1041. $this->paste_layout($copy_layoutid);
  1042. $layconf->set_value("copy_layoutid", "");
  1043. $layconf->put();
  1044. }
  1045. }
  1046. // Updating plain cell content..
  1047. elseif (isset($_update_flag) && $_update_flag == "true") {
  1048. global $_update_data;
  1049. // Get layout table, so we can alter it..
  1050. $this->get($edit_layoutid);
  1051. $updated = false;
  1052. if (isset($_update_data) && $_update_data != "") {
  1053. $updates = explode($update_delim, $_update_data);
  1054. foreach ($updates as $update) {
  1055. $bits = explode("|", $update);
  1056. if ($bits[0] == "_tcell") {
  1057. $row = $bits[1];
  1058. $col = $bits[2];
  1059. $tgroup = $bits[3];
  1060. $postval = rawurldecode($bits[4]);
  1061. debugbr("POSTED cell: $row,$col = '$postval'", DBG_DEBUG);
  1062. $this->layout_table->poke_cell($row, $col, $postval, "", "", $tgroup);
  1063. $updated = true;
  1064. }
  1065. }
  1066. }
  1067. if ($updated) {
  1068. $this->put();
  1069. }
  1070. }
  1071. elseif (isset($_export_flag) && $_export_flag == "true") {
  1072. // Get layout table, so we can export it..
  1073. $this->get($edit_layoutid);
  1074. $RESPONSE->discard();
  1075. header("Content-Type: text/csv");
  1076. header("Content-Disposition: attachment; filename=$this->layout_name" . ".csv");
  1077. echo $this->layout_table->csv();
  1078. exit;
  1079. }
  1080. break;
  1081.  
  1082. // Save button clicked..
  1083. case "save":
  1084. global $index_category, $layout_rows, $layout_cols, $layout_padding;
  1085. global $background_colour, $width_profile, $layout_newcell;
  1086. global $show_last_modified, $format_last_modified;
  1087. global $prefix_last_modified, $table_style, $table_width;
  1088. global $table_autojustify, $table_rowstripes, $layout_style;
  1089. global $language;
  1090. global $privs_recmaintpost_data, $privs_recmaintpost_flds, $privs_recmaintpost_form;
  1091.  
  1092. // Get layout table, so we can alter it..
  1093. $this->get($edit_layoutid);
  1094.  
  1095. // Updated layout parameters..
  1096. if ($this->index_category != $index_category) {
  1097. $this->index_category = $index_category;
  1098. $this->index();
  1099. }
  1100. $this->language = $language;
  1101. $this->show_last_modified = isset($show_last_modified);
  1102. $this->format_last_modified = $format_last_modified;
  1103. $this->prefix_last_modified = $prefix_last_modified;
  1104. $this->layout_style = $layout_style;
  1105.  
  1106. // Table size changed flag..
  1107. $sizechanged = false;
  1108.  
  1109. // Set layout table parameters..
  1110. $this->layout_table->setcss("");
  1111. $this->layout_table->setclass($table_style);
  1112. $this->layout_table->setwidth($table_width);
  1113. if (isset($table_rowstripes)) {
  1114. $this->layout_table->rowstripes("axyl_rowstripe_lite,axyl_rowstripe_dark");
  1115. }
  1116. else {
  1117. $this->layout_table->rowstripes("");
  1118. }
  1119. $this->layout_table->autojustify(isset($table_autojustify));
  1120. $this->layout_table->setpadding($layout_padding);
  1121. $this->layout_table->setbgcolor($background_colour);
  1122. if (isset($width_profile)) {
  1123. $this->layout_table->set_width_profile($width_profile);
  1124. }
  1125. // Adjust row changes..
  1126. $Trows = $this->layout_table->rowcount();
  1127. if ($layout_rows != $Trows) {
  1128. $sizechanged = true;
  1129. if ($layout_rows < $Trows) {
  1130. $last = $Trows - 1;
  1131. for ($i = 0; $i < $Trows - $layout_rows; $i++) {
  1132. $this->layout_table->delete_row($last);
  1133. $last -= 1;
  1134. }
  1135. }
  1136. else {
  1137. for ($i = 0; $i < $layout_rows - $Trows; $i++) {
  1138. $this->layout_table->append_row( new tablecell("&nbsp;") );
  1139. }
  1140. }
  1141. }
  1142. // Adjust for column changes..
  1143. $Tcols = $this->layout_table->cellcount();
  1144. if ($layout_cols != $Tcols) {
  1145. $sizechanged = true;
  1146. if ($layout_cols < $Tcols) {
  1147. $last = $Tcols - 1;
  1148. for ($i = 0; $i < $Tcols - $layout_cols; $i++) {
  1149. $this->layout_table->delete_cols($last);
  1150. $last -= 1;
  1151. }
  1152. }
  1153. else {
  1154. $this->layout_table->append_cols($layout_cols - $Tcols, new tablecell("&nbsp;"));
  1155. }
  1156. }
  1157. // Look for new layout cells..
  1158. if (isset($layout_newcell)) {
  1159. foreach ($layout_newcell as $request) {
  1160. $bits = explode("|", $request);
  1161. $celltype = $bits[0];
  1162. $row = $bits[1];
  1163. $col = $bits[2];
  1164. // Get table cell to change it..
  1165. if ($this->layout_table->cell_exists($row, $col)) {
  1166. $cell = $this->layout_table->get_cell($row, $col);
  1167. // Block cells get new block, plain cells don't..
  1168. switch ($celltype) {
  1169. // Content Block or Wysiwyg cell..
  1170. case BLOCK_CONTENT:
  1171. case WYSIWYG_EDITOR:
  1172. $b = new block();
  1173. $b->layoutid = $this->layoutid;
  1174. $b->block_type = $celltype;
  1175. $b->put();
  1176. $cell->celltype = $celltype;
  1177. $cell->blockid = $b->blockid;
  1178. break;
  1179. // Plain cell..
  1180. case PLAIN_CELL:
  1181. $cell->celltype = PLAIN_CELL;
  1182. $cell->blockid = "";
  1183. // Set default cell permissions..
  1184. $cell->permit($this->editor_groups, PERM_ALL);
  1185. $cell->permit($this->author_groups, PERM_READ|PERM_UPDATE);
  1186. break;
  1187. } // switch
  1188. // Return cell to table..
  1189. $this->layout_table->set_cell($row, $col, $cell);
  1190. }
  1191. } // foreach
  1192. } // new layout cells
  1193. // Save the layout, stay in edit mode..
  1194. $this->assign_cellids();
  1195. $this->put();
  1196.  
  1197. // Privilege settings..
  1198. if (isset($privs_recmaintpost_form)) {
  1199. if (isset($privs_recmaintpost_data)
  1200. && $privs_recmaintpost_data != "") {
  1201. $recs = explode(RECORD_DELIM, $privs_recmaintpost_data);
  1202. foreach ($recs as $rec) {
  1203. $values = explode(FIELD_DELIM, $rec);
  1204. $group_id = array_shift($values);
  1205. $fields = explode(",", $privs_recmaintpost_flds);
  1206. $pos = 0;
  1207. foreach ($fields as $field) {
  1208. $privilege = str_replace("priv_", "", $field);
  1209. $priv_granted = $values[$pos];
  1210. switch ($priv_granted) {
  1211. case "t":
  1212. if (!isset($this->privileges["$privilege|$group_id"])) {
  1213. $pin = new dbinsert("ax_layout_set_group");
  1214. $pin->set("layout_name", $this->layout_name);
  1215. $pin->set("cm_privilege", "'" . $privilege . "'");
  1216. $pin->set("group_id", $group_id);
  1217. $pin->execute();
  1218. }
  1219. break;
  1220. case "f":
  1221. if (!isset($this->privileges["none|$group_id"])) {
  1222. $pdel = new dbdelete("ax_layout_set_group");
  1223. $pdel->where("group_id=$group_id");
  1224. $pdel->where("AND cm_privilege='$privilege'");
  1225. $pdel->execute();
  1226. }
  1227. break;
  1228. } // switch
  1229. $pos += 1;
  1230. } // foreach
  1231. } // foreach recs
  1232. }
  1233. }
  1234. $this->mode = "editing";
  1235. break;
  1236.  
  1237. case "saving":
  1238. // Get layout table, so we can alter it..
  1239. $this->get($edit_layoutid);
  1240.  
  1241. global $_new_x, $_save_x, $_cancel_x, $_done_x;
  1242. global $layout_action, $_perm_set_x, $_perm_unset_x;
  1243.  
  1244. // Let me out of here..
  1245. if (isset($_done_x) || isset($_cancel_x)) {
  1246. // Drop through to viewing..
  1247. $this->mode = "viewing";
  1248. }
  1249. // Blow away whole layout, and start again..
  1250. elseif (isset($_new_x)) {
  1251. start_transaction();
  1252. $blocks = dbrecordset("SELECT block_id FROM ax_block WHERE layout_id=$this->layoutid");
  1253. if ($blocks->hasdata) {
  1254. do {
  1255. $b = new block($blocks->field("block_id"));
  1256. $b->delete();
  1257. } while ($blocks->get_next());
  1258. }
  1259. $Lup = new dbupdate("ax_layout");
  1260. $Lup->set("layout_table", NULLVALUE);
  1261. $Lup->where("layout_id=$this->layoutid");
  1262. $Lup->execute();
  1263. commit();
  1264. if (isset($this->layout_table)) unset($this->layout_table);
  1265. if (isset($this->layout_blocks)) unset($this->layout_blocks);
  1266. $this->mode = "editing";
  1267. }
  1268. // Permissions setting activity..
  1269. elseif (isset($_perm_set_x) || isset($_perm_unset_x)) {
  1270. global $layout_cellsel, $perm_groups, $perm_perms;
  1271. if (isset($layout_cellsel) && isset($perm_groups) && isset($perm_perms)) {
  1272. foreach ($layout_cellsel as $cellsel) {
  1273. $bits = explode("|", $cellsel);
  1274. $row = $bits[0];
  1275. $col = $bits[1];
  1276. if ($this->layout_table->cell_exists($row, $col)) {
  1277. $setgroups = implode(",", $perm_groups);
  1278. $setperms = 0;
  1279. foreach ($perm_perms as $perm) {
  1280. $setperms |= $perm;
  1281. }
  1282. if (isset($_perm_set_x)) {
  1283. $this->layout_table->permit_cell($row, $col, $setgroups, $setperms);
  1284. }
  1285. else {
  1286. $this->layout_table->unpermit_cell($row, $col, $setgroups, $setperms);
  1287. }
  1288. }
  1289. }
  1290. $this->put();
  1291. }
  1292. $this->mode = "editing";
  1293. }
  1294. // Other layout management action..
  1295. elseif (isset($layout_action) && $layout_action != "") {
  1296. $req = explode("|", $layout_action);
  1297. $activity = $req[0];
  1298. switch ($activity) {
  1299. // Merging of rows or cols
  1300. case "merge":
  1301. $object = $req[1];
  1302. $row = $req[2]; $col = $req[3];
  1303. switch ($object) {
  1304. case "col":
  1305. $this->cell_merge($row, $col, $row, $col + 1);
  1306. $this->layout_table->merge_cols($row, $col, 2);
  1307. break;
  1308. case "row":
  1309. $this->cell_merge($row, $col, $row + 1, $col);
  1310. $this->layout_table->merge_rows($row, $col, 2);
  1311. break;
  1312. case "allcols":
  1313. $this->layout_table->merge_cols($row, $col, $this->tot_cols);
  1314. break;
  1315. } // switch
  1316. break;
  1317. // Splitting of merged rows or cols
  1318. case "split":
  1319. $object = $req[1];
  1320. $row = $req[2]; $col = $req[3];
  1321. switch ($object) {
  1322. case "col":
  1323. $this->layout_table->split_cols($row, $col);
  1324. break;
  1325. case "row":
  1326. $this->layout_table->split_rows($row, $col);
  1327. break;
  1328. } // switch
  1329. break;
  1330. // Delete content block or plain cell..
  1331. case "deletecell":
  1332. $row = $req[1];
  1333. $col = $req[2];
  1334. $this->cell_vacate($row, $col);
  1335. $this->layout_blocks = array();
  1336. break;
  1337. // Inserting a row
  1338. case "insrow":
  1339. $row = $req[1]; $col = $req[2];
  1340. $this->layout_table->insert_row($row);
  1341. $this->layout_blocks = array();
  1342. break;
  1343. // Inserting a column
  1344. case "inscol":
  1345. $row = $req[1]; $col = $req[2];
  1346. $this->layout_table->insert_cols($col);
  1347. $this->layout_blocks = array();
  1348. break;
  1349. case "delrow":
  1350. $row = $req[1]; $col = $req[2];
  1351. $this->layout_table->delete_row($row);
  1352. $this->layout_blocks = array();
  1353. break;
  1354. // Inserting a column
  1355. case "delcol":
  1356. $row = $req[1]; $col = $req[2];
  1357. $this->layout_table->delete_cols($col);
  1358. $this->layout_blocks = array();
  1359. break;
  1360. } // switch
  1361.  
  1362. // Save..
  1363. $this->assign_cellids();
  1364. $this->put();
  1365. // Stay in editing..
  1366. $this->mode = "editing";
  1367. }
  1368. break;
  1369. } // switch
  1370. } // layoutid is this one
  1371. } // got $layoutmode and $layoutid
  1372. } // layout form is us
  1373.  
  1374. // If the user preference says so, then set the mode to
  1375. // content preview mode..
  1376. $prefs = new configuration("preferences", $RESPONSE->userid);
  1377. if ($prefs->field_exists("Content Preview Mode")) {
  1378. if ($prefs->value("Content Preview Mode") === true) {
  1379. $this->mode = "previewing";
  1380. }
  1381. }
  1382. debugbr("mode now set to: $this->mode", DBG_DEBUG);
  1383. debug_trace();
  1384. } // POSTprocess
  1385.  
  1386. } // layout class
  1387. // ----------------------------------------------------------------------
  1388.  
  1389. /**
  1390. * Named Layout. A named layout is just another way of grabbing a layout,
  1391. * but by name, rather than by ID. A given "name" can have multiple
  1392. * versions in existence, if it has been published, and these will all
  1393. * have unique ID's, so this class is concerned with sorting out which
  1394. * version of a named layout is required, and acquiring the correct
  1395. * layout ID.
  1396. * @package cm
  1397. */
  1398. class named_layout extends layout {
  1399. // Public
  1400. /** The version of the layout we have */
  1401.  
  1402. var $version = VERSION_UNDEFINED;
  1403. /** Total versions of this layout in database */
  1404.  
  1405. var $version_count = 0;
  1406.  
  1407. // Private
  1408. /** Flag to indicate POST told us to publish */
  1409.  
  1410. var $posted_publish = false;
  1411. /** Flag to indicate POST told us to revert */
  1412.  
  1413. var $posted_revert = false;
  1414. // ....................................................................
  1415. /**
  1416. * Constructor
  1417. * Create a new named_layout object. A named layout is a layout which
  1418. * is identified by its name, and by the version. Versions are numbered
  1419. * from zero (0), which represents the most recent. The higher the
  1420. * version number, the further back in time you go. We define three
  1421. * special version numbers:
  1422. * VERSION_PENDING (0) The layout waiting to be made live
  1423. * VERSION_LIVE (1) The currently live layout
  1424. * VERSION_PREVIOUS (2) The version previously live
  1425. * Accordingly, these versions are the most recent three in the set of
  1426. * all versions of the layout.
  1427. * @param string $name Layout name
  1428. * @param integer $version Version number, (zero=most recent)
  1429. */
  1430. function named_layout($name="", $version=VERSION_UNDEFINED) {
  1431. global $RESPONSE;
  1432.  
  1433. // Initialise version..
  1434. if ($version != VERSION_UNDEFINED) {
  1435. $this->version = $version;
  1436. }
  1437.  
  1438. // Process any form submissions...
  1439. $this->POSTprocess();
  1440.  
  1441. // Fallback if required version still not defined..
  1442. if ($this->version == VERSION_UNDEFINED) {
  1443. if ($this->mode != "previewing"
  1444. && $RESPONSE->ismemberof_group_in( array_merge($this->editor_groups, $this->author_groups, $this->entry_groups) )) {
  1445. $this->version = VERSION_PENDING;
  1446. }
  1447. else {
  1448. $this->version = VERSION_LIVE;
  1449. }
  1450. }
  1451.  
  1452. // Process POSTs, and determine the layout ID..
  1453. if ($name != "") {
  1454.  
  1455. // How many versions do we have..
  1456. $q = "SELECT COUNT(*) AS vercnt FROM ax_layout";
  1457. $q .= " WHERE layout_name='". addslashes($name) . "'";
  1458. $Lcnt = dbrecordset($q);
  1459. if ($Lcnt->hasdata) {
  1460. $this->version_count = $Lcnt->field("vercnt");
  1461. }
  1462. debugbr("layout: version history of $this->version_count", DBG_DEBUG);
  1463.  
  1464. // Now, if there are no versions of this layout then we are
  1465. // accessing it for the very first time, so we create it,.
  1466. if ($this->version_count == 0) {
  1467. // Create new set if required..
  1468. $checkSet = dbrecordset("SELECT * FROM ax_layout_set WHERE layout_name='". addslashes($name) . "'");
  1469. if ($checkSet->rowcount == 0) {
  1470. $LSin = new dbinsert("ax_layout_set");
  1471. $LSin->set("layout_name", $name);
  1472. $LSin->execute();
  1473. }
  1474. // Create new layout..
  1475. $newlay = new layout();
  1476. $newlay->layout_name = $name;
  1477. $newlay->put();
  1478. $this->version_count = 1;
  1479. }
  1480.  
  1481. // Grab all relevant versions of the layout..
  1482. $LQ = new dbselect("ax_layout");
  1483. $LQ->where("layout_name='". addslashes($name) . "'");
  1484. $LQ->orderby("layout_id DESC");
  1485. $LQ->execute();
  1486. if ($LQ->hasdata) {
  1487. $row = false;
  1488. // NON-PENDING..
  1489. if ($this->version > 0) {
  1490. if ($LQ->rowexists($this->version)) {
  1491. debugbr("layout: going for version $this->version", DBG_DEBUG);
  1492. $row = $LQ->get_row($this->version);
  1493. }
  1494. else {
  1495. if ($this->mode != "previewing"
  1496. && $RESPONSE->ismemberof_group_in( array_merge($this->editor_groups, $this->author_groups, $this->entry_groups) )) {
  1497. $this->message = "Selected layout does not exist. Falling back to Pending.";
  1498. }
  1499. }
  1500. }
  1501. // PENDING..
  1502. if ($row === false) {
  1503. // Show pending, if no live..
  1504. $this->version = VERSION_PENDING;
  1505. debugbr("layout: falling back to version $this->version", DBG_DEBUG);
  1506. if ($LQ->rowexists($this->version)) {
  1507. $row = $LQ->get_row($this->version);
  1508. }
  1509. }
  1510. if ($row !== false) {
  1511. $this->layout( $LQ->field("layout_id") );
  1512. }
  1513. }
  1514.  
  1515. // Do parent POST processing..
  1516. layout::POSTprocess();
  1517.  
  1518. // Refresh local picture..
  1519. $this->get( $this->layoutid );
  1520.  
  1521. // Now do any of the actions, such as publishing
  1522. // which may have been specified by POST..
  1523. if ($this->posted_publish) {
  1524. $this->publish();
  1525. }
  1526. if ($this->posted_revert) {
  1527. $this->unpublish();
  1528. }
  1529. }
  1530. } // named_layout
  1531. // ....................................................................
  1532. /**
  1533. * Index the named layout. We only do this if the layout version
  1534. * is LIVE or there is only a single version in existence.
  1535. */
  1536. function index() {
  1537. // Find page we belong to..
  1538. $q = "SELECT * FROM ax_layout_set ls, ax_sitepage pg";
  1539. $q .= " WHERE ls.layout_name='" . addslashes($this->layout_name) . "'";
  1540. $q .= " AND pg.page_id=ls.page_id";
  1541. $sitepage = dbrecordset($q);
  1542. if ($sitepage->hasdata) {
  1543. $path = $sitepage->field("page_path");
  1544. $title = $sitepage->field("page_title");
  1545. layout::index($path, $title);
  1546. }
  1547. } // index
  1548. // ....................................................................
  1549. /**
  1550. * Un-Index the named layout. We only do this if the layout version
  1551. * is LIVE or there is only a single version in existence.
  1552. */
  1553. function unindex() {
  1554. if ($this->version_count == 1 || $this->version == VERSION_LIVE) {
  1555. layout::unindex();
  1556. }
  1557. } // unindex
  1558. // ....................................................................
  1559. /**
  1560. * Publish a pending named layout. All we do in fact, is to replicate
  1561. * the current pending version of the layout (this one) into a new
  1562. * version. That automatically makes this layout the current LIVE one,
  1563. * and the newly created version becomes the new PENDING one.
  1564. */
  1565. function publish() {
  1566. if ($this->version == VERSION_PENDING) {
  1567. debugbr("publishing this layout as LIVE", DBG_DEBUG);
  1568. $this->replicate();
  1569. $this->index();
  1570. }
  1571. } // publish
  1572. // ....................................................................
  1573. /**
  1574. * Un-Publish a live named layout. This simply deletes the current
  1575. * pending version of the layout. That makes the current LIVE version
  1576. * the new pending version.
  1577. */
  1578. function unpublish() {
  1579. if ($this->version == VERSION_LIVE) {
  1580. debugbr("unpublishing this layout, reverting previous layout to LIVE", DBG_DEBUG);
  1581. $pending = new named_layout($this->layout_name, VERSION_PENDING);
  1582. if ($pending->exists) {
  1583. debugbr("deleting layout ID $pending->layoutid", DBG_DEBUG);
  1584. $pending->unindex();
  1585. $pending->delete();
  1586. $this->version = VERSION_PENDING;
  1587. $this->index();
  1588. }
  1589. }
  1590. } // unpublish
  1591. // ....................................................................
  1592. /**
  1593. * Return HTML for this named layout.
  1594. */
  1595. function html() {
  1596. if ($this->exists) {
  1597. return layout::html();
  1598. }
  1599. else {
  1600. return "No such layout exists.";
  1601. }
  1602. } // html
  1603. // ....................................................................
  1604. /**
  1605. * Process a block edit form POST.
  1606. * access private
  1607. */
  1608. function POSTprocess() {
  1609. debug_trace($this);
  1610. global $layout_version, $edit_layoutid;
  1611. global $_publish_x, $_revert_x, $_copy_x, $_paste_x;
  1612. if (isset($layout_version)) {
  1613. if ($this->version == VERSION_UNDEFINED) {
  1614. debugbr("setting layout version to $layout_version", DBG_DEBUG);
  1615. $this->version = $layout_version;
  1616. }
  1617. }
  1618. // Buttons..
  1619. if (isset($_publish_x)) {
  1620. $this->posted_publish = true;
  1621. }
  1622. elseif (isset($_revert_x)) {
  1623. $this->posted_revert = true;
  1624. }
  1625.  
  1626. // Do parent POST processing..
  1627. //layout::POSTprocess();
  1628.  
  1629. debug_trace($this);
  1630. }
  1631. } // named_layout class
  1632. // ----------------------------------------------------------------------
  1633.  
  1634. ?>

Documentation generated by phpDocumentor 1.3.0RC3