Example #1
0
 function pages($params, $node, $mode = 0)
 {
     global $CTX, $FUNCS, $PAGE, $DB, $AUTH;
     $attr = $FUNCS->get_named_vars(array('masterpage' => '', 'id' => '', 'page_name' => '', 'page_title' => '', 'is_master' => '0', 'limit' => '', 'offset' => '0', 'startcount' => '', 'folder' => '', 'include_subfolders' => '1', 'start_on' => '', 'stop_before' => '', 'show_future_entries' => '0', 'orderby' => '', 'order' => '', 'paginate' => '0', 'custom_field' => '', 'skip_custom_fields' => '0', 'keywords' => '', 'page_id' => '', 'pid' => '', 'cid' => '', 'fid' => '', 'qs_param' => '', 'count_only' => '0', 'ids_only' => '0', 'sql' => '', 'fetch_pages' => '0', 'return_sql' => '0', 'show_unpublished' => '0', 'aggregate_by' => '', 'base_link' => ''), $params);
     // HOOK: alter_page_tag_params
     $FUNCS->dispatch_event('alter_page_tag_params', array(&$attr, $params, $node, &$mode));
     extract($attr);
     // sanitize params
     $masterpage = trim($masterpage);
     $page_name = trim($page_name);
     $page_title = trim($page_title);
     $limit = $FUNCS->is_non_zero_natural($limit) ? intval($limit) : 1000;
     //Practically unlimited.
     $offset = $FUNCS->is_natural($offset) ? intval($offset) : 0;
     $startcount = $FUNCS->is_int($startcount) ? intval($startcount) : 1;
     if ($mode == 1) {
         $paginate = 1;
     }
     //pagination always on for 'search' tag
     if ($mode == 3) {
         $paginate = 0;
     }
     //pagination always off for 'calendar' tag
     $paginate = $paginate == 1 ? 1 : 0;
     $pgn_pno = 1;
     $skip_custom_fields = $skip_custom_fields == 1 ? 1 : 0;
     $count_only = $count_only == 1 ? 1 : 0;
     $ids_only = $ids_only == 1 ? 1 : 0;
     $raw_sql = trim($sql);
     $fetch_pages = $fetch_pages == 1 ? 1 : 0;
     $return_sql = $return_sql == 1 || $return_sql == 2 ? intval($return_sql) : 0;
     $show_unpublished = $show_unpublished == 1 ? 1 : 0;
     $aggregate_by = trim($aggregate_by);
     $base_link = trim($base_link);
     $qs_param = trim($qs_param);
     if ($qs_param == '') {
         $qs_param = $mode == 2 ? 'comments_pg' : 'pg';
     }
     if ($paginate) {
         if (isset($_GET[$qs_param]) && $FUNCS->is_non_zero_natural($_GET[$qs_param])) {
             $pgn_pno = (int) $_GET[$qs_param];
         }
     }
     $show_future_entries = $show_future_entries == 1 ? 1 : 0;
     $hide_future_entries = !$show_future_entries;
     $sql = '';
     $order_sql = '';
     $limit_sql = '';
     $distinct = 0;
     $group_by = array();
     $having = array();
     $count_query_field_as = 'cnt';
     $rec_tpl = array();
     if ($mode == 0 || $mode == 3 || $mode == 4) {
         // 3 if called from calender tag, 4 if called from related_pages/reverse_related_pages tag
         $query_table = K_TBL_PAGES . ' p';
         $default_orderby = 'publish_date';
         if ($mode == 4) {
             // related pages
             if ($pid) {
                 $query_table .= "\r\n" . 'inner join ' . K_TBL_RELATIONS . ' rel on rel.cid = p.id';
                 $sql .= "rel.pid=" . $DB->sanitize($pid) . " AND rel.fid=" . $DB->sanitize($fid) . " AND\r\n";
             } elseif ($cid) {
                 // reverse related
                 $query_table .= "\r\n" . 'inner join ' . K_TBL_RELATIONS . ' rel on rel.pid = p.id';
                 $sql .= "rel.cid=" . $DB->sanitize($cid) . " AND rel.fid=" . $DB->sanitize($fid) . " AND\r\n";
             } else {
                 //huh?
                 return;
             }
             $default_orderby = 'rel.weight';
             $mode = 0;
             // convert to the normal 'pages' tag
         }
         $query_fields = array('p.id', 'p.template_id');
         if ($mode == 3) {
             $query_fields[] = 'p.publish_date';
         }
         $count_query_field = 'p.id';
         if ($masterpage == '') {
             $masterpage = $PAGE->tpl_name;
         }
         $include_subfolders = $include_subfolders == 0 ? 0 : 1;
         $start_on = trim($start_on);
         if ($start_on) {
             $start_on = $FUNCS->make_date($start_on);
         }
         $stop_before = trim($stop_before);
         if ($stop_before) {
             $stop_before = $FUNCS->make_date($stop_before);
         }
         // build the sql where clause using the supplied params.
         // masterpage
         $rs = $DB->select(K_TBL_TEMPLATES, array('*'), "name='" . $DB->sanitize($masterpage) . "'");
         if (!count($rs)) {
             die("ERROR: Tag \"" . $node->name . "\": masterpage '" . $FUNCS->cleanXSS($masterpage) . "' not found");
         }
         $rec_tpl = $rs[0];
         $tpl_id = $rs[0]['id'];
         $tpl_is_gallery = $rs[0]['gallery'];
         $sql .= "p.template_id='" . $DB->sanitize($tpl_id) . "'";
         // id?
         if ($id) {
             $sql .= $FUNCS->gen_sql($id, 'p.id', 1);
         }
         // name?
         if ($page_name) {
             $sql .= $FUNCS->gen_sql($page_name, 'p.page_name');
         }
         // title?
         if ($page_title) {
             $sql .= $FUNCS->gen_sql($page_title, 'p.page_title');
         }
         // folder?
         $folder = trim($folder);
         if ($folder != '') {
             $arr_folders = array();
             // get all the folders of the masterpage
             if ($masterpage == $PAGE->tpl_name) {
                 $folders =& $PAGE->folders;
             } else {
                 $folders =& $FUNCS->get_folders_tree($tpl_id, $masterpage);
             }
             // Negation?
             $neg = 0;
             $pos = strpos(strtoupper($folder), 'NOT ');
             if ($pos !== false && $pos == 0) {
                 $neg = 1;
                 $folder = trim(substr($folder, strpos($folder, ' ')));
             }
             // multiple folders specified?
             $arr_parent_folders = array_map("trim", explode(',', $folder));
             foreach ($arr_parent_folders as $parent_folder) {
                 if ($parent_folder) {
                     // locate the folder
                     $f =& $folders->find($parent_folder);
                     if ($f) {
                         if ($include_subfolders) {
                             // get all the child folders of it
                             $sub_folders = $f->get_children();
                             //includes the parent folder too
                             foreach ($sub_folders as $sf) {
                                 if (!array_key_exists($sf->name, $arr_folders)) {
                                     $arr_folders[$sf->name] = $sf->id;
                                 }
                             }
                         } else {
                             if (!array_key_exists($f->name, $arr_folders)) {
                                 $arr_folders[$f->name] = $f->id;
                             }
                         }
                     }
                 }
             }
             if (count($arr_folders)) {
                 $sql .= " AND ";
                 if ($neg) {
                     $sql .= "NOT";
                 }
                 $sql .= "(";
                 $sep = "";
                 foreach ($arr_folders as $k => $v) {
                     $sql .= $sep . "p.page_folder_id='" . $DB->sanitize($v) . "'";
                     $sep = " OR ";
                 }
                 $sql .= ")";
             }
         } else {
             if (!$include_subfolders) {
                 $sql .= " AND p.page_folder_id='-1'";
             }
         }
         // is_master?
         if ($is_master) {
             $sql .= " AND p.is_master = '1'";
         }
         // dates
         if ($start_on) {
             $sql .= " AND p.publish_date >= '" . $DB->sanitize($start_on) . "'";
         }
         if ($hide_future_entries) {
             $cur_time = $FUNCS->get_current_desktop_time();
             $stop_before = $FUNCS->smaller_date($stop_before, $cur_time);
         }
         if ($stop_before) {
             $sql .= " AND p.publish_date < '" . $DB->sanitize($stop_before) . "'";
         }
         if ($AUTH->user->access_level < K_ACCESS_LEVEL_ADMIN || !$show_unpublished) {
             $sql .= " AND NOT p.publish_date = '0000-00-00 00:00:00'";
         }
         // orderby
         // canonical orderby will be prefixed with 'p.' in generated sql
         // TODO: order by folder_name, folder_title, recent_comment, relation fields
         $arr_canonical_orderby = array('publish_date', 'page_name', 'page_title', 'modification_date', 'comments_count');
         if ($tpl_is_gallery) {
             $arr_canonical_orderby = array_merge($arr_canonical_orderby, array('file_name', 'file_ext', 'file_size'));
         }
         $arr_acceptable_orderby = array('random');
         if ($aggregate_by) {
             $arr_acceptable_orderby[] = 'k_rel_count';
         }
         // HOOK: alter_valid_orderby
         $FUNCS->dispatch_event('alter_valid_orderby', array(&$arr_acceptable_orderby, &$arr_canonical_orderby, $params, $node, $rec_tpl));
         $arr_acceptable_orderby = array_merge($arr_canonical_orderby, $arr_acceptable_orderby);
         $arr_custom_orderby = array();
         // custom fields in 'order_by' clause (points to the entry in $arr_orderby and $arr_order below)
         if ($mode == 3) {
             // for calendar, these two params are always fixed
             $order = 'asc';
             $orderby = 'publish_date';
         }
         $arr_order = array_map("strtolower", array_map("trim", explode(',', $order)));
         $arr_orderby = array_map("strtolower", array_map("trim", explode(',', $orderby)));
         for ($i = 0; $i < count($arr_orderby); $i++) {
             $orderby = $arr_orderby[$i];
             if ($orderby) {
                 if (!in_array($orderby, $arr_acceptable_orderby)) {
                     $arr_custom_orderby[$arr_orderby[$i]] = $i;
                 }
             } else {
                 $arr_orderby[$i] = $default_orderby;
                 //'publish_date';
             }
             $order = $arr_order[$i];
             if ($order != 'desc' && $order != 'asc') {
                 $arr_order[$i] = 'desc';
             }
         }
         if ($mode == 0) {
             // custom fields
             // e:g custom_field='my_intro=East | my_price>100000'
             $arr_ops = array('\\!==', '\\!=', '\\<=', '\\>=', '==', '=', '\\<\\>', '\\<', '\\>');
             $arr_params = array_map("trim", preg_split("/(?<!\\\\)\\|/", $custom_field));
             // split at unescaped pipe char
             $arr_custom_fields = array();
             foreach ($arr_params as $param) {
                 if (!$param) {
                     continue;
                 }
                 foreach ($arr_ops as $op) {
                     $pattern = "/(?<!\\\\)" . $op . "/";
                     //split at unescaped ops
                     if (preg_match($pattern, $param, $matches)) {
                         $arr_tmp = array_map("trim", preg_split($pattern, $param));
                         $key = $arr_tmp[0];
                         $val = array_map("trim", preg_split("/(?<!\\\\),/", $arr_tmp[1]));
                         //split at unescaped comma
                         for ($x = 0; $x < count($val); $x++) {
                             $val[$x] = $DB->sanitize(trim(stripslashes($val[$x]), "'\""));
                         }
                         $arr_custom_fields[] = array('name' => $key, 'val' => $val, 'op' => stripslashes($op));
                         break;
                     }
                 }
             }
             // if 'aggregate_by' specified, set it as a custom relational field
             if ($aggregate_by) {
                 $arr_custom_fields[] = array('name' => $aggregate_by, 'op' => '=', 'val' => array(), 'is_aggregate' => 1);
             }
             // HOOK: alter_page_tag_fields
             $FUNCS->dispatch_event('alter_page_tag_fields', array(&$arr_custom_fields, &$arr_orderby, &$arr_order, &$arr_custom_orderby, $params, $node, $rec_tpl));
             $arr_rel_fields = array();
             $arr_rel_types = array();
             // HOOK: alter_relational_types
             // modules can add their custom types that store data in relation table
             $FUNCS->dispatch_event('alter_relational_types', array(&$arr_rel_types, $params, $node, $rec_tpl));
             $arr_rel_types = array_merge(array('relation'), $arr_rel_types);
             if (count($arr_custom_fields) || count($arr_custom_orderby)) {
                 // resolve custom field names to ids
                 $rs_cf = $DB->select(K_TBL_FIELDS, array('*'), "template_id='" . $DB->sanitize($tpl_id) . "'");
                 $arr_tables = array();
                 $count = 0;
                 for ($x = 0; $x < count($arr_custom_fields); $x++) {
                     if ($arr_custom_fields[$x]['processed']) {
                         continue;
                     }
                     // can be set from hook
                     // is it a 'relation' field with template name ( e.g. 'courses.php::taken' )?
                     if (strpos($arr_custom_fields[$x]['name'], '::') !== false) {
                         list($rel_field_tpl, $rel_field_name) = array_map("trim", explode('::', $arr_custom_fields[$x]['name']));
                         if ($rel_field_tpl != $masterpage) {
                             $arr_rel_fields[$rel_field_tpl][] = array('name' => $rel_field_name, 'op' => $arr_custom_fields[$x]['op'], 'val' => $arr_custom_fields[$x]['val'], 'is_aggregate' => $arr_custom_fields[$x]['is_aggregate']);
                             $arr_custom_fields[$x]['processed'] = 1;
                             continue;
                         } else {
                             $arr_custom_fields[$x]['name'] = $rel_field_name;
                         }
                     }
                     // is it the 'k_rel_count' field that becomes available with 'aggregate_by'?
                     if ($aggregate_by && $arr_custom_fields[$x]['name'] == 'k_rel_count') {
                         $rel_op = $arr_custom_fields[$x]['op'];
                         if ($rel_op == '==') {
                             $rel_op = '=';
                         } elseif ($rel_op == '!==' || $rel_op == '!=') {
                             $rel_op = '<>';
                         }
                         $rel_val = $arr_custom_fields[$x]['val'][0];
                         if ($FUNCS->_validate_natural($rel_val)) {
                             $having[] = "k_rel_count {$rel_op} {$rel_val}";
                             $count_query_field_as = 'k_rel_count';
                         }
                         $arr_custom_fields[$x]['processed'] = 1;
                         continue;
                     }
                     for ($i = 0; $i < count($rs_cf); $i++) {
                         $f = $rs_cf[$i];
                         if ($f['name'] == $arr_custom_fields[$x]['name']) {
                             // 'relation' field?
                             if (in_array($f['k_type'], $arr_rel_types)) {
                                 $arr_rel_fields[$masterpage][] = array('related_field' => $f, 'name' => $f['name'], 'op' => $arr_custom_fields[$x]['op'], 'val' => $arr_custom_fields[$x]['val'], 'id' => $f['id'], 'is_aggregate' => $arr_custom_fields[$x]['is_aggregate']);
                                 $arr_custom_fields[$x]['processed'] = 1;
                                 continue 2;
                             }
                             $arr_custom_fields[$x]['id'] = $f['id'];
                             $arr_custom_fields[$x]['type'] = $f['search_type'];
                             $arr_custom_fields[$x]['field_name'] = $f['search_type'] == 'text' ? 'search_value' : 'value';
                             if ($f['search_type'] == 'text') {
                                 if ($arr_custom_fields[$x]['op'] == '=' || $arr_custom_fields[$x]['op'] == '!=') {
                                     if ($arr_custom_fields[$x]['op'] == '=') {
                                         $arr_custom_fields[$x]['op'] = 'LIKE';
                                     } else {
                                         $arr_custom_fields[$x]['op'] = 'NOT LIKE';
                                     }
                                     for ($c = 0; $c < count($arr_custom_fields[$x]['val']); $c++) {
                                         $arr_custom_fields[$x]['val'][$c] = "%" . $arr_custom_fields[$x]['val'][$c] . "%";
                                     }
                                 }
                             }
                             if ($arr_custom_fields[$x]['op'] == '==') {
                                 $arr_custom_fields[$x]['op'] = '=';
                             } elseif ($arr_custom_fields[$x]['op'] == '!==') {
                                 $arr_custom_fields[$x]['op'] = '!=';
                             }
                             if (!array_key_exists($f['name'], $arr_tables)) {
                                 $arr_tables[$f['name']]['id'] = $f['id'];
                                 $arr_tables[$f['name']]['tbl_name'] = $f['search_type'] == 'text' ? K_TBL_DATA_TEXT : K_TBL_DATA_NUMERIC;
                                 $arr_tables[$f['name']]['alias'] = sprintf("t%d", $count++);
                             }
                             $arr_custom_fields[$x]['table_name'] = $arr_tables[$f['name']]['alias'];
                             break;
                         }
                     }
                     if (!array_key_exists('id', $arr_custom_fields[$x])) {
                         die("ERROR: Custom Field \"" . $arr_custom_fields[$x]['name'] . "\" does not exist in '" . $FUNCS->cleanXSS($masterpage) . "'");
                     }
                 }
                 // resolve relation fields
                 if (count($arr_rel_fields)) {
                     foreach ($arr_rel_fields as $rel_field_tpl => $rel_fields) {
                         // for each masterpage
                         $rel_field_tpl_id = 0;
                         $rel_count = 0;
                         foreach ($rel_fields as $rel_field) {
                             // for each relation field in the masterpage
                             if ($rel_field['op'] !== '=' && $rel_field['op'] !== '!=') {
                                 die("ERROR: Tag \"" . $node->name . "\": custom field '" . $FUNCS->cleanXSS($rel_field['name']) . "' does not support '" . $rel_field['op'] . "' operator");
                             }
                             //  id of the field itself
                             if ($rel_field_tpl != $masterpage) {
                                 if (!$rel_field_tpl_id) {
                                     // get template_id of masterpage
                                     $rs = $DB->select(K_TBL_TEMPLATES, array('id'), "name='" . $DB->sanitize($rel_field_tpl) . "'");
                                     if (count($rs)) {
                                         $rel_field_tpl_id = $rs[0]['id'];
                                     } else {
                                         die("ERROR: Tag \"" . $node->name . "\": masterpage '" . $FUNCS->cleanXSS($rel_field_tpl) . "' not found for custom field '" . $FUNCS->cleanXSS($rel_field['name']) . "'");
                                     }
                                 }
                                 // get relation_field_id using template_id
                                 $rs = $DB->select(K_TBL_FIELDS, array('*'), "template_id='" . $DB->sanitize($rel_field_tpl_id) . "'" . $FUNCS->gen_sql(implode(",", $arr_rel_types), 'k_type') . " AND name='" . $DB->sanitize($rel_field['name']) . "'");
                                 if (count($rs)) {
                                     $arr_rel_fields[$rel_field_tpl][$rel_count]['id'] = $rs[0]['id'];
                                 } else {
                                     die("ERROR: Tag \"" . $node->name . "\": custom field '" . $FUNCS->cleanXSS($rel_field['name']) . "' not defined in " . $FUNCS->cleanXSS($rel_field_tpl));
                                 }
                             }
                             // ids of the field's values
                             if (count($rel_field['val'])) {
                                 // .. check if values are already ids (e.g. 'id(373,372,371)')
                                 $val1 = trim($rel_field['val'][0]);
                                 $val2 = trim($rel_field['val'][count($rel_field['val']) - 1]);
                                 if (stripos($val1, 'id(') === 0 && substr($val2, -1) == ')') {
                                     $val1 = substr($val1, 3);
                                     $arr_rel_fields[$rel_field_tpl][$rel_count]['val'][0] = $val1;
                                     if (count($rel_field['val']) == 1) {
                                         $val2 = $val1;
                                     }
                                     $val2 = substr($val2, 0, -1);
                                     $arr_rel_fields[$rel_field_tpl][$rel_count]['val'][count($rel_field['val']) - 1] = $val2;
                                 } else {
                                     if ($rel_field_tpl != $masterpage) {
                                         // reverse related - the related pages should belong to this very template
                                     } else {
                                         // get the related template
                                         $obj_field = new Relation($rel_field['related_field'], new KError('dummy'), new KError('dummy'));
                                         $related_template_name = trim($obj_field->masterpage);
                                         unset($obj_field);
                                         $rs = $DB->select(K_TBL_TEMPLATES, array('id'), "name='" . $DB->sanitize($related_template_name) . "'");
                                         if (count($rs)) {
                                             $rel_field_tpl_id = $rs[0]['id'];
                                         } else {
                                             die("ERROR: Tag \"" . $node->name . "\": masterpage '" . $FUNCS->cleanXSS($related_template_name) . "' not found for related field '" . $FUNCS->cleanXSS($rel_field['name']) . "'");
                                         }
                                     }
                                     // convert related page_names to ids (if not 'ANY')
                                     if (count($rel_field['val']) == 1 && trim($rel_field['val'][0]) == 'ANY') {
                                         $arr_rel_fields[$rel_field_tpl][$rel_count]['skip_ids'] = 1;
                                         $arr_rel_fields[$rel_field_tpl][$rel_count]['val'] = array();
                                     } else {
                                         $str_names = implode(",", $rel_field['val']);
                                         $rs = $DB->select(K_TBL_PAGES, array('id'), "template_id='" . $DB->sanitize($rel_field_tpl_id) . "'" . $FUNCS->gen_sql($str_names, 'page_name'));
                                         $arr_vals = array();
                                         foreach ($rs as $rec) {
                                             $arr_vals[] = $rec['id'];
                                         }
                                         $arr_rel_fields[$rel_field_tpl][$rel_count]['val'] = $arr_vals;
                                     }
                                 }
                             }
                             $rel_count++;
                         }
                     }
                 }
                 // resolve custom_fields used as order_by
                 foreach ($arr_custom_orderby as $k => $v) {
                     $cf_found = 0;
                     for ($i = 0; $i < count($rs_cf); $i++) {
                         $f = $rs_cf[$i];
                         if ($f['name'] == $k) {
                             // 'relation' field?
                             if (in_array($f['k_type'], $arr_rel_types)) {
                                 unset($arr_orderby[$v]);
                                 unset($arr_order[$v]);
                                 continue 2;
                             }
                             $cf_found = 1;
                             if (!array_key_exists($f['name'], $arr_tables)) {
                                 $arr_tables[$f['name']]['id'] = $f['id'];
                                 $arr_tables[$f['name']]['tbl_name'] = $f['search_type'] == 'text' ? K_TBL_DATA_TEXT : K_TBL_DATA_NUMERIC;
                                 $arr_tables[$f['name']]['alias'] = sprintf("t%d", $count++);
                             }
                             $arr_orderby[$v] = $arr_tables[$f['name']]['alias'] . "." . ($f['search_type'] == 'text' ? 'search_value' : 'value');
                             break;
                         }
                     }
                     if (!$cf_found) {
                         die("ERROR: Unknown orderby clause \"" . $FUNCS->cleanXSS($k) . "\"");
                     }
                 }
                 // generate sql to query custom fields
                 if (count($arr_rel_fields)) {
                     if (count($arr_rel_fields) > 1) {
                         $distinct = 1;
                     }
                     $rel_suffix = 1;
                     foreach ($arr_rel_fields as $rel_field_tpl => $rel_fields) {
                         // for each masterpage
                         foreach ($rel_fields as $rel_field) {
                             // for each relation field in the masterpage
                             if (count($rel_field['val']) > 1 || $rel_field['skip_ids'] && $rel_field['op'] == '=') {
                                 $distinct = 1;
                             }
                             $rel_tbl = 'rel' . $rel_suffix;
                             $join_field = $rel_field_tpl == $masterpage ? 'pid' : 'cid';
                             $where_field = $rel_field_tpl == $masterpage ? 'cid' : 'pid';
                             if ($rel_field['is_aggregate']) {
                                 $query_fields[] = 'count(p.id) as k_rel_count';
                                 $group_by[] = 'p.id';
                                 foreach ($arr_rel_fields[$rel_field_tpl] as $rfld) {
                                     if ($rfld['id'] == $rel_field['id'] && !$rfld['is_aggregate']) {
                                         continue 2;
                                         // skip if table already joined
                                     }
                                 }
                             }
                             if ($rel_field['op'] == '!=') {
                                 // Negation in N:M relation requires special consideration
                                 $str_ids = $FUNCS->gen_sql(implode(",", $rel_field['val']), "{$where_field}", 1);
                                 if ($str_ids || $rel_field['skip_ids']) {
                                     $rs = $DB->select(K_TBL_RELATIONS, array("{$join_field} as id"), "fid='" . $DB->sanitize($rel_field['id']) . "'" . $str_ids, 1);
                                     $arr_vals = array();
                                     foreach ($rs as $rec) {
                                         $arr_vals[] = $rec['id'];
                                     }
                                     if (count($arr_vals)) {
                                         $sql .= " \r\n" . 'AND p.id NOT IN(' . implode(",", $arr_vals) . ')';
                                     }
                                 }
                             } else {
                                 $str_ids = '';
                                 if (!$rel_field['is_aggregate'] && !$rel_field['skip_ids']) {
                                     $str_ids = $FUNCS->gen_sql(implode(",", $rel_field['val']), "{$rel_tbl}.{$where_field}", 1);
                                     if (!$str_ids) {
                                         $str_ids = " AND {$rel_tbl}.{$where_field}=-1";
                                     }
                                 }
                                 $query_table .= "\r\n inner join " . K_TBL_RELATIONS . " {$rel_tbl} on {$rel_tbl}.{$join_field} = p.id";
                                 $sql .= " \r\n" . $str_ids . " AND {$rel_tbl}.fid=" . $DB->sanitize($rel_field['id']);
                             }
                             $rel_suffix++;
                         }
                     }
                 }
                 if (count($arr_tables)) {
                     $where = ' AND ' . "\r\n" . '(' . "\r\n";
                     $sep = '';
                     foreach ($arr_tables as $k => $tbl) {
                         $join .= ' inner join ' . $tbl['tbl_name'] . ' ' . $tbl['alias'] . ' on ' . $tbl['alias'] . '.page_id = p.id' . "\r\n";
                         $where .= $sep . $tbl['alias'] . '.field_id=' . $DB->sanitize($tbl['id']);
                         $sep = ' AND' . "\r\n";
                     }
                     $where .= "\r\n" . ')' . "\r\n";
                 }
                 if (count($arr_custom_fields)) {
                     // skip processed custom_fields
                     $arr_tmp = $arr_custom_fields;
                     $arr_custom_fields = array();
                     foreach ($arr_tmp as $cf) {
                         if ($cf['processed']) {
                             continue;
                         }
                         $arr_custom_fields[] = $cf;
                     }
                     if (count($arr_custom_fields)) {
                         $where .= ' AND ' . "\r\n" . '(' . "\r\n";
                         $sep = '';
                         foreach ($arr_custom_fields as $cf) {
                             $where .= $sep;
                             if (count($cf['val']) > 1) {
                                 $where .= '(';
                             }
                             $sep2 = '';
                             foreach ($cf['val'] as $val) {
                                 $where .= $sep2 . $cf['table_name'] . '.' . $cf['field_name'] . ' ' . $cf['op'] . ' \'' . $val . '\'';
                                 $sep2 = ' OR ';
                             }
                             if (count($cf['val']) > 1) {
                                 $where .= ')';
                             }
                             $sep = ' AND' . "\r\n";
                         }
                         $where .= "\r\n" . ')' . "\r\n";
                     }
                 }
                 // append to original sql
                 $query_table .= "\r\n" . $join;
                 $sql .= $where;
             }
         }
         // orderby
         $sep = '';
         for ($i = 0; $i < count($arr_orderby); $i++) {
             $orderby = $arr_orderby[$i];
             if (in_array($orderby, $arr_canonical_orderby)) {
                 $orderby = 'p.' . $orderby;
             }
             if ($orderby == 'random') {
                 if ($paginate) {
                     if (!session_id()) {
                         @session_start();
                     }
                     if (empty($_SESSION['k_seed'])) {
                         $_SESSION['k_seed'] = rand();
                     }
                     $orderby = 'RAND(' . $_SESSION['k_seed'] . ')';
                 } else {
                     $orderby = 'RAND()';
                 }
                 $PAGE->no_cache = 1;
             }
             $order_sql .= $sep . $DB->sanitize($orderby);
             $order = $arr_order[$i];
             $order_sql .= " " . $DB->sanitize($order);
             $sep = ", ";
         }
     } elseif ($mode == 1) {
         // called from 'Search' tag
         $keywords = trim($keywords);
         if (!strlen($keywords)) {
             return;
         }
         // add the '+' for boolean search
         $sep = "";
         $keywords = explode(' ', $keywords);
         foreach ($keywords as $kw) {
             $kw = trim($kw);
             if (!$kw) {
                 continue;
             }
             $bool_keywords .= $sep . "+" . $kw;
             $sep = " ";
         }
         $query_table = K_TBL_FULLTEXT . " cf\r\n                                inner join  " . K_TBL_PAGES . " cp on cp.id=cf.page_id\r\n                                inner join " . K_TBL_TEMPLATES . " ct on ct.id=cp.template_id";
         $score_field = "((MATCH(cf.content) AGAINST ('" . $DB->sanitize($bool_keywords) . "') * 1) + (MATCH(cf.title) AGAINST ('" . $DB->sanitize($bool_keywords) . "') * 1.25)) as score";
         $query_fields = array('cp.template_id', 'cp.id', 'cf.title', 'cf.content', $score_field);
         $count_query_field = 'cf.page_id';
         $sql = " ((MATCH(cf.content) AGAINST ('" . $DB->sanitize($bool_keywords) . "' IN BOOLEAN MODE) * 1) + (MATCH(cf.title) AGAINST ('" . $DB->sanitize($bool_keywords) . "' IN BOOLEAN MODE) * 1.25))";
         // search within which template(s)?
         if ($masterpage) {
             // masterpage="NOT blog.php, testimonial.php"
             $sql .= $FUNCS->gen_sql($masterpage, 'ct.name');
         }
         if ($hide_future_entries) {
             $sql .= " AND cp.publish_date < '" . $FUNCS->get_current_desktop_time() . "'";
         }
         $sql .= " AND NOT cp.publish_date = '0000-00-00 00:00:00'";
         $sql .= " AND cp.access_level<='" . $AUTH->user->access_level . "'";
         $sql .= " AND ct.executable=1";
         $order_sql = 'score DESC';
     } elseif ($mode == 2) {
         // called from 'Comments' tag
         $query_table = K_TBL_COMMENTS . " cc";
         $query_table .= "\n inner join " . K_TBL_TEMPLATES . " ct on ct.id=cc.tpl_id";
         $query_table .= "\n inner join " . K_TBL_PAGES . " cp on cp.id=cc.page_id";
         $query_fields = array('cp.page_title, cp.page_name, ct.name tpl_name, ct.clonable, cc.*');
         $count_query_field = 'cc.id';
         $sql = "cc.approved=1";
         // comments of which template(s)?
         if ($masterpage) {
             // masterpage="NOT blog.php, testimonial.php"
             $sql .= $FUNCS->gen_sql($masterpage, 'ct.name');
         }
         // comments of which page(s)?
         if ($page_id) {
             $sql .= $FUNCS->gen_sql($page_id, 'cc.page_id', 1);
         }
         if ($page_name) {
             //$query_table .= "\n inner join couch_pages cp on cp.id=cc.page_id";
             $sql .= $FUNCS->gen_sql($page_name, 'cp.page_name');
         }
         $sql .= " AND NOT cp.publish_date = '0000-00-00 00:00:00'";
         // Order?
         $order = strtolower(trim($order));
         if ($order != 'desc' && $order != 'asc') {
             $order = 'desc';
         }
         $order_sql = "cc.date " . $order;
         // if being invoked on a page which has been loaded via comment_id,
         // need to calculate the page (of paginated comments) where this comment will appear
         if ($PAGE->comment_id && $page_id == $PAGE->id) {
             $parent_id = $PAGE->id;
             $tmp_sql = "page_id='" . $DB->sanitize($parent_id) . "' and ";
             $tmp_sql .= "approved=1 and ";
             if ($order == 'desc') {
                 $tmp_sql .= "date>='" . $DB->sanitize($PAGE->comment_date) . "' ";
             } else {
                 $tmp_sql .= "date<='" . $DB->sanitize($PAGE->comment_date) . "' ";
             }
             $rs = $DB->select(K_TBL_COMMENTS, array('count(id) as cnt'), $tmp_sql);
             $total_rows = $rs[0]['cnt'];
             $total_rows -= $offset;
             if ($total_rows > $limit) {
                 $PAGE->comment_page = ceil($total_rows / $limit);
             }
             // no need to process further. Redirection is imminent.
             return;
         }
     }
     // end mode==2 (comments)
     // limit
     $limit_sql = sprintf("%d, %d", ($pgn_pno - 1) * $limit + $offset, $limit);
     // We have the sql query here..
     if ($mode == 5) {
         // raw query .. called from 'query' tag
         $raw_sql = rtrim($raw_sql, ' ;');
         $pattern = '/^(\\s*\\(?\\s*)(select\\s)/i';
         $replacement = '${1}${2}SQL_CALC_FOUND_ROWS ';
         // is SELECT?
         if (!preg_match($pattern, $raw_sql)) {
             ob_end_clean();
             die("ERROR: Tag \"query\" can process only SELECT statements");
         }
         $raw_sql = preg_replace($pattern, $replacement, $raw_sql);
         // retained for backward compatibility where
         // ORDER BY clause containing calculated fields could mess up the count(*) query.
         // For such cases the 'orderby' param was used to provide the raw ORDER BY statement.
         // Now, the raw query itself can contain any orderby clause.
         $orderby = trim($orderby);
         if ($orderby) {
             if (!preg_match("/^order\\s/is", $orderby)) {
                 $raw_sql .= ' ORDER BY';
             }
             $raw_sql .= ' ' . $orderby;
         }
         $raw_sql = rtrim($raw_sql, ' ;');
         $raw_sql .= ' LIMIT ' . $limit_sql;
         $rs = $DB->raw_select($raw_sql);
         // get count for pagination
         $rs2 = $DB->raw_select('SELECT FOUND_ROWS() as cnt;');
         $total_rows = $rs2[0]['cnt'];
         // return if only count asked for
         if ($count_only) {
             return $total_rows;
         }
         if ($fetch_pages && count($rs)) {
             // do some sanity checks to make sure the query can fetch pages like cms:pages does
             if (!(array_key_exists('id', $rs[0]) && array_key_exists('template_id', $rs[0]))) {
                 ob_end_clean();
                 die("ERROR: 'fetch_pages' param of tag \"query\" requires 'id' and 'template_id' fields in the SQL statement");
             }
         }
     } else {
         // HOOK: alter_page_tag_query
         // called routine should check for $node->name to know which tag is being executed.
         // rs_tpl (masterpage info) will be filled only for mode 0 (i.e. pages/related_pages/reverse_related_pages tags)
         $FUNCS->dispatch_event('alter_page_tag_query', array(&$distinct, &$count_query_field, &$count_query_field_as, &$query_fields, &$query_table, &$sql, &$group_by, &$having, &$order_sql, &$limit_sql, &$mode, $params, $node, $rec_tpl));
         $orig_sql = $sql;
         $group_by = array_filter(array_map("trim", $group_by));
         if (count($group_by)) {
             $group_by = 'GROUP BY ' . implode(",", $group_by);
             $sql .= "\r\n" . $group_by;
             $distinct = 0;
         } else {
             $group_by = '';
         }
         $having = array_filter(array_map("trim", $having));
         if (count($having)) {
             $having = 'HAVING ' . implode(" AND ", $having);
             $sql .= "\r\n" . $having;
         } else {
             $having = '';
         }
         // first query for pagination
         $rs = $DB->select($query_table, array('count(' . $count_query_field . ') as ' . $count_query_field_as), $sql, $distinct);
         $total_rows = $rs[0][$count_query_field_as];
         // Return if only count asked for
         if ($count_only) {
             return $total_rows;
         }
         // actual query
         if ($return_sql) {
             $sep = $fields = $html = '';
             foreach ($query_fields as $field) {
                 $fields .= $sep . $field;
                 $sep = ', ';
             }
             if ($return_sql == 2) {
                 // return query parts
                 $CTX->set('k_sql_distinct', $distinct);
                 // distinct
                 $CTX->set('k_sql_select', $fields);
                 // fields
                 $CTX->set('k_sql_from', $query_table);
                 // tables
                 $CTX->set('k_sql_where', $orig_sql);
                 // where
                 $CTX->set('k_sql_group_by', $group_by);
                 // group_by
                 $CTX->set('k_sql_having', $having);
                 // having
                 $CTX->set('k_sql_order', $order_sql);
                 // order
                 $CTX->set('k_sql_limit', $limit_sql);
                 // limit
                 foreach ($node->children as $child) {
                     $html .= $child->get_HTML();
                 }
             } else {
                 // return complete query
                 $html = $distinct ? 'SELECT DISTINCT ' : 'SELECT ';
                 $html .= $fields . ' FROM ' . $query_table . ' WHERE ' . $sql . ' ORDER BY ' . $order_sql . ' LIMIT ' . $limit_sql;
             }
             return $html;
         } else {
             $sql .= ' ORDER BY ' . $order_sql;
             $sql .= ' LIMIT ' . $limit_sql;
             $rs = $DB->select($query_table, $query_fields, $sql, $distinct);
         }
     }
     // If only ids asked for, return with them
     if ($ids_only) {
         $sep = '';
         $html = '';
         foreach ($rs as $rec) {
             $html .= $sep . $rec['id'];
             $sep = ',';
         }
         return $html;
     }
     // if called from calendar tag, return results.
     if ($mode == 3) {
         return $rs;
     }
     $total_rows -= $offset;
     $total_pages = ceil($total_rows / $limit);
     $count = count($rs);
     $page_link = strlen($base_link) ? $base_link : K_SITE_URL . $PAGE->link;
     // append querystring params, if any
     $sep = '';
     // HOOK: skip_qs_params_in_paginator
     $skip_qs = array();
     $FUNCS->dispatch_event('skip_qs_params_in_paginator', array(&$skip_qs));
     foreach ($_GET as $qk => $qv) {
         if ($qk == 'p' || $qk == 'f' || $qk == 'd' || $qk == 'fname' || $qk == 'pname' || $qk == '_nr_') {
             continue;
         }
         if ($qk == $qs_param) {
             continue;
         }
         //'pg' or 'comments_pg'
         if (in_array($qk, $skip_qs)) {
             continue;
         }
         if (is_array($qv)) {
             //checkboxes
             foreach ($qv as $qvv) {
                 $qs .= $sep . $qk . '[]=' . urlencode($qvv);
                 $sep = '&';
             }
         } else {
             $qs .= $sep . $qk . '=' . urlencode($qv);
             $sep = '&';
         }
     }
     if ($qs) {
         $page_link .= strpos($page_link, '?') === false ? '?' : '&';
         $page_link .= $qs;
     }
     if ($total_rows > $limit) {
         $paginated = 1;
         $sep = strpos($page_link, '?') === false ? '?' : '&';
         // 'Prev' link
         if ($pgn_pno > 1) {
             if ($pgn_pno == 2) {
                 $pgn_prev_link = $page_link;
             } else {
                 $pgn_prev_link = sprintf("%s%s%s=%d", $page_link, $sep, $qs_param, $pgn_pno - 1);
             }
         }
         // 'Next' link
         if ($pgn_pno < $total_pages) {
             $pgn_next_link = sprintf("%s%s%s=%d", $page_link, $sep, $qs_param, $pgn_pno + 1);
         }
         // Current paginated link
         $pgn_cur_link = $pgn_pno == 1 ? $page_link : sprintf("%s%s%s=%d", $page_link, $sep, $qs_param, $pgn_pno);
     }
     if ($count) {
         for ($x = 0; $x < $count; $x++) {
             $rec = $rs[$x];
             if ($mode == 2) {
                 //Comments
                 $CTX->set('k_comment_id', $rec['id']);
                 $CTX->set('k_comment_page_id', $rec['page_id']);
                 $CTX->set('k_comment_page_title', $rec['page_title']);
                 $CTX->set('k_comment_page_name', $rec['page_name']);
                 $CTX->set('k_comment_template_name', $rec['tpl_name']);
                 $CTX->set('k_comment_author_id', $rec['user_id']);
                 // 0 for unregistered
                 $CTX->set('k_comment_author', $rec['name']);
                 $CTX->set('k_comment_author_email', $rec['email']);
                 $CTX->set('k_comment_author_website', $rec['link']);
                 $CTX->set('k_comment_date', $rec['date']);
                 $CTX->set('k_comment', $rec['data']);
                 $CTX->set('k_comment_anchor', "comment-" . $rec['id']);
                 //anchor name
                 $parent_link = K_PRETTY_URLS ? $FUNCS->get_pretty_template_link($rec['tpl_name']) : $rec['tpl_name'];
                 $CTX->set('k_comment_link', K_SITE_URL . $parent_link . "?comment=" . $rec['id']);
             } else {
                 // pages, search, query
                 if ($mode == 5) {
                     // raw query
                     $CTX->reset();
                     $rec_vars = array();
                     foreach ($rec as $rec_k => $rec_v) {
                         $rec_vars[$rec_k] = $rec_v;
                     }
                     $CTX->set_all($rec_vars);
                 }
                 if ($mode != 5 || $mode == 5 && $fetch_pages) {
                     //Pages & Search
                     $pg = new KWebpage($rec['template_id'], $rec['id'], 0, 0, $skip_custom_fields);
                     if ($pg->error) {
                         ob_end_clean();
                         die('ERROR: ' . $pg->err_msg);
                     }
                     $pg->set_context();
                     $pg->destroy();
                     // release the memory held by fields
                     if ($aggregate_by) {
                         $CTX->set('k_rel_count', $rec['k_rel_count']);
                     }
                 }
                 if ($mode == 1) {
                     // Search
                     if ($pg->tpl_is_clonable) {
                         $hilited = $FUNCS->hilite_search_terms($keywords, $rec['title'], 1);
                     } else {
                         $hilited = $pg->tpl_title ? $pg->tpl_title : $pg->tpl_name;
                     }
                     $CTX->set('k_search_title', $hilited);
                     $CTX->set('k_search_content', $rec['content']);
                     //entire content searched
                     $hilited = $FUNCS->hilite_search_terms($keywords, $rec['content']);
                     $CTX->set('k_search_excerpt', $hilited);
                     //hilighted excerpt of searched content
                 }
             }
             // Pagination related variables
             $first_record_on_page = $limit * ($pgn_pno - 1) + $startcount;
             $total_records_on_page = $count < $limit ? $count : $limit;
             $CTX->set('k_count', $x + $startcount);
             $CTX->set('k_total_records', $total_rows);
             $CTX->set('k_total_records_on_page', $total_records_on_page);
             $CTX->set('k_current_record', $first_record_on_page + $x);
             $CTX->set('k_absolute_count', $first_record_on_page + $x);
             //same as current record
             $CTX->set('k_record_from', $first_record_on_page);
             $CTX->set('k_record_to', $first_record_on_page + $total_records_on_page - 1);
             $CTX->set('k_total_pages', $total_pages);
             $CTX->set('k_current_page', $pgn_pno);
             $CTX->set('k_paginate_limit', $limit);
             if ($x == 0) {
                 $CTX->set('k_paginated_top', 1);
             } else {
                 $CTX->set('k_paginated_top', 0);
             }
             if ($x == $count - 1) {
                 $CTX->set('k_paginated_bottom', 1);
             } else {
                 $CTX->set('k_paginated_bottom', 0);
             }
             if ($paginate && $paginated) {
                 $CTX->set('k_paginator_required', 1);
                 $CTX->set('k_page_being_paginated', $page_link);
                 $CTX->set('k_qs_param', $qs_param);
                 $CTX->set('k_paginate_link_next', $pgn_next_link);
                 $CTX->set('k_paginate_link_prev', $pgn_prev_link);
                 $CTX->set('k_paginate_link_cur', $pgn_cur_link);
             } else {
                 $CTX->set('k_paginator_required', 0);
                 $CTX->set('k_paginate_link_next', '');
                 $CTX->set('k_paginate_link_prev', '');
                 $CTX->set('k_paginate_link_cur', '');
             }
             // HOOK: alter_page_tag_context
             $FUNCS->dispatch_event('alter_page_tag_context', array($rec, $mode, $params, $node, $rec_tpl));
             // call the children
             foreach ($node->children as $child) {
                 $html .= $child->get_HTML();
             }
         }
     } else {
         // find and execute 'no_results' tag
         $html = '';
         foreach ($node->children as $child) {
             if ($child->type == K_NODE_TYPE_CODE && $child->name == 'no_results') {
                 // call the children of no_results
                 foreach ($child->children as $grand_child) {
                     $html .= $grand_child->get_HTML();
                 }
                 break;
             }
         }
     }
     return $html;
 }
 function db_delete($params, $node)
 {
     global $FUNCS, $DB, $CTX;
     if (count($node->children)) {
         die("ERROR: Tag \"" . $node->name . "\" is a self closing tag");
     }
     // handle params
     extract($FUNCS->get_named_vars(array('masterpage' => '', 'page_id' => '', 'invalidate_cache' => '0'), $params));
     $masterpage = trim($masterpage);
     if (!$masterpage) {
         die("ERROR: Tag \"" . $node->name . "\": 'masterpage' attribute missing");
     }
     $page_id = isset($page_id) && $FUNCS->is_non_zero_natural($page_id) ? (int) $page_id : null;
     if (!$page_id) {
         die("ERROR: Tag \"" . $node->name . "\": 'page_id' required");
     }
     // get down to business
     $rs = $DB->select(K_TBL_TEMPLATES, array('id', 'clonable'), "name='" . $DB->sanitize($masterpage) . "'");
     if (!count($rs)) {
         die("ERROR: Tag \"" . $node->name . "\" - masterpage does not exist");
     }
     if (!$rs[0]['clonable']) {
         die("ERROR: Tag \"" . $node->name . "\" - cannot delete non-clonable template");
     }
     $pg = new KWebpage($rs[0]['id'], $page_id);
     if ($pg->error) {
         die("ERROR: Tag \"" . $node->name . "\" - " . $pg->err_msg);
     }
     // delete..
     $pg->delete();
     // if we are here, delete was successful (script would have died otherwise)
     $pg->destroy();
     unset($pg);
     if ($invalidate_cache) {
         $FUNCS->invalidate_cache();
     }
 }
