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

Documentation generated by phpDocumentor 1.3.0RC3