false, 'module' => $module ]; if ($_REQUEST['reset']) { del_pconfig(local_channel(), 'system', 'mod_' . $module . '.pdl'); Libsync::build_sync_packet(); $ret['success'] = true; json_return_and_die($ret); } if ($_REQUEST['save']) { if (!$_REQUEST['data']) { return $ret; } $data = json_decode($_REQUEST['data'],true); $stored_pdl_result = self::get_pdl($module); $pdl = $stored_pdl_result['pdl']; foreach ($data as $region => $entries) { $region_pdl = ''; foreach ($entries as $entry) { $region_pdl .= base64_decode($entry) . "\r\n"; } $pdl = preg_replace('/\[region=' . $region . '\](.*?)\[\/region\]/ism', '[region=' . $region . ']' . "\r\n" . $region_pdl . "\r\n" . '[/region]', $pdl); } set_pconfig(local_channel(), 'system', 'mod_' . $module . '.pdl', escape_tags($pdl)); Libsync::build_sync_packet(); $ret['success'] = true; json_return_and_die($ret); } if ($_REQUEST['save_src']) { set_pconfig(local_channel(), 'system', 'mod_' . $module . '.pdl', escape_tags($_REQUEST['src'])); Libsync::build_sync_packet(); $ret['success'] = true; json_return_and_die($ret); } if ($_REQUEST['save_template']) { if (!$_REQUEST['data']) { return $ret; } $template = $_REQUEST['data'][0]['value']; $pdl_result = self::get_pdl($module); $stored_template = self::get_template($pdl_result['pdl']); if ($template === $stored_template) { $ret['success'] = true; return $ret; } $cnt = preg_match("/\[template\](.*?)\[\/template\]/ism", $pdl_result['pdl'], $matches); if ($cnt) { $pdl = str_replace('[template]' . $stored_template . '[/template]', '[template]' . $template . '[/template]', $pdl_result['pdl']); } else { $pdl = '[template]' . $template . '[/template]' . "\r\n"; $pdl .= $pdl_result['pdl']; } set_pconfig(local_channel(), 'system', 'mod_' . $module . '.pdl', escape_tags($pdl)); Libsync::build_sync_packet(); $ret['success'] = true; json_return_and_die($ret); } } function get() { if(! local_channel()) { return EMPTY_STR; } $module = argv(1); if (!$module) { goaway(z_root() . '/pdledit_gui/hq'); } $pdl_result = self::get_pdl($module); $pdl = $pdl_result['pdl']; $modified = $pdl_result['modified']; if(!$pdl) { return t('Layout not found'); } $template = self::get_template($pdl); $template_info = self::get_template_info($template); if(empty($template_info['contentregion'])) { return t('This template does not support pdledi_gui (no content regions defined)'); } App::$page['template'] = $template; $regions = self::get_regions($pdl); foreach ($regions as $k => $v) { $region_str = ''; if (is_array($v)) { ksort($v); foreach ($v as $entry) { // Get the info from the file and replace entry if we get anything useful $widget_info = get_widget_info($entry['name']); $entry['name'] = (($widget_info['name']) ? $widget_info['name'] : $entry['name']); $entry['desc'] = (($widget_info['description']) ? $widget_info['description'] : $entry['desc']); $region_str .= replace_macros(get_markup_template('pdledit_gui_item.tpl'), [ '$entry' => $entry ]); } } App::$layout['region_' . $k] = $region_str; } $templates = self::get_templates(); $templates_html = replace_macros(get_markup_template('pdledit_gui_templates.tpl'), [ '$templates' => $templates, '$active' => $template ]); $items_html = ''; //$items_html .= replace_macros(get_markup_template('pdledit_gui_item.tpl'), [ //'$entry' => [ //'type' => 'content', //'name' => t('Main page content'), //'src' => base64_encode('$content') //], //'$disable_controls' => true //]); foreach (self::get_widgets($module) as $entry) { $items_html .= replace_macros(get_markup_template('pdledit_gui_item.tpl'), [ '$entry' => $entry, '$disable_controls' => true ]); } foreach (self::get_menus() as $entry) { $items_html .= replace_macros(get_markup_template('pdledit_gui_item.tpl'), [ '$entry' => $entry, '$disable_controls' => true ]); } foreach (self::get_blocks() as $entry) { $items_html .= replace_macros(get_markup_template('pdledit_gui_item.tpl'), [ '$entry' => $entry, '$disable_controls' => true ]); } App::$layout['region_content'] .= replace_macros(get_markup_template('pdledit_gui.tpl'), [ '$content_regions' => $template_info['contentregion'], '$page_src' => base64_encode($pdl), '$templates' => base64_encode($templates_html), '$modules' => base64_encode(self::get_modules()), '$items' => base64_encode($items_html), '$module_modified' => $modified, '$module' => $module ]); } function get_templates() { $ret = []; $files = glob('view/php/*.php'); if($files) { foreach($files as $f) { $name = basename($f, '.php'); $x = get_template_info($name); if(!empty($x['contentregion'])) { $ret[] = [ 'name' => $name, 'desc' => $x['description'] ]; } } } return $ret; } function get_modules() { $ret = ''; $arr = []; $files = glob('Zotlabs/Module/*.php'); if($files) { foreach($files as $f) { $name = lcfirst(basename($f,'.php')); if ($name === 'admin' && !is_site_admin()) { continue; } $x = theme_include('mod_' . $name . '.pdl'); if($x) { $arr[] = $name; } } } $addons = plugins_installed_list(); if ($addons) { foreach ($addons as $name) { if (!Apps::addon_app_installed(local_channel(), $name)) { continue; } $path = 'addon/' . $name . '/mod_' . $name . '.pdl'; if (file_exists($path)) { $arr[] = $name; } } } sort($arr); foreach ($arr as $name) { $ret .= '
' . $name . '
'; } return $ret; } function get_widgets($module) { $ret = []; $checkpaths = [ 'Zotlabs/Widget/*.php', 'view/theme/' . lcfirst(App::$theme_info['name']) . '/widget/*.php' ]; $addons = plugins_installed_list(); if ($addons) { foreach ($addons as $name) { if (!Apps::addon_app_installed(local_channel(), $name)) { continue; } $path = 'addon/' . $name . '/Widget'; if (is_dir($path)) { $checkpaths[] = $path . '/*.php'; } } } foreach ($checkpaths as $path) { $files = glob($path); if($files) { foreach($files as $f) { $name = lcfirst(basename($f, '.php')); $widget_info = get_widget_info($name); if ($widget_info['requires'] && strpos($widget_info['requires'], 'admin') !== false && !is_site_admin()) { continue; } if ($widget_info['requires'] && strpos($widget_info['requires'], $module) === false) { continue; } $ret[] = [ 'type' => 'widget', 'name' => $widget_info['name'] ?? $name, 'desc' => $widget_info['description'] ?? '', 'src' => base64_encode('[widget=' . $name . '][/widget]') ]; } } } usort($ret, fn($a, $b) => $a['name'] <=> $b['name']); return $ret; } function get_menus() { $ret = []; $r = q("select * from menu where menu_channel_id = %d and menu_flags = 0", intval(local_channel()) ); foreach ($r as $rr) { $name = $rr['menu_name']; $desc = $rr['menu_desc']; $ret[] = [ 'type' => 'menu', 'name' => $name, 'desc' => $desc, 'src' => base64_encode('[menu]' . $name . '[/menu]') ]; } return $ret; } function get_blocks() { $ret = []; $r = q("select v, title, summary from item join iconfig on iconfig.iid = item.id and item.uid = %d and iconfig.cat = 'system' and iconfig.k = 'BUILDBLOCK'", intval(local_channel()) ); foreach ($r as $rr) { $name = $rr['v']; $desc = (($rr['title']) ? $rr['title'] : $rr['summary']); $ret[] = [ 'type' => 'block', 'name' => $name, 'desc' => $desc, 'src' => base64_encode('[block]' . $name . '[/block]') ]; } return $ret; } function get_template($pdl) { $ret = 'default'; $cnt = preg_match("/\[template\](.*?)\[\/template\]/ism", $pdl, $matches); if($cnt && isset($matches[1])) { $ret = trim($matches[1]); } return $ret; } function get_regions($pdl) { $ret = []; $supported_regions = ['aside', 'content', 'right_aside']; $cnt = preg_match_all("/\[region=(.*?)\](.*?)\[\/region\]/ism", $pdl, $matches, PREG_SET_ORDER); if($cnt) { foreach($matches as $mtch) { if (!in_array($mtch[1], $supported_regions)) { continue; } $ret[$mtch[1]] = self::parse_region($mtch[2]); } } return $ret; } function parse_region($pdl) { $ret = []; $cnt = preg_match_all('/\$content\b/ism', $pdl, $matches, PREG_SET_ORDER|PREG_OFFSET_CAPTURE); if($cnt) { foreach($matches as $mtch) { $offset = intval($mtch[0][1]); $name = trim($mtch[0][0]); //$src = base64url_encode(preg_replace(['/\s*\[/', '/\]\s*/'], ['[', ']'], $mtch[0][0])); $src = base64_encode($mtch[0][0]); $ret[$offset] = [ 'type' => 'content', 'name' => t('Main page content'), 'desc' => t('The main page content can not be edited!'), 'src' => $src ]; } } $cnt = preg_match_all("/\[menu\](.*?)\[\/menu\]/ism", $pdl, $matches, PREG_SET_ORDER|PREG_OFFSET_CAPTURE); if($cnt) { foreach($matches as $mtch) { $offset = intval($mtch[1][1]); $name = trim($mtch[1][0]); //$src = base64url_encode(preg_replace(['/\s*\[/', '/\]\s*/'], ['[', ']'], $mtch[0][0])); $src = base64_encode($mtch[0][0]); $ret[$offset] = [ 'type' => 'menu', 'name' => $name, 'desc' => '', 'src' => $src ]; } } // menu class e.g. [menu=horizontal]my_menu[/menu] or [menu=tabbed]my_menu[/menu] // allows different menu renderings to be applied //$cnt = preg_match_all("/\[menu=(.*?)\](.*?)\[\/menu\]/ism", $s, $matches, PREG_SET_ORDER); //if($cnt) { //foreach($matches as $mtch) { //$s = str_replace($mtch[0],$this->menu(trim($mtch[2]),$mtch[1]),$s); //} //} $cnt = preg_match_all("/\[block\](.*?)\[\/block\]/ism", $pdl, $matches, PREG_SET_ORDER|PREG_OFFSET_CAPTURE); if($cnt) { foreach($matches as $mtch) { $offset = intval($mtch[1][1]); $name = trim($mtch[1][0]); //$src = base64url_encode(preg_replace(['/\s*\[/', '/\]\s*/'], ['[', ']'], $mtch[0][0])); $src = base64_encode($mtch[0][0]); $ret[$offset] = [ 'type' => 'block', 'name' => $name, 'desc' => '', 'src' => $src ]; } } //$cnt = preg_match_all("/\[block=(.*?)\](.*?)\[\/block\]/ism", $s, $matches, PREG_SET_ORDER); //if($cnt) { //foreach($matches as $mtch) { //$s = str_replace($mtch[0],$this->block(trim($mtch[2]),trim($mtch[1])),$s); //} //} //$cnt = preg_match_all("/\[js\](.*?)\[\/js\]/ism", $s, $matches, PREG_SET_ORDER); //if($cnt) { //foreach($matches as $mtch) { //$s = str_replace($mtch[0],$this->js(trim($mtch[1])),$s); //} //} //$cnt = preg_match_all("/\[css\](.*?)\[\/css\]/ism", $s, $matches, PREG_SET_ORDER); //if($cnt) { //foreach($matches as $mtch) { //$s = str_replace($mtch[0],$this->css(trim($mtch[1])),$s); //} //} // need to modify this to accept parameters $cnt = preg_match_all("/\[widget=(.*?)\](.*?)\[\/widget\]/ism", $pdl, $matches, PREG_SET_ORDER|PREG_OFFSET_CAPTURE); if($cnt) { foreach($matches as $mtch) { $offset = intval($mtch[1][1]); $name = trim($mtch[1][0]); //$src = base64url_encode(preg_replace(['/\s*\[/', '/\]\s*/'], ['[', ']'], $mtch[0][0])); $src = base64_encode($mtch[0][0]); $ret[$offset] = [ 'type' => 'widget', 'name' => $name, 'desc' => '', 'src' => $src ]; } } return $ret; } /** * @brief Parse template comment in search of template info. * * like * \code * * Name: MyWidget * * Description: A widget * * Version: 1.2.3 * * Author: John * * Author: Jane * * ContentRegionID: some_id * * ContentRegionID: some_other_id * * *\endcode * @param string $template the name of the template * @return array with the information */ function get_template_info($template){ $m = []; $info = [ 'name' => $template, 'description' => '', 'author' => [], 'maintainer' => [], 'version' => '', 'contentregion' => [] ]; $checkpaths = [ 'view/php/' . $template . '.php', ]; $template_found = false; foreach ($checkpaths as $path) { if (is_file($path)) { $template_found = true; $f = file_get_contents($path); break; } } if(!($template_found && $f)) return $info; $f = escape_tags($f); $r = preg_match('|/\*.*\*/|msU', $f, $m); if ($r) { $ll = explode("\n", $m[0]); foreach($ll as $l) { $l = trim($l, "\t\n\r */"); if ($l != ''){ list($k, $v) = array_map('trim', explode(':', $l, 2)); $k = strtolower($k); if (in_array($k, ['author', 'maintainer'])){ $r = preg_match('|([^<]+)<([^>]+)>|', $v, $m); if ($r) { $info[$k][] = array('name' => $m[1], 'link' => $m[2]); } else { $info[$k][] = array('name' => $v); } } elseif (in_array($k, ['contentregion'])){ $info[$k][] = array_map('trim', explode(',', $v)); } else { $info[$k] = $v; } } } } return $info; } function get_pdl($module) { $ret = [ 'pdl' => null, 'modified' => true ]; $pdl = 'mod_' . $module . '.pdl'; $pdl_path = ''; $ret['pdl'] = get_pconfig(local_channel(), 'system', $pdl); if(!$ret['pdl']) { $pdl_path = theme_include($pdl); if (!$pdl_path) { $addon_path = 'addon/' . $module . '/' . $pdl; if (file_exists($addon_path)) { $pdl_path = $addon_path; } } if ($pdl_path) { $ret['pdl'] = file_get_contents($pdl_path); $ret['modified'] = false; } } return $ret; } }