Example #3
0
function create_cloned_page($tpl_id, $fid, $cid, $rid, $page_title, $img_url)
{
    global $FUNCS;
    // create a single cloned page
    $pg = new KWebpage($tpl_id, -1);
    if ($pg->error) {
        return $FUNCS->raise_error($pg->err_msg);
    }
    // fill fields
    $f =& $pg->_fields['k_page_title'];
    // title
    $f->store_posted_changes($page_title);
    unset($f);
    $f =& $pg->_fields['k_page_folder_id'];
    // folder
    $f->store_posted_changes($fid);
    unset($f);
    $f =& $pg->_fields['k_publish_date'];
    // publish date
    $f->store_posted_changes($FUNCS->get_current_desktop_time());
    unset($f);
    // find the image field (set 'required' off for all other fields as we go)
    // also find the relation field if specified
    if ($cid && $rid) {
        $find_related = 1;
    }
    for ($x = 0; $x < count($pg->fields); $x++) {
        $f =& $pg->fields[$x];
        if (!$f->system) {
            if ($f->k_type == 'image' && $f->name == 'gg_image') {
                $f->store_posted_changes($img_url);
            }
            // related?
            if ($find_related) {
                if ($f->id == $rid && $f->k_type == 'relation') {
                    $f->store_posted_changes($cid);
                    $find_related = 0;
                }
            }
        }
        $f->required = 0;
        unset($f);
    }
    // save
    $errors = $pg->save();
    if ($errors) {
        $sep = '';
        if (count($errors)) {
            $str_err = '';
            for ($x = 0; $x < count($pg->fields); $x++) {
                $f =& $pg->fields[$x];
                if ($f->err_msg) {
                    $str_err .= $sep . '<b>' . $f->name . ':</b> ' . $f->err_msg;
                    $sep = '<br/>';
                }
            }
            return $FUNCS->raise_error($str_err);
        }
    }
    $page_id = $pg->id;
    $pg->destroy();
    unset($pg);
    return $page_id;
}