/** * Constructor. */ public function __construct() { global $step; $steps = array('visible' => true); if ($step && bouncer($step, $steps) && has_privs(ps('origin'))) { $this->{$step}(); } }
function link_multi_edit() { global $txp_user; $selected = ps('selected'); if (!$selected or !is_array($selected)) { link_edit(); return; } $selected = array_map('assert_int', $selected); $method = ps('edit_method'); $changed = array(); switch ($method) { case 'delete': if (!has_privs('link.delete')) { if (has_privs('link.delete.own')) { $selected = safe_column('id', 'txp_link', 'id IN (' . join(',', $selected) . ') AND author=\'' . doSlash($txp_user) . '\''); } else { $selected = array(); } } foreach ($selected as $id) { if (safe_delete('txp_link', 'id = ' . $id)) { $changed[] = $id; } } $key = ''; break; case 'changecategory': $key = 'category'; $val = ps('category'); break; case 'changeauthor': $key = 'author'; $val = ps('author'); break; default: $key = ''; $val = ''; break; } if ($selected and $key) { foreach ($selected as $id) { if (safe_update('txp_link', "{$key} = '" . doSlash($val) . "'", "id = {$id}")) { $changed[] = $id; } } } if ($changed) { update_lastmod(); link_edit(gTxt($method == 'delete' ? 'links_deleted' : 'link_updated', array($method == 'delete' ? '{list}' : '{name}' => join(', ', $changed)))); return; } link_edit(); }
function require_privs($res, $user = '') { if (!has_privs($res, $user)) { exit(pageTop('Restricted') . '<p style="margin-top:3em;text-align:center">' . gTxt('restricted_area') . '</p>'); } }
function navPop($inline = '') { $areas = areas(); $out = array(); foreach ($areas as $a => $b) { if (!has_privs('tab.' . $a)) { continue; } if (count($b) > 0) { $out[] = n . t . '<optgroup label="' . gTxt('tab_' . $a) . '">'; foreach ($b as $c => $d) { if (has_privs($d)) { $out[] = n . t . t . '<option value="' . $d . '">' . $c . '</option>'; } } $out[] = n . t . '</optgroup>'; } } if ($out) { $style = $inline ? ' style="display: inline;"' : ''; return '<form method="get" action="index.php" class="navpop"' . $style . '>' . n . '<select name="event" onchange="submit(this.form);">' . n . t . '<option>' . gTxt('go') . '…</option>' . join('', $out) . n . '</select>' . n . '</form>'; } }
/** * The main author list. * * @param string|array $message The activity message */ function author_list($message = '') { global $txp_user, $author_list_pageby; pagetop(gTxt('tab_site_admin'), $message); if (is_disabled('mail')) { echo graf(span(null, array('class' => 'ui-icon ui-icon-alert')) . ' ' . gTxt('warn_mail_unavailable'), array('class' => 'alert-block warning')); } echo hed(gTxt('tab_site_admin'), 1, array('class' => 'txp-heading')); echo n . '<div id="users_control" class="txp-control-panel">'; $buttons = array(); // Change password button. $buttons[] = sLink('admin', 'new_pass_form', gTxt('change_password')); if (!has_privs('admin.edit')) { // Change email address button. $buttons[] = sLink('admin', 'change_email_form', gTxt('change_email_address')); } else { // New author button. $buttons[] = sLink('admin', 'author_edit', gTxt('add_new_author')); } echo graf(join(n, $buttons), array('class' => 'txp-buttons')); // User list. if (has_privs('admin.list')) { extract(gpsa(array('page', 'sort', 'dir', 'crit', 'search_method'))); if ($sort === '') { $sort = get_pref('admin_sort_column', 'name'); } if ($dir === '') { $dir = get_pref('admin_sort_dir', 'asc'); } $dir = $dir == 'desc' ? 'desc' : 'asc'; if (!in_array($sort, array('name', 'RealName', 'email', 'privs', 'last_login'))) { $sort = 'name'; } $sort_sql = $sort . ' ' . $dir; set_pref('admin_sort_column', $sort, 'admin', 2, '', 0, PREF_PRIVATE); set_pref('admin_sort_dir', $dir, 'admin', 2, '', 0, PREF_PRIVATE); $switch_dir = $dir == 'desc' ? 'asc' : 'desc'; $criteria = 1; if ($search_method and $crit != '') { $verbatim = preg_match('/^"(.*)"$/', $crit, $m); $crit_escaped = $verbatim ? doSlash($m[1]) : doLike($crit); $critsql = $verbatim ? array('id' => "user_id in ('" . join("','", do_list($crit_escaped)) . "')", 'login' => "name = '{$crit_escaped}'", 'real_name' => "RealName = '{$crit_escaped}'", 'email' => "email = '{$crit_escaped}'", 'privs' => "convert(privs, char) in ('" . join("','", do_list($crit_escaped)) . "')") : array('id' => "user_id in ('" . join("','", do_list($crit_escaped)) . "')", 'login' => "name like '%{$crit_escaped}%'", 'real_name' => "RealName like '%{$crit_escaped}%'", 'email' => "email like '%{$crit_escaped}%'", 'privs' => "convert(privs, char) in ('" . join("','", do_list($crit_escaped)) . "')"); if (array_key_exists($search_method, $critsql)) { $criteria = $critsql[$search_method]; } else { $search_method = ''; $crit = ''; } } else { $search_method = ''; $crit = ''; } $criteria .= callback_event('admin_criteria', 'author_list', 0, $criteria); $total = getCount('txp_users', $criteria); if ($total < 1) { if ($criteria != 1) { echo n . author_search_form($crit, $search_method) . graf(gTxt('no_results_found'), ' class="indicator"') . '</div>'; } return; } $limit = max($author_list_pageby, 15); list($page, $offset, $numPages) = pager($total, $limit, $page); $use_multi_edit = has_privs('admin.edit') && safe_count('txp_users', '1=1') > 1; echo author_search_form($crit, $search_method) . '</div>'; $rs = safe_rows_start('*, unix_timestamp(last_access) as last_login', 'txp_users', "{$criteria} order by {$sort_sql} limit {$offset}, {$limit}"); if ($rs) { echo n . tag_start('div', array('id' => 'users_container', 'class' => 'txp-container')) . n . tag_start('form', array('action' => 'index.php', 'id' => 'users_form', 'class' => 'multi_edit_form', 'method' => 'post', 'name' => 'longform')) . n . tag_start('div', array('class' => 'txp-listtables')) . n . tag_start('table', array('class' => 'txp-list')) . n . tag_start('thead') . tr(($use_multi_edit ? hCell(fInput('checkbox', 'select_all', 0, '', '', '', '', '', 'select_all'), '', ' scope="col" title="' . gTxt('toggle_all_selected') . '" class="txp-list-col-multi-edit"') : hCell('', '', ' scope="col" class="txp-list-col-multi-edit"')) . column_head('login_name', 'name', 'admin', true, $switch_dir, '', '', ('name' == $sort ? "{$dir} " : '') . 'txp-list-col-login-name name') . column_head('real_name', 'RealName', 'admin', true, $switch_dir, '', '', ('RealName' == $sort ? "{$dir} " : '') . 'txp-list-col-real-name name') . column_head('email', 'email', 'admin', true, $switch_dir, '', '', ('email' == $sort ? "{$dir} " : '') . 'txp-list-col-email') . column_head('privileges', 'privs', 'admin', true, $switch_dir, '', '', ('privs' == $sort ? "{$dir} " : '') . 'txp-list-col-privs') . column_head('last_login', 'last_login', 'admin', true, $switch_dir, '', '', ('last_login' == $sort ? "{$dir} " : '') . 'txp-list-col-last-login date')) . n . tag_end('thead') . n . tag_start('tbody'); while ($a = nextRow($rs)) { extract(doSpecial($a)); echo tr(td((has_privs('admin.edit') and $txp_user != $a['name']) ? fInput('checkbox', 'selected[]', $a['name'], 'checkbox') : '', '', 'txp-list-col-multi-edit') . hCell(has_privs('admin.edit') ? eLink('admin', 'author_edit', 'user_id', $user_id, $name) : $name, '', ' scope="row" class="txp-list-col-login-name name"') . td($RealName, '', 'txp-list-col-real-name name') . td(href($email, 'mailto:' . $email), '', 'txp-list-col-email') . td(get_priv_level($privs), '', 'txp-list-col-privs') . td($last_login ? safe_strftime('%b %Y', $last_login) : '', '', 'txp-list-col-last-login date')); } echo n . tag_end('tbody') . n . tag_end('table') . n . tag_end('div') . ($use_multi_edit ? author_multiedit_form($page, $sort, $dir, $crit, $search_method) : '') . tInput() . n . tag_end('form') . n . tag_start('div', array('id' => 'users_navigation', 'class' => 'txp-navigation')) . pageby_form('admin', $author_list_pageby) . nav_form('admin', $page, $numPages, $sort, $dir, $crit, $search_method) . n . tag_end('div') . n . tag_end('div'); } } else { echo n . tag_end('div'); } }
function article_edit($message = "") { global $txpcfg, $txp_user, $vars; extract(get_prefs()); extract(gpsa(array('view', 'from_view', 'step'))); if (!empty($GLOBALS['ID'])) { // newly-saved article $ID = intval($GLOBALS['ID']); $step = 'edit'; } else { $ID = gps('ID'); } include_once $txpcfg['txpath'] . '/lib/classTextile.php'; $textile = new Textile(); if (!$view) { $view = "text"; } if (!$step) { $step = "create"; } if ($step == "edit" && $view == "text" && !empty($ID) && $from_view != "preview" && $from_view != 'html') { $pull = true; //-- it's an existing article - off we go to the db $rs = safe_row("*, unix_timestamp(Posted) as sPosted,\n\t\t\t\tunix_timestamp(LastMod) as sLastMod", "textpattern", "ID={$ID}"); extract($rs); if ($AnnotateInvite != $comments_default_invite) { $AnnotateInvite = $AnnotateInvite; } else { $AnnotateInvite = $comments_default_invite; } } else { $pull = false; //-- assume they came from post if (!$from_view or $from_view == 'text') { extract(gpsa($vars)); } elseif ($from_view == 'preview' or $from_view == 'html') { // coming from either html or preview if (isset($_POST['store'])) { $store = unserialize(base64_decode($_POST['store'])); extract($store); } } foreach ($vars as $var) { if (isset(${$var})) { $store_out[$var] = ${$var}; } } } $GLOBALS['step'] = $step; if ($step == 'create') { $textile_body = 1; $textile_excerpt = 1; } if ($step != 'create') { // Previous record? $prev_id = checkIfNeighbour('prev', $sPosted); // Next record? $next_id = checkIfNeighbour('next', $sPosted); } pagetop($Title, $message); echo '<form action="index.php" method="post" name="article">'; if (!empty($store_out)) { echo hInput('store', base64_encode(serialize($store_out))); } echo hInput('ID', $ID), eInput('article'), sInput($step); echo '<input type="hidden" name="view" />', startTable('edit'); echo '<tr><td> </td><td colspan="3">', $view == 'preview' ? hed(ucfirst(gTxt('preview')), 2) . graf($Title) : '', $view == 'html' ? hed('XHTML', 2) . graf($Title) : '', $view == 'text' ? br . '<input type="text" name="Title" value="' . cleanfInput($Title) . '" class="edit" size="40" tabindex="1" />' : '', '</td></tr>'; //-- article input -------------- echo '<tr> <td valign="top">', $view == 'text' && $use_textile == 2 ? '<p><a href="#" onclick="toggleDisplay(\'textile_help\');">' . gTxt('textile_help') . '</a></p> <div id="textile_help" style="display:none;">' . sidehelp() . '</div>' : sp; if ($view == 'text') { echo '<p><a href="#" onclick="toggleDisplay(\'advanced\');">' . gTxt('advanced_options') . '</a></p>', '<div id="advanced" style="display:none;">', graf(gTxt('use_textile') . br . tag(checkbox2('textile_body', $textile_body) . gTxt('article'), 'label') . br . tag(checkbox2('textile_excerpt', $textile_excerpt) . gTxt('excerpt'), 'label')), $allow_form_override ? graf(gTxt('override_default_form') . br . form_pop($override_form) . popHelp('override_form')) : '', $custom_1_set ? custField(1, $custom_1_set, $custom_1) : '', $custom_2_set ? custField(2, $custom_2_set, $custom_2) : '', $custom_3_set ? custField(3, $custom_3_set, $custom_3) : '', $custom_4_set ? custField(4, $custom_4_set, $custom_4) : '', $custom_5_set ? custField(5, $custom_5_set, $custom_5) : '', $custom_6_set ? custField(6, $custom_6_set, $custom_6) : '', $custom_7_set ? custField(7, $custom_7_set, $custom_7) : '', $custom_8_set ? custField(8, $custom_8_set, $custom_8) : '', $custom_9_set ? custField(9, $custom_9_set, $custom_9) : '', $custom_10_set ? custField(10, $custom_10_set, $custom_10) : '', graf(gTxt('keywords') . popHelp('keywords') . br . '<textarea name="Keywords" style="width:100px;height:80px" rows="1" cols="1">' . $Keywords . '</textarea>'), graf(gTxt('article_image') . popHelp('article_image') . br . fInput('text', 'Image', $Image, 'edit')), graf(gTxt('url_title') . popHelp('url_title') . br . fInput('text', 'url_title', $url_title, 'edit')) . '</div> <p><a href="#" onclick="toggleDisplay(\'recent\');">' . gTxt('recent_articles') . '</a>' . '</p>' . '<div id="recent" style="display:none;">'; $recents = safe_rows_start("Title, ID", 'textpattern', "1 order by LastMod desc limit 10"); if ($recents) { echo '<p>'; while ($recent = nextRow($recents)) { extract($recent); if (!$Title) { $Title = gTxt('untitled') . sp . $ID; } echo '<a href="?event=article' . a . 'step=edit' . a . 'ID=' . $ID . '">' . $Title . '</a>' . br . n; } echo '</p>'; } echo '</div>'; } else { echo sp; } echo '</td> <td valign="top" style="width:400px">'; if ($view == "preview") { if ($use_textile == 2) { echo $textile->TextileThis($Body); } else { if ($use_textile == 1) { echo nl2br($Body); } else { if ($use_textile == 0) { echo $Body; } } } } elseif ($view == "html") { if ($use_textile == 2) { $bod = $textile->TextileThis($Body); } else { if ($use_textile == 1) { $bod = nl2br($Body); } else { if ($use_textile == 0) { $bod = $Body; } } } echo tag(str_replace(array(n, t), array(br, sp . sp . sp . sp), htmlspecialchars($bod)), 'code'); } else { echo '<textarea style="width:400px;height:420px" rows="1" cols="1" name="Body" tabindex="2">', htmlspecialchars($Body), '</textarea>'; } //-- excerpt -------------------- if ($articles_use_excerpts) { if ($view == 'text') { $Excerpt = str_replace("&", "&", htmlspecialchars($Excerpt)); echo graf(gTxt('excerpt') . popHelp('excerpt') . br . '<textarea style="width:400px;height:50px" rows="1" cols="1" name="Excerpt" tabindex="3">' . $Excerpt . '</textarea>'); } else { echo '<hr width="50%" />'; echo $textile_excerpt ? $view == 'preview' ? graf($textile->textileThis($Excerpt), 1) : tag(str_replace(array(n, t), array(br, sp . sp . sp . sp), htmlspecialchars($textile->TextileThis($Excerpt), 1)), 'code') : graf($Excerpt); } } //-- author -------------- if ($view == "text" && $step != "create") { echo "<p><small>" . gTxt('posted_by') . " {$AuthorID}: ", date("H:i, d M y", $sPosted + tz_offset()); if ($sPosted != $sLastMod) { echo br . gTxt('modified_by') . " {$LastModID}: ", date("H:i, d M y", $sLastMod + tz_offset()); } echo '</small></p>'; } echo hInput('from_view', $view), '</td>'; echo '<td valign="top" align="left" width="20">'; //-- layer tabs ------------------- echo $use_textile == 2 ? tab('text', $view) . tab('html', $view) . tab('preview', $view) : ' '; echo '</td>'; ?> <td width="200" valign="top" style="padding-left:10px" align="left" id="articleside"> <?php //-- prev/next article links -- if ($view == 'text') { if ($step != 'create' and ($prev_id or $next_id)) { echo '<p>', $prev_id ? prevnext_link('‹' . gTxt('prev'), 'article', 'edit', $prev_id, gTxt('prev')) : '', $next_id ? prevnext_link(gTxt('next') . '›', 'article', 'edit', $next_id, gTxt('next')) : '', '</p>'; } } //-- status radios -------------- echo $view == 'text' ? n . graf(status_radio($Status)) . n : ''; //-- category selects ----------- echo $view == 'text' ? graf(gTxt('categorize') . ' [' . eLink('category', '', '', '', gTxt('edit')) . ']' . br . category_popup('Category1', $Category1) . category_popup('Category2', $Category2)) : ''; //-- section select -------------- if (!$from_view && !$pull) { $Section = getDefaultSection(); } echo $view == 'text' ? graf(gTxt('section') . ' [' . eLink('section', '', '', '', gTxt('edit')) . ']' . br . section_popup($Section)) : ''; //-- comments stuff -------------- if ($step == "create") { //Avoiding invite disappear when previewing $AnnotateInvite = !empty($store_out['AnnotateInvite']) ? $store_out['AnnotateInvite'] : $comments_default_invite; if ($comments_on_default == 1) { $Annotate = 1; } } echo $use_comments == 1 && $view == 'text' ? graf(gTxt('comments') . onoffRadio("Annotate", $Annotate) . '<br />' . gTxt('comment_invitation') . '<br />' . fInput('text', 'AnnotateInvite', $AnnotateInvite, 'edit')) : ''; //-- timestamp ------------------- if ($step == "create" and empty($GLOBALS['ID'])) { if ($view == 'text') { //Avoiding modified date to disappear $persist_timestamp = !empty($store_out['year']) ? mktime($store_out['hour'], $store_out['minute'], '00', $store_out['month'], $store_out['day'], $store_out['year']) : time(); echo graf(tag(checkbox('publish_now', '1') . gTxt('set_to_now'), 'label')), '<p>', gTxt('or_publish_at'), popHelp("timestamp"), br, tsi('year', 'Y', $persist_timestamp), tsi('month', 'm', $persist_timestamp), tsi('day', 'd', $persist_timestamp), sp, tsi('hour', 'H', $persist_timestamp), ':', tsi('minute', 'i', $persist_timestamp), '</p>'; } //-- publish button -------------- if ($view == 'text') { echo has_privs('article.publish') ? fInput('submit', 'publish', gTxt('publish'), "publish") : fInput('submit', 'publish', gTxt('save'), "publish"); } } else { if ($view == 'text') { echo '<p>', gTxt('published_at'), popHelp("timestamp"), br, tsi('year', 'Y', $sPosted, 5), tsi('month', 'm', $sPosted, 6), tsi('day', 'd', $sPosted, 7), sp, tsi('hour', 'H', $sPosted, 8), ':', tsi('minute', 'i', $sPosted, 9), '</p>', hInput('sPosted', $sPosted), hInput('sLastMod', $sLastMod), hInput('AuthorID', $AuthorID), hInput('LastModID', $LastModID), graf(checkbox('reset_time', '1', 0) . gTxt('reset_time')); } //-- save button -------------- if ($view == 'text') { if ($Status >= 4 and has_privs('article.edit.published') or $Status >= 4 and $AuthorID == $txp_user and has_privs('article.edit.own.published') or $Status < 4 and has_privs('article.edit') or $Status < 4 and $AuthorID == $txp_user and has_privs('article.edit.own')) { echo fInput('submit', 'save', gTxt('save'), "publish"); } } } echo '</td></tr></table></form>'; }
function section_edit() { global $event, $step, $txp_user, $all_pages, $all_styles; $name = gps('name'); $is_edit = $name && $step == 'section_edit'; if ($is_edit) { $name = assert_string($name); $rs = safe_row('*', 'txp_section', "name = '" . doSlash($name) . "'"); } else { $rs = array_flip(getThings('describe `' . PFX . 'txp_section`')); } if ($rs) { if (!has_privs('section.edit')) { sec_section_list(gTxt('restricted_area')); return; } pagetop(gTxt('tab_sections')); extract($rs, EXTR_PREFIX_ALL, 'sec'); extract(gpsa(array('page', 'sort', 'dir', 'crit', 'search_method'))); $is_default_section = $is_edit && $sec_name == 'default'; $caption = gTxt($is_default_section ? 'edit_default_section' : ($is_edit ? 'edit_section' : 'create_section')); if (!$is_edit) { // Pulling out the radio items from the default entry might seem pointless since they can't be directly // edited, but they will take on either: // a) the default (SQL) values as defined at table creation time, or // b) the values set when a multi-edit was performed that included the default section (because the values are silently updated then) $default = doSlash(safe_row('page, css, on_frontpage, in_rss, searchable', 'txp_section', "name = 'default'")); $sec_name = $sec_title = ''; $sec_page = $default['page']; $sec_css = $default['css']; $sec_on_frontpage = $default['on_frontpage']; $sec_in_rss = $default['in_rss']; $sec_searchable = $default['searchable']; } echo '<div id="' . $event . '_container" class="txp-container">'; echo form('<div class="txp-edit">' . hed($caption, 2) . ($is_default_section ? hInput('name', 'default') : inputLabel('section_name', fInput('text', 'name', $sec_name, '', '', '', INPUT_REGULAR, '', 'section_name'), 'section_name')) . ($is_default_section ? '' : inputLabel('section_title', fInput('text', 'title', $sec_title, '', '', '', INPUT_REGULAR, '', 'section_title'), 'section_longtitle')) . inputLabel('section_page', selectInput('section_page', $all_pages, $sec_page, '', '', 'section_page'), 'uses_page', 'section_uses_page') . inputLabel('section_css', selectInput('css', $all_styles, $sec_css, '', '', 'section_css'), 'uses_style', 'section_uses_css') . ($is_default_section ? '' : inputLabel('on_front_page', yesnoradio('on_frontpage', $sec_on_frontpage, '', $sec_name), '', 'section_on_frontpage')) . ($is_default_section ? '' : inputLabel('syndicate', yesnoradio('in_rss', $sec_in_rss, '', $sec_name), '', 'section_syndicate')) . ($is_default_section ? '' : inputLabel('include_in_search', yesnoradio('searchable', $sec_searchable, '', $sec_name), '', 'section_searchable')) . pluggable_ui('section_ui', 'extend_detail_form', '', $rs) . graf(fInput('submit', '', gTxt('save'), 'publish')) . eInput('section') . sInput('section_save') . hInput('old_name', $sec_name) . hInput('search_method', $search_method) . hInput('crit', $crit) . hInput('page', $page) . hInput('sort', $sort) . hInput('dir', $dir) . '</div>', '', '', 'post', 'edit-form', '', 'section_details'); echo '</div>'; } }
function mail_comment($message, $cname, $cemail, $cweb, $parentid, $discussid) { global $sitename; $parentid = assert_int($parentid); $discussid = assert_int($discussid); $article = safe_row("Section, Posted, ID, url_title, AuthorID, Title", "textpattern", "ID = {$parentid}"); extract($article); extract(safe_row("RealName, email", "txp_users", "name = '" . doSlash($AuthorID) . "'")); $evaluator =& get_comment_evaluator(); $out = gTxt('greeting') . " {$RealName}," . n . n; $out .= str_replace('{title}', $Title, gTxt('comment_recorded')) . n; $out .= permlinkurl_id($parentid) . n; if (has_privs('discuss', $AuthorID)) { $out .= hu . 'textpattern/index.php?event=discuss&step=discuss_edit&discussid=' . $discussid . n; } $out .= gTxt('status') . ": " . $evaluator->get_result('text') . '. ' . implode(',', $evaluator->get_result_message()) . n; $out .= n; $out .= gTxt('comment_name') . ": {$cname}" . n; $out .= gTxt('comment_email') . ": {$cemail}" . n; $out .= gTxt('comment_web') . ": {$cweb}" . n; $out .= gTxt('comment_comment') . ": {$message}"; $subject = strtr(gTxt('comment_received'), array('{site}' => $sitename, '{title}' => $Title)); $success = txpMail($email, $subject, $out, $cemail); }
function _sed_si_section_pre($event, $step) { if (!has_privs('section')) { return; } ob_start('_sed_si_inject_section_admin'); }
function php($atts, $thing) { global $is_article_body, $thisarticle, $prefs; ob_start(); if (empty($is_article_body)) { if (!empty($prefs['allow_page_php_scripting'])) { eval($thing); } } else { if (!empty($prefs['allow_article_php_scripting']) and has_privs('article.php', $thisarticle['authorid'])) { eval($thing); } } return ob_get_clean(); }
/** * 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>'; }
/** * The main panel listing all sections. * * So-named to avoid clashing with the <txp:section_list /> tag. * * @param string|array $message The activity message */ 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', 'name'); } else { if (!in_array($sort, array('title', 'page', 'css', 'in_rss', 'on_frontpage', 'searchable', 'article_count'))) { $sort = 'name'; } set_pref('section_sort_column', $sort, 'section', 2, '', 0, PREF_PRIVATE); } if ($dir === '') { $dir = get_pref('section_sort_dir', 'desc'); } else { $dir = $dir == 'asc' ? "asc" : "desc"; set_pref('section_sort_dir', $dir, 'section', 2, '', 0, PREF_PRIVATE); } 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; } $switch_dir = $dir == 'desc' ? 'asc' : 'desc'; $search = new Filter($event, array('name' => array('column' => 'txp_section.name', 'label' => gTxt('name')), 'title' => array('column' => 'txp_section.title', 'label' => gTxt('title')), 'page' => array('column' => 'txp_section.page', 'label' => gTxt('page')), 'css' => array('column' => 'txp_section.css', 'label' => gTxt('css')), 'on_frontpage' => array('column' => 'txp_section.on_frontpage', 'label' => gTxt('on_front_page'), 'type' => 'boolean'), 'in_rss' => array('column' => 'txp_section.in_rss', 'label' => gTxt('syndicate'), 'type' => 'boolean'), 'searchable' => array('column' => 'txp_section.searchable', 'label' => gTxt('include_in_search'), 'type' => 'boolean'))); $alias_yes = '1, Yes'; $alias_no = '0, No'; $search->setAliases('on_frontpage', array($alias_no, $alias_yes)); $search->setAliases('in_rss', array($alias_no, $alias_yes)); $search->setAliases('searchable', array($alias_no, $alias_yes)); list($criteria, $crit, $search_method) = $search->getFilter(); $search_render_options = array('placeholder' => 'search_sections'); $total = safe_count('txp_section', $criteria); echo n . tag(hed(gTxt('tab_sections'), 1, array('class' => 'txp-heading')), 'div', array('class' => 'txp-layout-2col-cell-1')); $searchBlock = n . tag($search->renderForm('sec_section', $search_render_options), 'div', array('class' => 'txp-layout-2col-cell-2', 'id' => $event . '_control')); $createBlock = array(); if (has_privs('section.edit')) { $createBlock[] = n . tag(sLink('section', 'section_edit', gTxt('create_section'), 'txp-button') . n . tag_start('form', array('class' => 'async', 'id' => 'default_section_form', 'name' => 'default_section_form', 'method' => 'post', 'action' => 'index.php')) . tag(gTxt('default_write_section'), 'label', array('for' => 'default_section')) . popHelp('section_default') . section_select_list() . eInput('section') . sInput('section_set_default') . n . tag_end('form'), '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')) . n . tag_end('div'); } return; } $limit = max($section_list_pageby, 15); list($page, $offset, $numPages) = pager($total, $limit, $page); echo $searchBlock . $contentBlockStart . $createBlock; $rs = safe_rows_start("*, (SELECT COUNT(*) FROM " . safe_pfx_j('textpattern') . " WHERE textpattern.Section = txp_section.name) AS article_count", 'txp_section', "{$criteria} ORDER BY {$sort_sql} LIMIT {$offset}, {$limit}"); if ($rs) { echo n . tag(toggle_box('section_detail'), 'div', array('class' => 'txp-list-options')) . n . tag_start('form', array('class' => 'multi_edit_form', 'id' => 'section_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('name', 'name', 'section', true, $switch_dir, $crit, $search_method, ('name' == $sort ? "{$dir} " : '') . 'txp-list-col-name') . column_head('title', 'title', 'section', true, $switch_dir, $crit, $search_method, ('title' == $sort ? "{$dir} " : '') . 'txp-list-col-title') . column_head('page', 'page', 'section', true, $switch_dir, $crit, $search_method, ('page' == $sort ? "{$dir} " : '') . 'txp-list-col-page') . column_head('css', 'css', 'section', true, $switch_dir, $crit, $search_method, ('css' == $sort ? "{$dir} " : '') . 'txp-list-col-style') . column_head('on_front_page', 'on_frontpage', 'section', true, $switch_dir, $crit, $search_method, ('on_frontpage' == $sort ? "{$dir} " : '') . 'txp-list-col-frontpage section_detail') . column_head('syndicate', 'in_rss', 'section', true, $switch_dir, $crit, $search_method, ('in_rss' == $sort ? "{$dir} " : '') . 'txp-list-col-syndicate section_detail') . column_head('include_in_search', 'searchable', 'section', true, $switch_dir, $crit, $search_method, ('searchable' == $sort ? "{$dir} " : '') . 'txp-list-col-searchable section_detail') . column_head('articles', 'article_count', 'section', true, $switch_dir, $crit, $search_method, ('article_count' == $sort ? "{$dir} " : '') . 'txp-list-col-article_count section_detail')) . n . tag_end('thead') . n . tag_start('tbody'); while ($a = nextRow($rs)) { extract($a, EXTR_PREFIX_ALL, 'sec'); $edit_url = array('event' => 'section', 'step' => 'section_edit', 'name' => $sec_name, 'sort' => $sort, 'dir' => $dir, 'page' => $page, 'search_method' => $search_method, 'crit' => $crit); if ($sec_name == 'default') { $articles = $sec_searchable = $sec_in_rss = $sec_on_frontpage = '-'; } else { $sec_on_frontpage = asyncHref(yes_no($sec_on_frontpage), array('step' => 'section_toggle_option', 'thing' => $sec_name, 'property' => 'on_frontpage')); $sec_in_rss = asyncHref(yes_no($sec_in_rss), array('step' => 'section_toggle_option', 'thing' => $sec_name, 'property' => 'in_rss')); $sec_searchable = asyncHref(yes_no($sec_searchable), array('step' => 'section_toggle_option', 'thing' => $sec_name, 'property' => 'searchable')); if ($sec_article_count > 0) { $articles = href($sec_article_count, array('event' => 'list', 'search_method' => 'section', 'crit' => '"' . $sec_name . '"'), array('title' => gTxt('article_count', array('{num}' => $sec_article_count)))); } else { $articles = 0; } } $sec_page = href(txpspecialchars($sec_page), array('event' => 'page', 'name' => $sec_page), array('title' => gTxt('edit'))); $sec_css = href(txpspecialchars($sec_css), array('event' => 'css', 'name' => $sec_css), array('title' => gTxt('edit'))); echo tr(td(fInput('checkbox', 'selected[]', $sec_name), '', 'txp-list-col-multi-edit') . hCell(href(txpspecialchars($sec_name), $edit_url, array('title' => gTxt('edit'))) . span(sp . span('|', array('role' => 'separator')) . sp . href(gTxt('view'), pagelinkurl(array('s' => $sec_name))), array('class' => 'txp-option-link section_detail')), '', array('class' => 'txp-list-col-name', 'scope' => 'row')) . td(txpspecialchars($sec_title), '', 'txp-list-col-title') . td($sec_page, '', 'txp-list-col-page') . td($sec_css, '', 'txp-list-col-style') . td($sec_on_frontpage, '', 'txp-list-col-frontpage section_detail') . td($sec_in_rss, '', 'txp-list-col-syndicate section_detail') . td($sec_searchable, '', 'txp-list-col-searchable section_detail') . td($articles, '', 'txp-list-col-article_count section_detail'), array('id' => 'txp_section_' . $sec_name)); } echo n . tag_end('tbody') . n . tag_end('table') . n . tag_end('div') . section_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('section', $section_list_pageby) . nav_form('section', $page, $numPages, $sort, $dir, $crit, $search_method, $total, $limit) . n . tag_end('div'); } echo n . tag_end('div'); }
/** * Renders article editor form. * * @param string|array $message The activity message * @param bool $concurrent Treat as a concurrent save * @param bool $refresh_partials Whether refresh partial contents */ function article_edit($message = '', $concurrent = false, $refresh_partials = false) { global $vars, $txp_user, $prefs, $event, $view; extract($prefs); /* $partials is an array of: $key => array ( 'mode' => {PARTIAL_STATIC | PARTIAL_VOLATILE | PARTIAL_VOLATILE_VALUE}, 'selector' => $DOM_selector, 'cb' => $callback_function, 'html' => $return_value_of_callback_function (need not be intialised here) ) */ $partials = array('html_title' => array('mode' => PARTIAL_VOLATILE, 'selector' => 'title', 'cb' => 'article_partial_html_title'), 'sLastMod' => array('mode' => PARTIAL_VOLATILE_VALUE, 'selector' => '[name=sLastMod]', 'cb' => 'article_partial_value'), 'sPosted' => array('mode' => PARTIAL_VOLATILE_VALUE, 'selector' => '[name=sPosted]', 'cb' => 'article_partial_value'), 'sidehelp' => array('mode' => PARTIAL_VOLATILE, 'selector' => '#textfilter_group', 'cb' => 'article_partial_sidehelp'), 'url_title' => array('mode' => PARTIAL_STATIC, 'selector' => 'p.url-title', 'cb' => 'article_partial_url_title'), 'url_title_value' => array('mode' => PARTIAL_VOLATILE_VALUE, 'selector' => '#url-title', 'cb' => 'article_partial_url_title_value'), 'description' => array('mode' => PARTIAL_STATIC, 'selector' => 'p.description', 'cb' => 'article_partial_description'), 'description_value' => array('mode' => PARTIAL_VOLATILE_VALUE, 'selector' => '#description', 'cb' => 'article_partial_description_value'), 'keywords' => array('mode' => PARTIAL_STATIC, 'selector' => 'p.keywords', 'cb' => 'article_partial_keywords'), 'keywords_value' => array('mode' => PARTIAL_VOLATILE_VALUE, 'selector' => '#keywords', 'cb' => 'article_partial_keywords_value'), 'image' => array('mode' => PARTIAL_STATIC, 'selector' => '#image_group', 'cb' => 'article_partial_image'), 'custom_fields' => array('mode' => PARTIAL_STATIC, 'selector' => '#custom_field_group', 'cb' => 'article_partial_custom_fields'), 'recent_articles' => array('mode' => PARTIAL_VOLATILE, 'selector' => '#recent_group .recent', 'cb' => 'article_partial_recent_articles'), 'title' => array('mode' => PARTIAL_STATIC, 'selector' => 'p.title', 'cb' => 'article_partial_title'), 'title_value' => array('mode' => PARTIAL_VOLATILE_VALUE, 'selector' => '#title', 'cb' => 'article_partial_title_value'), 'article_clone' => array('mode' => PARTIAL_VOLATILE, 'selector' => '#article_partial_article_clone', 'cb' => 'article_partial_article_clone'), 'article_view' => array('mode' => PARTIAL_VOLATILE, 'selector' => '#article_partial_article_view', 'cb' => 'article_partial_article_view'), 'body' => array('mode' => PARTIAL_STATIC, 'selector' => 'p.body', 'cb' => 'article_partial_body'), 'excerpt' => array('mode' => PARTIAL_STATIC, 'selector' => 'p.excerpt', 'cb' => 'article_partial_excerpt'), 'author' => array('mode' => PARTIAL_VOLATILE, 'selector' => 'p.author', 'cb' => 'article_partial_author'), 'view_modes' => array('mode' => PARTIAL_VOLATILE, 'selector' => '#view_modes', 'cb' => 'article_partial_view_modes'), 'article_nav' => array('mode' => PARTIAL_VOLATILE, 'selector' => 'p.nav-tertiary', 'cb' => 'article_partial_article_nav'), 'status' => array('mode' => PARTIAL_VOLATILE, 'selector' => '#write-status', 'cb' => 'article_partial_status'), 'categories' => array('mode' => PARTIAL_STATIC, 'selector' => '#categories_group', 'cb' => 'article_partial_categories'), 'section' => array('mode' => PARTIAL_STATIC, 'selector' => 'p.section', 'cb' => 'article_partial_section'), 'comments' => array('mode' => PARTIAL_VOLATILE, 'selector' => '#write-comments', 'cb' => 'article_partial_comments'), 'posted' => array('mode' => PARTIAL_VOLATILE, 'selector' => '#write-timestamp', 'cb' => 'article_partial_posted'), 'expires' => array('mode' => PARTIAL_VOLATILE, 'selector' => '#write-expires', 'cb' => 'article_partial_expires')); // Add partials for custom fields (and their values which is redundant by // design, for plugins). global $cfs; foreach ($cfs as $k => $v) { $partials["custom_field_{$k}"] = array('mode' => PARTIAL_STATIC, 'selector' => "p.custom-field.custom-{$k}", 'cb' => 'article_partial_custom_field'); $partials["custom_{$k}"] = array('mode' => PARTIAL_STATIC, 'selector' => "#custom-{$k}", 'cb' => 'article_partial_value'); } extract(gpsa(array('view', 'from_view', 'step'))); // Newly-saved article. if (!empty($GLOBALS['ID'])) { $ID = $GLOBALS['ID']; $step = 'edit'; } else { $ID = gps('ID'); } // Switch to 'text' view upon page load and after article post. if (!$view || gps('save') || gps('publish')) { $view = 'text'; } if (!$step) { $step = "create"; } if ($step == "edit" && $view == "text" && !empty($ID) && $from_view != 'preview' && $from_view != 'html' && !$concurrent) { $pull = true; // It's an existing article - off we go to the database. $ID = assert_int($ID); $rs = safe_row("*, UNIX_TIMESTAMP(Posted) AS sPosted,\n UNIX_TIMESTAMP(Expires) AS sExpires,\n UNIX_TIMESTAMP(LastMod) AS sLastMod", 'textpattern', "ID = {$ID}"); if (empty($rs)) { return; } $rs['reset_time'] = $rs['publish_now'] = false; } else { $pull = false; // Assume they came from post. if ($from_view == 'preview' or $from_view == 'html') { $store_out = array(); $store = unserialize(base64_decode(ps('store'))); foreach ($vars as $var) { if (isset($store[$var])) { $store_out[$var] = $store[$var]; } } } else { $store_out = gpsa($vars); if ($concurrent) { $store_out['sLastMod'] = safe_field("UNIX_TIMESTAMP(LastMod) AS sLastMod", 'textpattern', "ID = {$ID}"); } if (!has_privs('article.set_markup') && !empty($ID)) { $oldArticle = safe_row("textile_body, textile_excerpt", 'textpattern', "ID = {$ID}"); if (!empty($oldArticle)) { $store_out['textile_body'] = $oldArticle['textile_body']; $store_out['textile_excerpt'] = $oldArticle['textile_excerpt']; } } } // Use preferred Textfilter as default and fallback. $hasfilter = new \Textpattern\Textfilter\Constraint(null); $validator = new Validator(); foreach (array('textile_body', 'textile_excerpt') as $k) { $hasfilter->setValue($store_out[$k]); $validator->setConstraints($hasfilter); if (!$validator->validate()) { $store_out[$k] = $use_textile; } } $rs = textile_main_fields($store_out); if (!empty($rs['exp_year'])) { if (empty($rs['exp_month'])) { $rs['exp_month'] = 1; } if (empty($rs['exp_day'])) { $rs['exp_day'] = 1; } if (empty($rs['exp_hour'])) { $rs['exp_hour'] = 0; } if (empty($rs['exp_minute'])) { $rs['exp_minute'] = 0; } if (empty($rs['exp_second'])) { $rs['exp_second'] = 0; } $rs['sExpires'] = safe_strtotime($rs['exp_year'] . '-' . $rs['exp_month'] . '-' . $rs['exp_day'] . ' ' . $rs['exp_hour'] . ':' . $rs['exp_minute'] . ':' . $rs['exp_second']); } if (!empty($rs['year'])) { $rs['sPosted'] = safe_strtotime($rs['year'] . '-' . $rs['month'] . '-' . $rs['day'] . ' ' . $rs['hour'] . ':' . $rs['minute'] . ':' . $rs['second']); } } $validator = new Validator(new SectionConstraint($rs['Section'])); if (!$validator->validate()) { $rs['Section'] = getDefaultSection(); } extract($rs); $GLOBALS['step'] = $step; if ($step != 'create' && isset($sPosted)) { // Previous record? $rs['prev_id'] = checkIfNeighbour('prev', $sPosted); // Next record? $rs['next_id'] = checkIfNeighbour('next', $sPosted); } else { $rs['prev_id'] = $rs['next_id'] = 0; } // Let plugins chime in on partials meta data. callback_event_ref('article_ui', 'partials_meta', 0, $rs, $partials); $rs['partials_meta'] =& $partials; // Get content for volatile partials. foreach ($partials as $k => $p) { if ($p['mode'] == PARTIAL_VOLATILE || $p['mode'] == PARTIAL_VOLATILE_VALUE) { $cb = $p['cb']; $partials[$k]['html'] = is_array($cb) ? call_user_func($cb, $rs, $k) : $cb($rs, $k); } } if ($refresh_partials) { $response[] = announce($message); $response[] = '$("#article_form [type=submit]").val(textpattern.gTxt("save"))'; if ($Status < STATUS_LIVE) { $response[] = '$("#article_form").addClass("saved").removeClass("published")'; } else { $response[] = '$("#article_form").addClass("published").removeClass("saved")'; } // Update the volatile partials. foreach ($partials as $k => $p) { // Volatile partials need a target DOM selector. if (empty($p['selector']) && $p['mode'] != PARTIAL_STATIC) { trigger_error("Empty selector for partial '{$k}'", E_USER_ERROR); } else { // Build response script. if ($p['mode'] == PARTIAL_VOLATILE) { // Volatile partials replace *all* of the existing HTML // fragment for their selector. $response[] = '$("' . $p['selector'] . '").replaceWith("' . escape_js($p['html']) . '")'; } elseif ($p['mode'] == PARTIAL_VOLATILE_VALUE) { // Volatile partial values replace the *value* of elements // matching their selector. $response[] = '$("' . $p['selector'] . '").val("' . escape_js($p['html']) . '")'; } } } send_script_response(join(";\n", $response)); // Bail out. return; } foreach ($partials as $k => $p) { if ($p['mode'] == PARTIAL_STATIC) { $cb = $p['cb']; $partials[$k]['html'] = is_array($cb) ? call_user_func($cb, $rs, $k) : $cb($rs, $k); } } $page_title = $ID ? $Title : gTxt('write'); pagetop($page_title, $message); $class = array(); if ($Status >= STATUS_LIVE) { $class[] = 'published'; } elseif ($ID) { $class[] = 'saved'; } if ($step !== 'create') { $class[] = 'async'; } echo n . tag_start('form', array('class' => $class, 'id' => 'article_form', 'name' => 'article_form', 'method' => 'post', 'action' => 'index.php')); if (!empty($store_out)) { echo hInput('store', base64_encode(serialize($store_out))); } echo hInput('ID', $ID) . eInput('article') . sInput($step) . hInput('sPosted', $sPosted) . hInput('sLastMod', $sLastMod) . hInput('AuthorID', $AuthorID) . hInput('LastModID', $LastModID) . n . '<input type="hidden" name="view" />'; echo n . '<div class="txp-layout-4col-cell-1-2-3">' . hed(gTxt('tab_write'), 1, array('class' => 'txp-heading')); echo n . '<div role="region" id="main_content">'; // View mode tabs. echo $partials['view_modes']['html']; // Title input. if ($view == 'preview') { echo n . '<div class="preview">' . graf(gTxt('title'), array('class' => 'alert-block information')) . hed($Title, 1, ' class="title"'); } elseif ($view == 'html') { echo n . '<div class="html">' . graf(gTxt('title'), array('class' => 'alert-block information')) . hed($Title, 1, ' class="title"'); } elseif ($view == 'text') { echo n . '<div class="text">' . $partials['title']['html']; } // Body. if ($view == 'preview') { echo n . '<div class="body">' . n . graf(gTxt('body'), array('class' => 'alert-block information')) . $Body_html . '</div>'; } elseif ($view == 'html') { echo graf(gTxt('body'), array('class' => 'alert-block information')) . n . tag(str_replace(array(n, t), array(br, sp . sp . sp . sp), txpspecialchars($Body_html)), 'pre', ' class="body"'); } else { echo $partials['body']['html']; } // Excerpt. if ($articles_use_excerpts) { if ($view == 'preview') { echo n . '<div class="excerpt">' . graf(gTxt('excerpt'), array('class' => 'alert-block information')) . $Excerpt_html . '</div>'; } elseif ($view == 'html') { echo graf(gTxt('excerpt'), array('class' => 'alert-block information')) . n . tag(str_replace(array(n, t), array(br, sp . sp . sp . sp), txpspecialchars($Excerpt_html)), 'pre', array('class' => 'excerpt')); } else { echo $partials['excerpt']['html']; } } echo hInput('from_view', $view), n . '</div>'; // Author. if ($view == "text" && $step != "create") { echo $partials['author']['html']; } echo n . '</div>' . n . '</div>'; // End of .txp-layout-4col-cell-1-2-3. // Sidebar column (only shown if in text editing view). if ($view == 'text') { echo n . '<div class="txp-layout-4col-cell-4alt">'; // 'Publish/Save' button. if ($step == 'create' and empty($GLOBALS['ID'])) { if (has_privs('article.publish')) { $push_button = fInput('submit', 'publish', gTxt('publish'), 'publish'); } else { $push_button = fInput('submit', 'publish', gTxt('save'), 'publish'); } echo graf($push_button, array('class' => 'txp-save')); } elseif ($Status >= STATUS_LIVE && has_privs('article.edit.published') || $Status >= STATUS_LIVE && $AuthorID === $txp_user && has_privs('article.edit.own.published') || $Status < STATUS_LIVE && has_privs('article.edit') || $Status < STATUS_LIVE && $AuthorID === $txp_user && has_privs('article.edit.own')) { echo graf(fInput('submit', 'save', gTxt('save'), 'publish'), array('class' => 'txp-save')); } // View/Duplicate/Create new article links. $an_cb = href('<span class="ui-icon ui-extra-icon-new-document"></span> ' . gTxt('create_new'), 'index.php?event=article', array('class' => 'txp-new')); $ac_cb = $rs['partials_meta']['article_clone']['cb']; $av_cb = $rs['partials_meta']['article_view']['cb']; echo $step != 'create' ? graf($an_cb . $ac_cb($rs) . $av_cb($rs), array('class' => 'txp-actions')) : ''; // Prev/next article links. if ($step != 'create' and ($rs['prev_id'] or $rs['next_id'])) { echo $partials['article_nav']['html']; } echo n . '<div role="region" id="supporting_content">'; // 'Sort and display' section. echo pluggable_ui('article_ui', 'sort_display', wrapRegion('txp-write-sort-group', $partials['status']['html'] . $partials['section']['html'] . $partials['categories']['html'], '', gTxt('sort_display')), $rs); // 'Date and time' collapsible section. if ($step == "create" and empty($GLOBALS['ID'])) { // Timestamp. // Avoiding modified date to disappear. if (!empty($store_out['year'])) { $persist_timestamp = safe_strtotime($store_out['year'] . '-' . $store_out['month'] . '-' . $store_out['day'] . ' ' . $store_out['hour'] . ':' . $store_out['minute'] . ':' . $store_out['second']); } else { $persist_timestamp = time(); } $posted_block = pluggable_ui('article_ui', 'timestamp', inputLabel('year', tsi('year', '%Y', $persist_timestamp, '', 'year') . ' <span role="separator">/</span> ' . tsi('month', '%m', $persist_timestamp, '', 'month') . ' <span role="separator">/</span> ' . tsi('day', '%d', $persist_timestamp, '', 'day'), 'publish_date', array('timestamp', 'instructions_publish_date'), array('class' => 'txp-form-field date posted')) . inputLabel('hour', tsi('hour', '%H', $persist_timestamp, '', 'hour') . ' <span role="separator">:</span> ' . tsi('minute', '%M', $persist_timestamp, '', 'minute') . ' <span role="separator">:</span> ' . tsi('second', '%S', $persist_timestamp, '', 'second'), 'publish_time', array('', 'instructions_publish_time'), array('class' => 'txp-form-field time posted')) . n . tag(checkbox('publish_now', '1', $publish_now, '', 'publish_now') . n . tag(gTxt('set_to_now'), 'label', array('for' => 'publish_now')), 'div', array('class' => 'posted-now')), array('sPosted' => $persist_timestamp) + $rs); // Expires. if (!empty($store_out['exp_year'])) { $persist_timestamp = safe_strtotime($store_out['exp_year'] . '-' . $store_out['exp_month'] . '-' . $store_out['exp_day'] . ' ' . $store_out['exp_hour'] . ':' . $store_out['exp_minute'] . ':' . $store_out['second']); } else { $persist_timestamp = 0; } $expires_block = pluggable_ui('article_ui', 'expires', inputLabel('exp_year', tsi('exp_year', '%Y', $persist_timestamp, '', 'exp_year') . ' <span role="separator">/</span> ' . tsi('exp_month', '%m', $persist_timestamp, '', 'exp_month') . ' <span role="separator">/</span> ' . tsi('exp_day', '%d', $persist_timestamp, '', 'exp_day'), 'expire_date', array('expires', 'instructions_expire_date'), array('class' => 'txp-form-field date expires')) . inputLabel('exp_hour', tsi('exp_hour', '%H', $persist_timestamp, '', 'exp_hour') . ' <span role="separator">:</span> ' . tsi('exp_minute', '%M', $persist_timestamp, '', 'exp_minute') . ' <span role="separator">:</span> ' . tsi('exp_second', '%S', $persist_timestamp, '', 'exp_second'), 'expire_time', array('', 'instructions_expire_time'), array('class' => 'txp-form-field time expires')), $rs); } else { // Timestamp. $posted_block = $partials['posted']['html']; // Expires. $expires_block = $partials['expires']['html']; } echo wrapRegion('txp-dates-group', $posted_block . $expires_block, 'txp-dates-group-content', 'date_settings', 'article_dates'); // 'Meta' collapsible section. // 'URL-only title' field. $html_url_title = $partials['url_title']['html']; // 'Description' field. $html_description = $partials['description']['html']; // 'Keywords' field. $html_keywords = $partials['keywords']['html']; echo wrapRegion('txp-meta-group', $html_url_title . $html_description . $html_keywords, 'txp-meta-group-content', 'meta', 'article_meta'); // 'Comment options' collapsible section. echo wrapRegion('txp-comments-group', $partials['comments']['html'], 'txp-comments-group-content', 'comment_settings', 'article_comments', $use_comments == 1 ? '' : 'empty'); // 'Article image' collapsible section. echo $partials['image']['html']; // 'Custom fields' collapsible section. echo $partials['custom_fields']['html']; // 'Advanced options' collapsible section. // 'Article markup'/'Excerpt markup' selection. if (has_privs('article.set_markup')) { $html_markup = inputLabel('markup-body', pref_text('textile_body', $textile_body, 'markup-body'), 'article_markup', array('', 'instructions_textile_body'), array('class' => 'txp-form-field markup markup-body')) . inputLabel('markup-excerpt', pref_text('textile_excerpt', $textile_excerpt, 'markup-excerpt'), 'excerpt_markup', array('', 'instructions_textile_excerpt'), array('class' => 'txp-form-field markup markup-excerpt')); } else { $html_markup = ''; } $html_markup = pluggable_ui('article_ui', 'markup', $html_markup, $rs); // 'Override form' selection. $form_pop = $allow_form_override ? form_pop($override_form, 'override-form') : ''; $html_override = $form_pop ? pluggable_ui('article_ui', 'override', inputLabel('override-form', $form_pop, 'override_default_form', array('override_form', 'instructions_override_form'), array('class' => 'txp-form-field override-form')), $rs) : ''; echo wrapRegion('txp-advanced-group', $html_markup . $html_override, 'txp-advanced-group-content', 'advanced_options', 'article_advanced'); // Custom menu entries. echo pluggable_ui('article_ui', 'extend_col_1', '', $rs); // 'Text formatting help' collapsible section. echo $partials['sidehelp']['html']; // 'Recent articles' collapsible section. echo wrapRegion('txp-recent-group', $partials['recent_articles']['html'], 'txp-recent-group-content', 'recent_articles', 'article_recent'); echo n . '</div>'; // End of #supporting_content. echo n . '</div>'; // End of .txp-layout-4col-cell-4alt. } echo tInput() . n . '</form>'; }
function doArticles($atts, $iscustom, $thing = NULL) { global $pretext, $prefs; extract($pretext); extract($prefs); $customFields = getCustomFields(); $customlAtts = array_null(array_flip($customFields)); //getting attributes $theAtts = lAtts(array('form' => 'default', 'listform' => '', 'searchform' => '', 'limit' => 10, 'pageby' => '', 'category' => '', 'section' => '', 'excerpted' => '', 'author' => '', 'sort' => '', 'sortby' => '', 'sortdir' => '', 'month' => '', 'keywords' => '', 'expired' => $publish_expired_articles, 'frontpage' => '', 'id' => '', 'time' => 'past', 'status' => '4', 'pgonly' => 0, 'searchall' => 1, 'searchsticky' => 0, 'allowoverride' => !$q and !$iscustom, 'offset' => 0, 'wraptag' => '', 'break' => '', 'label' => '', 'labeltag' => '', 'class' => '') + $customlAtts, $atts); // if an article ID is specified, treat it as a custom list $iscustom = !empty($theAtts['id']) ? true : $iscustom; //for the txp:article tag, some attributes are taken from globals; //override them before extract if (!$iscustom) { $theAtts['category'] = $c ? $c : ''; $theAtts['section'] = $s && $s != 'default' ? $s : ''; $theAtts['author'] = !empty($author) ? $author : ''; $theAtts['month'] = !empty($month) ? $month : ''; $theAtts['frontpage'] = $s && $s == 'default' ? true : false; $theAtts['excerpted'] = ''; } extract($theAtts); // if a listform is specified, $thing is for doArticle() - hence ignore here. if (!empty($listform)) { $thing = ''; } $pageby = empty($pageby) ? $limit : $pageby; // treat sticky articles differently wrt search filtering, etc $status = in_array(strtolower($status), array('sticky', '5')) ? 5 : 4; $issticky = $status == 5; // give control to search, if necessary if ($q && !$iscustom && !$issticky) { include_once txpath . '/publish/search.php'; $s_filter = $searchall ? filterSearch() : ''; $q = trim($q); $quoted = $q[0] === '"' && $q[strlen($q) - 1] === '"'; $q = doSlash($quoted ? trim(trim($q, '"')) : $q); // searchable article fields are limited to the columns of // the textpattern table and a matching fulltext index must exist. $cols = do_list($searchable_article_fields); if (empty($cols) or $cols[0] == '') { $cols = array('Title', 'Body'); } $match = ', match (`' . join('`, `', $cols) . "`) against ('{$q}') as score"; $search_terms = preg_replace('/\\s+/', ' ', str_replace(array('\\', '%', '_', '\''), array('\\\\', '\\%', '\\_', '\\\''), $q)); if ($quoted || empty($m) || $m === 'exact') { for ($i = 0; $i < count($cols); $i++) { $cols[$i] = "`{$cols[$i]}` like '%{$search_terms}%'"; } } else { $colJoin = $m === 'any' ? 'or' : 'and'; $search_terms = explode(' ', $search_terms); for ($i = 0; $i < count($cols); $i++) { $like = array(); foreach ($search_terms as $search_term) { $like[] = "`{$cols[$i]}` like '%{$search_term}%'"; } $cols[$i] = '(' . join(' ' . $colJoin . ' ', $like) . ')'; } } $cols = join(' or ', $cols); $search = " and ({$cols}) {$s_filter}"; // searchall=0 can be used to show search results for the current section only if ($searchall) { $section = ''; } if (!$sort) { $sort = 'score desc'; } } else { $match = $search = ''; if (!$sort) { $sort = 'Posted desc'; } } // for backwards compatibility // sortby and sortdir are deprecated if ($sortby) { trigger_error(gTxt('deprecated_attribute', array('{name}' => 'sortby')), E_USER_NOTICE); if (!$sortdir) { $sortdir = 'desc'; } else { trigger_error(gTxt('deprecated_attribute', array('{name}' => 'sortdir')), E_USER_NOTICE); } $sort = "{$sortby} {$sortdir}"; } elseif ($sortdir) { trigger_error(gTxt('deprecated_attribute', array('{name}' => 'sortdir')), E_USER_NOTICE); $sort = "Posted {$sortdir}"; } //Building query parts $frontpage = ($frontpage and (!$q or $issticky)) ? filterFrontPage() : ''; $category = join("','", doSlash(do_list($category))); $category = !$category ? '' : " and (Category1 IN ('" . $category . "') or Category2 IN ('" . $category . "'))"; $section = !$section ? '' : " and Section IN ('" . join("','", doSlash(do_list($section))) . "')"; $excerpted = $excerpted == 'y' || $excerpted == '1' ? " and Excerpt !=''" : ''; $author = !$author ? '' : " and AuthorID IN ('" . join("','", doSlash(do_list($author))) . "')"; $month = !$month ? '' : " and Posted like '" . doSlash($month) . "%'"; $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); } } //Allow keywords for no-custom articles. That tagging mode, you know if ($keywords) { $keys = doSlash(do_list($keywords)); foreach ($keys as $key) { $keyparts[] = "FIND_IN_SET('" . $key . "',Keywords)"; } $keywords = " and (" . join(' or ', $keyparts) . ")"; } if ($q and $searchsticky) { $statusq = ' and Status >= 4'; } elseif ($id) { $statusq = ' and Status >= 4'; } else { $statusq = ' and Status = ' . intval($status); } $where = "1=1" . $statusq . $time . $search . $id . $category . $section . $excerpted . $month . $author . $keywords . $custom . $frontpage; //do not paginate if we are on a custom list if (!$iscustom and !$issticky) { $grand_total = safe_count('textpattern', $where); $total = $grand_total - $offset; $numPages = ceil($total / $pageby); $pg = !$pg ? 1 : $pg; $pgoffset = $offset + ($pg - 1) * $pageby; // send paging info to txp:newer and txp:older $pageout['pg'] = $pg; $pageout['numPages'] = $numPages; $pageout['s'] = $s; $pageout['c'] = $c; $pageout['context'] = 'article'; $pageout['grand_total'] = $grand_total; $pageout['total'] = $total; global $thispage; if (empty($thispage)) { $thispage = $pageout; } if ($pgonly) { return; } } else { $pgoffset = $offset; } // preserve order of custom article ids unless 'sort' attribute is set if (!empty($atts['id']) && empty($atts['sort'])) { $safe_sort = 'field(id, ' . join(',', $ids) . ')'; } else { $safe_sort = doSlash($sort); } $rs = safe_rows_start("*, unix_timestamp(Posted) as uPosted, unix_timestamp(Expires) as uExpires, unix_timestamp(LastMod) as uLastMod" . $match, 'textpattern', $where . ' order by ' . $safe_sort . ' limit ' . intval($pgoffset) . ', ' . intval($limit)); // get the form name if ($q and !$iscustom and !$issticky) { $fname = $searchform ? $searchform : 'search_results'; } else { $fname = $listform ? $listform : $form; } if ($rs) { $count = 0; $last = numRows($rs); $articles = array(); while ($a = nextRow($rs)) { ++$count; populateArticleData($a); global $thisarticle, $uPosted, $limit; $thisarticle['is_first'] = $count == 1; $thisarticle['is_last'] = $count == $last; filterAtts($theAtts); // article form preview if (txpinterface === 'admin' && ps('Form')) { doAuth(); if (!has_privs('form')) { txp_status_header('401 Unauthorized'); exit(hed('401 Unauthorized', 1) . graf(gTxt('restricted_area'))); } $articles[] = parse(gps('Form')); } elseif ($allowoverride and $a['override_form']) { $articles[] = parse_form($a['override_form']); } else { $articles[] = $thing ? parse($thing) : parse_form($fname); } // sending these to paging_link(); Required? $uPosted = $a['uPosted']; unset($GLOBALS['thisarticle']); } return doLabel($label, $labeltag) . doWrap($articles, $wraptag, $break, $class); } }
function author_list($message = '') { global $txp_user, $author_list_pageby; pagetop(gTxt('tab_site_admin'), $message); if (is_disabled('mail')) { echo tag(gTxt('warn_mail_unavailable'), 'p', ' class="alert-block warning" '); } echo '<h1 class="txp-heading">' . gTxt('tab_site_admin') . '</h1>'; echo '<div id="users_control" class="txp-control-panel">'; // Change password button echo '<p class="txp-buttons">'; echo sLink('admin', 'new_pass_form', gTxt('change_password')); // Change email address button if (!has_privs('admin.edit')) { echo n . sLink('admin', 'change_email_form', gTxt('change_email_address')); } // User list if (has_privs('admin.list')) { extract(gpsa(array('page', 'sort', 'dir', 'crit', 'search_method'))); if ($sort === '') { $sort = get_pref('admin_sort_column', 'name'); } if ($dir === '') { $dir = get_pref('admin_sort_dir', 'asc'); } $dir = $dir == 'desc' ? 'desc' : 'asc'; if (!in_array($sort, array('name', 'RealName', 'email', 'privs', 'last_login'))) { $sort = 'name'; } $sort_sql = $sort . ' ' . $dir; set_pref('admin_sort_column', $sort, 'admin', 2, '', 0, PREF_PRIVATE); set_pref('admin_sort_dir', $dir, 'admin', 2, '', 0, PREF_PRIVATE); $switch_dir = $dir == 'desc' ? 'asc' : 'desc'; $criteria = 1; if ($search_method and $crit != '') { $crit_escaped = doSlash(str_replace(array('\\', '%', '_', '\''), array('\\\\', '\\%', '\\_', '\\\''), $crit)); $critsql = array('id' => "user_id in ('" . join("','", do_list($crit_escaped)) . "')", 'login' => "name like '%{$crit_escaped}%'", 'real_name' => "RealName like '%{$crit_escaped}%'", 'email' => "email like '%{$crit_escaped}%'", 'privs' => "privs in ('" . join("','", do_list($crit_escaped)) . "')"); if (array_key_exists($search_method, $critsql)) { $criteria = $critsql[$search_method]; } else { $search_method = ''; $crit = ''; } } else { $search_method = ''; $crit = ''; } $criteria .= callback_event('admin_criteria', 'author_list', 0, $criteria); $total = getCount('txp_users', $criteria); // New author button if (has_privs('admin.edit')) { echo n . sLink('admin', 'author_edit', gTxt('add_new_author')); } echo '</p>'; // end txp-buttons if ($total < 1) { if ($criteria != 1) { echo n . author_search_form($crit, $search_method) . n . graf(gTxt('no_results_found'), ' class="indicator"') . '</div>'; } return; } $limit = max($author_list_pageby, 15); list($page, $offset, $numPages) = pager($total, $limit, $page); $use_multi_edit = has_privs('admin.edit') && safe_count('txp_users', '1=1') > 1; echo author_search_form($crit, $search_method) . '</div>'; $rs = safe_rows_start('*, unix_timestamp(last_access) as last_login', 'txp_users', "{$criteria} order by {$sort_sql} limit {$offset}, {$limit}"); if ($rs) { echo n . '<div id="users_container" class="txp-container">'; echo '<form action="index.php" id="users_form" class="multi_edit_form" method="post" name="longform">' . n . '<div class="txp-listtables">' . n . startTable('', '', 'txp-list') . n . '<thead>' . n . tr(n . ($use_multi_edit ? hCell(fInput('checkbox', 'select_all', 0, '', '', '', '', '', 'select_all'), '', ' title="' . gTxt('toggle_all_selected') . '" class="multi-edit"') : hCell('', '', ' class="multi-edit"')) . n . column_head('login_name', 'name', 'admin', true, $switch_dir, '', '', ('name' == $sort ? "{$dir} " : '') . 'name login-name') . n . column_head('real_name', 'RealName', 'admin', true, $switch_dir, '', '', ('RealName' == $sort ? "{$dir} " : '') . 'name real-name') . n . column_head('email', 'email', 'admin', true, $switch_dir, '', '', ('email' == $sort ? "{$dir} " : '') . 'email') . n . column_head('privileges', 'privs', 'admin', true, $switch_dir, '', '', ('privs' == $sort ? "{$dir} " : '') . 'privs') . n . column_head('last_login', 'last_login', 'admin', true, $switch_dir, '', '', ('last_login' == $sort ? "{$dir} " : '') . 'date last-login modified')) . n . '</thead>'; echo '<tbody>'; while ($a = nextRow($rs)) { extract(doSpecial($a)); echo tr(td((has_privs('admin.edit') and $txp_user != $a['name']) ? fInput('checkbox', 'selected[]', $a['name'], 'checkbox') : '', '', 'multi-edit') . td(has_privs('admin.edit') ? eLink('admin', 'author_edit', 'user_id', $user_id, $name) : $name, '', 'name login-name') . td($RealName, '', 'name real-name') . td('<a href="mailto:' . $email . '">' . $email . '</a>', '', 'email') . td(get_priv_level($privs), '', 'privs') . td($last_login ? safe_strftime('%b %Y', $last_login) : '', '', 'date last-login modified')); } echo '</tbody>', n, endTable(), n, '</div>', n, $use_multi_edit ? author_multiedit_form($page, $sort, $dir, $crit, $search_method) : '', n, tInput(), n, '</form>', n, '<div id="users_navigation" class="txp-navigation">', n, nav_form('admin', $page, $numPages, $sort, $dir, $crit, $search_method), n, pageby_form('admin', $author_list_pageby), n, '</div>', n, '</div>'; } } else { echo '</div>'; } }
/** * Executes the real action for @see udpateArticleId and @see newArticle * @param array $incoming containing the desired article fields * @param mixed(string|integer) $article_id the ID of the article to update * @return mixed integer article id on success, false otherwise * @access private */ function _setArticle($incoming, $article_id = null) { global $txpcfg; $prefs = get_prefs(); extract($prefs); if (!empty($incoming['Section']) && !$this->getSection($incoming['Section'])) { return false; } if (!empty($incoming['Category1']) && !$this->getCategory($incoming['Category1'])) { return false; } if (!empty($incoming['Category2']) && !$this->getCategory($incoming['Category2'])) { return false; } if ($article_id !== null) { $article_id = assert_int($article_id); } //All validation rules assumed to be passed before this point. //Do content processing here $incoming_with_markup = $this->textile_main_fields($incoming, $use_textile); $incoming['Title'] = $incoming_with_markup['Title']; if (empty($incoming['Body_html']) && !empty($incoming['Body'])) { $incoming['Body_html'] = $incoming_with_markup['Body_html']; } if (empty($incoming['Excerpt_html']) && !empty($incoming['Excerpt'])) { $incoming['Excerpt_html'] = $incoming_with_markup['Excerpt_html']; } unset($incoming_with_markup); if (empty($incoming['Posted'])) { if ($article_id === null) { $when = !$article_id ? 'now()' : ''; $incoming['Posted'] = $when; } else { # do not override post time for existing articles unless Posted is present unset($incoming['Posted']); } } else { $when = strtotime($incoming['Posted']) - tz_offset(); $when = "from_unixtime({$when})"; } if ($incoming['Title'] || $incoming['Body'] || $incoming['Excerpt']) { //Build SQL then and run query //Prevent data erase if not defined on the update action //but it was on the DB from a previous creation/edition time if ($article_id) { $old = safe_row('*', 'textpattern', "ID = {$article_id}"); //Status should be defined previously. Be sure of that. if (!has_privs('article.publish', $this->txp_user) && $incoming['Status'] == 4 && $old['Status'] != 4) { $incoming['Status'] = 3; } foreach ($old as $key => $val) { if (!isset($incoming[$key])) { $incoming[$key] = $val; } } } else { //Status should be defined previously. Be sure of that. if (!has_privs('article.publish', $this->txp_user) && $incoming['Status'] == 4) { $incoming['Status'] = 3; } } if (empty($incoming['Section']) && $article_id) { $incoming['Section'] = safe_field('Section', 'textpattern', "ID = {$article_id}"); } $incoming = $this->_check_keys($incoming, array('AuthorID' => $this->txp_user, 'Annotate' => $comments_on_default, 'AnnotateInvite' => $comments_default_invite, 'textile_body' => $use_textile, 'textile_excerpt' => $use_textile, 'url_title' => stripSpace($incoming['Title']))); //Build the SQL query $sql = array(); foreach ($incoming as $key => $val) { if ($key == 'Posted' && $val == 'now()') { $sql[] = "{$key} = {$val}"; } elseif ($key != 'ID' && $key != 'uid' && $key != 'feed_time' && $key != 'LastMod' && $key != 'LastModID') { $sql[] = "{$key} = '" . doSlash($val) . "'"; } } $sql[] = 'LastMod = now()'; $sql[] = "LastModID = '" . doSlash($this->txp_user) . "'"; if (!$article_id) { $sql[] = "uid = '" . doSlash(md5(uniqid(rand(), true))) . "'"; } if (!$article_id) { if (empty($incoming['Posted'])) { $sql[] = "feed_time = curdate()"; } else { $when = strtotime($incoming['Posted']) - tz_offset(); $when = strftime("%Y-%m-%d", $when); $sql[] = "feed_time ='" . doSlash($when) . "'"; } } $sql = join(', ', $sql); $rs = $article_id ? safe_update('textpattern', $sql, "ID = {$article_id}") : safe_insert('textpattern', $sql); $oldstatus = $article_id ? $old['Status'] : ''; if (!$article_id && $rs) { $article_id = $rs; } if ($incoming['Status'] >= 4 && !$article_id || $oldstatus != 4 && $article_id) { safe_update("txp_prefs", "val = now()", "name = 'lastmod'"); //@$this->_sendPings(); } return $article_id; } return false; }
if (!$dbversion or $dbversion != $thisversion or $txp_using_svn) { define('TXP_UPDATE', 1); include txpath . '/update/_update.php'; } janitor(); // article or form preview if (isset($_POST['form_preview']) || isset($_GET['txpreview'])) { include txpath . '/publish.php'; textpattern(); exit; } if (!empty($admin_side_plugins) and gps('event') != 'plugin') { load_plugins(1); } // plugins may have altered privilege settings if (!defined('TXP_UPDATE_DONE') && !gps('event') && !empty($default_event) && has_privs($default_event)) { $event = $default_event; } // init private theme $theme = theme::init(); include txpath . '/lib/txplib_head.php'; // ugly hack, for the people that don't update their admin_config.php // Get rid of this when we completely remove admin_config and move privs to db if ($event == 'list') { require_privs('article'); } else { require_privs($event); } callback_event($event, $step, 1); $inc = txpath . '/include/txp_' . $event . '.php'; if (is_readable($inc)) {
/** * Processes multi-edit actions. */ function list_multi_edit() { global $txp_user, $statuses, $all_cats, $all_authors, $all_sections; extract(psa(array('selected', 'edit_method'))); if (!$selected || !is_array($selected)) { return list_list(); } $selected = array_map('assert_int', $selected); // Empty entry to permit clearing the categories. $categories = array(''); foreach ($all_cats as $row) { $categories[] = $row['name']; } $allowed = array(); $field = $value = ''; switch ($edit_method) { // Delete. case 'delete': if (!has_privs('article.delete')) { if (has_privs('article.delete.own')) { $allowed = safe_column_num("ID", 'textpattern', "ID IN (" . join(',', $selected) . ") AND AuthorID = '" . doSlash($txp_user) . "'"); } $selected = $allowed; } if ($selected && safe_delete('textpattern', "ID IN (" . join(',', $selected) . ")")) { safe_update('txp_discuss', "visible = " . MODERATE, "parentid IN (" . join(',', $selected) . ")"); callback_event('articles_deleted', '', 0, $selected); callback_event('multi_edited.articles', 'delete', 0, compact('selected', 'field', 'value')); update_lastmod('articles_deleted', $selected); now('posted', true); now('expires', true); return list_list(messenger('article', join(', ', $selected), 'deleted')); } return list_list(); break; // Change author. // Change author. case 'changeauthor': $value = ps('AuthorID'); if (has_privs('article.edit') && in_array($value, $all_authors, true)) { $field = 'AuthorID'; } break; // Change category1. // Change category1. case 'changecategory1': $value = ps('Category1'); if (in_array($value, $categories, true)) { $field = 'Category1'; } break; // Change category2. // Change category2. case 'changecategory2': $value = ps('Category2'); if (in_array($value, $categories, true)) { $field = 'Category2'; } break; // Change comment status. // Change comment status. case 'changecomments': $field = 'Annotate'; $value = (int) ps('Annotate'); break; // Change section. // Change section. case 'changesection': $value = ps('Section'); if (in_array($value, $all_sections, true)) { $field = 'Section'; } break; // Change status. // Change status. case 'changestatus': $value = (int) ps('Status'); if (array_key_exists($value, $statuses)) { $field = 'Status'; } if (!has_privs('article.publish') && $value >= STATUS_LIVE) { $value = STATUS_PENDING; } break; } $selected = safe_rows("ID, AuthorID, Status", 'textpattern', "ID IN (" . join(',', $selected) . ")"); foreach ($selected as $item) { if ($item['Status'] >= STATUS_LIVE && has_privs('article.edit.published') || $item['Status'] >= STATUS_LIVE && $item['AuthorID'] === $txp_user && has_privs('article.edit.own.published') || $item['Status'] < STATUS_LIVE && has_privs('article.edit') || $item['Status'] < STATUS_LIVE && $item['AuthorID'] === $txp_user && has_privs('article.edit.own')) { $allowed[] = $item['ID']; } } $selected = $allowed; if ($selected) { $message = messenger('article', join(', ', $selected), 'modified'); if ($edit_method === 'duplicate') { $rs = safe_rows_start("*", 'textpattern', "ID IN (" . join(',', $selected) . ")"); if ($rs) { while ($a = nextRow($rs)) { unset($a['ID'], $a['LastMod'], $a['LastModID'], $a['Expires']); $a['uid'] = md5(uniqid(rand(), true)); $a['AuthorID'] = $txp_user; foreach ($a as $name => &$value) { $value = "`{$name}` = '" . doSlash($value) . "'"; } if ($id = (int) safe_insert('textpattern', join(',', $a))) { safe_update('textpattern', "Title = CONCAT(Title, ' (', {$id}, ')'),\n url_title = CONCAT(url_title, '-', {$id}),\n Posted = NOW(),\n feed_time = NOW()", "ID = {$id}"); } } } $message = gTxt('duplicated_articles', array('{id}' => join(', ', $selected))); } elseif (!$field || safe_update('textpattern', "{$field} = '" . doSlash($value) . "'", "ID IN (" . join(',', $selected) . ")") === false) { return list_list(); } update_lastmod('articles_updated', compact('selected', 'field', 'value')); now('posted', true); now('expires', true); callback_event('multi_edited.articles', $edit_method, 0, compact('selected', 'field', 'value')); return list_list($message); } return list_list(); }
function doArticles($atts, $iscustom, $thing = null) { global $pretext, $prefs; extract($pretext); extract($prefs); $customFields = getCustomFields(); $customlAtts = array_null(array_flip($customFields)); if ($iscustom) { $extralAtts = array('category' => '', 'section' => '', 'excerpted' => '', 'author' => '', 'month' => '', 'expired' => $publish_expired_articles, 'id' => '', 'exclude' => ''); } else { $extralAtts = array('listform' => '', 'searchform' => '', 'searchall' => 1, 'searchsticky' => 0, 'pageby' => '', 'pgonly' => 0); } // Getting attributes. $theAtts = lAtts(array('form' => 'default', 'limit' => 10, 'sort' => '', 'sortby' => '', 'sortdir' => '', 'keywords' => '', 'time' => 'past', 'status' => STATUS_LIVE, 'allowoverride' => !$q and !$iscustom, 'offset' => 0, 'wraptag' => '', 'break' => '', 'label' => '', 'labeltag' => '', 'class' => '') + $customlAtts + $extralAtts, $atts); // For the txp:article tag, some attributes are taken from globals; // override them, then stash all filter attributes. if (!$iscustom) { $theAtts['category'] = $c ? $c : ''; $theAtts['section'] = $s && $s != 'default' ? $s : ''; $theAtts['author'] = !empty($author) ? $author : ''; $theAtts['month'] = !empty($month) ? $month : ''; $theAtts['frontpage'] = $s && $s == 'default' ? true : false; $theAtts['excerpted'] = 0; $theAtts['exclude'] = 0; $theAtts['expired'] = $publish_expired_articles; filterAtts($theAtts); } else { $theAtts['frontpage'] = false; } extract($theAtts); // If a listform is specified, $thing is for doArticle() - hence ignore here. if (!empty($listform)) { $thing = ''; } $pageby = empty($pageby) ? $limit : $pageby; // Treat sticky articles differently wrt search filtering, etc. $status = in_array(strtolower($status), array('sticky', STATUS_STICKY)) ? STATUS_STICKY : STATUS_LIVE; $issticky = $status == STATUS_STICKY; // Give control to search, if necessary. if ($q && !$iscustom && !$issticky) { include_once txpath . '/publish/search.php'; $s_filter = $searchall ? filterSearch() : ''; $q = trim($q); $quoted = $q[0] === '"' && $q[strlen($q) - 1] === '"'; $q = doSlash($quoted ? trim(trim($q, '"')) : $q); // Searchable article fields are limited to the columns of the // textpattern table and a matching fulltext index must exist. $cols = do_list_unique($searchable_article_fields); if (empty($cols) or $cols[0] == '') { $cols = array('Title', 'Body'); } $match = ", MATCH (`" . join("`, `", $cols) . "`) AGAINST ('{$q}') AS score"; $search_terms = preg_replace('/\\s+/', ' ', str_replace(array('\\', '%', '_', '\''), array('\\\\', '\\%', '\\_', '\\\''), $q)); if ($quoted || empty($m) || $m === 'exact') { for ($i = 0; $i < count($cols); $i++) { $cols[$i] = "`{$cols[$i]}` LIKE '%{$search_terms}%'"; } } else { $colJoin = $m === 'any' ? "OR" : "AND"; $search_terms = explode(' ', $search_terms); for ($i = 0; $i < count($cols); $i++) { $like = array(); foreach ($search_terms as $search_term) { $like[] = "`{$cols[$i]}` LIKE '%{$search_term}%'"; } $cols[$i] = "(" . join(" {$colJoin} ", $like) . ")"; } } $cols = join(" OR ", $cols); $search = " AND ({$cols}) {$s_filter}"; // searchall=0 can be used to show search results for the current // section only. if ($searchall) { $section = ''; } if (!$sort) { $sort = "score DESC"; } } else { $match = $search = ''; if (!$sort) { $sort = "Posted DESC"; } } // For backwards compatibility. sortby and sortdir are deprecated. if ($sortby) { trigger_error(gTxt('deprecated_attribute', array('{name}' => 'sortby')), E_USER_NOTICE); if (!$sortdir) { $sortdir = "DESC"; } else { trigger_error(gTxt('deprecated_attribute', array('{name}' => 'sortdir')), E_USER_NOTICE); } $sort = "{$sortby} {$sortdir}"; } elseif ($sortdir) { trigger_error(gTxt('deprecated_attribute', array('{name}' => 'sortdir')), E_USER_NOTICE); $sort = "Posted {$sortdir}"; } // Building query parts. $frontpage = ($frontpage and (!$q or $issticky)) ? filterFrontPage() : ''; $category = join("','", doSlash(do_list_unique($category))); $category = !$category ? '' : " AND (Category1 IN ('" . $category . "') OR Category2 IN ('" . $category . "'))"; $section = !$section ? '' : " AND Section IN ('" . join("','", doSlash(do_list_unique($section))) . "')"; $excerpted = !$excerpted ? '' : " AND Excerpt !=''"; $author = !$author ? '' : " AND AuthorID IN ('" . join("','", doSlash(do_list_unique($author))) . "')"; $month = !$month ? '' : " AND Posted LIKE '" . doSlash($month) . "%'"; $ids = $id ? array_map('intval', do_list_unique($id)) : array(); $exclude = $exclude ? array_map('intval', do_list_unique($exclude)) : array(); $id = (!$id ? '' : " AND ID IN (" . join(',', $ids) . ")") . (!$exclude ? '' : " AND ID NOT IN (" . join(',', $exclude) . ")"); 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); } } // Allow keywords for no-custom articles. That tagging mode, you know. if ($keywords) { $keys = doSlash(do_list_unique($keywords)); foreach ($keys as $key) { $keyparts[] = "FIND_IN_SET('" . $key . "', Keywords)"; } $keywords = " AND (" . join(' or ', $keyparts) . ")"; } if ($q and $searchsticky) { $statusq = " AND Status >= " . STATUS_LIVE; } elseif ($id) { $statusq = " AND Status >= " . STATUS_LIVE; } else { $statusq = " AND Status = " . intval($status); } $where = "1 = 1" . $statusq . $time . $search . $id . $category . $section . $excerpted . $month . $author . $keywords . $custom . $frontpage; // Do not paginate if we are on a custom list. if (!$iscustom and !$issticky) { $grand_total = safe_count('textpattern', $where); $total = $grand_total - $offset; $numPages = ceil($total / $pageby); $pg = !$pg ? 1 : $pg; $pgoffset = $offset + ($pg - 1) * $pageby; // Send paging info to txp:newer and txp:older. $pageout['pg'] = $pg; $pageout['numPages'] = $numPages; $pageout['s'] = $s; $pageout['c'] = $c; $pageout['context'] = 'article'; $pageout['grand_total'] = $grand_total; $pageout['total'] = $total; global $thispage; if (empty($thispage)) { $thispage = $pageout; } if ($pgonly) { return; } } else { $pgoffset = $offset; } // Preserve order of custom article ids unless 'sort' attribute is set. if (!empty($atts['id']) && empty($atts['sort'])) { $safe_sort = "FIELD(id, " . join(',', $ids) . ")"; } else { $safe_sort = doSlash($sort); } $rs = safe_rows_start("*, UNIX_TIMESTAMP(Posted) AS uPosted, UNIX_TIMESTAMP(Expires) AS uExpires, UNIX_TIMESTAMP(LastMod) AS uLastMod" . $match, 'textpattern', "{$where} ORDER BY {$safe_sort} LIMIT " . intval($pgoffset) . ", " . intval($limit)); // Get the form name. if ($q and !$iscustom and !$issticky) { $fname = $searchform ? $searchform : 'search_results'; } else { $fname = !empty($listform) ? $listform : $form; } if ($rs) { $count = 0; $last = numRows($rs); $articles = array(); while ($a = nextRow($rs)) { ++$count; populateArticleData($a); global $thisarticle, $uPosted, $limit; $thisarticle['is_first'] = $count == 1; $thisarticle['is_last'] = $count == $last; // Article form preview. if (txpinterface === 'admin' && ps('Form')) { doAuth(); if (!has_privs('form')) { txp_status_header('401 Unauthorized'); exit(hed('401 Unauthorized', 1) . graf(gTxt('restricted_area'))); } $articles[] = parse(gps('Form')); } elseif ($allowoverride and $a['override_form']) { $articles[] = parse_form($a['override_form']); } else { $articles[] = $thing ? parse($thing) : parse_form($fname); } // Sending these to paging_link(); Required? $uPosted = $a['uPosted']; unset($GLOBALS['thisarticle']); } return doLabel($label, $labeltag) . doWrap($articles, $wraptag, $break, $class); } }
function list_multi_edit() { global $txp_user; $selected = ps('selected'); if (!$selected or !is_array($selected)) { return list_list(); } $selected = array_map('assert_int', $selected); $method = ps('edit_method'); $changed = false; $ids = array(); if ($method == 'delete') { if (!has_privs('article.delete')) { $allowed = array(); if (has_privs('article.delete.own')) { foreach ($selected as $id) { $author = safe_field('AuthorID', 'textpattern', "ID = {$id}"); if ($author == $txp_user) { $allowed[] = $id; } } } $selected = $allowed; } foreach ($selected as $id) { if (safe_delete('textpattern', "ID = {$id}")) { $ids[] = $id; } } $changed = join(', ', $ids); if ($changed) { safe_update('txp_discuss', "visible = " . MODERATE, "parentid in({$changed})"); } } else { $selected = array_map('assert_int', $selected); $selected = safe_rows('ID, AuthorID, Status', 'textpattern', 'ID in (' . implode(',', $selected) . ')'); $allowed = array(); foreach ($selected as $item) { if ($item['Status'] >= 4 and has_privs('article.edit.published') or $item['Status'] >= 4 and $item['AuthorID'] == $txp_user and has_privs('article.edit.own.published') or $item['Status'] < 4 and has_privs('article.edit') or $item['Status'] < 4 and $item['AuthorID'] == $txp_user and has_privs('article.edit.own')) { $allowed[] = $item['ID']; } } $selected = $allowed; unset($allowed); switch ($method) { // change author case 'changeauthor': $key = 'AuthorID'; $val = has_privs('article.edit') ? ps('AuthorID') : ''; // do not allow to be set to an empty value if (!$val) { $selected = array(); } break; // change category1 // change category1 case 'changecategory1': $key = 'Category1'; $val = ps('Category1'); break; // change category2 // change category2 case 'changecategory2': $key = 'Category2'; $val = ps('Category2'); break; // change comments // change comments case 'changecomments': $key = 'Annotate'; $val = (int) ps('Annotate'); break; // change section // change section case 'changesection': $key = 'Section'; $val = ps('Section'); // do not allow to be set to an empty value if (!$val) { $selected = array(); } break; // change status // change status case 'changestatus': $key = 'Status'; $val = ps('Status'); if (!has_privs('article.publish') && $val >= 4) { $val = 3; } // do not allow to be set to an empty value if (!$val) { $selected = array(); } break; default: $key = ''; $val = ''; break; } if ($selected and $key) { foreach ($selected as $id) { if (safe_update('textpattern', "{$key} = '" . doSlash($val) . "'", "ID = {$id}")) { $ids[] = $id; } } $changed = join(', ', $ids); } } if ($changed) { update_lastmod(); return list_list(messenger('article', $changed, $method == 'delete' ? 'deleted' : 'modified')); } return list_list(); }
/** * Sets Textpatterns menu structure, message contents and other application states * @param string $area Currently active top level menu * @param string $event Currently active second level menu * @param boolean $is_popup Just a popup window for tag builder et cetera * @param array $message The contents of the notification message pane * @return object This theme object */ function set_state($area, $event, $is_popup, $message) { $this->is_popup = $is_popup; $this->message = $message; if ($is_popup) { return $this; } // use legacy areas() for b/c $areas = areas(); $defaults = array('content' => 'article', 'presentation' => 'page', 'admin' => 'admin'); if (empty($areas['start'])) { unset($areas['start']); } if (empty($areas['extensions'])) { unset($areas['extensions']); } foreach ($areas as $ar => $items) { $l_ = gTxt('tab_' . $ar); $e_ = array_key_exists($ar, $defaults) ? $defaults[$ar] : reset($areas[$ar]); if (has_privs('tab.' . $ar)) { $this->menu[$ar] = array('label' => $l_, 'event' => $e_, 'active' => $ar == $area); foreach ($items as $a => $b) { if (has_privs($b)) { $this->menu[$ar]['items'][] = array('label' => $a, 'event' => $b, 'active' => $b == $event); } } } } return $this; }
function file_delete($ids = array()) { global $file_base_path, $txp_user; $ids = $ids ? array_map('assert_int', $ids) : array(assert_int(ps('id'))); $message = ''; if (!has_privs('file.delete')) { if (has_privs('file.delete.own')) { $ids = safe_column('id', 'txp_file', 'id IN (' . join(',', $ids) . ') AND author=\'' . doSlash($txp_user) . '\''); } else { $ids = array(); } } if (!empty($ids)) { $fail = array(); $rs = safe_rows_start('id, filename', 'txp_file', 'id IN (' . join(',', $ids) . ')'); if ($rs) { while ($a = nextRow($rs)) { extract($a); $filepath = build_file_path($file_base_path, $filename); $rsd = safe_delete('txp_file', "id = {$id}"); $ul = false; if ($rsd && is_file($filepath)) { $ul = unlink($filepath); } if (!$rsd or !$ul) { $fail[] = $id; } } if ($fail) { $message = messenger(gTxt('file_delete_failed'), join(', ', $fail), ''); } else { update_lastmod(); $message = gTxt('file_deleted', array('{name}' => join(', ', $ids))); } } else { $message = messenger(gTxt('file_not_found'), join(', ', $ids), ''); } } file_list($message); }
function author_list() { global $txp_user, $author_list_pageby; extract(gpsa(array('page', 'sort', 'dir', 'crit', 'search_method'))); if (!in_array($sort, array('name', 'RealName', 'email', 'privs', 'last_login'))) { $sort = 'name'; } $dir = $dir == 'desc' ? 'desc' : 'asc'; $sort_sql = $sort . ' ' . $dir; $switch_dir = $dir == 'desc' ? 'asc' : 'desc'; $total = getCount('txp_users', '1=1'); $limit = max($author_list_pageby, 15); list($page, $offset, $numPages) = pager($total, $limit, $page); $rs = safe_rows_start('*, unix_timestamp(last_access) as last_login', 'txp_users', '1 = 1 order by ' . $sort_sql . ' limit ' . $offset . ', ' . $limit); if ($rs) { echo '<form action="index.php" method="post" name="longform" onsubmit="return verify(\'' . gTxt('are_you_sure') . '\')">' . startTable('list') . tr(column_head('login_name', 'name', 'admin', true, $switch_dir, '', '', 'name' == $sort ? $dir : '') . column_head('real_name', 'RealName', 'admin', true, $switch_dir, '', '', 'RealName' == $sort ? $dir : '') . column_head('email', 'email', 'admin', true, $switch_dir, '', '', 'email' == $sort ? $dir : '') . column_head('privileges', 'privs', 'admin', true, $switch_dir, '', '', 'privs' == $sort ? $dir : '') . column_head('last_login', 'last_login', 'admin', true, $switch_dir, '', '', 'last_login' == $sort ? $dir : '') . hCell() . hCell()); while ($a = nextRow($rs)) { extract(doSpecial($a)); echo tr(td($name) . td($RealName) . td('<a href="mailto:' . $email . '">' . $email . '</a>') . td(get_priv_level($privs)) . td($last_login ? safe_strftime('%b %Y', $last_login) : '') . td(has_privs('admin.edit') ? eLink('admin', 'author_edit', 'user_id', $user_id, gTxt('edit')) : '') . td((has_privs('admin.edit') and $txp_user != $a['name']) ? fInput('checkbox', 'selected[]', $a['name']) : '')); } echo n . n . tr(tda(select_buttons() . author_multiedit_form($page, $sort, $dir, $crit, $search_method), ' colspan="6" style="text-align: right; border: none;"')) . endTable() . '</form>' . nav_form('admin', $page, $numPages, $sort, $dir, $crit, $search_method) . pageby_form('admin', $author_list_pageby); } }
function adminErrorHandler($errno, $errstr, $errfile, $errline) { global $production_status, $theme, $event, $step; if (!error_reporting()) { return; } // When even a minimum environment is missing... if (!isset($production_status)) { echo '<pre>' . gTxt('internal_error') . ' "' . $errstr . '"' . n . "in {$errfile} at line {$errline}" . '</pre>'; return; } if ($production_status == 'live' || $production_status != 'debug' && $errno == E_USER_NOTICE) { $backtrace = $msg = ''; } else { $backtrace = ''; $msg = gTxt('internal_error'); if (has_privs('debug.verbose')) { $msg .= ' "' . $errstr . '"'; } if ($production_status == 'debug') { if (has_privs('debug.backtrace')) { $msg .= n . "in {$errfile} at line {$errline}"; $backtrace = join(n, get_caller(5, 1)); } } } $httpstatus = in_array($errno, array(E_ERROR, E_USER_ERROR)) ? '500' : '200'; $out = "{$msg}.\n{$backtrace}"; if (http_accept_format('html')) { if (!empty($backtrace)) { echo "<pre>{$msg}.</pre>" . n . '<pre style="padding-left: 2em;" class="backtrace"><code>' . txpspecialchars($backtrace) . '</code></pre>'; } elseif (!empty($msg)) { echo is_object($theme) ? $theme->announce(array($out, E_ERROR), true) : "<pre>{$out}</pre>"; } $c = array('in' => '', 'out' => ''); } elseif (http_accept_format('js')) { send_script_response(is_object($theme) && !empty($msg) ? $theme->announce_async(array($out, E_ERROR), true) : "/* {$out} */"); $c = array('in' => '/* ', 'out' => ' */'); } elseif (http_accept_format('xml')) { send_xml_response(array('http-status' => $httpstatus, 'internal_error' => "{$out}")); $c = array('in' => '<!-- ', 'out' => ' -->'); } else { txp_die($msg, 500); } if ($production_status != 'live' && in_array($errno, array(E_ERROR, E_USER_ERROR))) { die($c['in'] . gTxt('get_off_my_lawn', array('{event}' => $event, '{step}' => $step)) . $c['out']); } }
function author_list() { global $txp_user; echo n . n . hed(gTxt('authors'), 3, ' style="text-align: center;"') . n . n . startTable('list') . n . tr(n . hCell(gTxt('real_name')) . n . hCell(gTxt('login_name')) . n . hCell(gTxt('email')) . n . hCell(gTxt('privileges')) . n . hCell() . n . hCell()); $rs = safe_rows_start('*', 'txp_users', '1 = 1 order by name asc'); if ($rs) { if (has_privs('admin.edit')) { while ($a = nextRow($rs)) { extract($a); echo n . n . '<tr>' . n . '<form method="post" action="index.php">' . n . td(fInput('text', 'RealName', $RealName, 'edit')) . td(htmlspecialchars($name)) . td(fInput('text', 'email', $email, 'edit')); if ($name != $txp_user) { echo td(privs($privs) . sp . popHelp('about_privileges')); } else { echo td(get_priv_level($privs) . sp . popHelp('about_privileges') . hInput('privs', $privs)); } echo td(fInput('submit', 'save', gTxt('save'), 'smallerbox')) . n . hInput('user_id', $user_id) . n . eInput('admin') . n . sInput('author_save') . n . '</form>'; if ($name != $txp_user) { echo td(dLink('admin', 'author_delete', 'user_id', $user_id)); } else { echo td(); } echo n . '</tr>'; } } else { while ($a = nextRow($rs)) { extract(doSpecial($a)); echo tr(td($RealName) . td($name) . td('<a href="mailto:' . $email . '">' . $email . '</a>') . td(get_priv_level($privs) . sp . popHelp('about_privileges') . hInput('privs', $privs)) . td() . td()); } } echo n . endTable(); } }
function link_multi_edit() { global $txp_user, $all_link_cats, $all_link_authors; // Empty entry to permit clearing the category $categories = array(''); foreach ($all_link_cats as $row) { $categories[] = $row['name']; } $selected = ps('selected'); if (!$selected or !is_array($selected)) { link_list(); return; } $selected = array_map('assert_int', $selected); $method = ps('edit_method'); $changed = array(); $key = ''; switch ($method) { case 'delete': if (!has_privs('link.delete')) { if (has_privs('link.delete.own')) { $selected = safe_column('id', 'txp_link', 'id IN (' . join(',', $selected) . ') AND author=\'' . doSlash($txp_user) . '\''); } else { $selected = array(); } } foreach ($selected as $id) { if (safe_delete('txp_link', 'id = ' . $id)) { $changed[] = $id; } } if ($changed) { callback_event('links_deleted', '', 0, $changed); } $key = ''; break; case 'changecategory': $val = ps('category'); if (in_array($val, $categories)) { $key = 'category'; } break; case 'changeauthor': $val = ps('author'); if (in_array($val, $all_link_authors)) { $key = 'author'; } break; default: $key = ''; $val = ''; break; } if ($selected and $key) { foreach ($selected as $id) { if (safe_update('txp_link', "{$key} = '" . doSlash($val) . "'", "id = {$id}")) { $changed[] = $id; } } } if ($changed) { update_lastmod(); link_list(gTxt($method == 'delete' ? 'links_deleted' : 'link_updated', array($method == 'delete' ? '{list}' : '{name}' => join(', ', $changed)))); return; } link_list(); }
function article_edit($message = '', $concurrent = FALSE) { global $vars, $txp_user, $comments_disabled_after, $txpcfg, $prefs; extract($prefs); extract(gpsa(array('view', 'from_view', 'step'))); if (!empty($GLOBALS['ID'])) { // newly-saved article $ID = $GLOBALS['ID']; $step = 'edit'; } else { $ID = gps('ID'); } include_once txpath . '/lib/classTextile.php'; $textile = new Textile(); // switch to 'text' view upon page load and after article post if (!$view || gps('save') || gps('publish')) { $view = 'text'; } if (!$step) { $step = "create"; } if ($step == "edit" && $view == "text" && !empty($ID) && $from_view != 'preview' && $from_view != 'html' && !$concurrent) { $pull = true; //-- it's an existing article - off we go to the db $ID = assert_int($ID); $rs = safe_row("*, unix_timestamp(Posted) as sPosted,\n\t\t\t\tunix_timestamp(Expires) as sExpires,\n\t\t\t\tunix_timestamp(LastMod) as sLastMod", "textpattern", "ID={$ID}"); extract($rs); $reset_time = $publish_now = $Status < 4; } else { $pull = false; //-- assume they came from post if ($from_view == 'preview' or $from_view == 'html') { $store_out = array(); $store = unserialize(base64_decode(ps('store'))); foreach ($vars as $var) { if (isset($store[$var])) { $store_out[$var] = $store[$var]; } } } else { $store_out = gpsa($vars); if ($concurrent) { $store_out['sLastMod'] = safe_field('unix_timestamp(LastMod) as sLastMod', 'textpattern', 'ID=' . $ID); } } extract($store_out); } $GLOBALS['step'] = $step; if ($step == 'create') { $textile_body = $use_textile; $textile_excerpt = $use_textile; } if ($step != 'create') { // Previous record? $prev_id = checkIfNeighbour('prev', $sPosted); // Next record? $next_id = checkIfNeighbour('next', $sPosted); } $page_title = $Title ? $Title : gTxt('write'); pagetop($page_title, $message); echo n . n . '<form name="article" method="post" action="index.php">'; if (!empty($store_out)) { echo hInput('store', base64_encode(serialize($store_out))); } echo hInput('ID', $ID) . eInput('article') . sInput($step) . '<input type="hidden" name="view" />' . startTable('edit') . '<tr>' . n . '<td id="article-col-1">'; if ($view == 'text') { //-- markup help -------------- echo side_help($textile_body, $textile_excerpt) . '<h3 class="plain"><a href="#advanced" onclick="toggleDisplay(\'advanced\'); return false;">' . gTxt('advanced_options') . '</a></h3>', '<div id="advanced" class="toggle" style="display:none">', n . graf('<label for="markup-body">' . gTxt('article_markup') . '</label>' . br . pref_text('textile_body', $textile_body, 'markup-body')), n . graf('<label for="markup-excerpt">' . gTxt('excerpt_markup') . '</label>' . br . pref_text('textile_excerpt', $textile_excerpt, 'markup-excerpt')), $allow_form_override ? graf('<label for="override-form">' . gTxt('override_default_form') . '</label>' . sp . popHelp('override_form') . br . form_pop($override_form, 'override-form')) : '', $custom_1_set ? custField(1, $custom_1_set, $custom_1) : '', $custom_2_set ? custField(2, $custom_2_set, $custom_2) : '', $custom_3_set ? custField(3, $custom_3_set, $custom_3) : '', $custom_4_set ? custField(4, $custom_4_set, $custom_4) : '', $custom_5_set ? custField(5, $custom_5_set, $custom_5) : '', $custom_6_set ? custField(6, $custom_6_set, $custom_6) : '', $custom_7_set ? custField(7, $custom_7_set, $custom_7) : '', $custom_8_set ? custField(8, $custom_8_set, $custom_8) : '', $custom_9_set ? custField(9, $custom_9_set, $custom_9) : '', $custom_10_set ? custField(10, $custom_10_set, $custom_10) : '', n . graf('<label for="keywords">' . gTxt('keywords') . '</label>' . sp . popHelp('keywords') . br . n . '<textarea id="keywords" name="Keywords" cols="18" rows="5">' . htmlspecialchars(str_replace(',', ', ', $Keywords)) . '</textarea>'), n . graf('<label for="article-image">' . gTxt('article_image') . '</label>' . sp . popHelp('article_image') . br . fInput('text', 'Image', $Image, 'edit', '', '', 22, '', 'article-image')), n . graf('<label for="url-title">' . gTxt('url_title') . '</label>' . sp . popHelp('url_title') . br . fInput('text', 'url_title', $url_title, 'edit', '', '', 22, '', 'url-title')), '</div> <h3 class="plain"><a href="#recent" onclick="toggleDisplay(\'recent\'); return false;">' . gTxt('recent_articles') . '</a>' . '</h3>' . '<div id="recent" class="toggle" style="display:none">'; $recents = safe_rows_start("Title, ID", 'textpattern', "1=1 order by LastMod desc limit 10"); if ($recents) { echo '<ul class="plain-list">'; while ($recent = nextRow($recents)) { if (!$recent['Title']) { $recent['Title'] = gTxt('untitled') . sp . $recent['ID']; } echo n . t . '<li><a href="?event=article' . a . 'step=edit' . a . 'ID=' . $recent['ID'] . '">' . escape_title($recent['Title']) . '</a></li>'; } echo '</ul>'; } echo '</div>'; } else { echo sp; } echo '</td>' . n . '<td id="article-main">'; //-- title input -------------- if ($view == 'preview') { echo hed(gTxt('preview'), 2) . hed($Title, 1); } elseif ($view == 'html') { echo hed('XHTML', 2) . hed($Title, 1); } elseif ($view == 'text') { echo n . '<p><label for="title">' . gTxt('title') . '</label>' . sp . popHelp('title') . br . '<input type="text" id="title" name="Title" value="' . escape_title($Title) . '" class="edit" size="40" tabindex="1" />'; if ($step != 'create') { include_once txpath . '/publish/taghandlers.php'; $url = permlinkurl_id($ID); if ($Status != 4 and $Status != 5) { $url .= (strpos($url, '?') === FALSE ? '?' : '&') . 'txpreview=' . intval($ID) . '.' . time(); } echo sp . sp . '<a href="' . $url . '" class="article-view">' . gTxt('view') . '</a>'; } echo '</p>'; } //-- body -------------------- if ($view == 'preview') { if ($textile_body == USE_TEXTILE) { echo $textile->TextileThis($Body); } else { if ($textile_body == CONVERT_LINEBREAKS) { echo nl2br($Body); } else { if ($textile_body == LEAVE_TEXT_UNTOUCHED) { echo $Body; } } } } elseif ($view == 'html') { if ($textile_body == USE_TEXTILE) { $bod = $textile->TextileThis($Body); } else { if ($textile_body == CONVERT_LINEBREAKS) { $bod = nl2br($Body); } else { if ($textile_body == LEAVE_TEXT_UNTOUCHED) { $bod = $Body; } } } echo tag(str_replace(array(n, t), array(br, sp . sp . sp . sp), htmlspecialchars($bod)), 'code'); } else { echo n . graf('<label for="body">' . gTxt('body') . '</label>' . sp . popHelp('body') . br . '<textarea id="body" name="Body" cols="55" rows="31" tabindex="2">' . htmlspecialchars($Body) . '</textarea>'); } //-- excerpt -------------------- if ($articles_use_excerpts) { if ($view == 'text') { echo n . graf('<label for="excerpt">' . gTxt('excerpt') . '</label>' . sp . popHelp('excerpt') . br . '<textarea id="excerpt" name="Excerpt" cols="55" rows="5" tabindex="3">' . htmlspecialchars($Excerpt) . '</textarea>'); } else { echo n . '<hr width="50%" />'; echo $textile_excerpt == USE_TEXTILE ? $view == 'preview' ? graf($textile->textileThis($Excerpt)) : tag(str_replace(array(n, t), array(br, sp . sp . sp . sp), htmlspecialchars($textile->TextileThis($Excerpt))), 'code') : graf($Excerpt); } } //-- author -------------- if ($view == "text" && $step != "create") { echo '<p class="small">' . gTxt('posted_by') . ': ' . htmlspecialchars($AuthorID) . ' · ' . safe_strftime('%d %b %Y · %X', $sPosted); if ($sPosted != $sLastMod) { echo br . gTxt('modified_by') . ': ' . htmlspecialchars($LastModID) . ' · ' . safe_strftime('%d %b %Y · %X', $sLastMod); } echo '</p>'; } echo hInput('from_view', $view), '</td>'; echo '<td id="article-tabs">'; //-- layer tabs ------------------- echo $use_textile == USE_TEXTILE || $textile_body == USE_TEXTILE ? '<ul>' . (tab('text', $view) . tab('html', $view) . tab('preview', $view)) . '</ul>' : ' '; echo '</td>'; echo '<td id="article-col-2">'; if ($view == 'text') { if ($step != 'create') { echo n . graf(href(gtxt('create_new'), 'index.php?event=article')); } //-- prev/next article links -- if ($step != 'create' and ($prev_id or $next_id)) { echo '<p>', $prev_id ? prevnext_link('‹' . gTxt('prev'), 'article', 'edit', $prev_id, gTxt('prev')) : '', $next_id ? prevnext_link(gTxt('next') . '›', 'article', 'edit', $next_id, gTxt('next')) : '', '</p>'; } //-- status radios -------------- echo n . n . '<fieldset id="write-status">' . n . '<legend>' . gTxt('status') . '</legend>' . n . status_radio($Status) . n . '</fieldset>'; //-- category selects ----------- echo n . n . '<fieldset id="write-sort">' . n . '<legend>' . gTxt('sort_display') . '</legend>' . n . graf('<label for="category-1">' . gTxt('category1') . '</label> ' . '<span class="small">[' . eLink('category', '', '', '', gTxt('edit')) . ']</span>' . br . n . category_popup('Category1', $Category1, 'category-1')) . n . graf('<label for="category-2">' . gTxt('category2') . '</label>' . br . n . category_popup('Category2', $Category2, 'category-2')); //-- section select -------------- if (!$from_view && !$pull) { $Section = getDefaultSection(); } echo n . graf('<label for="section">' . gTxt('section') . '</label> ' . '<span class="small">[' . eLink('section', '', '', '', gTxt('edit')) . ']</span>' . br . section_popup($Section, 'section')) . n . '</fieldset>' . n . n . '<h3 class="plain"><a href="#more" onclick="toggleDisplay(\'more\'); return false;">' . gTxt('more') . '</a></h3>', '<div id="more" class="toggle" style="display:none">'; //-- comments stuff -------------- if ($step == "create") { //Avoiding invite disappear when previewing $AnnotateInvite = !empty($store_out['AnnotateInvite']) ? $store_out['AnnotateInvite'] : $comments_default_invite; if ($comments_on_default == 1) { $Annotate = 1; } } if ($use_comments == 1) { echo n . n . '<fieldset id="write-comments">' . n . '<legend>' . gTxt('comments') . '</legend>'; $comments_expired = false; if ($step != 'create' && $comments_disabled_after) { $lifespan = $comments_disabled_after * 86400; $time_since = time() - $sPosted; if ($time_since > $lifespan) { $comments_expired = true; } } if ($comments_expired) { echo n . n . graf(gTxt('expired')); } else { echo n . n . graf(onoffRadio('Annotate', $Annotate)) . n . n . graf('<label for="comment-invite">' . gTxt('comment_invitation') . '</label>' . br . fInput('text', 'AnnotateInvite', $AnnotateInvite, 'edit', '', '', '', '', 'comment-invite')); } echo n . n . '</fieldset>'; } if ($step == "create" and empty($GLOBALS['ID'])) { //-- timestamp ------------------- //Avoiding modified date to disappear $persist_timestamp = !empty($store_out['year']) ? safe_strtotime($store_out['year'] . '-' . $store_out['month'] . '-' . $store_out['day'] . ' ' . $store_out['hour'] . ':' . $store_out['minute'] . ':' . $store_out['second']) : time(); echo n . n . '<fieldset id="write-timestamp">' . n . '<legend>' . gTxt('timestamp') . '</legend>' . n . graf(checkbox('publish_now', '1', $publish_now, '', 'publish_now') . '<label for="publish_now">' . gTxt('set_to_now') . '</label>') . n . graf(gTxt('or_publish_at') . sp . popHelp('timestamp')) . n . graf(gtxt('date') . sp . tsi('year', '%Y', $persist_timestamp) . ' / ' . tsi('month', '%m', $persist_timestamp) . ' / ' . tsi('day', '%d', $persist_timestamp)) . n . graf(gTxt('time') . sp . tsi('hour', '%H', $persist_timestamp) . ' : ' . tsi('minute', '%M', $persist_timestamp) . ' : ' . tsi('second', '%S', $persist_timestamp)) . n . '</fieldset>'; //-- expires ------------------- $persist_timestamp = !empty($store_out['exp_year']) ? safe_strtotime($store_out['exp_year'] . '-' . $store_out['exp_month'] . '-' . $store_out['exp_day'] . ' ' . $store_out['exp_hour'] . ':' . $store_out['exp_minute'] . ':' . $store_out['second']) : NULLDATETIME; echo n . n . '<fieldset id="write-expires">' . n . '<legend>' . gTxt('expires') . '</legend>' . n . graf(gtxt('date') . sp . tsi('exp_year', '%Y', $persist_timestamp) . ' / ' . tsi('exp_month', '%m', $persist_timestamp) . ' / ' . tsi('exp_day', '%d', $persist_timestamp)) . n . graf(gTxt('time') . sp . tsi('exp_hour', '%H', $persist_timestamp) . ' : ' . tsi('exp_minute', '%M', $persist_timestamp) . ' : ' . tsi('exp_second', '%S', $persist_timestamp)) . n . '</fieldset>' . n . n . '</div>'; //-- publish button -------------- echo has_privs('article.publish') ? fInput('submit', 'publish', gTxt('publish'), "publish", '', '', '', 4) : fInput('submit', 'publish', gTxt('save'), "publish", '', '', '', 4); } else { //-- timestamp ------------------- if (!empty($year)) { $sPosted = safe_strtotime($year . '-' . $month . '-' . $day . ' ' . $hour . ':' . $minute . ':' . $second); } echo n . n . '<fieldset id="write-timestamp">' . n . '<legend>' . gTxt('timestamp') . '</legend>' . n . graf(checkbox('reset_time', '1', $reset_time, '', 'reset_time') . '<label for="reset_time">' . gTxt('reset_time') . '</label>') . n . graf(gTxt('published_at') . sp . popHelp('timestamp')) . n . graf(gtxt('date') . sp . tsi('year', '%Y', $sPosted) . ' / ' . tsi('month', '%m', $sPosted) . ' / ' . tsi('day', '%d', $sPosted)) . n . graf(gTxt('time') . sp . tsi('hour', '%H', $sPosted) . ' : ' . tsi('minute', '%M', $sPosted) . ' : ' . tsi('second', '%S', $sPosted)) . n . hInput('sPosted', $sPosted), n . hInput('sLastMod', $sLastMod), n . hInput('AuthorID', $AuthorID), n . hInput('LastModID', $LastModID), n . '</fieldset>'; //-- expires ------------------- if (!empty($exp_year)) { if (empty($exp_month)) { $exp_month = 1; } if (empty($exp_day)) { $exp_day = 1; } if (empty($exp_hour)) { $exp_hour = 0; } if (empty($exp_minute)) { $exp_minute = 0; } if (empty($exp_second)) { $exp_second = 0; } $sExpires = safe_strtotime($exp_year . '-' . $exp_month . '-' . $exp_day . ' ' . $exp_hour . ':' . $exp_minute . ':' . $exp_second); } echo n . n . '<fieldset id="write-expires">' . n . '<legend>' . gTxt('expires') . '</legend>' . n . graf(gtxt('date') . sp . tsi('exp_year', '%Y', $sExpires) . ' / ' . tsi('exp_month', '%m', $sExpires) . ' / ' . tsi('exp_day', '%d', $sExpires)) . n . graf(gTxt('time') . sp . tsi('exp_hour', '%H', $sExpires) . ' : ' . tsi('exp_minute', '%M', $sExpires) . ' : ' . tsi('exp_second', '%S', $sExpires)) . n . hInput('sExpires', $sExpires) . n . '</fieldset>' . n . n . '</div>'; //-- save button -------------- if ($Status >= 4 and has_privs('article.edit.published') or $Status >= 4 and $AuthorID == $txp_user and has_privs('article.edit.own.published') or $Status < 4 and has_privs('article.edit') or $Status < 4 and $AuthorID == $txp_user and has_privs('article.edit.own')) { echo fInput('submit', 'save', gTxt('save'), "publish", '', '', '', 4); } } } echo '</td></tr></table></form>'; }
/** * 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>'; }
function customer_edit($event, $step) { global $statuses, $comments_disabled_after, $step, $txp_user; pagetop("Customer", $message); //CSS FOR CUSTOMER EDIT //================================== echo n . '<style type="text/css">' . n . '.customerEdit legend{' . n . ' font-size: 11px;' . n . ' font-weight: bold;' . n . '}' . n . '.customerEdit label{' . n . ' float: left;' . n . ' width: 100px;' . n . ' text-align: right;' . n . ' padding: 5px;' . n . '}' . n . '.customerEdit br{' . n . ' clear: both;' . n . '}' . n . '.customerEdit input{' . n . ' margin: 5px 0 5px 0;' . n . ' font-size: 11px;' . n . '}' . n . '</style>'; doJS(); if (isset($_REQUEST['user_id'])) { $user_id = $_REQUEST['user_id']; $customer = safe_row("*", "txp_users", "user_id = {$user_id}"); extract($customer); $step = "update_customer"; } else { $step = "save_customer"; } //DELETE CUSTOMER FORM //==================================== echo n . n . '<form name="product" method="post" action="index.php" enctype="multipart/form-data" id="customerDelete">'; echo n . "<input type='hidden' name='user_id' value='{$user_id}'/>" . eInput('customers') . sInput('delete_customer'); echo n . n . '</form>'; echo n . n . '<form name="product" method="post" action="index.php" enctype="multipart/form-data">'; echo hInput('user_id', $user_id) . eInput('customers') . sInput($step) . '<input type="hidden" name="view" />' . startTable('edit') . '<tr>' . n; //if ($view == 'text') //{ //-- markup help -------------- echo '<td id="article-main">' . n; echo "<fieldset class='customerEdit'>" . n . "<legend>Customer Details</legend>" . n . '<label for="name">Username</label>' . n . '<input id="name" name="name" value="' . $name . '"/>' . br . n . '<label for="email">Email</label>' . n . '<input id="email" name="email" value="' . $email . '"/>' . n . '<label for="billing_firstname">First name</label>' . n . '<input type="text" id="billing_firstname" name="billing_firstname" value="' . $billing_firstname . '"/>' . br . n . '<label for="billing_lastname">Last name</label>' . n . '<input type="text" id="billing_lastname" name="billing_lastname" value="' . $billing_lastname . '"/>' . br . n . '</fieldset>'; echo "<fieldset class='customerEdit'>" . n . "<legend>Billing Information</legend>" . n . '<label for="billing_company">Company</label>' . n . '<input type="text" id="billing_company" name="billing_company" value="' . $billing_company . '"/>' . br . n . '<label for="billing_address1">Address 1</label>' . n . '<input type="text" id="billing_address1" name="billing_address1" value="' . $billing_address1 . '"/>' . br . n . '<label for="billing_address2">Address 2</label>' . n . '<input type="text" id="billing_address2" name="billing_address2" value="' . $billing_address2 . '"/>' . br . n . '<label for="billing_city">City</label>' . n . '<input type="text" id="billing_city" name="billing_city" value="' . $billing_city . '"/>' . br . n . '<label for="billing_state">State</label>' . n . '<input type="text" id="billing_state" name="billing_state" value="' . $billing_state . '"/>' . br . n . '<label for="billing_zip">Zip/Postal Code</label>' . n . '<input type="text" id="billing_zip" name="billing_zip" value="' . $billing_zip . '"/>' . br . n . '<label for="billing_country">Country</label>' . n . '<input type="text" id="billing_country" name="billing_country" value="' . $billing_country . '"/>' . br . n . '<label for="billing_fax">Fax Number</label>' . n . '<input type="text" id="billing_fax" name="billing_fax" value="' . $billing_fax . '"/>' . br . n . '<label for="billing_phone">Phone Number</label>' . n . '<input type="text" id="billing_phone" name="billing_phone" value="' . $billing_phone . '"/>' . br . n . '<label for="shipping_same"> </label>'; if ($shipping_same_as_billing == "1") { $checked = "checked='checked'"; } else { $checked = ''; } echo n . '<input type="checkbox" id="shipping_same" name="shipping_same_as_billing" value="' . $shipping_same_as_billing . '" ' . $checked . ' onclick="toggleShipping()"/> Shipping info same as billing' . br . n . '</fieldset>'; doJS(); if ($shipping_same_as_billing == "1") { $display = "none"; } else { $display = "block"; } echo "<fieldset class='customerEdit' id='shippingInfo' style='display: {$display}'>" . n . "<legend>Shipping Information</legend>" . n . '<label for="shipping_company">Company</label>' . n . '<input type="text" id="shipping_company" name="shipping_company" value="' . $shipping_company . '"/>' . br . n . '<label for="shipping_firstname">First name</label>' . n . '<input type="text" id="shipping_firstname" name="shipping_firstname" value="' . $shipping_firstname . '"/>' . br . n . '<label for="shipping_lastname">Last name</label>' . n . '<input type="text" id="shipping_lastname" name="shipping_lastname" value="' . $shipping_lastname . '"/>' . br . n . '<label for="shipping_address1">Address 1</label>' . n . '<input type="text" id="shipping_address1" name="shipping_address1" value="' . $shipping_address1 . '"/>' . br . n . '<label for="shipping_address2">Address 2</label>' . n . '<input type="text" id="shipping_address2" name="shipping_address2" value="' . $shipping_address2 . '"/>' . br . n . '<label for="shipping_city">City</label>' . n . '<input type="text" id="shipping_city" name="shipping_city" value="' . $shipping_city . '"/>' . br . n . '<label for="shipping_state">State</label>' . n . '<input type="text" id="shipping_state" name="shipping_state" value="' . $shipping_state . '"/>' . br . n . '<label for="shipping_zip">Zip/Postal Code</label>' . n . '<input type="text" id="shipping_zip" name="shipping_zip" value="' . $shipping_zip . '"/>' . br . n . '<label for="shipping_country">Country</label>' . n . '<input type="text" id="shipping_country" name="shipping_country" value="' . $shipping_country . '"/>' . br . n . '<label for="shipping_fax">Fax Number</label>' . n . '<input type="text" id="shipping_fax" name="shipping_fax" value="' . $shipping_fax . '"/>' . br . n . '<label for="shipping_phone">Phone Number</label>' . n . '<input type="text" id="shipping_phone" name="shipping_phone" value="' . $shipping_phone . '"/>' . br . n . '</fieldset>'; echo '</td>'; echo '<td id="article-col-2" style="padding-top: 13px;">'; //start article-col-2 echo '<a href="?event=customers&step=edit_customer" class="navlink">Add new customer</a>'; if (isset($user_id)) { echo n . br . br . '<a href="javascript:deleteCustomer()" style="color:#990000">Delete this customer</a>' . br . br; } else { echo br . br; } //-- publish button -------------- echo has_privs('article.publish') ? fInput('submit', 'publish', gTxt('save'), "publish", '', '', '', 4) : fInput('submit', 'publish', gTxt('save'), "publish", '', '', '', 4); if ($user_id) { $orders = safe_rows("*", "orders", "user_id = {$user_id} ORDER BY last_updated DESC"); if (count($orders) > 0) { echo br . br . "<fieldset>" . n . '<legend>Order History</legend>' . n . '<ul class="plain-list">'; foreach ($orders as $order) { echo n . '<li><a href="?event=orders&step=edit_order&id=' . $order['id'] . '">ORDER #' . $order['id'] . '</a></li>'; } n . '</ul>'; echo '</fieldset>'; } } echo '</td></tr></table></form>'; }
function file_delete($ids = array()) { global $file_base_path, $txp_user; $ids = $ids ? array_map('assert_int', $ids) : array(assert_int(ps('id'))); if (!has_privs('file.delete')) { if (has_privs('file.delete.own')) { $ids = safe_column('id', 'txp_file', 'id IN (' . join(',', $ids) . ') AND author=\'' . doSlash($txp_user) . '\''); } else { $ids = array(); } } if (!empty($ids)) { $fail = array(); $rs = safe_rows_start('id, filename', 'txp_file', 'id IN (' . join(',', $ids) . ')'); if ($rs) { while ($a = nextRow($rs)) { extract($a); $filepath = build_file_path($file_base_path, $filename); // Notify plugins of pending deletion, pass file's id and path. callback_event('file_deleted', '', false, $id, $filepath); $rsd = safe_delete('txp_file', "id = {$id}"); $ul = false; if ($rsd && is_file($filepath)) { $ul = unlink($filepath); } if (!$rsd or !$ul) { $fail[] = $id; } } if ($fail) { file_list(array(messenger(gTxt('file_delete_failed'), join(', ', $fail)), E_ERROR)); return; } else { update_lastmod('file_deleted', $ids); file_list(gTxt('file_deleted', array('{name}' => join(', ', $ids)))); return; } } else { file_list(array(messenger(gTxt('file_not_found'), join(', ', $ids), ''), E_ERROR)); return; } } file_list(); }