Squiz Matrix  4.12.2
 All Data Structures Namespaces Functions Variables Pages
bodycopy_container_edit_fns.inc
1 <?php
17 require_once SQ_INCLUDE_PATH.'/asset_edit/asset_edit_fns.inc';
18 require_once SQ_FUDGE_PATH.'/var_serialise/var_serialise.inc';
19 require_once SQ_FUDGE_PATH.'/general/file_system.inc';
20 require_once SQ_CORE_PACKAGE_PATH.'/bodycopy/bodycopy/bodycopy_edit_fns.inc';
21 
34 {
35 
36 
41  function __construct()
42  {
43  parent::__construct();
44  unset($this->static_screens['metadataSchemas']);
45  unset($this->static_screens['metadata']);
46  unset($this->static_screens['settings']);
47  unset($this->static_screens['tagging']);
48 
49  }//end constructor
50 
51 
64  public function setAttribute(Array &$attributes, $name, $value)
65  {
66  $name = strtolower($name);
67  if (empty($attributes[$name])) $attributes[$name] = '';
68  if ($attributes[$name] == $value) return FALSE;
69  $attributes[$name] = $value;
70 
71  return TRUE;
72 
73  }//end setAttribute()
74 
75 
85  public function paintBackendJsData(Bodycopy_Container $asset, $prefix)
86  {
87 
88  }//end paintBackendJsData()
89 
90 
101  public function paintGenericBackend(Bodycopy_Container $asset, Backend_Outputter $o, $prefix)
102  {
103 
104  }//end paintGenericBackend()
105 
106 
117  public function paint(Bodycopy_Container $asset, $editing=FALSE, $generating=FALSE)
118  {
119 
120  }//end paint()
121 
122 
133  public function paintContainer(Bodycopy_Container $asset, Backend_Outputter $o, $prefix)
134  {
135  if (!$asset->writeAccess('content')) {
136  if ($asset->readAccess()) {
137  $conflict_tags = Array(
138  '<form',
139  '</form',
140  '<input',
141  '<option',
142  '<select',
143  '<textarea',
144  '<button',
145  '<optgroup',
146  '<label',
147  '<fieldset',
148  '<legend',
149  );
150  $conflict_tag_search_string = '~('.implode(')|(', $conflict_tags).')~i';
151 
152  ob_start();
153  $this->paint($asset, TRUE);
154  $container_content = ob_get_clean();
155 
156  if (preg_match($conflict_tag_search_string, $container_content)) {
157  // Aww damn, the content conflicts...
158  // So regenerate the content without the editing interface
159  ob_start();
160  $this->paint($asset, FALSE);
161  $container_content = ob_get_clean();
162  $container_content = '<div style="padding: 1ex; margin-bottom: 1ex; border: solid 1px grey;"><strong>Container ID '.$asset->id.'</strong><div class="sq-backend-warning">'.translate('bodycopy_html_conflict_warning').'</div><hr /><pre>'.htmlentities($container_content, ENT_COMPAT, SQ_CONF_DEFAULT_CHARACTER_SET).'</pre></div>';
163  }
164 
165  echo $container_content.'<br />';
166 
167 
168  } else {
169  echo '<span class="sq-backend-warning">You do not have access to view the contents of this container</span>';
170  }
171  return FALSE;
172  }//end if
173 
174  return TRUE;
175 
176  }//end paintContainer()
177 
178 
193  public function processContainer(Bodycopy_Container $asset, Backend_Outputter $o, $prefix, $bc_action, $bc_name, Array $bc_data, Array $bc_saved)
194  {
195  $updated = FALSE;
196 
197  // save any changed attributes
198  if (!empty($bc_data[$prefix][$asset->id]['attributes']) || !empty($bc_saved[$prefix][$asset->id]['attributes'])) {
199  $attributes_updated = FALSE;
200  $attributes = $asset->attr('attributes');
201  if (isset($bc_data[$prefix][$asset->id]['attributes'])) {
202  foreach ($bc_data[$prefix][$asset->id]['attributes'] as $name => $value) {
203  if ($name == 'identifier') {
204  if ($value != '') {
205  if ($asset->setAttrValue('name', $value)) {
206  $updated = TRUE;
207  }
208  }
209  } else {
210  if ($this->setAttribute($attributes, $name, $value)) {
211  if ($name == 'desc') {
212  // update description attr when desc property field gets updated
213  $asset->setAttrValue('description', $value);
214  }
215  $attributes_updated = TRUE;
216  }
217  }
218  }
219  }
220  if (isset($bc_saved[$prefix][$asset->id]['attributes'])) {
221 
222  foreach ($bc_saved[$prefix][$asset->id]['attributes'] as $name => $value) {
223  if ($name == 'identifier') {
224  if ($value != '') {
225  if ($asset->setAttrValue('name', $value)) {
226  $updated = TRUE;
227  }
228  }
229  } else {
230  if ($this->setAttribute($attributes, $name, $value)) {
231  if ($name == 'desc') {
232  // update description attr when desc property field gets updated
233  $asset->setAttrValue('description', $value);
234  }
235  $attributes_updated = TRUE;
236  }
237  }
238  }
239  }
240  if ($attributes_updated) {
241  $asset->setAttrValue('attributes', $attributes);
242  $updated = TRUE;
243  }
244  }//end if - there are any attributes to be saved
245 
246  return $updated;
247 
248  }//end processContainer()
249 
250 
259  public function generateContentFile(Bodycopy_Container $asset)
260  {
261  ob_start();
262  $this->paint($asset, FALSE, TRUE);
263  $output = ob_get_contents();
264  ob_end_clean();
265 
266  if (!$this->createContentLinks($asset, $output)) {
267  return FALSE;
268  }
269 
270  require_once SQ_FUDGE_PATH.'/general/text.inc';
271  $keywords = retrieve_keywords_replacements($output);
272 
273  // Temporarily remove the keywords containing './?a=xxx' from the contnet
274  // This will ensure the './?a=xxx' urls in the keywords are not replaced here in the bodycopy level
275  // but rather at global level, hence not breaking the keywords having matrix assetid URLs (bug #5906)
276  $matrix_url_keywords = Array();
277  foreach($keywords as $keyword) {
278  if (strpos($keyword, './?a=') !== FALSE) {
279  $hash = md5($keyword);
280  $matrix_url_keywords[$hash] = $keyword;
281  $output = preg_replace('|%((<([^>]+?)>)+)?'.escape_regex_chars($keyword).'((<([^>]+?)>)+)?%|', '%${1}'.$hash.'$4%', $output);
282  }//end if
283  }//end foreach
284 
285  // replacing normal assetids is simple because they can only be numerical chars :)
286  $e = '|\\./\\?a=([0-9]+)([^0-9:])|';
287  $r = '<'.'?php echo array_get_index($sq_asset_url_list, $1, "./?a=$1"); ?'.'>$2';
288  $output = preg_replace($e, $r, $output);
289  // replacing shadow assetids isn't so simple because they can have any characters...and therefore need to be escaped
290  $e = '|\\./\\?a=([0-9]+:[^$]*)\\$|';
291  $matches = Array();
292  if (preg_match_all($e, $output, $matches, PREG_PATTERN_ORDER)) {
293 
294  $replacements = Array();
295  foreach ($matches[1] as $shadow_assetid) {
296  // if this is a shadow asset, then we need to escape the shadow part (as it is plain text)
297  $replacements[] = '<'.'?php echo $sq_asset_url_list['.var_export($shadow_assetid, 1).']; ?'.'>';
298  }
299 
300  $output = str_replace($matches[0], $replacements, $output);
301 
302  }// end if
303 
304  // Put the keywords containing './?a=xxx' urls back
305  foreach($matrix_url_keywords as $hash => $keyword) {
306  $output = preg_replace('|%((<([^>]+?)>)+)?'.$hash.'((<([^>]+?)>)+)?%|', '%${1}'.$keyword.'$4%', $output);
307  }
308 
309  $attributes = $asset->attr('attributes');
310  if (empty($attributes['disable_keywords'])) {
311  foreach ($keywords as $keyword) {
312  // Escape the regex characters in the keyword
313  $regex_safe_keyword = escape_regex_chars($keyword);
314  // Escape the double quotes, newlines and '$' in the keyword
315  $keyword = str_replace('$', '\\\$', str_replace('\n', '\\\\\n', htmlentities($keyword)));
316 
317  $output = preg_replace('|%((<([^>]+?)>)+)?'.$regex_safe_keyword.'((<([^>]+?)>)+)?%|', '\\1<'.'?php echo (isset($keyword_replacements["'.$keyword.'"])) ? $keyword_replacements["'.$keyword.'"] : ""; ?'.'>\\4', $output);
318  }
319 
320  } else {
321  // if 'Disable Keywords' is checked, change '%' sign to '&#37;'
322  // so that keywords get printed out correctly on the frontend, and replacements at higher level are not affected
323  // content file is generated each time the user commits, so we dont have to bother to convert the special char back
324  foreach ($keywords as $keyword) {
325  $output = preg_replace('|%((<([^>]+?)>)+)?'.$keyword.'((<([^>]+?)>)+)?%|', '\\1<'.'?php echo "&#37;'.$keyword.'&#37;"; ?'.'>\\4', $output);
326  }
327  }
328 
329  // php removes new line character if closing php tag is before it
330  // add another new line character at the end of the line if line ends with php closing tag
331  $output = str_replace("\r\n","\n", $output);
332  $output = str_replace("\r","\n", $output);
333  $output = preg_replace("/\\?>\n/m", '?'.'>'."\n\n", $output);
334 
335  // Line endings should really be \r\n; when sent to a browser, MIME type
336  // standards require \r\n line endings for all text/* types
337  // [cf. RFC 2046]. Best to cache it out using \r\n endings then
338  $output = str_replace("\n","\r\n", $output);
339 
340  create_directory($asset->data_path);
341 
342  $contextid = (int)$GLOBALS['SQ_SYSTEM']->getContextId();
343  $file_name = 'content_file'.(($contextid === 0) ? '' : ('.'.$contextid)).'.php';
344 
345  return string_to_file($output, $asset->data_path.'/'.$file_name);
346 
347  }//end generateContentFile()
348 
349 
361  public function createContentLinks(Bodycopy_Container $asset, $output=NULL)
362  {
363  if (is_null($output)) {
364  ob_start();
365  $this->paint($asset, TRUE);
366  $output = ob_get_contents();
367  ob_end_clean();
368 
369  }
370 
371  // Grab the output from other contexts, so we can keep notice
372  // links from them, too. (Content file is fine enough.)
373  // But exclude the current context, because it's either been
374  // sent to us, or generated above.
375  $files = glob($asset->data_path.'/content_file*.php');
376  $contextid = $GLOBALS['SQ_SYSTEM']->getContextId();
377  $current_filename = 'content_file'.(($contextid === 0) ? '' : ('.'.$contextid)).'.php';
378  foreach ($files as $file) {
379  if (strpos($file, $current_filename) === FALSE) {
380  $output .= file_get_contents($file);
381  }
382  }
383 
384  $existing_links = $asset->attr('shadow_links');
385  $notice_links = $GLOBALS['SQ_SYSTEM']->am->getLinks($asset->id, SQ_LINK_NOTICE);
386  foreach ($notice_links as $link_data) {
387  $existing_links[] = $link_data['minorid'];
388  }
389 
390  // only matches './?a=(normal or shadow id)'
391  $shadow_reg = '|\./\?a=(\d+:[0-9a-zA-Z]*)\$|';
392  $normal_reg = '|\./\?a=(\d+)|';
393  $shadow_matches = Array();
394  $normal_matches = Array();
395  preg_match_all($shadow_reg, $output, $shadow_matches);
396  preg_match_all($normal_reg, $output, $normal_matches);
397  $shadow_matches = $shadow_matches[1];
398  $normal_matches = $normal_matches[1];
399  $replace_assetids = Array();
400  foreach ($shadow_matches as $data) {
401  $replace_assetids[] = $data;
402  }
403  foreach ($normal_matches as $data) {
404  $replace_assetids[] = $data;
405  }
406  $replace_assetids = array_unique($replace_assetids);
407 
408  if ($asset->status & SQ_SC_STATUS_SAFE_EDITING) {
409  $notice_links_file = file_to_string($asset->data_path.'/.sq_system/.notice_links');
410  if (!empty($notice_links_file)) {
411  // this container currently has a system version floating around
412  // so we have to be careful not to delete notice links that are
413  // still being used in this system version
414  require_once SQ_FUDGE_PATH.'/general/file_system.inc';
415  $system_assetids = unserialize($notice_links_file);
416  $replace_assetids = array_merge($replace_assetids, $system_assetids);
417  }//end if
418  }//end if
419 
420  if (!empty($replace_assetids) || !empty($notice_links)) {
421 
422  $replace_assetids = array_unique($replace_assetids);
423 
424  // delete existing notice links that are no longer being used (only delete those without a link value)
425  $GLOBALS['SQ_SYSTEM']->changeDatabaseConnection('db2');
426  $GLOBALS['SQ_SYSTEM']->doTransaction('BEGIN');
427 
428  $run_level_changed = FALSE;
429  if ($GLOBALS['SQ_SYSTEM']->runLevelEnables(SQ_SECURITY_LOCKING)) {
430  $GLOBALS['SQ_SYSTEM']->setRunLevel($GLOBALS['SQ_SYSTEM']->getRunLevel() - SQ_SECURITY_LOCKING);
431  $run_level_changed = TRUE;
432  }
433 
434  foreach ($notice_links as $link_data) {
435  // if the link value doesn't indicate a thumbnail, or tag weighting, etc.
436  // NOTE: This needs to be refactored.
437  if (empty($link_data['value'])) {
438  if (!in_array($link_data['minorid'], $replace_assetids)) {
439  if (!$asset->deleteLink($link_data['linkid'])) {
440  if ($run_level_changed) {
441  $GLOBALS['SQ_SYSTEM']->restoreRunLevel();
442  }
443  $GLOBALS['SQ_SYSTEM']->doTransaction('ROLLBACK');
444  $GLOBALS['SQ_SYSTEM']->restoreDatabaseConnection();
445  return FALSE;
446  }
447  }
448  }
449  }
450 
451  $shadow_links = array_values(array_intersect($asset->attr('shadow_links'), $replace_assetids));
452  foreach ($replace_assetids as $assetid) {
453  if (!assert_valid_assetid($assetid, '', FALSE, FALSE)) {
454  continue;
455  }
456  if (in_array($assetid, $existing_links)) continue;
457 
458  $ereg_asset = $GLOBALS['SQ_SYSTEM']->am->getAsset($assetid);
459  if (is_null($ereg_asset)) continue;
460 
461  if (strpos($ereg_asset->id, ':') !== FALSE) {
462  $shadow_links[] = $ereg_asset->id;
463 
464  } else {
465 
466  // dont show errors here if the link already exists
467  // as we rely on the fact that this ereg_asset cant be notice linked
468  // to asset mutiple times to stop redunant links from
469  // being created (eg same image on a page 10 times should only
470  // produce one notice link)
471  $asset->createLink($ereg_asset, SQ_LINK_NOTICE);
472  }
473 
474  }//end foreach
475 
476  if (!$asset->setAttrValue('shadow_links', $shadow_links) || !$asset->saveAttributes()) {
477  if ($run_level_changed) {
478  $GLOBALS['SQ_SYSTEM']->restoreRunLevel();
479  }
480  $GLOBALS['SQ_SYSTEM']->doTransaction('ROLLBACK');
481  $GLOBALS['SQ_SYSTEM']->restoreDatabaseConnection();
482  return FALSE;
483  }
484 
485  if ($run_level_changed) {
486  $GLOBALS['SQ_SYSTEM']->restoreRunLevel();
487  }
488 
489  $GLOBALS['SQ_SYSTEM']->doTransaction('COMMIT');
490  $GLOBALS['SQ_SYSTEM']->restoreDatabaseConnection();
491 
492 
493  }//end if replace_assetids or notice_links
494 
495  return TRUE;
496 
497  }//end createContentLinks()
498 
499 
508  public function _contentsUpdated(Bodycopy_Container $asset)
509  {
510  if (is_null($asset)) return FALSE;
511  $em = $GLOBALS['SQ_SYSTEM']->getEventManager();
512  return $em->broadcastEvent($asset, 'contentsUpdated', Array());
513 
514  }//end _contentsUpdated()
515 
516 
525  protected function _saveCssIds(Backend_Outputter $o)
526  {
527  $am =& $GLOBALS['SQ_SYSTEM']->am;
528 
529  $url = $GLOBALS['sq_preview_url'];
530  $url = preg_replace('|^http[s]?://|', '', $url);
531 
532  $designid = $am->getValueFromURL($url, 'design::%', TRUE);
533 
534  if ($designid) {
535  if (!SQ_IN_LIMBO) {
536  $design = $am->getAsset($designid);
537  $stylesheets = $design->getStylesheets();
538 
539  // save the ids of all the css files into a global var so the wysiwyg style
540  // drop down plugin can access this information without another querey
541  // we can also limit the stylesheets that are available to it here if we want
542  $GLOBALS['sq_bodycopy_cssids'] = array_keys($stylesheets);
543 
544  $css_urls = $am->getAssetURL($GLOBALS['sq_bodycopy_cssids']);
545 
546  $am->forgetAsset($design);
547  unset($design);
548 
549  return $css_urls;
550  }
551  }
552  return NULL;
553 
554  }//end _saveCssIds()
555 
556 
572  {
573  $am =& $GLOBALS['SQ_SYSTEM']->am;
574 
575  // if there's a preview url set for this asset, get the design info for
576  // it.
577  if (isset($GLOBALS['sq_preview_url']) && !empty($GLOBALS['sq_preview_url'])) {
578  // save css ids into global var
579  $css_urls = $this->_saveCssIds($o);
580  if (!is_null($css_urls)) {
581  ?>
582  <style type="text/css">
583  /* import styles from the design for this asset */
584  <?php
585  foreach ($css_urls as $cssid => $css_url) {
586  ?>@import url("<?php echo $css_url; ?>");<?php
587  }
588  ?>
589  </style>
590  <?php
591  } else {
592  ?>
593  <p class="sq-backend-notice"><b>NOTE:</b> This asset does not have a design applied to it for the URL currently being edited [<b><?php echo $GLOBALS['sq_preview_url']; ?></b>]. No style information is available to use for content editing.</p>
594  <?php
595  }
596  } else {
597  ?>
598  <p class="sq-backend-notice"><b>NOTE:</b> This asset does not have a preview URL or design applied to it in this context. No style information is available to use for content editing.</p>
599  <?php
600  }
601 
602  // if there's no write access to the content
603  if (!$asset->writeAccess('content')) {
604  if ($asset->useSystemVersion()) {
605  $keyword_replacements = Array(); //Do not want to replace keywords
606  $asset->printBody($keyword_replacements);
607  } else {
608  $this->paintContainer($asset, $o, $prefix);
609  }
610  return FALSE;
611  }
612 
613  // the initial width and height to have the layer display created at;
614  $init_layer_width = 500;
615  $init_layer_height = 500;
616 
617  // all available content types
618  $content_types = Array();
619  require_once SQ_CORE_PACKAGE_PATH.'/content_type/content_type.inc';
621 
622  foreach ($types as $type => $type_data) {
623  $content_types[$type] = Array('name' => str_replace(' Content Type', '', $type_data['name']));
624  }
625 
626  ?>
627  <input type="hidden" name="bodycopy_action" value="">
628  <input type="hidden" name="bodycopy_name" value="">
629  <input type="hidden" name="bodycopy_data" value="">
630 
631  <script type="text/javascript"src="<?php echo sq_web_path('fudge').'/var_serialise/var_serialise.js'?>" ></script>
632  <script type="text/javascript"src="<?php echo sq_web_path('lib').'/js/detect.js';?>" ></script>
633  <script type="text/javascript"src="<?php echo sq_web_path('lib').'/js/layer_handler.js';?>" ></script>
634  <script type="text/javascript"src="<?php echo sq_web_path('lib').'/js/general.js';?>" ></script>
635  <script type="text/javascript"src="<?php echo sq_web_path('lib').'/js/debug.js';?>" ></script>
636  <script type="text/javascript"src="<?php echo sq_web_path('lib').'/js/tooltip.js';?>" ></script>
637  <script type="text/javascript"src="<?php echo sq_web_path('lib').'/html_form/html_form.js';?>" ></script>
638 
639  <script type="text/javascript">
640  // this is an array of data that each element (divs, tables, rows, and cells)
641  // can place data for use in editing
642  var bodycopy_current_data = new Object();
643  var bodycopy_saved = new Object();
644 
645  // this is an object that gets set everytime something is getting edited
646  // (as apposed to inserted or deleted) so that the pop-ups can get the info once
647  // they have loaded themselves
648  var bodycopy_current_edit = new Object();
649  bodycopy_current_edit["data"] = null;
650  bodycopy_current_edit["bodycopy_name"] = null;
651 
652  var bodycopy_initialised = false; // TRUE once init() has been run
653  var bodycopy_popup = null; // pointer to the popup Layer_Handler Object
654  var bodycopy_popup_visible = false; // boolean indicating whether the popup is visisble ( not access directly )
655  var bodycopy_nested_doc = null; // pointer to the Netscape Layer or the IE Iframe
656 
657  // initialise the popup
658  function bodycopy_init() {
659  bodycopy_popup = new Layer_Handler("bodycopyPopupDiv", 0,<?php echo $init_layer_width?>,<?php echo $init_layer_height?>,0);
660  set_bodycopy_nested_doc();
661  bodycopy_hide_popup();
662  bodycopy_initialised = true;
663  bodycopy_otheronload();
664  }
665 
666  var bodycopy_otheronload = (window.onload) ? window.onload : new Function;
667  window.onload = bodycopy_init;
668 
669  // generic function used everywhere to send the form
670  function bodycopy_submit(bodycopy_action, bodycopy_name, bodycopy_data) {
671  var form = document.main_form;
672 
673  form.bodycopy_action.value = bodycopy_action;
674  form.bodycopy_name.value = bodycopy_name;
675 
676  // pack up the passed object
677  form.bodycopy_data.value = var_serialise(bodycopy_data);
678 
679  // need to call the onsubmit event explicitly or it will
680  // not get called when we do a form.submit()
681  form.onsubmit();
682  form.submit();
683  }//end bodycopy_submit()
684 
685  function set_bodycopy_nested_doc() {
686  if (is_ie4up) {
687  bodycopy_nested_doc = bodycopyFrame;
688  } else if (is_dom) {
689  bodycopy_nested_doc = document.getElementById("bodycopyFrame");
690  } else {
691  bodycopy_nested_doc = bodycopy_popup.layer;
692  }//end if
693  }
694 
695  function get_bodycopy_popup_visibilty() {
696  return bodycopy_popup_visible;
697  }
698 
699  function bodycopy_show_popup(file, width, height) {
700  if (!bodycopy_initialised) {
701  if (confirm(js_translate('page_not_loaded_yet'))) {
702  document.edit.action.value='';
703  document.edit.submit()
704  }
705  return;
706  }
707 
708  var w = (width != null) ? width : 500;
709  var h = (height != null) ? height : 400;
710  var border = 15;
711  var top_offset = 20;
712 
713  var page_w = (is_nav4 || is_gecko) ? w - 17 : w;
714  var page_h = (is_nav4 || is_gecko) ? h - 17 : h;
715 
716  file = '<?php echo $asset->getBackendHref('show_popup');?>' + '&popup_file=' + file;
717  file += '&page_width=' + page_w;
718  file += '&page_height=' + page_h;
719  file += '&body_extra=';
720  file += '&browser=' + ((is_dom) ? "dom" : ((is_ie4up) ? "ie" : "ns"));
721 
722  bodycopy_popup.w = w;
723  bodycopy_popup.h = h;
724  bodycopy_popup.clip(null, w, h, null);
725  bodycopy_popup_visible = true;
726 
727  if (is_ie4up) {
728  // frameElement is IE 5.5 only
729  bodycopy_nested_doc.width = w - border;
730  bodycopy_nested_doc.height = h - border;
731  bodycopy_nested_doc.location = file;
732  } else if (is_dom) {
733  bodycopy_nested_doc.width = w - border;
734  bodycopy_nested_doc.height = h - border;
735  bodycopy_nested_doc.src = file;
736  } else {
737  bodycopy_nested_doc.clip.right = w - border;
738  bodycopy_nested_doc.clip.width = w - border;
739  bodycopy_nested_doc.clip.height = h - border;
740  bodycopy_nested_doc.clip.bottom = h - border;
741  bodycopy_nested_doc.load(file, w - 5);
742  }
743  if (is_linux && is_gecko) {
744  // On Ubuntu Firefox, fonts and buttons are bigger so they need to expand.
745  bodycopy_nested_doc.height = '100%';
746  }
747 
748  // how far down the page we want to display this popup
749  var scroll_top = ((is_ie4up) ? document.body.scrollTop : self.pageYOffset);
750  bodycopy_popup.move(null, scroll_top + top_offset);
751  bodycopy_popup.show();
752  }//end bodycopy_show_popup()
753 
754  function bodycopy_hide_popup() {
755  if (!bodycopy_initialised) { return; }
756  bodycopy_show_popup("blank.php");
757  bodycopy_popup_visible = null;
758  bodycopy_popup.hide();
759  }//end bodycopy_hide_popup()
760 
761  // get the available cell types
762  var BODYCOPY_AVAILABLE_CONTENT_TYPES = null;
763  function get_bodycopy_available_content_types() {
764  if (BODYCOPY_AVAILABLE_CONTENT_TYPES == null) {
765  BODYCOPY_AVAILABLE_CONTENT_TYPES = var_unserialise('<?php echo var_serialise($content_types, TRUE)?>');
766  }
767  return BODYCOPY_AVAILABLE_CONTENT_TYPES;
768  }
769 
770  function bodycopy_data_exists(args) {
771  var str = 'bodycopy_saved';
772  for (var i = 0; i < args.length; i++) {
773  switch (typeof(args[i])) {
774  case "number" :
775  str += '[' + args[i] + ']';
776  break;
777  default :
778  str += '["' + args[i] + '"]';
779  }
780  eval('var exists = (' + str + ') ? true : false;');
781  if (!exists) return false;
782  }
783  return true;
784  }
785 
786  function bodycopy_chgColor(id, colour) {
787  if (is_dom) {
788  var chgcell
789  if (!colour) { colour = '559AE7'; }
790  chgcell = "document.getElementById('"+ id + "').style.backgroundColor = '#"+ colour +"'";
791  eval(chgcell);
792  }
793  }
794 
795  function bodycopy_insert_container(bodycopy_name, containerid, before) {
796  var form = document.main_form;
797  var container_type = form_element_value(form.<?php echo $prefix; ?>_insert_container_type);
798  eval('bodycopy_insert_' + container_type + '("' + bodycopy_name + '", ' + containerid + ', ' + before + ');');
799  }
800 
801  bodycopy_current_data["<?php echo $prefix?>"] = new Object();
802  </script>
803 
804  <?php
805  // print JS functions for each of the container types we have installed
806  $container_types = $am->getAssetTypeHierarchy('bodycopy_container');
807  foreach ($container_types as $type => $type_data) {
808  $GLOBALS['SQ_SYSTEM']->am->includeAsset($type);
809  $type_asset = new $type();
810  $edit_fns = $type_asset->getEditFns();
811  $edit_fns->paintGenericBackend($asset, $o, $prefix);
812  }
813 
814  $container_type_options = Array();
815  $default = '';
816  foreach ($container_types as $type => $type_data) {
817  $code = strtolower(substr($type,9));
818  $container_type_options[$code] = ucfirst(substr($type,9));
819  if (empty($default)) $default = $code;
820  }
821  echo hidden_field($prefix.'_insert_container_type', $default);
822 
823  ?>
824 
825  <style type="text/css">
826  #bodycopyPopupDiv {
827  color: #ffffff;
828  position:absolute;
829  left:100;
830  top:120;
831  width:<?php echo $init_layer_width?>;
832  height:<?php echo $init_layer_height?>;
833  clip:rect(0,600,600,0);
834  visibility: hidden;
835  }
836  #bodycopyToolTipDiv {
837  position:absolute;
838  width: 1px;
839  height: 1px;
840  visibility: hidden;
841  }
842  </style>
843 
844  <!-- Begin Tooltip -->
845  <div id="bodycopyToolTipDiv" style="z-index:1000"></div>
846  <!-- End Tooltip -->
847 
848  <!-- Begin Popup -->
849  <div id="bodycopyPopupDiv" style="z-index:1001">
850  <iframe name="bodycopyFrame" id="bodycopyFrame" scrolling="no" width="<?php echo $init_layer_width?>" height="<?php echo $init_layer_height?>" marginwidth=0 marginheight=0 frameborder="no"></iframe>
851  </div>
852  <!-- End Popup -->
853 
854  <table border="0" cellspacing="0" cellpadding="0" width="100%" class="bodytext">
855  <tr>
856  <td>
857  <input type="hidden" name="bodycopy_saved[<?php echo $prefix?>][<?php echo $asset->id?>]" value="">
858  <?php $this->paintContainer($asset, $o, $prefix); ?>
859  </td>
860  </tr>
861  </table>
862  <?php
863  return TRUE;
864 
865  }//end paintBodycopyContainer()
866 
867 
879  function processBodycopyContainer(Bodycopy_Container $asset, Backend_Outputter $o, $prefix)
880  {
881  // save css ids into global var
882  // we don't care about the return value here
883  $this->_saveCssIds($o);
884 
885  $updated = FALSE;
886  $bc_action = (empty($_POST['bodycopy_action'])) ? '' : $_POST['bodycopy_action'];
887  $bc_name = (empty($_POST['bodycopy_name'])) ? '' : $_POST['bodycopy_name'];
888  $bc_data = (empty($_POST['bodycopy_data'])) ? Array() : $_POST['bodycopy_data'];
889  $bc_saved = (empty($_POST['bodycopy_saved'])) ? Array() : $_POST['bodycopy_saved'];
890 
891  // if there is some bodycopy data, deserialise it into the arrays
892  // so that everything else can use it
893  if ($bc_data) $bc_data = var_unserialise($bc_data);
894 
895  // unserialize the data for a bodycopy.
896  for (reset($bc_saved); NULL !== ($k = key($bc_saved)); next($bc_saved)) {
897  $containers =& $bc_saved[$k];
898  for (reset($containers); NULL !== ($containersid = key($containers)); next($containers)) {
899  $containers[$containersid] = var_unserialise($containers[$containersid]);
900  }
901  }
902 
903  unset($containers);
904 
905  if ($this->processContainer($asset, $o, $prefix, $bc_action, $bc_name, $bc_data, $bc_saved)) {
906  if ($asset->saveAttributes()) $updated = TRUE;
907  }
908  return $updated;
909 
910  }//end processBodycopyContainer()
911 
912 
923  function paintDescription(Bodycopy_Container $asset, Backend_Outputter $o, $prefix)
924  {
925  if ($asset->writeAccess('attributes')) {
926  text_area($prefix.'_description', $asset->attr('description'), 20, 3);
927 
928  } else {
929  // read only
930  echo nl2br(htmlspecialchars($asset->attr('description')));
931  }
932  return TRUE;
933 
934  }//end paintDescription()
935 
936 
947  public function processDescription(Bodycopy_Container $asset, Backend_Outputter $o, $prefix)
948  {
949  if (isset($_POST[$prefix.'_description']) && !empty($_POST[$prefix.'_description'])) {
950  if ($asset->writeAccess('attributes')) {
951  $value = $_REQUEST[$prefix.'_description'];
952  $asset->setAttrValue('description', $value);
953  // also updated the properties array
954  $attributes = $asset->attr('attributes');
955  $attributes['desc'] = $value;
956  $asset->setAttrValue('attributes', $attributes);
957  if (!$asset->saveAttributes()) {
958  trigger_localised_error('CORE0121', E_USER_WARNING, $asset->name, $asset->id);
959  return FALSE;
960  }
961  } else {
962  return FALSE;
963  }
964  }
965  return TRUE;
966 
967  }//end processDescription()
968 
969 
970 }//end class
971 ?>