/** * Counts the number of rows in a table. * * @param array $atts * @param string $atts['table'] MySQL table name. * @param string $atts['where'] MySQL WHERE clause. */ function jmd_count($atts) { extract(lAtts(array('table' => '', 'where' => ''), $atts)); if ($where != '') { $where = ' where ' . $where; } return getThing("select count(*) from " . safe_pfx($table) . " {$where}"); }
function jmd_admin_js() { global $event; if ($rs = getRows('select name, js from ' . safe_pfx('txp_js'))) { foreach ($rs as $row) { if ($row['name'] === 'default' || $row['name'] === $event) { $out[] = base64_decode($row['js']); } } echo tag(join("\n", $out), 'script', ' type="text/javascript"'); } }
function cnk_ver_do_deinstall() { $sql = "ALTER TABLE " . safe_pfx('txp_form') . " DROP `file_mod_time`;ALTER TABLE " . safe_pfx('txp_page') . " DROP `file_mod_time`;ALTER TABLE " . safe_pfx('txp_css') . " DROP `file_mod_time`;"; if (!cnk_ver_batch_query($sql)) { return false; } else { return true; } }
private function getEntry() { $row = getRow("SELECT last_mod, contents FROM " . safe_pfx('jmd_wiki_events') . " WHERE title = '{$this->day}'"); if ($row) { $diff = str_replace('-', '', $this->currentDate) - str_replace('-', '', $row['last_mod']); // if the content is at least two months old, update if ($diff > 200) { return $this->setEntry($update = 1); } else { return $row['contents']; } } }
function sec_section_list($message = '') { global $event, $section_list_pageby; pagetop(gTxt('tab_sections'), $message); extract(gpsa(array('page', 'sort', 'dir', 'crit', 'search_method'))); if ($sort === '') { $sort = get_pref('section_sort_column', 'time'); } if ($dir === '') { $dir = get_pref('section_sort_dir', 'desc'); } $dir = $dir == 'asc' ? 'asc' : 'desc'; switch ($sort) { case 'title': $sort_sql = 'title ' . $dir; break; case 'page': $sort_sql = 'page ' . $dir; break; case 'css': $sort_sql = 'css ' . $dir; break; case 'in_rss': $sort_sql = 'in_rss ' . $dir; break; case 'on_frontpage': $sort_sql = 'on_frontpage ' . $dir; break; case 'searchable': $sort_sql = 'searchable ' . $dir; break; case 'article_count': $sort_sql = 'article_count ' . $dir; break; default: $sort_sql = 'name ' . $dir; break; } set_pref('section_sort_column', $sort, 'section', 2, '', 0, PREF_PRIVATE); set_pref('section_sort_dir', $dir, 'section', 2, '', 0, PREF_PRIVATE); $switch_dir = $dir == 'desc' ? 'asc' : 'desc'; $criteria = 1; if ($search_method and $crit != '') { $verbatim = preg_match('/^"(.*)"$/', $crit, $m); $crit_escaped = doSlash($verbatim ? $m[1] : str_replace(array('\\', '%', '_', '\''), array('\\\\', '\\%', '\\_', '\\\''), $crit)); $critsql = $verbatim ? array('name' => "name = '{$crit_escaped}'", 'title' => "title = '{$crit_escaped}'", 'page' => "page = '{$crit_escaped}'", 'css' => "css = '{$crit_escaped}'", 'in_rss' => "in_rss = '{$crit_escaped}'", 'on_frontpage' => "on_frontpage = '{$crit_escaped}'", 'searchable' => "searchable = '{$crit_escaped}'") : array('name' => "name like '%{$crit_escaped}%'", 'title' => "title like '%{$crit_escaped}%'", 'page' => "page like '%{$crit_escaped}%'", 'css' => "css like '%{$crit_escaped}%'", 'in_rss' => "in_rss = '{$crit_escaped}'", 'on_frontpage' => "on_frontpage = '{$crit_escaped}'", 'searchable' => "searchable = '{$crit_escaped}'"); if (array_key_exists($search_method, $critsql)) { $criteria = $critsql[$search_method]; $limit = 500; } else { $search_method = ''; $crit = ''; } } else { $search_method = ''; $crit = ''; } $criteria .= callback_event('admin_criteria', 'section_list', 0, $criteria); $total = safe_count('txp_section', "{$criteria}"); echo '<h1 class="txp-heading">' . gTxt('tab_sections') . sp . popHelp('section_category') . '</h1>'; echo '<div id="' . $event . '_control" class="txp-control-panel">'; echo graf(sLink('section', 'section_edit', gTxt('create_section')), ' class="txp-buttons"'); echo n . '<form id="default_section_form" name="default_section_form" method="post" action="index.php" class="async">'; echo graf('<label>' . gTxt('default_write_section') . '</label>' . sp . popHelp('section_default') . n . section_select_list()) . eInput('section') . sInput('section_set_default'); echo '</form>'; if ($total < 1) { if ($criteria != 1) { echo n . section_search_form($crit, $search_method) . n . graf(gTxt('no_results_found'), ' class="indicator"') . '</div>'; } return; } $limit = max($section_list_pageby, 15); list($page, $offset, $numPages) = pager($total, $limit, $page); echo n . section_search_form($crit, $search_method) . '</div>'; $rs = safe_rows_start('*, (SELECT count(*) FROM ' . safe_pfx('textpattern') . ' articles WHERE articles.Section = txp_section.name) AS article_count', 'txp_section', "{$criteria} order by {$sort_sql} limit {$offset}, {$limit}"); if ($rs) { echo n . '<div id="' . $event . '_container" class="txp-container">'; echo n . n . '<form action="index.php" id="section_form" class="multi_edit_form" method="post" name="longform">' . n . '<div class="txp-listtables">' . n . n . startTable('', '', 'txp-list') . n . '<thead>' . n . tr(n . hCell(fInput('checkbox', 'select_all', 0, '', '', '', '', '', 'select_all'), '', ' title="' . gTxt('toggle_all_selected') . '" class="multi-edit"') . n . column_head('name', 'name', 'section', true, $switch_dir, $crit, $search_method, ('name' == $sort ? "{$dir} " : '') . 'name') . n . column_head('title', 'title', 'section', true, $switch_dir, $crit, $search_method, ('title' == $sort ? "{$dir} " : '') . 'title') . n . column_head('page', 'page', 'section', true, $switch_dir, $crit, $search_method, ('page' == $sort ? "{$dir} " : '') . 'page') . n . column_head('css', 'css', 'section', true, $switch_dir, $crit, $search_method, ('css' == $sort ? "{$dir} " : '') . 'style') . n . column_head('on_front_page', 'on_frontpage', 'section', true, $switch_dir, $crit, $search_method, ('on_frontpage' == $sort ? "{$dir} " : '') . 'section_detail frontpage') . n . column_head('syndicate', 'in_rss', 'section', true, $switch_dir, $crit, $search_method, ('in_rss' == $sort ? "{$dir} " : '') . 'section_detail syndicate') . n . column_head('include_in_search', 'searchable', 'section', true, $switch_dir, $crit, $search_method, ('searchable' == $sort ? "{$dir} " : '') . 'section_detail searchable') . n . column_head('articles', 'article_count', 'section', true, $switch_dir, $crit, $search_method, ('article_count' == $sort ? "{$dir} " : '') . 'section_detail article_count')) . n . '</thead>'; echo '<tbody>'; while ($a = nextRow($rs)) { extract($a, EXTR_PREFIX_ALL, 'sec'); $is_default_section = $sec_name == 'default'; $edit_url = '?event=section' . a . 'step=section_edit' . a . 'name=' . $sec_name . a . 'sort=' . $sort . a . 'dir=' . $dir . a . 'page=' . $page . a . 'search_method=' . $search_method . a . 'crit=' . $crit; $page_url = '?event=page' . a . 'name=' . $sec_page; $style_url = '?event=css' . a . 'name=' . $sec_css; $articles = $sec_article_count > 0 ? href($sec_article_count, '?event=list' . a . 'search_method=section' . a . 'crit="' . txpspecialchars($sec_name) . '"', ' title="' . gTxt('article_count', array('{num}' => $sec_article_count)) . '"') : ($is_default_section ? '' : '0'); // $can_delete = ($sec_name != 'default' && $sec_article_count == 0); $parms = array('step' => 'section_toggle_option', 'thing' => $sec_name); echo tr(td(fInput('checkbox', 'selected[]', $sec_name), '', 'multi-edit') . td('<a href="' . $edit_url . '" title="' . gTxt('edit') . '">' . $sec_name . '</a>' . n . '<span class="section_detail">[<a href="' . hu . $sec_name . '">' . gTxt('view') . '</a>]</span>', '', 'name') . td(txpspecialchars($sec_title), '', 'title') . td('<a href="' . $page_url . '" title="' . gTxt('edit') . '">' . $sec_page . '</a>', '', 'page') . td('<a href="' . $style_url . '" title="' . gTxt('edit') . '">' . $sec_css . '</a>', '', 'style') . td($is_default_section ? '-' : asyncHref($sec_on_frontpage ? gTxt('yes') : gTxt('no'), $parms + array('property' => 'on_frontpage')), '', 'section_detail frontpage') . td($is_default_section ? '-' : asyncHref($sec_in_rss ? gTxt('yes') : gTxt('no'), $parms + array('property' => 'in_rss')), '', 'section_detail syndicate') . td($is_default_section ? '-' : asyncHref($sec_searchable ? gTxt('yes') : gTxt('no'), $parms + array('property' => 'searchable')), '', 'section_detail searchable') . td($is_default_section ? '' : $articles, '', 'section_detail article_count'), ' id="txp_section_' . $sec_name . '"'); } echo '</tbody>', n, endTable(), n, '</div>', n, section_multiedit_form($page, $sort, $dir, $crit, $search_method), n, tInput(), n, '</form>', n, graf(toggle_box('section_detail'), ' class="detail-toggle"'), n, '<div id="' . $event . '_navigation" class="txp-navigation">', n, nav_form('section', $page, $numPages, $sort, $dir, $crit, $search_method, $total, $limit), n, pageby_form('section', $section_list_pageby), n, '</div>', n, '</div>'; echo script_js(<<<EOS \t\t\t\$('#default_section').change(function() { \t\t\t\t\$('#default_section_form').submit(); \t\t\t}); EOS ); } }
/** * Renders the list of preferences. * * Plugins may add their own prefs, for example by using plugin lifecycle events or * raising a (pre) callback on event=admin / step=prefs_list so they are installed * or updated when accessing the Preferences panel. Access to the prefs can be * controlled by using add_privs() on 'prefs.your-prefs-event-name'. * * @param string $message The feedback / error string to display */ function prefs_list($message = '') { global $prefs, $txp_user; extract($prefs); pagetop(gTxt('tab_preferences'), $message); $locale = setlocale(LC_ALL, $locale); echo hed(gTxt('tab_preferences'), 1, array('class' => 'txp-heading')); echo n . '<div id="prefs_container" class="txp-container">' . n . '<form method="post" class="prefs-form" action="index.php">' . n . '<div class="txp-layout-textbox">'; // TODO: remove 'custom' when custom fields are refactored. $core_events = array('site', 'admin', 'publish', 'feeds', 'comments', 'custom'); $joined_core = join(',', quote_list($core_events)); $sql = array(); $sql[] = 'prefs_id = 1 and event != "" and type in(' . PREF_CORE . ', ' . PREF_PLUGIN . ')'; $sql[] = "(user_name = '' or (user_name='" . doSlash($txp_user) . "' and name not in(\n select name from " . safe_pfx('txp_prefs') . " where user_name = ''\n )))"; if (!get_pref('use_comments', 1, 1)) { $sql[] = "event != 'comments'"; } $rs = safe_rows_start("*, FIELD(event,{$joined_core}) as sort_value", 'txp_prefs', join(' and ', $sql) . " ORDER BY sort_value = 0, sort_value, event, position"); $last_event = null; $out = array(); if (numRows($rs)) { while ($a = nextRow($rs)) { if (!has_privs('prefs.' . $a['event'])) { continue; } if ($a['event'] !== $last_event) { if ($last_event !== null) { echo wrapRegion('prefs_group_' . $last_event, join(n, $out), 'prefs_' . $last_event, $last_event, 'prefs_' . $last_event); } $last_event = $a['event']; $out = array(); } $label = ''; if (!in_array($a['html'], array('yesnoradio', 'is_dst'))) { $label = $a['name']; } // TODO: remove exception when custom fields move to meta store. $help = ''; if (strpos($a['name'], 'custom_') === false) { $help = $a['name']; } if ($a['html'] == 'text_input') { $size = INPUT_REGULAR; } else { $size = ''; } $out[] = inputLabel($a['name'], pref_func($a['html'], $a['name'], $a['val'], $size), $label, $help, array('id' => 'prefs-' . $a['name'])); } } if ($last_event === null) { echo graf(gTxt('no_preferences')); } else { echo wrapRegion('prefs_group_' . $last_event, join(n, $out), 'prefs_' . $last_event, $last_event, 'prefs_' . $last_event); } echo n . '</div>' . sInput('prefs_save') . eInput('prefs') . hInput('prefs_id', '1') . tInput(); if ($last_event !== null) { echo graf(fInput('submit', 'Submit', gTxt('save'), 'publish')); } echo n . '</form>' . n . '</div>'; }
/** * Renders the list of preferences. * * Plugins may add their own prefs, for example by using plugin lifecycle events * or raising a (pre) callback on event=admin / step=prefs_list so they are * installed or updated when accessing the Preferences panel. Access to the * prefs can be controlled by using add_privs() on 'prefs.your-prefs-event-name'. * * @param string $message The feedback / error string to display */ function prefs_list($message = '') { global $prefs, $txp_user; extract($prefs); pagetop(gTxt('tab_preferences'), $message); $locale = setlocale(LC_ALL, $locale); echo n . '<form class="prefs-form" id="prefs_form" method="post" action="index.php">'; // TODO: remove 'custom' when custom fields are refactored. $core_events = array('site', 'admin', 'publish', 'feeds', 'comments', 'custom'); $joined_core = join(',', quote_list($core_events)); $sql = array(); $sql[] = 'prefs_id = 1 and event != "" and type in(' . PREF_CORE . ', ' . PREF_PLUGIN . ')'; $sql[] = "(user_name = '' OR (user_name = '" . doSlash($txp_user) . "' AND name NOT IN (\n SELECT name FROM " . safe_pfx('txp_prefs') . " WHERE user_name = ''\n )))"; if (!get_pref('use_comments', 1, 1)) { $sql[] = "event != 'comments'"; } $rs = safe_rows_start("*, FIELD(event, {$joined_core}) AS sort_value", 'txp_prefs', join(" AND ", $sql) . " ORDER BY sort_value = 0, sort_value, event, position"); $last_event = null; $out = array(); $build = array(); $groupOut = array(); if (numRows($rs)) { while ($a = nextRow($rs)) { if (!has_privs('prefs.' . $a['event'])) { continue; } if ($a['event'] !== $last_event) { if ($last_event !== null) { $build[] = tag(hed(gTxt($last_event), 2, array('id' => 'prefs_group_' . $last_event . '-label')) . join(n, $out), 'section', array('class' => 'txp-prefs-group', 'id' => 'prefs_group_' . $last_event, 'aria-labelledby' => 'prefs_group_' . $last_event . '-label')); $groupOut[] = n . tag(href(gTxt($last_event), '#prefs_group_' . $last_event, array('data-txp-pane' => $last_event, 'data-txp-token' => form_token())), 'li'); } $last_event = $a['event']; $out = array(); } $label = ''; if (!in_array($a['html'], array('yesnoradio', 'is_dst'))) { $label = $a['name']; } // TODO: remove exception when custom fields move to meta store. $help = ''; if (strpos($a['name'], 'custom_') === false) { $help = $a['name']; } if ($a['html'] == 'text_input') { $size = INPUT_REGULAR; } else { $size = ''; } $out[] = inputLabel($a['name'], pref_func($a['html'], $a['name'], $a['val'], $size), $label, $help, array('class' => 'txp-form-field', 'id' => 'prefs-' . $a['name'])); } } if ($last_event === null) { echo graf(gTxt('no_preferences')); } else { $build[] = tag(hed(gTxt($last_event), 2, array('id' => 'prefs_group_' . $last_event . '-label')) . join(n, $out), 'section', array('class' => 'txp-prefs-group', 'id' => 'prefs_group_' . $last_event, 'aria-labelledby' => 'prefs_group_' . $last_event . '-label')); $groupOut[] = n . tag(href(gTxt($last_event), '#prefs_group_' . $last_event, array('data-txp-pane' => $last_event, 'data-txp-token' => form_token())), 'li') . n; echo hed(gTxt('tab_preferences'), 1, array('class' => 'txp-heading')) . n . '<div class="txp-layout-4col-cell-1alt">' . wrapGroup('all_preferences', n . tag(join($groupOut), 'ul', array('class' => 'switcher-list')), 'all_preferences'); if ($last_event !== null) { echo graf(fInput('submit', 'Submit', gTxt('save'), 'publish'), array('class' => 'txp-save')); } echo n . '</div>' . n . '<div class="txp-layout-4col-cell-2-3-4">' . join(n, $build) . n . '</div>' . sInput('prefs_save') . eInput('prefs') . hInput('prefs_id', '1') . tInput(); } echo n . '</form>'; }
/** * Processes delete actions sent using the multi-edit form. */ function section_delete() { $selectedList = ps('selected'); $selected = join(',', quote_list($selectedList)); $message = ''; $sections = safe_column('name', 'txp_section', "name != 'default' and name in ({$selected}) and name not in (select Section from " . safe_pfx('textpattern') . ")"); $sectionsNotDeleted = array_diff($selectedList, $sections); if ($sections && safe_delete('txp_section', 'name in (' . join(',', quote_list($sections)) . ')')) { callback_event('sections_deleted', '', 0, $sections); $message = gTxt('section_deleted', array('{name}' => join(', ', $sections))); } if ($sectionsNotDeleted) { $severity = $message ? E_WARNING : E_ERROR; $message = array(($message ? $message . n : '') . gTxt('section_delete_failure', array('{name}' => join(', ', $sectionsNotDeleted))), $severity); } sec_section_list($message); }
function getNeighbour($Posted, $s, $type) { global $prefs; extract($prefs); $expired = $publish_expired_articles ? '' : ' and (now() <= Expires or Expires = ' . NULLDATETIME . ')'; $type = $type == '>' ? '>' : '<'; $safe_name = safe_pfx('textpattern'); $q = array("select ID, Title, url_title, unix_timestamp(Posted) as uposted\n\t\t\tfrom " . $safe_name . " where Posted {$type} '" . doSlash($Posted) . "'", $s != '' && $s != 'default' ? "and Section = '" . doSlash($s) . "'" : filterFrontPage(), 'and Status=4 and Posted < now()' . $expired . ' order by Posted', $type == '<' ? 'desc' : 'asc', 'limit 1'); $out = getRow(join(' ', $q)); return is_array($out) ? $out : ''; }
/** * Sends a password reset link to a user's email address. * * This function will return a success message even when the specified user * doesn't exist. Though an error message could be thrown when a user isn't * found, this is done due to security, which prevents the function from * leaking existing account names. * * @param string $name The login name * @return string A localized message string * @see send_new_password() * @see reset_author_pass() * @example * echo send_reset_confirmation_request('username'); */ function send_reset_confirmation_request($name) { global $sitename; $expiryTimestamp = time() + 60 * RESET_EXPIRY_MINUTES; $expiry = strftime('%Y-%m-%d %H:%M:%S', $expiryTimestamp); $rs = safe_query("SELECT\n txp_users.user_id, txp_users.email,\n txp_users.nonce, txp_users.pass,\n txp_token.type\n FROM " . safe_pfx('txp_users') . " txp_users\n LEFT JOIN " . safe_pfx('txp_token') . " txp_token\n ON txp_users.user_id = txp_token.reference_id\n WHERE txp_users.name = '" . doSlash($name) . "'\n AND TIMESTAMPDIFF(SECOND, txp_token.expires, '" . $expiry . "') > " . 60 * RESET_RATE_LIMIT_MINUTES . "\n AND txp_token.type = 'password_reset'"); $row = nextRow($rs); if ($row) { extract($row); $uid = assert_int($user_id); // The selector becomes an indirect reference to the txp_users row, // which does not leak information. $selector = Txp::get('\\Textpattern\\Password\\Random')->generate(12); $expiryYear = safe_strftime('%Y', $expiryTimestamp); $expiryMonth = safe_strftime('%B', $expiryTimestamp); $expiryDay = safe_strftime('%Oe', $expiryTimestamp); $expiryTime = safe_strftime('%H:%M', $expiryTimestamp); // Use a hash of the nonce, selector and password. // This ensures that confirmation requests expire automatically when: // a) The person next logs in, or // b) They successfully change their password (usually as a result of this reset request) // Using the selector in the hash just injects randomness, otherwise two requests // back-to-back would generate the same confirmation code. // Old requests for the same user id are purged every time a new request is made. $token = bin2hex(pack('H*', substr(hash(HASHING_ALGORITHM, $nonce . $selector . $pass), 0, SALT_LENGTH))); $confirm = $token . $selector; // Remove any previous reset tokens and insert the new one. safe_delete("txp_token", "reference_id = {$uid} AND type = 'password_reset'"); safe_insert("txp_token", "reference_id = {$uid},\n type = 'password_reset',\n selector = '" . doSlash($selector) . "',\n token = '" . doSlash($token) . "',\n expires = '" . doSlash($expiry) . "'\n "); $message = gTxt('salutation', array('{name}' => $name)) . n . n . gTxt('password_reset_confirmation') . n . hu . 'textpattern/index.php?confirm=' . $confirm . n . n . gTxt('link_expires', array('{year}' => $expiryYear, '{month}' => $expiryMonth, '{day}' => $expiryDay, '{time}' => $expiryTime)); if (txpMail($email, "[{$sitename}] " . gTxt('password_reset_confirmation_request'), $message)) { return gTxt('password_reset_confirmation_request_sent'); } else { return array(gTxt('could_not_mail'), E_ERROR); } } else { // Though 'unknown_author' could be thrown, send generic 'request_sent' // message instead so that (non-)existence of account names are not leaked. // Since this is a short circuit, there's a possibility of a timing attack // revealing the existence of an account, which we could defend against // to some degree. return gTxt('password_reset_confirmation_request_sent'); } }
function _sed_cp_safe_pfx($table) { if (is_callable('safe_pfx')) { $table = safe_pfx($table); } else { $table = PFX . $table; } return $table; }
/** Installer @param $event string Admin-side event. @param $step string Admin-side event, plugin-lifecycle step. */ function rah_textile_bar_install($event = '', $step = '') { if ($step == 'deleted') { safe_delete('txp_prefs', "name like 'rah_textile_bar_%'"); return; } global $prefs, $event, $textarray; if ($event == 'prefs') { /* Generate language strings if not existing */ $strings = array('rah_txtbar' => 'Textile Bar', 'rah_textile_bar_body' => 'Attach to Body field', 'rah_textile_bar_excerpt' => 'Attach to Excerpt field'); foreach (rah_textile_bar_buttons() as $att) { $strings['rah_textile_bar_' . $att[0]] = 'Show ' . $att[0]; } foreach ($strings as $string => $translation) { if (!isset($textarray[$string])) { $textarray[$string] = $translation; } } } $version = '0.7'; $current = isset($prefs['rah_textile_bar_version']) ? $prefs['rah_textile_bar_version'] : ''; if ($current == $version) { return; } $default = array('disable' => '', 'fields' => ''); if (!$current) { /* Run migration and clean-up if older version was installed */ @($rs = safe_rows('name, value', 'rah_textile_bar', '1=1')); if (!empty($rs) && is_array($rs)) { foreach ($rs as $a) { if (isset($default[$a['name']])) { $default[$a['name']] = $a['value']; } } @safe_query('DROP TABLE IF EXISTS ' . safe_pfx('rah_textile_bar')); } } /* Add preference strings */ $disabled = explode(',', $default['disable']); $position = 230; $values = rah_textile_bar_buttons(); foreach (array('body', 'excerpt') as $val) { $values[] = array($val); } foreach ($values as $att) { $val = $att[0] == 'body' || $att[0] == 'excerpt' ? strpos($default['fields'], $att[0]) !== false || !$default['fields'] ? 1 : 0 : (in_array('#textilebar .' . $att[0], $disabled) ? 0 : 1); if ($att[0] == 'body' || $att[0] == 'excerpt') { $position = 225; } $name = 'rah_textile_bar_' . $att[0]; if (!isset($prefs[$name])) { safe_insert('txp_prefs', "prefs_id=1,\n\t\t\t\t\tname='" . doSlash($name) . "',\n\t\t\t\t\tval='" . doSlash($val) . "',\n\t\t\t\t\ttype=1,\n\t\t\t\t\tevent='rah_txtbar',\n\t\t\t\t\thtml='yesnoradio',\n\t\t\t\t\tposition=" . $position); $prefs[$name] = $val; } $position++; } set_pref('rah_textile_bar_version', $version, 'rah_txtbar', 2, '', 0); $prefs['rah_textile_bar_version'] = $version; }
function recent_comments($atts) { extract(lAtts(array('break' => br, 'class' => __FUNCTION__, 'label' => '', 'labeltag' => '', 'limit' => 10, 'sort' => 'posted desc', 'wraptag' => ''), $atts)); $sort = preg_replace('/\\bposted\\b/', 'd.posted', $sort); $rs = startRows('select d.name, d.discussid, t.ID as thisid, unix_timestamp(t.Posted) as posted, t.Title as title, t.Section as section, t.url_title ' . 'from ' . safe_pfx('txp_discuss') . ' as d inner join ' . safe_pfx('textpattern') . ' as t on d.parentid = t.ID ' . 'where t.Status >= 4 and d.visible = ' . VISIBLE . ' order by ' . doSlash($sort) . ' limit 0,' . intval($limit)); if ($rs) { $out = array(); while ($c = nextRow($rs)) { $out[] = href($c['name'] . ' (' . escape_title($c['title']) . ')', permlinkurl($c) . '#c' . $c['discussid']); } if ($out) { return doLabel($label, $labeltag) . doWrap($out, $wraptag, $break, $class); } } return ''; }
function cat_event_category_list($event) { $rs = getTree('root', $event); $parent = ps('parent_cat'); $heading = 'tab_' . ($event == 'article' ? 'list' : $event); $for = $rs ? ' for="' . $event . '_category_parent"' : ''; $out = n . n . hed(gTxt($heading) . sp . popHelp($event . '_category'), 2) . form(fInput('text', 'title', '', '', '', '', INPUT_REGULAR) . ($rs ? '<div class="parent"><label' . $for . '>' . gTxt('parent') . '</label>' . treeSelectInput('parent_cat', $rs, $parent, $event . '_category_parent') . '</div>' : '') . n . fInput('submit', '', gTxt('Create')) . n . eInput('category') . n . sInput('cat_' . $event . '_create'), '', '', 'post', 'action-create ' . $event); if ($rs) { $total_count = array(); if ($event == 'article') { // Count distinct articles for both categories, avoid duplicates $rs2 = getRows('select category, count(*) as num from (' . 'select ID, Category1 as category from ' . safe_pfx('textpattern') . ' union ' . 'select ID, Category2 as category from ' . safe_pfx('textpattern') . ') as t where category != "" group by category'); if ($rs2 !== false) { foreach ($rs2 as $a) { $total_count[$a['category']] = $a['num']; } } } else { switch ($event) { case 'link': $rs2 = safe_rows_start('category, count(*) as num', 'txp_link', "1 group by category"); break; case 'image': $rs2 = safe_rows_start('category, count(*) as num', 'txp_image', "1 group by category"); break; case 'file': $rs2 = safe_rows_start('category, count(*) as num', 'txp_file', "1 group by category"); break; } while ($a = nextRow($rs2)) { $name = $a['category']; $num = $a['num']; $total_count[$name] = $num; } } $items = array(); foreach ($rs as $a) { extract($a); // format count switch ($event) { case 'article': $url = 'index.php?event=list' . a . 'search_method=categories' . a . 'crit=' . $name; break; case 'link': $url = 'index.php?event=link' . a . 'search_method=category' . a . 'crit=' . $name; break; case 'image': $url = 'index.php?event=image' . a . 'search_method=category' . a . 'crit=' . $name; break; case 'file': $url = 'index.php?event=file' . a . 'search_method=category' . a . 'crit=' . $name; break; } $count = isset($total_count[$name]) ? href('(' . $total_count[$name] . ')', $url) : '(0)'; if (empty($title)) { $edit_link = '<em>' . eLink('category', 'cat_' . $event . '_edit', 'id', $id, gTxt('untitled')) . '</em>'; } else { $edit_link = eLink('category', 'cat_' . $event . '_edit', 'id', $id, $title); } $items[] = graf(checkbox('selected[]', $id, 0) . sp . str_repeat(sp . sp, $level * 2) . $edit_link . sp . $count, ' class="level-' . $level . '"'); } if ($items) { $out .= cat_article_multiedit_form($event, $items); } } else { $out .= graf(gTxt('no_categories_exist')); } return $out; }
/** Run the query. * Runs an UPDATE query if $where is set, otherwise INSERT * @return bool success or failure */ public function upsert() { $this->init_query(); if (count($this->where)) { return safe_upsert($this->table, $this->set_clause, $this->clause_string()); } if ($this->set_clause) { return safe_insert($this->table, $this->set_clause); } if ($this->values_clause) { return safe_query('insert into ' . safe_pfx($this->table) . $this->values_clause); } }
function fetch($col, $table, $key, $val, $debug = '') { $key = doSlash($key); $val = is_int($val) ? $val : "'" . doSlash($val) . "'"; $q = "select {$col} from " . safe_pfx($table) . " where `{$key}` = {$val} limit 1"; if ($r = safe_query($q, $debug)) { $thing = mysql_num_rows($r) > 0 ? mysql_result($r, 0) : ''; mysql_free_result($r); return $thing; } return false; }
/** * Find an adjacent article relative to a provided threshold level. * * @param scalar $threshold The value to compare against * @param string $s Optional section restriction * @param string $type Lesser or greater neighbour? Either '<' (previous) or '>' (next) * @param array $atts Attribute of article at threshold * @param string $threshold_type 'cooked': Use $threshold as SQL clause; 'raw': Use $threshold as an escapable scalar * @return array|bool An array populated with article data, or 'false' in case of no matches */ function getNeighbour($threshold, $s, $type, $atts = array(), $threshold_type = 'raw') { global $prefs; static $cache = array(); $key = md5($threshold . $s . $type . join(n, $atts)); if (isset($cache[$key])) { return $cache[$key]; } extract($atts); $expired = $expired && $prefs['publish_expired_articles']; $customFields = getCustomFields(); // Building query parts; lifted from publish.php. $ids = array_map('intval', do_list($id)); $id = !$id ? '' : " AND ID IN (" . join(',', $ids) . ")"; switch ($time) { case 'any': $time = ""; break; case 'future': $time = " AND Posted > " . now('posted'); break; default: $time = " AND Posted <= " . now('posted'); } if (!$expired) { $time .= " AND (" . now('expires') . " <= Expires OR Expires = " . NULLDATETIME . ")"; } $custom = ''; if ($customFields) { foreach ($customFields as $cField) { if (isset($atts[$cField])) { $customPairs[$cField] = $atts[$cField]; } } if (!empty($customPairs)) { $custom = buildCustomSql($customFields, $customPairs); } } if ($keywords) { $keys = doSlash(do_list($keywords)); foreach ($keys as $key) { $keyparts[] = "FIND_IN_SET('" . $key . "', Keywords)"; } $keywords = " AND (" . join(" OR ", $keyparts) . ")"; } $sortdir = strtolower($sortdir); // Invert $type for ascending sortdir. $types = array('>' => array('desc' => '>', 'asc' => '<'), '<' => array('desc' => '<', 'asc' => '>')); $type = $type == '>' ? $types['>'][$sortdir] : $types['<'][$sortdir]; // Escape threshold and treat it as a string unless explicitly told otherwise. if ($threshold_type != 'cooked') { $threshold = "'" . doSlash($threshold) . "'"; } $safe_name = safe_pfx('textpattern'); $q = array("SELECT ID AS thisid, Section AS section, Title AS title, url_title, UNIX_TIMESTAMP(Posted) AS posted\n FROM {$safe_name} WHERE {$sortby} {$type} {$threshold}", $s != '' && $s != 'default' ? "AND Section = '" . doSlash($s) . "'" : filterFrontPage(), $id, $time, $custom, $keywords, "AND Status = 4", "ORDER BY {$sortby}", $type == '<' ? "DESC" : "ASC", "LIMIT 1"); $cache[$key] = getRow(join(n . ' ', $q)); return is_array($cache[$key]) ? $cache[$key] : false; }
function drop_table() { return safe_query('DROP TABLE ' . safe_pfx($this->_table_name), $this->_debug); }
/** * Processes delete actions sent using the multi-edit form. */ function section_delete() { $selectedList = ps('selected'); $selected = join(',', quote_list($selectedList)); $message = ''; $sections = safe_column("name", 'txp_section', "name != 'default' AND name IN ({$selected}) AND name NOT IN (SELECT Section FROM " . safe_pfx('textpattern') . ")"); $sectionsNotDeleted = array_diff($selectedList, $sections); if ($sections && safe_delete('txp_section', "name IN (" . join(',', quote_list($sections)) . ")")) { callback_event('sections_deleted', '', 0, $sections); $message = gTxt('section_deleted', array('{name}' => join(', ', $sections))); } if ($sectionsNotDeleted) { $severity = $message ? E_WARNING : E_ERROR; $message = array(($message ? $message . n : '') . gTxt('section_delete_failure', array('{name}' => join(', ', $sectionsNotDeleted))), $severity); } sec_section_list($message); }
function recent_comments($atts, $thing = NULL) { global $prefs; global $thisarticle, $thiscomment; extract(lAtts(array('break' => br, 'class' => __FUNCTION__, 'form' => '', 'label' => '', 'labeltag' => '', 'limit' => 10, 'offset' => 0, 'sort' => 'posted desc', 'wraptag' => ''), $atts)); $sort = preg_replace('/\\bposted\\b/', 'd.posted', $sort); $expired = $prefs['publish_expired_articles'] ? '' : ' and (now() <= t.Expires or t.Expires = ' . NULLDATETIME . ') '; $rs = startRows('select d.name, d.email, d.web, d.message, d.discussid, unix_timestamp(d.Posted) as time, ' . 't.ID as thisid, unix_timestamp(t.Posted) as posted, t.Title as title, t.Section as section, t.url_title ' . 'from ' . safe_pfx('txp_discuss') . ' as d inner join ' . safe_pfx('textpattern') . ' as t on d.parentid = t.ID ' . 'where t.Status >= 4' . $expired . ' and d.visible = ' . VISIBLE . ' order by ' . doSlash($sort) . ' limit ' . intval($offset) . ',' . intval($limit)); if ($rs) { $out = array(); $old_article = $thisarticle; while ($c = nextRow($rs)) { if (empty($form) && empty($thing)) { $out[] = href(txpspecialchars($c['name']) . ' (' . escape_title($c['title']) . ')', permlinkurl($c) . '#c' . $c['discussid']); } else { $thiscomment['name'] = $c['name']; $thiscomment['email'] = $c['email']; $thiscomment['web'] = $c['web']; $thiscomment['message'] = $c['message']; $thiscomment['discussid'] = $c['discussid']; $thiscomment['time'] = $c['time']; // allow permlink guesstimation in permlinkurl(), elsewhere $thisarticle['thisid'] = $c['thisid']; $thisarticle['posted'] = $c['posted']; $thisarticle['title'] = $c['title']; $thisarticle['section'] = $c['section']; $thisarticle['url_title'] = $c['url_title']; $out[] = $thing ? parse($thing) : parse_form($form); } } if ($out) { unset($GLOBALS['thiscomment']); $thisarticle = $old_article; return doLabel($label, $labeltag) . doWrap($out, $wraptag, $break, $class); } } return ''; }
function doImportWP($b2dblogin, $b2db, $b2dbpass, $b2dbhost, $wpdbprefix, $insert_into_section, $insert_with_status, $default_comment_invite, $wpdbcharset) { global $txpcfg; $b2link = mysql_connect($b2dbhost, $b2dblogin, $b2dbpass, true); if (!$b2link) { return 'WordPress database values don’t work. Go back, replace them and try again.'; } mysql_select_db($b2db, $b2link); if (!mysql_query('SET NAMES ' . doslash($wpdbcharset), $b2link)) { return 'WordPress database does not support the requested character set. Aborting.'; } // Keep some response on some part $results = array(); $errors = array(); $results[] = hed('Connected to WordPress database. Importing Data…', 1); /* export users */ $users = array(); $user_query = mysql_query("\n\t\t\tselect\n\t\t\t\tID as user_id,\n\t\t\t\tuser_login as name,\n\t\t\t\tuser_email as email,\n\t\t\t\tdisplay_name as RealName\n\t\t\tfrom " . $wpdbprefix . "users\n\t\t", $b2link) or $errors[] = mysql_error(); while ($user = mysql_fetch_array($user_query)) { $user_privs_query = mysql_query("\n\t\t\t\tselect\n\t\t\t\t\tmeta_value\n\t\t\t\tfrom " . $wpdbprefix . "usermeta\n\t\t\t\twhere user_id = " . $user['user_id'] . " and meta_key = '" . $wpdbprefix . "capabilities'\n\t\t\t", $b2link) or $errors[] = mysql_error(); $privs = unserialize(mysql_result($user_privs_query, 0)); foreach ($privs as $key => $val) { // convert the built-in WordPress roles // to their Txp equivalent switch ($key) { // publisher case 'administrator': $user['privs'] = 1; break; // managing editor // managing editor case 'editor': $user['privs'] = 2; break; // staff writer // staff writer case 'author': $user['privs'] = 4; break; // freelancer // freelancer case 'contributor': $user['privs'] = 5; break; // none // none case 'subscriber': default: $user['privs'] = 0; break; } } $users[] = $user; } /* export article and link categories */ $categories = array(); $category_query = mysql_query("\n\t\t\tselect\n\t\t\t\tt.slug as name,\n\t\t\t\tt.name as title,\n\t\t\t\ttt.taxonomy as type,\n\t\t\t\ttt.parent as parent\n\t\t\tfrom " . $wpdbprefix . "terms as t inner join " . $wpdbprefix . "term_taxonomy as tt\n\t\t\t\ton(t.term_id = tt.term_id)\n\t\t\torder by field(tt.taxonomy, 'category','post_tag','link_category'), tt.parent asc, t.name asc\n\t\t", $b2link) or $errors[] = mysql_error(); while ($category = mysql_fetch_array($category_query)) { if ($category['parent'] != 0) { $category_parent_query = mysql_query("\n\t\t\t\t\tselect\n\t\t\t\t\t\tslug as name\n\t\t\t\t\tfrom " . $wpdbprefix . "terms\n\t\t\t\t\twhere term_id = '" . doSlash($category['parent']) . "'\n\t\t\t\t", $b2link) or $errors[] = mysql_error(); while ($parent = mysql_fetch_array($category_parent_query)) { $category['parent'] = $parent['name']; } } else { $category['parent'] = 'root'; } switch ($category['type']) { case 'post_tag': case 'category': $category['type'] = 'article'; break; case 'link_category': $category['type'] = 'link'; break; } $categories[] = $category; } /* export articles - do not export post revisions from WP 2.6+ */ $article_query = mysql_query("\n\t\t\tselect\n\t\t\t\tp.ID as ID,\n\t\t\t\tp.post_status as Status,\n\t\t\t\tp.post_date as Posted,\n\t\t\t\tp.post_modified as LastMod,\n\t\t\t\tp.post_title as Title,\n\t\t\t\tp.post_content as Body,\n\t\t\t\tp.comment_status as Annotate,\n\t\t\t\tp.comment_count as comments_count,\n\t\t\t\tp.post_name as url_title,\n\t\t\t\tu.user_login as AuthorID\n\t\t\tfrom " . $wpdbprefix . "posts as p left join " . $wpdbprefix . "users as u\n\t\t\t\ton u.ID = p.post_author\n\t\t\twhere p.post_type = 'post'\n\t\t\torder by p.ID asc\n\t\t", $b2link) or $errors[] = mysql_error(); while ($article = mysql_fetch_array($article_query)) { // convert WP article status to Txp equivalent switch ($article['Status']) { case 'draft': $article['Status'] = 1; break; // hidden // hidden case 'private': $article['Status'] = 2; break; case 'pending': $article['Status'] = 3; break; // live // live case 'publish': $article['Status'] = 4; break; default: $article['Status'] = $insert_with_status; break; } // convert WP comment status to Txp equivalent switch ($article['Annotate']) { // on case 'open': $article['Annotate'] = 1; break; // off // off case 'closed': case 'registered_only': $article['Annotate'] = 0; break; } // article commments $comments = array(); $comment_query = mysql_query("\n\t\t\t\tselect\n\t\t\t\t\tcomment_author_IP as ip,\n\t\t\t\t\tcomment_author as name,\n\t\t\t\t\tcomment_author_email as email,\n\t\t\t\t\tcomment_author_url as web,\n\t\t\t\t\tcomment_content as message,\n\t\t\t\t\tcomment_date as posted\n\t\t\t\tfrom " . $wpdbprefix . "comments\n\t\t\t\twhere comment_post_ID = '" . $article['ID'] . "'\n\t\t\t\torder by comment_ID asc\n\t\t\t", $b2link) or $errors[] = mysql_error(); while ($comment = mysql_fetch_assoc($comment_query)) { $comments[] = $comment; } $article['comments'] = $comments; // article categories $article_categories = array(); $article_category_query = mysql_query("\n\t\t\t\tselect\n\t\t\t\t\tt.name as title,\n\t\t\t\t\tt.slug as name\n\t\t\t\tfrom " . $wpdbprefix . "terms as t inner join " . $wpdbprefix . "term_taxonomy as tt\n\t\t\t\t\ton(t.term_id = tt.term_id)\n\t\t\t\tinner join " . $wpdbprefix . "term_relationships as tr\n\t\t\t\t\ton(tt.term_taxonomy_id = tr.term_taxonomy_id)\n\t\t\t\twhere tr.object_id = '" . $article['ID'] . "' and tt.taxonomy in('post_tag', 'category')\n\t\t\t\torder by tr.object_id asc, t.name asc\n\t\t\t\tlimit 2;\n\t\t\t", $b2link) or $errors[] = mysql_error(); while ($category = mysql_fetch_array($article_category_query)) { $article_categories[] = $category; } $article['Category1'] = !empty($article_categories[0]) ? $article_categories[0]['name'] : ''; $article['Category2'] = !empty($article_categories[1]) ? $article_categories[1]['name'] : ''; // article images $article_images = array(); $article_image_query = mysql_query("\n\t\t\tselect\n\t\t\t\tguid\n\t\t\tfrom " . $wpdbprefix . "posts\n\t\t\twhere post_type = 'attachment' and post_mime_type like 'image/%' and post_parent=" . $article['ID'], $b2link) or $errors[] = mysql_error(); while ($image = mysql_fetch_array($article_image_query)) { $article_images[] = $image['guid']; } // Comma-separated image urls preserve multiple attachments. // Attn: If more than one image is attached, <txp:article_image /> will not work out of the box. $article['Image'] = join(',', $article_images); $articles[] = $article; } /* export links */ $links = array(); $link_query = mysql_query("\n\t\t\tselect\n\t\t\t\tlink_id as id,\n\t\t\t\tlink_name as linkname,\n\t\t\t\tlink_description as description,\n\t\t\t\tlink_updated as date,\n\t\t\t\tlink_url as url\n\t\t\tfrom " . $wpdbprefix . "links\n\t\t\torder by link_id asc\n\t\t", $b2link) or $errors[] = mysql_error(); while ($link = mysql_fetch_array($link_query)) { // link categories $link_categories = array(); $link_category_query = mysql_query("\n\t\t\t\tselect\n\t\t\t\t\tt.name as title,\n\t\t\t\t\tt.slug as name\n\t\t\t\tfrom " . $wpdbprefix . "terms as t inner join " . $wpdbprefix . "term_taxonomy as tt\n\t\t\t\t\ton(t.term_id = tt.term_id)\n\t\t\t\tinner join " . $wpdbprefix . "term_relationships as tr\n\t\t\t\t\ton(tt.term_taxonomy_id = tr.term_taxonomy_id)\n\t\t\t\twhere tr.object_id = '" . $link['id'] . "' and tt.taxonomy = 'link_category'\n\t\t\t\torder by tr.object_id asc, t.name asc\n\t\t\t", $b2link) or $errors[] = mysql_error(); while ($category = mysql_fetch_array($link_category_query)) { $link['category'] = $category['name']; } $links[] = $link; } mysql_close($b2link); /* begin import */ // keep a handy copy of txpdb values, and do not alter Dean code // for now! ;-) $txpdb = $txpcfg['db']; $txpdblogin = $txpcfg['user']; $txpdbpass = $txpcfg['pass']; $txpdbhost = $txpcfg['host']; // Yes, we have to make a new connection // otherwise doArray complains $DB = new DB(); $txplink =& $DB->link; mysql_select_db($txpdb, $txplink); /* import users */ if ($users) { include_once txpath . '/lib/txplib_admin.php'; $results[] = hed('Imported Users:', 2) . n . graf('Because WordPress uses a different password mechanism than Textpattern, you will need to reset each user’s password from <a href="index.php?event=admin">the Users tab</a>.') . n . '<ul>'; foreach ($users as $user) { extract($user); if (!safe_row('user_id', 'txp_users', "name = '" . doSlash($name) . "'")) { $pass = doSlash(generate_password(6)); $nonce = doSlash(md5(uniqid(mt_rand(), TRUE))); $rs = mysql_query("\n\t\t\t\t\t\tinsert into " . safe_pfx('txp_users') . " set\n\t\t\t\t\t\t\tname = '" . doSlash($name) . "',\n\t\t\t\t\t\t\tpass = '******',\n\t\t\t\t\t\t\temail = '" . doSlash($email) . "',\n\t\t\t\t\t\t\tRealName = '" . doSlash($RealName) . "',\n\t\t\t\t\t\t\tprivs = " . $privs . ",\n\t\t\t\t\t\t\tnonce = '" . doSlash($nonce) . "'\n\t\t\t\t\t", $txplink) or $errors[] = mysql_error(); if (mysql_insert_id()) { $results[] = '<li>' . $name . ' (' . $RealName . ')</li>'; } } } $results[] = '</ul>'; } /* import categories */ if ($categories) { $results[] = hed('Imported Categories:', 2) . n . '<ul>'; foreach ($categories as $category) { extract($category); if (!safe_row('id', 'txp_category', "name = '" . doSlash($name) . "' and type = '" . doSlash($type) . "' and parent = '" . doSlash($parent) . "'")) { $rs = mysql_query("\n\t\t\t\t\t\tinsert into " . safe_pfx('txp_category') . " set\n\t\t\t\t\t\t\tname = '" . doSlash($name) . "',\n\t\t\t\t\t\t\ttitle = '" . doSlash($title) . "',\n\t\t\t\t\t\t\ttype = '" . doSlash($type) . "',\n\t\t\t\t\t\t\tparent = '" . doSlash($parent) . "'\n\t\t\t\t\t", $txplink) or $errors[] = mysql_error(); if (mysql_insert_id()) { $results[] = '<li>' . $title . ' (' . $type . ')</li>'; } } } rebuild_tree_full('article'); rebuild_tree_full('link'); $results[] = '</ul>'; } /* import articles */ if ($articles) { $results[] = hed('Imported Articles and Comments:', 2) . n . '<ul>'; include txpath . '/lib/classTextile.php'; $textile = new Textile(); foreach ($articles as $article) { extract($article); // Ugly, really ugly way to workaround the slashes WP gotcha $Body = str_replace('<!--more-->', '', $Body); $Body_html = $textile->textileThis($Body); // can not use array slash due to way on which comments are selected $rs = mysql_query("\n\t\t\t\t\tinsert into " . safe_pfx('textpattern') . " set\n\t\t\t\t\t\tPosted = '" . doSlash($Posted) . "',\n\t\t\t\t\t\tLastMod = '" . doSlash($LastMod) . "',\n\t\t\t\t\t\tTitle = '" . doSlash($textile->TextileThis($Title, 1)) . "',\n\t\t\t\t\t\turl_title = '" . doSlash($url_title) . "',\n\t\t\t\t\t\tBody = '" . doSlash($Body) . "',\n\t\t\t\t\t\tBody_html = '" . doSlash($Body_html) . "',\n\t\t\t\t\t\tImage = '" . doSlash($Image) . "',\n\t\t\t\t\t\tAuthorID = '" . doSlash($AuthorID) . "',\n\t\t\t\t\t\tCategory1 = '" . doSlash($Category1) . "',\n\t\t\t\t\t\tCategory2 = '" . doSlash($Category2) . "',\n\t\t\t\t\t\tSection = '{$insert_into_section}',\n\t\t\t\t\t\tuid = '" . md5(uniqid(rand(), true)) . "',\n\t\t\t\t\t\tfeed_time = '" . substr($Posted, 0, 10) . "',\n\t\t\t\t\t\tAnnotate = '" . doSlash($Annotate) . "',\n\t\t\t\t\t\tAnnotateInvite = '{$default_comment_invite}',\n\t\t\t\t\t\tStatus = '" . doSlash($Status) . "'\n\t\t\t\t", $txplink) or $errors[] = mysql_error(); if ((int) ($insert_id = mysql_insert_id($txplink))) { $results[] = '<li>' . $Title . '</li>'; if (!empty($comments)) { $inserted_comments = 0; foreach ($comments as $comment) { extract(array_slash($comment)); // The ugly workaroud again $message = nl2br($message); $rs = mysql_query("\n\t\t\t\t\t\t\t\tinsert into " . safe_pfx('txp_discuss') . " set\n\t\t\t\t\t\t\t\t\tparentid = '{$insert_id}',\n\t\t\t\t\t\t\t\t\tname = '" . doSlash($name) . "',\n\t\t\t\t\t\t\t\t\temail = '" . doSlash($email) . "',\n\t\t\t\t\t\t\t\t\tweb = '" . doSlash($web) . "',\n\t\t\t\t\t\t\t\t\tip = '" . doSlash($ip) . "',\n\t\t\t\t\t\t\t\t\tposted = '" . doSlash($posted) . "',\n\t\t\t\t\t\t\t\t\tmessage = '" . doSlash($message) . "',\n\t\t\t\t\t\t\t\t\tvisible = 1\n\t\t\t\t\t\t\t", $txplink) or $results[] = mysql_error(); if (mysql_insert_id()) { $inserted_comments++; } } $results[] = '<li>- ' . $inserted_comments . ' of ' . $comments_count . ' comment(s)</li>'; } } } $results[] = '</ul>'; } /* import links */ if ($links) { $results[] = hed('Imported Links:', 2) . n . '<ul>'; foreach ($links as $link) { extract($link); $rs = mysql_query("\n\t\t\t\t\tinsert into " . safe_pfx('txp_link') . " set\n\t\t\t\t\t\tlinkname = '" . doSlash($linkname) . "',\n\t\t\t\t\t\tlinksort = '" . doSlash($linkname) . "',\n\t\t\t\t\t\tdescription = '" . doSlash($description) . "',\n\t\t\t\t\t\tcategory = '" . doSlash($category) . "',\n\t\t\t\t\t\tdate = '" . doSlash($date) . "',\n\t\t\t\t\t\turl = '" . doSlash($url) . "'\n\t\t\t\t", $txplink) or $errors[] = mysql_error(); if (mysql_insert_id()) { $results[] = '<li>' . $linkname . '</li>'; } } $results[] = '</ul>'; } /* show any errors we encountered */ if ($errors) { $results[] = hed('Errors Encountered:', 2) . n . '<ul>'; foreach ($errors as $error) { $results[] = '<li>' . $error . '</li>'; } $results[] = '</ul>'; } return join(n, $results); }
function adi_get_sections() { $sql_fields = "name, title, adi_menu_parent, adi_menu_title, adi_menu_exclude, adi_menu_clone, adi_menu_sort"; $sql_tables = safe_pfx('txp_section'); $rs = safe_query("SELECT " . $sql_fields . " FROM " . $sql_tables . " ORDER BY name"); while ($a = nextRow($rs)) { extract($a); // set 'name','title','parent' etc in $a $out[$name] = $a; } return $out; }
/** * The main panel listing all articles. * * @param string|array $message The activity message * @param string $post Not used */ function list_list($message = '', $post = '') { global $statuses, $use_comments, $comments_disabled_after, $step, $txp_user, $article_list_pageby, $event; pagetop(gTxt('tab_list'), $message); extract(gpsa(array('page', 'sort', 'dir', 'crit', 'search_method'))); if ($sort === '') { $sort = get_pref('article_sort_column', 'posted'); } else { if (!in_array($sort, array('id', 'title', 'expires', 'section', 'category1', 'category2', 'status', 'author', 'comments', 'lastmod'))) { $sort = 'posted'; } set_pref('article_sort_column', $sort, 'list', 2, '', 0, PREF_PRIVATE); } if ($dir === '') { $dir = get_pref('article_sort_dir', 'desc'); } else { $dir = $dir == 'asc' ? "asc" : "desc"; set_pref('article_sort_dir', $dir, 'list', 2, '', 0, PREF_PRIVATE); } $sesutats = array_flip($statuses); switch ($sort) { case 'id': $sort_sql = "textpattern.ID {$dir}"; break; case 'title': $sort_sql = "textpattern.Title {$dir}, textpattern.Posted DESC"; break; case 'expires': $sort_sql = "textpattern.Expires {$dir}"; break; case 'section': $sort_sql = "section.title {$dir}, textpattern.Posted DESC"; break; case 'category1': $sort_sql = "category1.title {$dir}, textpattern.Posted DESC"; break; case 'category2': $sort_sql = "category2.title {$dir}, textpattern.Posted DESC"; break; case 'status': $sort_sql = "textpattern.Status {$dir}, textpattern.Posted DESC"; break; case 'author': $sort_sql = "user.RealName {$dir}, textpattern.Posted DESC"; break; case 'comments': $sort_sql = "textpattern.comments_count {$dir}, textpattern.Posted DESC"; break; case 'lastmod': $sort_sql = "textpattern.LastMod {$dir}, textpattern.Posted DESC"; break; default: $sort = 'posted'; $sort_sql = "textpattern.Posted {$dir}"; break; } $switch_dir = $dir == 'desc' ? 'asc' : 'desc'; $search = new Filter($event, array('id' => array('column' => 'textpattern.ID', 'label' => gTxt('ID'), 'type' => 'integer'), 'title_body_excerpt' => array('column' => array('textpattern.Title', 'textpattern.Body', 'textpattern.Excerpt'), 'label' => gTxt('title_body_excerpt')), 'section' => array('column' => array('textpattern.Section', 'section.title'), 'label' => gTxt('section')), 'keywords' => array('column' => 'textpattern.Keywords', 'label' => gTxt('keywords'), 'type' => 'find_in_set'), 'categories' => array('column' => array('textpattern.Category1', 'textpattern.Category2', 'category1.title', 'category2.title'), 'label' => gTxt('categories')), 'status' => array('column' => array('textpattern.Status'), 'label' => gTxt('status'), 'type' => 'boolean'), 'author' => array('column' => array('textpattern.AuthorID', 'user.RealName'), 'label' => gTxt('author')), 'article_image' => array('column' => array('textpattern.Image'), 'label' => gTxt('article_image'), 'type' => 'integer'), 'posted' => array('column' => array('textpattern.Posted'), 'label' => gTxt('posted')), 'lastmod' => array('column' => array('textpattern.LastMod'), 'label' => gTxt('article_modified')))); $search->setAliases('status', $statuses); list($criteria, $crit, $search_method) = $search->getFilter(array('id' => array('can_list' => true), 'article_image' => array('can_list' => true), 'title_body_excerpt' => array('always_like' => true))); $search_render_options = array('placeholder' => 'search_articles'); $sql_from = safe_pfx('textpattern') . " textpattern\n LEFT JOIN " . safe_pfx('txp_category') . " category1 ON category1.name = textpattern.Category1 AND category1.type = 'article'\n LEFT JOIN " . safe_pfx('txp_category') . " category2 ON category2.name = textpattern.Category2 AND category2.type = 'article'\n LEFT JOIN " . safe_pfx('txp_section') . " section ON section.name = textpattern.Section\n LEFT JOIN " . safe_pfx('txp_users') . " user ON user.name = textpattern.AuthorID"; if ($criteria === 1) { $total = safe_count('textpattern', $criteria); } else { $total = getThing("SELECT COUNT(*) FROM {$sql_from} WHERE {$criteria}"); } echo n . tag(hed(gTxt('tab_list'), 1, array('class' => 'txp-heading')), 'div', array('class' => 'txp-layout-2col-cell-1')); $searchBlock = n . tag($search->renderForm('list', $search_render_options), 'div', array('class' => 'txp-layout-2col-cell-2', 'id' => $event . '_control')); $createBlock = array(); if (has_privs('article.edit')) { $createBlock[] = n . tag(sLink('article', '', gTxt('add_new_article'), 'txp-button'), 'div', array('class' => 'txp-control-panel')); } $contentBlockStart = n . tag_start('div', array('class' => 'txp-layout-1col', 'id' => $event . '_container')); $createBlock = implode(n, $createBlock); if ($total < 1) { if ($criteria != 1) { echo $searchBlock . $contentBlockStart . $createBlock . graf(span(null, array('class' => 'ui-icon ui-icon-info')) . ' ' . gTxt('no_results_found'), array('class' => 'alert-block information')); } else { echo $contentBlockStart . $createBlock . graf(span(null, array('class' => 'ui-icon ui-icon-info')) . ' ' . gTxt('no_articles_recorded'), array('class' => 'alert-block information')); } echo n . tag_end('div'); return; } $limit = max($article_list_pageby, 15); list($page, $offset, $numPages) = pager($total, $limit, $page); echo $searchBlock . $contentBlockStart . $createBlock; $rs = safe_query("SELECT\n textpattern.ID, textpattern.Title, textpattern.url_title, textpattern.Section,\n textpattern.Category1, textpattern.Category2,\n textpattern.Status, textpattern.Annotate, textpattern.AuthorID,\n UNIX_TIMESTAMP(textpattern.Posted) AS posted,\n UNIX_TIMESTAMP(textpattern.LastMod) AS lastmod,\n UNIX_TIMESTAMP(textpattern.Expires) AS expires,\n category1.title AS category1_title,\n category2.title AS category2_title,\n section.title AS section_title,\n user.RealName AS RealName,\n (SELECT COUNT(*) FROM " . safe_pfx('txp_discuss') . " WHERE parentid = textpattern.ID) AS total_comments\n FROM {$sql_from} WHERE {$criteria} ORDER BY {$sort_sql} LIMIT {$offset}, {$limit}"); if ($rs) { $show_authors = !has_single_author('textpattern', 'AuthorID'); echo n . tag(toggle_box('articles_detail'), 'div', array('class' => 'txp-list-options')) . n . tag_start('form', array('class' => 'multi_edit_form', 'id' => 'articles_form', 'name' => 'longform', 'method' => 'post', 'action' => 'index.php')) . n . tag_start('div', array('class' => 'txp-listtables')) . n . tag_start('table', array('class' => 'txp-list')) . n . tag_start('thead') . tr(hCell(fInput('checkbox', 'select_all', 0, '', '', '', '', '', 'select_all'), '', ' class="txp-list-col-multi-edit" scope="col" title="' . gTxt('toggle_all_selected') . '"') . column_head('ID', 'id', 'list', true, $switch_dir, $crit, $search_method, ('id' == $sort ? "{$dir} " : '') . 'txp-list-col-id') . column_head('title', 'title', 'list', true, $switch_dir, $crit, $search_method, ('title' == $sort ? "{$dir} " : '') . 'txp-list-col-title') . column_head('posted', 'posted', 'list', true, $switch_dir, $crit, $search_method, ('posted' == $sort ? "{$dir} " : '') . 'txp-list-col-created date') . column_head('article_modified', 'lastmod', 'list', true, $switch_dir, $crit, $search_method, ('lastmod' == $sort ? "{$dir} " : '') . 'txp-list-col-lastmod date articles_detail') . column_head('expires', 'expires', 'list', true, $switch_dir, $crit, $search_method, ('expires' == $sort ? "{$dir} " : '') . 'txp-list-col-expires date articles_detail') . column_head('section', 'section', 'list', true, $switch_dir, $crit, $search_method, ('section' == $sort ? "{$dir} " : '') . 'txp-list-col-section') . column_head('category1', 'category1', 'list', true, $switch_dir, $crit, $search_method, ('category1' == $sort ? "{$dir} " : '') . 'txp-list-col-category1 category articles_detail') . column_head('category2', 'category2', 'list', true, $switch_dir, $crit, $search_method, ('category2' == $sort ? "{$dir} " : '') . 'txp-list-col-category2 category articles_detail') . column_head('status', 'status', 'list', true, $switch_dir, $crit, $search_method, ('status' == $sort ? "{$dir} " : '') . 'txp-list-col-status') . ($show_authors ? column_head('author', 'author', 'list', true, $switch_dir, $crit, $search_method, ('author' == $sort ? "{$dir} " : '') . 'txp-list-col-author name') : '') . ($use_comments == 1 ? column_head('comments', 'comments', 'list', true, $switch_dir, $crit, $search_method, ('comments' == $sort ? "{$dir} " : '') . 'txp-list-col-comments articles_detail') : '')) . n . tag_end('thead'); include_once txpath . '/publish/taghandlers.php'; echo n . tag_start('tbody'); $validator = new Validator(); while ($a = nextRow($rs)) { extract($a); if ($Title === '') { $Title = '<em>' . eLink('article', 'edit', 'ID', $ID, gTxt('untitled')) . '</em>'; } else { $Title = eLink('article', 'edit', 'ID', $ID, $Title); } // Valid section and categories? $validator->setConstraints(array(new SectionConstraint($Section))); $vs = $validator->validate() ? '' : ' error'; $validator->setConstraints(array(new CategoryConstraint($Category1, array('type' => 'article')))); $vc[1] = $validator->validate() ? '' : ' error'; $validator->setConstraints(array(new CategoryConstraint($Category2, array('type' => 'article')))); $vc[2] = $validator->validate() ? '' : ' error'; $Category1 = $Category1 ? span(txpspecialchars($category1_title), array('title' => $Category1)) : ''; $Category2 = $Category2 ? span(txpspecialchars($category2_title), array('title' => $Category2)) : ''; if ($Status != STATUS_LIVE and $Status != STATUS_STICKY) { $view_url = '?txpreview=' . intval($ID) . '.' . time(); } else { $view_url = permlinkurl($a); } if (isset($statuses[$Status])) { $Status = $statuses[$Status]; } $comments = '(' . $total_comments . ')'; if ($total_comments) { $comments = href($comments, array('event' => 'discuss', 'step' => 'list', 'search_method' => 'parent', 'crit' => $ID), array('title' => gTxt('manage'))); } $comment_status = $Annotate ? gTxt('on') : gTxt('off'); if ($comments_disabled_after) { $lifespan = $comments_disabled_after * 86400; $time_since = time() - $posted; if ($time_since > $lifespan) { $comment_status = gTxt('expired'); } } $comments = tag($comment_status, 'span', array('class' => 'comments-status')) . ' ' . tag($comments, 'span', array('class' => 'comments-manage')); echo tr(td(($a['Status'] >= STATUS_LIVE and has_privs('article.edit.published') or $a['Status'] >= STATUS_LIVE and $AuthorID === $txp_user and has_privs('article.edit.own.published') or $a['Status'] < STATUS_LIVE and has_privs('article.edit') or $a['Status'] < STATUS_LIVE and $AuthorID === $txp_user and has_privs('article.edit.own')) ? fInput('checkbox', 'selected[]', $ID, 'checkbox') : '', '', 'txp-list-col-multi-edit') . hCell(eLink('article', 'edit', 'ID', $ID, $ID) . sp . span(span('[', array('aria-hidden' => 'true')) . href(gTxt('view'), $view_url) . span(']', array('aria-hidden' => 'true')), array('class' => 'txp-option-link articles_detail')), '', ' class="txp-list-col-id" scope="row"') . td($Title, '', 'txp-list-col-title') . td(gTime($posted), '', 'txp-list-col-created date' . ($posted < time() ? '' : ' unpublished')) . td(gTime($lastmod), '', 'txp-list-col-lastmod date articles_detail' . ($posted === $lastmod ? ' not-modified' : '')) . td($expires ? gTime($expires) : '', '', 'txp-list-col-expires date articles_detail') . td(span(txpspecialchars($section_title), array('title' => $Section)), '', 'txp-list-col-section' . $vs) . td($Category1, '', 'txp-list-col-category1 category articles_detail' . $vc[1]) . td($Category2, '', 'txp-list-col-category2 category articles_detail' . $vc[2]) . td(href($Status, $view_url, join_atts(array('title' => gTxt('view')))), '', 'txp-list-col-status') . ($show_authors ? td(span(txpspecialchars($RealName), array('title' => $AuthorID)), '', 'txp-list-col-author name') : '') . ($use_comments ? td($comments, '', 'txp-list-col-comments articles_detail') : '')); } echo n . tag_end('tbody') . n . tag_end('table') . n . tag_end('div') . list_multiedit_form($page, $sort, $dir, $crit, $search_method) . tInput() . n . tag_end('form') . n . tag_start('div', array('class' => 'txp-navigation', 'id' => $event . '_navigation')) . pageby_form('list', $article_list_pageby) . nav_form('list', $page, $numPages, $sort, $dir, $crit, $search_method, $total, $limit) . n . tag_end('div'); } echo n . tag_end('div'); }
/** * Renders a list of categories. * * @param string $event Type of category * @return string HTML */ function cat_event_category_list($event) { $rs = getTree('root', $event); $parent = ps('parent_cat'); $heading = 'tab_' . ($event == 'article' ? 'list' : $event); $for = $rs ? ' for="' . $event . '_category_parent"' : ''; $out = hed(gTxt($heading) . popHelp($event . '_category'), 2) . form(graf(tag(gTxt('create_new_category'), 'label', array('for' => $event . '_category_new')) . br . fInput('text', 'title', '', '', '', '', INPUT_REGULAR, '', $event . '_category_new')) . ($rs ? graf('<label' . $for . '>' . gTxt('parent') . '</label>' . br . treeSelectInput('parent_cat', $rs, $parent, $event . '_category_parent'), array('class' => 'parent')) : '') . graf(fInput('submit', '', gTxt('Create')) . eInput('category') . sInput('cat_' . $event . '_create')), '', '', 'post', $event); if ($rs) { $total_count = array(); if ($event == 'article') { // Count distinct articles for both categories, avoid duplicates. $rs2 = getRows("SELECT category, COUNT(*) AS num FROM (\n SELECT ID, Category1 AS category FROM " . safe_pfx('textpattern') . "\n UNION\n SELECT ID, Category2 AS category FROM " . safe_pfx('textpattern') . "\n ) AS t WHERE category != '' GROUP BY category"); if ($rs2 !== false) { foreach ($rs2 as $a) { $total_count[$a['category']] = $a['num']; } } } else { switch ($event) { case 'link': $rs2 = safe_rows_start("category, COUNT(*) AS num", 'txp_link', "1 = 1 GROUP BY category"); break; case 'image': $rs2 = safe_rows_start("category, COUNT(*) AS num", 'txp_image', "1 = 1 GROUP BY category"); break; case 'file': $rs2 = safe_rows_start("category, COUNT(*) AS num", 'txp_file', "1 = 1 GROUP BY category"); break; } while ($a = nextRow($rs2)) { $name = $a['category']; $num = $a['num']; $total_count[$name] = $num; } } $items = array(); foreach ($rs as $a) { extract($a); // Format count. switch ($event) { case 'article': $url = 'index.php?event=list' . a . 'search_method=categories' . a . 'crit=' . $name; break; case 'link': $url = 'index.php?event=link' . a . 'search_method=category' . a . 'crit=' . $name; break; case 'image': $url = 'index.php?event=image' . a . 'search_method=category' . a . 'crit=' . $name; break; case 'file': $url = 'index.php?event=file' . a . 'search_method=category' . a . 'crit=' . $name; break; } $count = isset($total_count[$name]) ? href('(' . $total_count[$name] . ')', $url) : '(0)'; if (empty($title)) { $edit_link = '<em>' . eLink('category', 'cat_' . $event . '_edit', 'id', $id, gTxt('untitled')) . '</em>'; } else { $edit_link = eLink('category', 'cat_' . $event . '_edit', 'id', $id, $title); } $items[] = graf(checkbox('selected[]', $id, 0) . sp . str_repeat(sp . sp, $level * 2) . $edit_link . sp . $count, ' class="level-' . $level . '"'); } if ($items) { $out .= cat_article_multiedit_form($event, $items); } } else { $out .= graf(span(null, array('class' => 'ui-icon ui-icon-info')) . ' ' . gTxt('no_categories_exist'), array('class' => 'alert-block information')); } return $out; }
public function sitemapXML() { static $mlp_installed; if (!isset($mlp_installed)) { $mlp_installed = is_callable('l10n_installed') ? call_user_func('l10n_installed', true) : false; } $out = '<?xml version="1.0" encoding="utf-8"?>'; $out .= '<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">'; // Homepage $out .= $this->urlXML(hu); // Excluded sections $excluded = $GLOBALS['prefs']['jmd_sitemap_exclude']; $excluded = unserialize($excluded); foreach ($excluded as $key => $value) { $notIn[$key] = "'{$value}'"; } $notIn = implode(',', $notIn); $notIn .= ",'default'"; // List sections $site_langs = array(); if ($mlp_installed) { $site_langs = MLPLanguageHandler::get_site_langs(); } $sections = safe_column("name", "txp_section", "name not in({$notIn})"); foreach ($sections as $section) { if ($mlp_installed) { foreach ($site_langs as $lang) { $lang = substr($lang, 0, 2) . '/'; $loc = hu . $lang . urlencode($section) . '/'; $out .= $this->urlXML($loc); } } else { $loc = pagelinkurl(array('s' => $section)); $out .= $this->urlXML($loc); } } // Articles $fields = 'ID as thisid, Section as section, Title as title, url_title, unix_timestamp(Posted) as posted, unix_timestamp(LastMod) as lastmod'; if ($mlp_installed) { $fields .= ', l10n_lang'; } $articles = getRows("select {$fields} from " . safe_pfx('textpattern') . " where Status = 4 and Posted<= now() and section not in({$notIn})"); if ($articles) { include_once txpath . '/publish/taghandlers.php'; foreach ($articles as $article) { $loc = permlinkurl($article); if ($mlp_installed) { $loc = str_replace(hu, hu . substr($article['l10n_lang'], 0, 2) . '/', $loc); } $lastmod = date('c', $article['lastmod']); $out .= $this->urlXML($loc, $lastmod); } } $out .= '</urlset>'; return $out; }
function getNeighbour($Posted, $s, $type) { $type = $type == '>' ? '>' : '<'; $safe_name = safe_pfx('textpattern'); $q = array("select ID, Title, url_title, unix_timestamp(Posted) as uposted\n\t\t\tfrom " . $safe_name . " where Posted {$type} '" . doSlash($Posted) . "'", $s != '' && $s != 'default' ? "and Section = '" . doSlash($s) . "'" : filterFrontPage(), 'and Status=4 and Posted < now() order by Posted', $type == '<' ? 'desc' : 'asc', 'limit 1'); $out = getRow(join(' ', $q)); return is_array($out) ? $out : ''; }
/** * Find an adjacent article relative to a provided threshold level * * @param scalar $threshold The value to compare against * @param string $s string Optional section restriction * @param string $type string Find lesser or greater neighbour? Possible values: '<' (previous, default) or '>' (next) * @param array $atts Attribute of article at threshold * @param string $threshold_type 'cooked': Use $threshold as SQL clause; 'raw': Use $threshold as an escapable scalar * @return array|string An array populated with article data, or the empty string in case of no matches */ function getNeighbour($threshold, $s, $type, $atts = array(), $threshold_type = 'raw') { global $prefs; static $cache = array(); $key = md5($threshold . $s . $type . join(n, $atts)); if (isset($cache[$key])) { return $cache[$key]; } extract($atts); $expired = $expired && $prefs['publish_expired_articles']; $customFields = getCustomFields(); //Building query parts // lifted from publish.php. This is somewhat embarrassing, isn't it? $ids = array_map('intval', do_list($id)); $id = !$id ? '' : " and ID IN (" . join(',', $ids) . ")"; switch ($time) { case 'any': $time = ""; break; case 'future': $time = " and Posted > now()"; break; default: $time = " and Posted <= now()"; } if (!$expired) { $time .= " and (now() <= Expires or Expires = " . NULLDATETIME . ")"; } $custom = ''; if ($customFields) { foreach ($customFields as $cField) { if (isset($atts[$cField])) { $customPairs[$cField] = $atts[$cField]; } } if (!empty($customPairs)) { $custom = buildCustomSql($customFields, $customPairs); } } if ($keywords) { $keys = doSlash(do_list($keywords)); foreach ($keys as $key) { $keyparts[] = "FIND_IN_SET('" . $key . "',Keywords)"; } $keywords = " and (" . join(' or ', $keyparts) . ")"; } // invert $type for ascending sortdir $types = array('>' => array('desc' => '>', 'asc' => '<'), '<' => array('desc' => '<', 'asc' => '>')); $type = $type == '>' ? $types['>'][$sortdir] : $types['<'][$sortdir]; // escape threshold and treat it as a string unless explicitly told otherwise if ($threshold_type != 'cooked') { $threshold = "'" . doSlash($threshold) . "'"; } $safe_name = safe_pfx('textpattern'); $q = array("select ID, Title, url_title, unix_timestamp(Posted) as uposted\n\t\t\tfrom " . $safe_name . " where {$sortby} {$type} " . $threshold, $s != '' && $s != 'default' ? "and Section = '" . doSlash($s) . "'" : filterFrontPage(), $id, $time, $custom, $keywords, 'and Status=4', 'order by ' . $sortby, $type == '<' ? 'desc' : 'asc', 'limit 1'); $cache[$key] = getRow(join(n . ' ', $q)); return is_array($cache[$key]) ? $cache[$key] : ''; }
/** * Pushes content to $this->categories and $this->images */ private function getImages() { $this->images = getRows("select id, name, category, ext, w, h, thumbnail\n from " . safe_pfx('txp_image')); if ($this->images) { foreach ($this->images as $img) { if (!in_array($img['category'], $this->categories) && $img['category'] !== '') { array_push($this->categories, $img['category']); } } } }
// <txp:message /> is dropped safe_update('txp_form', "Form = REPLACE(Form, '<txp:message', '<txp:comment_message')", "1 = 1"); // Expiry datetime for articles safe_upgrade_table('textpattern', array('Expires' => "datetime NOT NULL default '0000-00-00 00:00:00' after `Posted`")); if (!safe_field('name', 'txp_prefs', "name = 'publish_expired_articles'")) { safe_insert('txp_prefs', "prefs_id = 1, name = 'publish_expired_articles', val = '0', type = '1', event='publish', html='yesnoradio', position='130'"); } /* * @todo determine section:article relation key */ // populate section_id values // foreach (safe_rows('id, name', 'txp_section', '1=1') as $row) { // safe_update('textpattern', "section_id='".doSlash($row['id'])."'", "Section='".doSlash($row['name'])."'"); //} // fix up the parent field in txp_category safe_query("alter ignore table " . safe_pfx('txp_category') . " modify parent INT not null"); $types = safe_column('distinct type', 'txp_category', '1=1'); foreach ($types as $type) { $root = safe_field('id', 'txp_category', "type='" . doSlash($type) . "' and name='root' and parent=0"); if (!$root) { $root = safe_insert('txp_category', "name='root', type='" . doSlash($type) . "', parent=0"); } safe_update('txp_category', "parent='" . $root . "'", "type='" . doSlash($type) . "' and parent=0 and id != '" . $root . "'"); tree_rebuild_full('txp_category', "type='" . doSlash($type) . "'"); } // index on form type safe_upgrade_index('txp_form', 'type_idx', '', 'type'); // dropdown ui for certain prefs safe_upgrade_table('txp_prefs', array('choices' => 'varchar(64)')); safe_update('txp_prefs', "html='checkbox'", "html='yesnoradio'"); safe_update('txp_prefs', "html='text'", "html='text_input'");
/** * Update the plugin and return a message * * @return string Message */ function yab_shop_update() { global $yab_shop_prefs, $plugins_ver; $old = $yab_shop_prefs['yab_shop_version']; $new = $plugins_ver['yab_shop_admin']; // update from 0.8.0 if ($old == '' or $old == '0.8.0') { $rs[] = "update " . safe_pfx('yab_shop_lang') . " set val='Yab Shop Preferences' where name='shop_prefs' AND lang='en-gb'"; $rs[] = "update " . safe_pfx('yab_shop_lang') . " set val='Yab Shop language saved.' where name='lang_updated' AND lang='en-gb'"; $rs[] = "update " . safe_pfx('yab_shop_lang') . " set val='Hit the button to update Yab Shop.' where name='klick_to_update' AND lang='en-gb'"; $rs[] = "update " . safe_pfx('yab_shop_lang') . " set val='Yab Shop database tables deleted.' where name='tables_delete_success' AND lang='en-gb'"; $rs[] = "update " . safe_pfx('yab_shop_lang') . " set val='Yab Shop preferences saved.' where name='prefs_updated' AND lang='en-gb'"; $rs[] = "update " . safe_pfx('yab_shop_lang') . " set val='Yab Shop public language and localisation' where name='lang_public' AND lang='en-gb'"; $rs[] = "update " . safe_pfx('yab_shop_lang') . " set val='Yab Shop L10n' where name='shop_lang' AND lang='en-gb'"; $rs[] = "update " . safe_pfx('yab_shop_lang') . " set val='Yab Shop common preferences' where name='shop_common_prefs' AND lang='en-gb'"; $rs[] = "update " . safe_pfx('yab_shop_prefs') . " set val='0.8.1' where name='yab_shop_version'"; } foreach ($rs as $query) { $result = safe_query($query); if (!$result) { return 'Could not update plugin from version ' . $old . ' to version ' . $new; } } return 'Plugin successfully updated to version ' . $new; }