/** * The main panel listing all installed plugins. * * @param string|array $message The activity message */ function plugin_list($message = '') { global $event; pagetop(gTxt('tab_plugins'), $message); extract(gpsa(array('sort', 'dir'))); if ($sort === '') { $sort = get_pref('plugin_sort_column', 'name'); } else { if (!in_array($sort, array('name', 'status', 'author', 'version', 'modified', 'load_order'))) { $sort = 'name'; } set_pref('plugin_sort_column', $sort, 'plugin', 2, '', 0, PREF_PRIVATE); } if ($dir === '') { $dir = get_pref('plugin_sort_dir', 'asc'); } else { $dir = $dir == 'desc' ? "desc" : "asc"; set_pref('plugin_sort_dir', $dir, 'plugin', 2, '', 0, PREF_PRIVATE); } $sort_sql = "{$sort} {$dir}"; $switch_dir = $dir == 'desc' ? 'asc' : 'desc'; echo n . tag(hed(gTxt('tab_plugins'), 1, array('class' => 'txp-heading')), 'div', array('class' => 'txp-layout-2col-cell-1')) . n . tag_start('div', array('class' => 'txp-layout-1col', 'id' => $event . '_container')) . n . tag(plugin_form(), 'div', array('class' => 'txp-control-panel')); $rs = safe_rows_start("name, status, author, author_uri, version, description, length(help) AS help, ABS(STRCMP(MD5(code), code_md5)) AS modified, load_order, flags", 'txp_plugin', "1 = 1 ORDER BY {$sort_sql}"); if ($rs and numRows($rs) > 0) { echo n . tag_start('form', array('class' => 'multi_edit_form', 'id' => 'plugin_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('plugin', 'name', 'plugin', true, $switch_dir, '', '', ('name' == $sort ? "{$dir} " : '') . 'txp-list-col-name') . column_head('author', 'author', 'plugin', true, $switch_dir, '', '', ('author' == $sort ? "{$dir} " : '') . 'txp-list-col-author') . column_head('version', 'version', 'plugin', true, $switch_dir, '', '', ('version' == $sort ? "{$dir} " : '') . 'txp-list-col-version') . column_head('plugin_modified', 'modified', 'plugin', true, $switch_dir, '', '', ('modified' == $sort ? "{$dir} " : '') . 'txp-list-col-modified') . hCell(gTxt('description'), '', ' class="txp-list-col-description" scope="col"') . column_head('active', 'status', 'plugin', true, $switch_dir, '', '', ('status' == $sort ? "{$dir} " : '') . 'txp-list-col-status') . column_head('order', 'load_order', 'plugin', true, $switch_dir, '', '', ('load_order' == $sort ? "{$dir} " : '') . 'txp-list-col-load-order') . hCell(gTxt('manage'), '', ' class="txp-list-col-manage" scope="col"')) . n . tag_end('thead') . n . tag_start('tbody'); while ($a = nextRow($rs)) { foreach ($a as $key => $value) { ${$key} = txpspecialchars($value); } // Fix up the description for clean cases. $description = preg_replace(array('#<br />#', '#<(/?(a|b|i|em|strong))>#', '#<a href="(https?|\\.|\\/|ftp)([A-Za-z0-9:/?.=_]+?)">#'), array('<br />', '<$1>', '<a href="$1$2">'), $description); if (!empty($help)) { $help = href(gTxt('help'), array('event' => 'plugin', 'step' => 'plugin_help', 'name' => $name), array('class' => 'plugin-help')); } if ($flags & PLUGIN_HAS_PREFS) { $plugin_prefs = href(gTxt('plugin_prefs'), array('event' => 'plugin_prefs.' . $name), array('class' => 'plugin-prefs')); } else { $plugin_prefs = ''; } $manage = array(); if ($help) { $manage[] = $help; } if ($plugin_prefs) { $manage[] = $plugin_prefs; } $manage_items = $manage ? join(tag(sp . '|' . sp, 'span'), $manage) : '-'; $edit_url = eLink('plugin', 'plugin_edit', 'name', $name, $name); echo tr(td(fInput('checkbox', 'selected[]', $name), '', 'txp-list-col-multi-edit') . hCell($edit_url, '', ' class="txp-list-col-name" scope="row"') . td(href($author, $a['author_uri'], array('rel' => 'external')), '', 'txp-list-col-author') . td($version, '', 'txp-list-col-version') . td($modified ? span(gTxt('yes'), array('class' => 'warning')) : '', '', 'txp-list-col-modified') . td($description, '', 'txp-list-col-description') . td(status_link($status, $name, yes_no($status)), '', 'txp-list-col-status') . td($load_order, '', 'txp-list-col-load-order') . td($manage_items, '', 'txp-list-col-manage'), $status ? ' class="active"' : ''); unset($name, $page, $deletelink); } echo n . tag_end('tbody') . n . tag_end('table') . n . tag_end('div') . plugin_multiedit_form('', $sort, $dir, '', '') . tInput() . n . tag_end('form'); } 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 file_list($message = '') { global $file_base_path, $file_statuses, $file_list_pageby, $txp_user, $event; pagetop(gTxt('tab_file'), $message); extract(gpsa(array('page', 'sort', 'dir', 'crit', 'search_method'))); if ($sort === '') { $sort = get_pref('file_sort_column', 'filename'); } if ($dir === '') { $dir = get_pref('file_sort_dir', 'asc'); } if ($dir === 'desc') { $dir = 'desc'; } else { $dir = 'asc'; } echo hed(gTxt('tab_file'), 1, array('class' => 'txp-heading')) . n . tag_start('div', array('id' => $event . '_control', 'class' => 'txp-control-panel')); if (!is_dir($file_base_path) || !is_writeable($file_base_path)) { echo graf(span(null, array('class' => 'ui-icon ui-icon-alert')) . ' ' . gTxt('file_dir_not_writeable', array('{filedir}' => $file_base_path)), array('class' => 'alert-block warning')); } elseif (has_privs('file.edit.own')) { $existing_files = get_filenames(); if ($existing_files) { echo form(eInput('file') . sInput('file_create') . graf(tag(gTxt('existing_file'), 'label', array('for' => 'file-existing')) . sp . selectInput('filename', $existing_files, '', 1, '', 'file-existing') . sp . fInput('submit', '', gTxt('Create')), array('class' => 'existing-file')), '', '', 'post', '', '', 'assign_file'); } echo file_upload_form(gTxt('upload_file'), 'upload', 'file_insert'); } switch ($sort) { case 'id': $sort_sql = 'txp_file.id ' . $dir; break; case 'description': $sort_sql = 'txp_file.description ' . $dir . ', txp_file.filename desc'; break; case 'category': $sort_sql = 'txp_category.title ' . $dir . ', txp_file.filename desc'; break; case 'title': $sort_sql = 'txp_file.title ' . $dir . ', txp_file.filename desc'; break; case 'downloads': $sort_sql = 'txp_file.downloads ' . $dir . ', txp_file.filename desc'; break; case 'author': $sort_sql = 'txp_users.RealName ' . $dir . ', txp_file.id asc'; break; default: $sort = 'filename'; $sort_sql = 'txp_file.filename ' . $dir; break; } set_pref('file_sort_column', $sort, 'file', PREF_HIDDEN, '', 0, PREF_PRIVATE); set_pref('file_sort_dir', $dir, 'file', PREF_HIDDEN, '', 0, PREF_PRIVATE); if ($dir == 'desc') { $switch_dir = 'asc'; } else { $switch_dir = 'desc'; } $criteria = 1; if ($search_method && $crit !== '') { $verbatim = preg_match('/^"(.*)"$/', $crit, $m); $crit_escaped = $verbatim ? doSlash($m[1]) : doLike($crit); $critsql = $verbatim ? array('id' => "txp_file.id in ('" . join("','", do_list($crit_escaped)) . "')", 'filename' => "txp_file.filename = '{$crit_escaped}'", 'title' => "txp_file.title = '{$crit_escaped}'", 'description' => "txp_file.description = '{$crit_escaped}'", 'category' => "txp_file.category = '{$crit_escaped}' or txp_category.title = '{$crit_escaped}'", 'author' => "txp_file.author = '{$crit_escaped}' or txp_users.RealName = '{$crit_escaped}'") : array('id' => "txp_file.id in ('" . join("','", do_list($crit_escaped)) . "')", 'filename' => "txp_file.filename like '%{$crit_escaped}%'", 'title' => "txp_file.title like '%{$crit_escaped}%'", 'description' => "txp_file.description like '%{$crit_escaped}%'", 'category' => "txp_file.category like '%{$crit_escaped}%' or txp_category.title like '%{$crit_escaped}%'", 'author' => "txp_file.author like '%{$crit_escaped}%' or txp_users.RealName like '%{$crit_escaped}%'"); if (array_key_exists($search_method, $critsql)) { $criteria = $critsql[$search_method]; $limit = 500; } else { $search_method = ''; $crit = ''; } } else { $search_method = ''; $crit = ''; } $criteria .= callback_event('admin_criteria', 'file_list', 0, $criteria); $sql_from = safe_pfx_j('txp_file') . "\n left join " . safe_pfx_j('txp_category') . " on txp_category.name = txp_file.category and txp_category.type = 'file'\n left join " . safe_pfx_j('txp_users') . " on txp_users.name = txp_file.author"; if ($criteria === 1) { $total = safe_count('txp_file', $criteria); } else { $total = getThing('select count(*) from ' . $sql_from . ' where ' . $criteria); } if ($total < 1) { if ($criteria != 1) { echo file_search_form($crit, $search_method) . graf(gTxt('no_results_found'), ' class="indicator"') . '</div>'; } else { echo graf(gTxt('no_files_recorded'), ' class="indicator"') . '</div>'; } return; } $limit = max($file_list_pageby, 15); list($page, $offset, $numPages) = pager($total, $limit, $page); echo file_search_form($crit, $search_method) . '</div>'; $rs = safe_query("select\n txp_file.id,\n txp_file.filename,\n txp_file.title,\n txp_file.category,\n txp_file.description,\n txp_file.downloads,\n txp_file.status,\n txp_file.author,\n txp_users.RealName as realname,\n txp_category.Title as category_title\n from {$sql_from} where {$criteria} order by {$sort_sql} limit {$offset}, {$limit}"); if ($rs && numRows($rs)) { $show_authors = !has_single_author('txp_file'); echo n . tag_start('div', array('id' => $event . '_container', 'class' => 'txp-container')) . n . tag_start('form', array('action' => 'index.php', 'id' => 'files_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(hCell(fInput('checkbox', 'select_all', 0, '', '', '', '', '', 'select_all'), '', ' scope="col" title="' . gTxt('toggle_all_selected') . '" class="txp-list-col-multi-edit"') . column_head('ID', 'id', 'file', true, $switch_dir, $crit, $search_method, ('id' == $sort ? "{$dir} " : '') . 'txp-list-col-id') . column_head('file_name', 'filename', 'file', true, $switch_dir, $crit, $search_method, ('filename' == $sort ? "{$dir} " : '') . 'txp-list-col-filename') . column_head('title', 'title', 'file', true, $switch_dir, $crit, $search_method, ('title' == $sort ? "{$dir} " : '') . 'txp-list-col-title') . column_head('description', 'description', 'file', true, $switch_dir, $crit, $search_method, ('description' == $sort ? "{$dir} " : '') . 'txp-list-col-description files_detail') . column_head('file_category', 'category', 'file', true, $switch_dir, $crit, $search_method, ('category' == $sort ? "{$dir} " : '') . 'txp-list-col-category category') . hCell(gTxt('tags'), '', ' scope="col" class="txp-list-col-tag-build files_detail"') . hCell(gTxt('status'), '', ' scope="col" class="txp-list-col-status"') . hCell(gTxt('condition'), '', ' scope="col" class="txp-list-col-condition"') . column_head('downloads', 'downloads', 'file', true, $switch_dir, $crit, $search_method, ('downloads' == $sort ? "{$dir} " : '') . 'txp-list-col-downloads') . ($show_authors ? column_head('author', 'author', 'file', true, $switch_dir, $crit, $search_method, ('author' == $sort ? "{$dir} " : '') . 'txp-list-col-author name') : '')) . n . tag_end('thead') . n . tag_start('tbody'); $validator = new Validator(); while ($a = nextRow($rs)) { extract($a); $filename = sanitizeForFile($filename); $edit_url = array('event' => 'file', 'step' => 'file_edit', 'id' => $id, 'sort' => $sort, 'dir' => $dir, 'page' => $page, 'search_method' => $search_method, 'crit' => $crit); $tag_url = array('event' => 'tag', 'tag_name' => 'file_download_link', 'id' => $id, 'description' => $description, 'filename' => $filename); $file_exists = file_exists(build_file_path($file_base_path, $filename)); $can_edit = has_privs('file.edit') || $author === $txp_user && has_privs('file.edit.own'); $validator->setConstraints(array(new CategoryConstraint($category, array('type' => 'file')))); if ($validator->validate()) { $vc = ''; } else { $vc = ' error'; } if ($file_exists) { $downloads = make_download_link($id, $downloads, $filename); $condition = span(gTxt('file_status_ok'), array('class' => 'success')); } else { $condition = span(gTxt('file_status_missing'), array('class' => 'error')); } if ($category) { $category = span(txpspecialchars($category_title), array('title' => $category)); } if ($can_edit) { $name = href(txpspecialchars($filename), $edit_url, array('title' => gTxt('edit'))); } else { $name = txpspecialchars($filename); } if ($can_edit) { $id_column = href($id, $edit_url, array('title' => gTxt('edit'))); $multi_edit = fInput('checkbox', 'selected[]', $id); } else { $id_column = $id; $multi_edit = ''; } if ($file_exists) { $id_column .= sp . span('[', array('aria-hidden' => 'true')) . make_download_link($id, gTxt('download'), $filename) . span(']', array('aria-hidden' => 'true')); } if (isset($file_statuses[$status])) { $status = $file_statuses[$status]; } else { $status = span(gTxt('none'), array('class' => 'error')); } echo tr(td($multi_edit, '', 'txp-list-col-multi-edit') . hCell($id_column, '', array('scope' => 'row', 'class' => 'txp-list-col-id')) . td($name, '', 'txp-list-col-filename') . td(txpspecialchars($title), '', 'txp-list-col-title') . td(txpspecialchars($description), '', 'txp-list-col-description files_detail') . td($category, '', 'txp-list-col-category category' . $vc) . td(href('Textile', $tag_url + array('type' => 'textile'), ' target="_blank" onclick="popWin(this.href); return false;"') . sp . span('|', array('role' => 'separator')) . sp . href('Textpattern', $tag_url + array('type' => 'textpattern'), ' target="_blank" onclick="popWin(this.href); return false;"') . sp . span('|', array('role' => 'separator')) . sp . href('HTML', $tag_url + array('type' => 'html'), ' target="_blank" onclick="popWin(this.href); return false;"'), '', 'txp-list-col-tag-build files_detail') . td($status, '', 'txp-list-col-status') . td($condition, '', 'txp-list-col-condition') . td($downloads, '', 'txp-list-col-downloads') . ($show_authors ? td(span(txpspecialchars($realname), array('title' => $author)), '', 'txp-list-col-author name') : '')); } echo n . tag_end('tbody') . n . tag_end('table') . n . tag_end('div') . file_multiedit_form($page, $sort, $dir, $crit, $search_method) . tInput() . n . tag_end('form') . graf(toggle_box('files_detail'), array('class' => 'detail-toggle')) . n . tag_start('div', array('id' => $event . '_navigation', 'class' => 'txp-navigation')) . pageby_form('file', $file_list_pageby) . nav_form('file', $page, $numPages, $sort, $dir, $crit, $search_method, $total, $limit) . n . tag_end('div') . n . tag_end('div'); } }
/** * The main panel listing all authors. * * @param string|array $message The activity message */ function author_list($message = '') { global $event, $txp_user, $author_list_pageby, $levels; 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')); } $buttons = array(); // Change password button. $buttons[] = sLink('admin', 'new_pass_form', gTxt('change_password'), 'txp-button'); if (!has_privs('admin.edit')) { // Change email address button. $buttons[] = sLink('admin', 'change_email_form', gTxt('change_email_address'), 'txp-button'); } else { // New author button. $buttons[] = sLink('admin', 'author_edit', gTxt('add_new_author'), 'txp-button'); } // 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'); } else { if (!in_array($sort, array('name', 'RealName', 'email', 'privs', 'last_login'))) { $sort = 'name'; } set_pref('admin_sort_column', $sort, 'admin', 2, '', 0, PREF_PRIVATE); } if ($dir === '') { $dir = get_pref('admin_sort_dir', 'asc'); } else { $dir = $dir == 'desc' ? "desc" : "asc"; set_pref('admin_sort_dir', $dir, 'admin', 2, '', 0, PREF_PRIVATE); } $sort_sql = $sort . ' ' . $dir; $switch_dir = $dir == 'desc' ? 'asc' : 'desc'; $search = new Filter($event, array('login' => array('column' => 'txp_users.name', 'label' => gTxt('login_name')), 'RealName' => array('column' => 'txp_users.RealName', 'label' => gTxt('real_name')), 'email' => array('column' => 'txp_users.email', 'label' => gTxt('email')), 'privs' => array('column' => array('txp_users.privs'), 'label' => gTxt('privileges'), 'type' => 'boolean'))); $search->setAliases('privs', $levels); list($criteria, $crit, $search_method) = $search->getFilter(); $search_render_options = array('placeholder' => 'search_users'); $total = getCount('txp_users', $criteria); echo n . tag(hed(gTxt('tab_site_admin'), 1, array('class' => 'txp-heading')), 'div', array('class' => 'txp-layout-2col-cell-1')); $searchBlock = n . tag($search->renderForm('author_list', $search_render_options), 'div', array('class' => 'txp-layout-2col-cell-2', 'id' => 'users_control')); $createBlock = array(); $createBlock[] = n . tag(implode(n, $buttons), 'div', array('class' => 'txp-control-panel')); $contentBlockStart = n . tag_start('div', array('class' => 'txp-layout-1col', 'id' => 'users_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($author_list_pageby, 15); list($page, $offset, $numPages) = pager($total, $limit, $page); $use_multi_edit = has_privs('admin.edit') && ($total > 1 or safe_count('txp_users', "1 = 1") > 1); echo $searchBlock . $contentBlockStart . $createBlock; $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('form', array('class' => 'multi_edit_form', 'id' => 'users_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(($use_multi_edit ? hCell(fInput('checkbox', 'select_all', 0, '', '', '', '', '', 'select_all'), '', ' class="txp-list-col-multi-edit" scope="col" title="' . gTxt('toggle_all_selected') . '"') : hCell('', '', ' class="txp-list-col-multi-edit" scope="col"')) . 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, '', ' class="txp-list-col-login-name name" scope="row"') . 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('class' => 'txp-navigation', 'id' => 'users_navigation')) . pageby_form('admin', $author_list_pageby) . nav_form('admin', $page, $numPages, $sort, $dir, $crit, $search_method) . n . tag_end('div'); } echo n . tag_end('div'); } else { echo n . tag_start('div', array('class' => 'txp-layout-1col', 'id' => 'users_container')) . n . tag(implode(n, $buttons), 'div', array('class' => 'txp-control-panel')) . n . tag_end('div'); } }
function image_list($message = '') { global $txpcfg, $extensions, $img_dir, $file_max_upload_size, $image_list_pageby, $txp_user, $event; pagetop(gTxt('tab_image'), $message); extract($txpcfg); extract(gpsa(array('page', 'sort', 'dir', 'crit', 'search_method'))); if ($sort === '') { $sort = get_pref('image_sort_column', 'id'); } if ($dir === '') { $dir = get_pref('image_sort_dir', 'desc'); } $dir = $dir == 'asc' ? 'asc' : 'desc'; echo hed(gTxt('tab_image'), 1, array('class' => 'txp-heading')); echo n . '<div id="' . $event . '_control" class="txp-control-panel">'; if (!is_dir(IMPATH) or !is_writeable(IMPATH)) { echo graf(span(null, array('class' => 'ui-icon ui-icon-alert')) . ' ' . gTxt('img_dir_not_writeable', array('{imgdir}' => IMPATH)), array('class' => 'alert-block warning')); } elseif (has_privs('image.edit.own')) { echo upload_form(gTxt('upload_image'), 'upload_image', 'image_insert', 'image', '', $file_max_upload_size); } switch ($sort) { case 'name': $sort_sql = 'name ' . $dir; break; case 'thumbnail': $sort_sql = 'thumbnail ' . $dir . ', id asc'; break; case 'category': $sort_sql = 'category ' . $dir . ', id asc'; break; case 'date': $sort_sql = 'date ' . $dir . ', id asc'; break; case 'author': $sort_sql = 'author ' . $dir . ', id asc'; break; default: $sort = 'id'; $sort_sql = 'id ' . $dir; break; } set_pref('image_sort_column', $sort, 'image', 2, '', 0, PREF_PRIVATE); set_pref('image_sort_dir', $dir, 'image', 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' => "ID in ('" . join("','", do_list($crit_escaped)) . "')", 'name' => "name = '{$crit_escaped}'", 'category' => "category = '{$crit_escaped}'", 'author' => "author = '{$crit_escaped}'", 'alt' => "alt = '{$crit_escaped}'", 'caption' => "caption = '{$crit_escaped}'") : array('id' => "ID in ('" . join("','", do_list($crit_escaped)) . "')", 'name' => "name like '%{$crit_escaped}%'", 'category' => "category like '%{$crit_escaped}%'", 'author' => "author like '%{$crit_escaped}%'", 'alt' => "alt like '%{$crit_escaped}%'", 'caption' => "caption like '%{$crit_escaped}%'"); if (array_key_exists($search_method, $critsql)) { $criteria = $critsql[$search_method]; $limit = 500; } else { $search_method = ''; $crit = ''; } } else { $search_method = ''; $crit = ''; } $criteria .= callback_event('admin_criteria', 'image_list', 0, $criteria); $total = safe_count('txp_image', "{$criteria}"); if ($total < 1) { if ($criteria != 1) { echo n . image_search_form($crit, $search_method) . graf(gTxt('no_results_found'), ' class="indicator"') . '</div>'; } else { echo graf(gTxt('no_images_recorded'), ' class="indicator"') . '</div>'; } return; } $limit = max($image_list_pageby, 15); list($page, $offset, $numPages) = pager($total, $limit, $page); echo image_search_form($crit, $search_method); $rs = safe_rows_start('*, unix_timestamp(date) as uDate', 'txp_image', "{$criteria} order by {$sort_sql} limit {$offset}, {$limit}\n "); echo pluggable_ui('image_ui', 'extend_controls', '', $rs); echo '</div>'; // End txp-control-panel. if ($rs) { $show_authors = !has_single_author('txp_image'); echo n . tag_start('div', array('id' => $event . '_container', 'class' => 'txp-container')) . n . tag_start('form', array('action' => 'index.php', 'id' => 'images_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(hCell(fInput('checkbox', 'select_all', 0, '', '', '', '', '', 'select_all'), '', ' scope="col" title="' . gTxt('toggle_all_selected') . '" class="txp-list-col-multi-edit"') . column_head('ID', 'id', 'image', true, $switch_dir, $crit, $search_method, ('id' == $sort ? "{$dir} " : '') . 'txp-list-col-id') . column_head('name', 'name', 'image', true, $switch_dir, $crit, $search_method, ('name' == $sort ? "{$dir} " : '') . 'txp-list-col-name') . column_head('date', 'date', 'image', true, $switch_dir, $crit, $search_method, ('date' == $sort ? "{$dir} " : '') . 'txp-list-col-created date images_detail') . column_head('thumbnail', 'thumbnail', 'image', true, $switch_dir, $crit, $search_method, ('thumbnail' == $sort ? "{$dir} " : '') . 'txp-list-col-thumbnail') . hCell(gTxt('tags'), '', ' scope="col" class="txp-list-col-tag-build images_detail"') . column_head('image_category', 'category', 'image', true, $switch_dir, $crit, $search_method, ('category' == $sort ? "{$dir} " : '') . 'txp-list-col-category category') . ($show_authors ? column_head('author', 'author', 'image', true, $switch_dir, $crit, $search_method, ('author' == $sort ? "{$dir} " : '') . 'txp-list-col-author name') : '')) . n . tag_end('thead') . n . tag_start('tbody'); $validator = new Validator(); while ($a = nextRow($rs)) { extract($a); $edit_url = array('event' => 'image', 'step' => 'image_edit', 'id' => $id, 'sort' => $sort, 'dir' => $dir, 'page' => $page, 'search_method' => $search_method, 'crit' => $crit); $name = empty($name) ? gTxt('unnamed') : txpspecialchars($name); if ($thumbnail) { if ($ext != '.swf') { $thumbnail = '<img class="content-image" src="' . imagesrcurl($id, $ext, true) . "?{$uDate}" . '" alt="" ' . "title='{$id}{$ext} ({$w} × {$h})'" . ($thumb_w ? " width='{$thumb_w}' height='{$thumb_h}'" : '') . ' />'; } else { $thumbnail = ''; } } else { $thumbnail = gTxt('no'); } if ($ext != '.swf') { $tag_url = '?event=tag' . a . 'tag_name=image' . a . 'id=' . $id . a . 'ext=' . $ext . a . 'w=' . $w . a . 'h=' . $h . a . 'alt=' . urlencode($alt) . a . 'caption=' . urlencode($caption); $tagbuilder = href('Textile', $tag_url . a . 'type=textile', ' target="_blank" onclick="popWin(this.href); return false;"') . sp . span('|', array('role' => 'separator')) . sp . href('Textpattern', $tag_url . a . 'type=textpattern', ' target="_blank" onclick="popWin(this.href); return false;"') . sp . span('|', array('role' => 'separator')) . sp . href('HTML', $tag_url . a . 'type=html', ' target="_blank" onclick="popWin(this.href); return false;"'); } else { $tagbuilder = sp; } $validator->setConstraints(array(new CategoryConstraint($category, array('type' => 'image')))); $vc = $validator->validate() ? '' : ' error'; $category = $category ? span($category, array('title' => fetch_category_title($category, 'image'))) : ''; $can_edit = has_privs('image.edit') || $author === $txp_user && has_privs('image.edit.own'); echo tr(td($can_edit ? fInput('checkbox', 'selected[]', $id) : ' ', '', 'txp-list-col-multi-edit') . hCell(($can_edit ? href($id, $edit_url, array('title' => gTxt('edit'))) : $id) . sp . span(span('[', array('aria-hidden' => 'true')) . href(gTxt('view'), imagesrcurl($id, $ext)) . span(']', array('aria-hidden' => 'true')), array('class' => 'images_detail')), '', ' scope="row" class="txp-list-col-id"') . td($can_edit ? href($name, $edit_url, ' title="' . gTxt('edit') . '"') : $name, '', 'txp-list-col-name') . td(gTime($uDate), '', 'txp-list-col-created date images_detail') . td(pluggable_ui('image_ui', 'thumbnail', $can_edit ? href($thumbnail, $edit_url) : $thumbnail, $a), '', 'txp-list-col-thumbnail') . td($tagbuilder, '', 'txp-list-col-tag-build images_detail') . td($category, '', 'txp-list-col-category category' . $vc) . ($show_authors ? td(span(txpspecialchars($author), array('title' => get_author_name($author))), '', 'txp-list-col-author name') : '')); } echo n . tag_end('tbody') . n . tag_end('table') . n . tag_end('div') . image_multiedit_form($page, $sort, $dir, $crit, $search_method) . tInput() . n . tag_end('form') . graf(toggle_box('images_detail'), array('class' => 'detail-toggle')) . n . tag_start('div', array('id' => $event . '_navigation', 'class' => 'txp-navigation')) . pageby_form('image', $image_list_pageby) . nav_form('image', $page, $numPages, $sort, $dir, $crit, $search_method, $total, $limit) . n . tag_end('div') . n . tag_end('div'); } }
/** * Outputs the main panel listing all comments. * * @param string|array $message The activity message */ function discuss_list($message = '') { global $event, $comment_list_pageby; pagetop(gTxt('list_discussions'), $message); extract(gpsa(array('sort', 'dir', 'page', 'crit', 'search_method'))); if ($sort === '') { $sort = get_pref('discuss_sort_column', 'date'); } else { if (!in_array($sort, array('id', 'ip', 'name', 'email', 'website', 'message', 'status', 'parent'))) { $sort = 'date'; } set_pref('discuss_sort_column', $sort, 'discuss', 2, '', 0, PREF_PRIVATE); } if ($dir === '') { $dir = get_pref('discuss_sort_dir', 'desc'); } else { $dir = $dir == 'asc' ? "asc" : "desc"; set_pref('discuss_sort_dir', $dir, 'discuss', 2, '', 0, PREF_PRIVATE); } switch ($sort) { case 'id': $sort_sql = "txp_discuss.discussid {$dir}"; break; case 'ip': $sort_sql = "txp_discuss.ip {$dir}"; break; case 'name': $sort_sql = "txp_discuss.name {$dir}"; break; case 'email': $sort_sql = "txp_discuss.email {$dir}"; break; case 'website': $sort_sql = "txp_discuss.web {$dir}"; break; case 'message': $sort_sql = "txp_discuss.message {$dir}"; break; case 'status': $sort_sql = "txp_discuss.visible {$dir}"; break; case 'parent': $sort_sql = "txp_discuss.parentid {$dir}"; break; default: $sort = 'date'; $sort_sql = "txp_discuss.posted {$dir}"; break; } if ($sort != 'date') { $sort_sql .= ", txp_discuss.posted ASC"; } $switch_dir = $dir == 'desc' ? 'asc' : 'desc'; $search = new Filter($event, array('id' => array('column' => 'txp_discuss.discussid', 'label' => gTxt('ID'), 'type' => 'integer'), 'parent' => array('column' => array('txp_discuss.parentid', 'textpattern.Title'), 'label' => gTxt('parent')), 'name' => array('column' => 'txp_discuss.name', 'label' => gTxt('name')), 'message' => array('column' => 'txp_discuss.message', 'label' => gTxt('message')), 'email' => array('column' => 'txp_discuss.email', 'label' => gTxt('email')), 'website' => array('column' => 'txp_discuss.web', 'label' => gTxt('website')), 'ip' => array('column' => 'txp_discuss.ip', 'label' => gTxt('IP')), 'visible' => array('column' => 'txp_discuss.visible', 'label' => gTxt('visible'), 'type' => 'numeric'))); $alias_yes = VISIBLE . ', Yes'; $alias_no = MODERATE . ', No, Unmoderated, Pending'; $alias_spam = SPAM . ', Spam'; $search->setAliases('visible', array(VISIBLE => $alias_yes, MODERATE => $alias_no, SPAM => $alias_spam)); list($criteria, $crit, $search_method) = $search->getFilter(array('id' => array('can_list' => true))); $search_render_options = array('placeholder' => 'search_comments'); $sql_from = safe_pfx_j('txp_discuss') . "\n left join " . safe_pfx_j('textpattern') . " on txp_discuss.parentid = textpattern.ID"; $counts = getRows("SELECT txp_discuss.visible, COUNT(*) AS c\n FROM " . safe_pfx_j('txp_discuss') . "\n LEFT JOIN " . safe_pfx_j('textpattern') . "\n ON txp_discuss.parentid = textpattern.ID\n WHERE {$criteria} GROUP BY txp_discuss.visible"); $count[SPAM] = $count[MODERATE] = $count[VISIBLE] = 0; if ($counts) { foreach ($counts as $c) { $count[$c['visible']] = $c['c']; } } // Grand total comment count. $total = $count[SPAM] + $count[MODERATE] + $count[VISIBLE]; echo n . tag(hed(gTxt('list_discussions'), 1, array('class' => 'txp-heading')), 'div', array('class' => 'txp-layout-2col-cell-1')); $searchBlock = n . tag($search->renderForm('discuss_list', $search_render_options), 'div', array('class' => 'txp-layout-2col-cell-2', 'id' => $event . '_control')); $contentBlockStart = n . tag_start('div', array('class' => 'txp-layout-1col', 'id' => $event . '_container')); if ($total < 1) { if ($criteria != 1) { echo $searchBlock . $contentBlockStart . graf(span(null, array('class' => 'ui-icon ui-icon-info')) . ' ' . gTxt('no_results_found'), array('class' => 'alert-block information')); } else { echo $contentBlockStart . graf(span(null, array('class' => 'ui-icon ui-icon-info')) . ' ' . gTxt('no_comments_recorded'), array('class' => 'alert-block information')); } echo n . tag_end('div'); return; } if (!cs('toggle_show_spam')) { $total = $count[MODERATE] + $count[VISIBLE]; $criteria = 'visible != ' . intval(SPAM) . ' and ' . $criteria; } $limit = max($comment_list_pageby, 15); list($page, $offset, $numPages) = pager($total, $limit, $page); echo $searchBlock . $contentBlockStart; $rs = safe_query("SELECT\n txp_discuss.discussid,\n txp_discuss.parentid,\n txp_discuss.name,\n txp_discuss.email,\n txp_discuss.web,\n txp_discuss.ip,\n txp_discuss.message,\n txp_discuss.visible,\n UNIX_TIMESTAMP(txp_discuss.posted) AS uPosted,\n textpattern.ID AS thisid,\n textpattern.Section AS section,\n textpattern.url_title,\n textpattern.Title AS title,\n textpattern.Status,\n UNIX_TIMESTAMP(textpattern.Posted) AS posted\n FROM " . safe_pfx_j('txp_discuss') . "\n LEFT JOIN " . safe_pfx_j('textpattern') . " ON txp_discuss.parentid = textpattern.ID\n WHERE {$criteria} ORDER BY {$sort_sql} LIMIT {$offset}, {$limit}"); if ($rs) { echo n . tag(cookie_box('show_spam') . toggle_box('discuss_detail'), 'div', array('class' => 'txp-list-options')) . n . tag_start('form', array('class' => 'multi_edit_form', 'id' => 'discuss_form', 'name' => 'longform', 'method' => 'post', 'action' => 'index.php')) . n . tag_start('div', array('class' => 'txp-listtables')) . n . tag_start('table', array('class' => 'txp-list')) . n . tag_start('thead') . tr(hCell(fInput('checkbox', 'select_all', 0, '', '', '', '', '', 'select_all'), '', ' class="txp-list-col-multi-edit" scope="col" title="' . gTxt('toggle_all_selected') . '"') . column_head('ID', 'id', 'discuss', true, $switch_dir, $crit, $search_method, ('id' == $sort ? "{$dir} " : '') . 'txp-list-col-id') . column_head('date', 'date', 'discuss', true, $switch_dir, $crit, $search_method, ('date' == $sort ? "{$dir} " : '') . 'txp-list-col-created date') . column_head('name', 'name', 'discuss', true, $switch_dir, $crit, $search_method, ('name' == $sort ? "{$dir} " : '') . 'txp-list-col-name') . column_head('message', 'message', 'discuss', true, $switch_dir, $crit, $search_method, 'message' == $sort ? "{$dir} " : 'txp-list-col-message') . column_head('email', 'email', 'discuss', true, $switch_dir, $crit, $search_method, ('email' == $sort ? "{$dir} " : '') . 'txp-list-col-email discuss_detail') . column_head('website', 'website', 'discuss', true, $switch_dir, $crit, $search_method, ('website' == $sort ? "{$dir} " : '') . 'txp-list-col-website discuss_detail') . column_head('IP', 'ip', 'discuss', true, $switch_dir, $crit, $search_method, ('ip' == $sort ? "{$dir} " : '') . 'txp-list-col-ip discuss_detail') . column_head('status', 'status', 'discuss', true, $switch_dir, $crit, $search_method, ('status' == $sort ? "{$dir} " : '') . 'txp-list-col-status') . column_head('parent', 'parent', 'discuss', true, $switch_dir, $crit, $search_method, ('parent' == $sort ? "{$dir} " : '') . 'txp-list-col-parent')) . n . tag_end('thead'); include_once txpath . '/publish/taghandlers.php'; echo n . tag_start('tbody'); while ($a = nextRow($rs)) { extract($a); $parentid = assert_int($parentid); $edit_url = array('event' => 'discuss', 'step' => 'discuss_edit', 'discussid' => $discussid, 'sort' => $sort, 'dir' => $dir, 'page' => $page, 'search_method' => $search_method, 'crit' => $crit); $dmessage = $visible == SPAM ? short_preview($message) : $message; switch ($visible) { case VISIBLE: $comment_status = gTxt('visible'); $row_class = 'visible'; break; case SPAM: $comment_status = gTxt('spam'); $row_class = 'spam'; break; case MODERATE: $comment_status = gTxt('unmoderated'); $row_class = 'moderate'; break; default: break; } if (empty($thisid)) { $parent = gTxt('article_deleted') . ' (' . $parentid . ')'; $view = ''; } else { $parent_title = empty($title) ? '<em>' . gTxt('untitled') . '</em>' : escape_title($title); $parent = href($parent_title, '?event=article' . a . 'step=edit' . a . 'ID=' . $parentid); $view = $comment_status; if ($visible == VISIBLE and in_array($Status, array(4, 5))) { $view = href($comment_status, permlinkurl($a) . '#c' . $discussid, ' title="' . gTxt('view') . '"'); } } echo tr(td(fInput('checkbox', 'selected[]', $discussid), '', 'txp-list-col-multi-edit') . hCell(href($discussid, $edit_url, ' title="' . gTxt('edit') . '"'), '', ' class="txp-list-col-id" scope="row"') . td(gTime($uPosted), '', 'txp-list-col-created date') . td(txpspecialchars(soft_wrap($name, 15)), '', 'txp-list-col-name') . td(short_preview($dmessage), '', 'txp-list-col-message') . td(txpspecialchars(soft_wrap($email, 15)), '', 'txp-list-col-email discuss_detail') . td(txpspecialchars(soft_wrap($web, 15)), '', 'txp-list-col-website discuss_detail') . td(href(txpspecialchars($ip), 'https://whois.domaintools.com/' . rawurlencode($ip), array('rel' => 'external', 'target' => '_blank')), '', 'txp-list-col-ip discuss_detail') . td($view, '', 'txp-list-col-status') . td($parent, '', 'txp-list-col-parent'), ' class="' . $row_class . '"'); } if (empty($message)) { echo n . tr(tda(gTxt('just_spam_results_found'), ' colspan="10"')); } echo n . tag_end('tbody') . n . tag_end('table') . n . tag_end('div') . discuss_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('discuss', $comment_list_pageby) . nav_form('discuss', $page, $numPages, $sort, $dir, $crit, $search_method, $total, $limit) . n . tag_end('div'); } echo n . tag_end('div'); }
/** * The main panel listing all log hits. * * @param string|array $message The activity message */ function log_list($message = '') { global $event, $log_list_pageby, $expire_logs_after; pagetop(gTxt('tab_logs'), $message); extract(gpsa(array('page', 'sort', 'dir', 'crit', 'search_method'))); if ($sort === '') { $sort = get_pref('log_sort_column', 'time'); } else { if (!in_array($sort, array('ip', 'host', 'page', 'refer', 'method', 'status'))) { $sort = 'time'; } set_pref('log_sort_column', $sort, 'log', 2, '', 0, PREF_PRIVATE); } if ($dir === '') { $dir = get_pref('log_sort_dir', 'desc'); } else { $dir = $dir == 'asc' ? "asc" : "desc"; set_pref('log_sort_dir', $dir, 'log', 2, '', 0, PREF_PRIVATE); } $expire_logs_after = assert_int($expire_logs_after); safe_delete('txp_log', "time < DATE_SUB(NOW(), INTERVAL {$expire_logs_after} DAY)"); switch ($sort) { case 'ip': $sort_sql = "ip {$dir}"; break; case 'host': $sort_sql = "host {$dir}"; break; case 'page': $sort_sql = "page {$dir}"; break; case 'refer': $sort_sql = "refer {$dir}"; break; case 'method': $sort_sql = "method {$dir}"; break; case 'status': $sort_sql = "status {$dir}"; break; default: $sort = 'time'; $sort_sql = "time {$dir}"; break; } $switch_dir = $dir == 'desc' ? 'asc' : 'desc'; $search = new Filter($event, array('ip' => array('column' => 'txp_log.ip', 'label' => gTxt('IP')), 'host' => array('column' => 'txp_log.host', 'label' => gTxt('host')), 'page' => array('column' => 'txp_log.page', 'label' => gTxt('page')), 'refer' => array('column' => 'txp_log.refer', 'label' => gTxt('referrer')), 'method' => array('column' => 'txp_log.method', 'label' => gTxt('method')), 'status' => array('column' => 'txp_log.status', 'label' => gTxt('status'), 'type' => 'integer'))); list($criteria, $crit, $search_method) = $search->getFilter(array('status' => array('can_list' => true))); $search_render_options = array('placeholder' => 'search_logs'); $total = safe_count('txp_log', "{$criteria}"); echo n . tag(hed(gTxt('tab_logs'), 1, array('class' => 'txp-heading')), 'div', array('class' => 'txp-layout-2col-cell-1')); $searchBlock = n . tag($search->renderForm('log_list', $search_render_options), 'div', array('class' => 'txp-layout-2col-cell-2', 'id' => $event . '_control')); $contentBlockStart = n . tag_start('div', array('class' => 'txp-layout-1col', 'id' => $event . '_container')); if ($total < 1) { if ($criteria != 1) { echo $searchBlock . $contentBlockStart . graf(span(null, array('class' => 'ui-icon ui-icon-info')) . ' ' . gTxt('no_results_found'), array('class' => 'alert-block information')); } else { echo $contentBlockStart . graf(span(null, array('class' => 'ui-icon ui-icon-info')) . ' ' . gTxt('no_refers_recorded'), array('class' => 'alert-block information')); } echo n . tag_end('div'); return; } $limit = max($log_list_pageby, 15); list($page, $offset, $numPages) = pager($total, $limit, $page); echo $searchBlock . $contentBlockStart; $rs = safe_rows_start("*, UNIX_TIMESTAMP(time) AS uTime", 'txp_log', "{$criteria} ORDER BY {$sort_sql} LIMIT {$offset}, {$limit}"); if ($rs) { echo n . tag(toggle_box('log_detail'), 'div', array('class' => 'txp-list-options')) . n . tag_start('form', array('class' => 'multi_edit_form', 'id' => 'log_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('time', 'time', 'log', true, $switch_dir, $crit, $search_method, ('time' == $sort ? "{$dir} " : '') . 'txp-list-col-time') . column_head('IP', 'ip', 'log', true, $switch_dir, $crit, $search_method, ('ip' == $sort ? "{$dir} " : '') . 'txp-list-col-ip') . column_head('host', 'host', 'log', true, $switch_dir, $crit, $search_method, ('host' == $sort ? "{$dir} " : '') . 'txp-list-col-host log_detail') . column_head('page', 'page', 'log', true, $switch_dir, $crit, $search_method, ('page' == $sort ? "{$dir} " : '') . 'txp-list-col-page') . column_head('referrer', 'refer', 'log', true, $switch_dir, $crit, $search_method, ('refer' == $sort ? "{$dir} " : '') . 'txp-list-col-refer') . column_head('method', 'method', 'log', true, $switch_dir, $crit, $search_method, ('method' == $sort ? "{$dir} " : '') . 'txp-list-col-method log_detail') . column_head('status', 'status', 'log', true, $switch_dir, $crit, $search_method, ('status' == $sort ? "{$dir} " : '') . 'txp-list-col-status log_detail')) . n . tag_end('thead') . n . tag_start('tbody'); while ($a = nextRow($rs)) { extract($a, EXTR_PREFIX_ALL, 'log'); if ($log_refer) { $log_refer = href(txpspecialchars(soft_wrap(preg_replace('#^http://#', '', $log_refer), 30)), txpspecialchars($log_refer), ' target="_blank"'); } if ($log_page) { $log_anchor = preg_replace('/\\/$/', '', $log_page); $log_anchor = soft_wrap(substr($log_anchor, 1), 30); $log_page = href(txpspecialchars($log_anchor), txpspecialchars($log_page), ' target="_blank"'); if ($log_method == 'POST') { $log_page = strong($log_page); } } echo tr(td(fInput('checkbox', 'selected[]', $log_id), '', 'txp-list-col-multi-edit') . hCell(gTime($log_uTime), '', ' class="txp-list-col-time" scope="row"') . td(href(txpspecialchars($log_ip), 'https://whois.domaintools.com/' . rawurlencode($log_ip), array('rel' => 'external', 'target' => '_blank')), '', 'txp-list-col-ip') . td(txpspecialchars($log_host), '', 'txp-list-col-host log_detail') . td($log_page, '', 'txp-list-col-page') . td($log_refer, '', 'txp-list-col-refer') . td(txpspecialchars($log_method), '', 'txp-list-col-method log_detail') . td($log_status, '', 'txp-list-col-status log_detail')); } echo n . tag_end('tbody') . n . tag_end('table') . n . tag_end('div') . log_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('log', $log_list_pageby) . nav_form('log', $page, $numPages, $sort, $dir, $crit, $search_method, $total, $limit) . n . tag_end('div'); } echo n . tag_end('div'); }
/** * The main panel listing all articles. * * @param string|array $message The activity message * @param string $post Not used */ function list_list($message = '', $post = '') { global $statuses, $use_comments, $comments_disabled_after, $step, $txp_user, $article_list_pageby, $event; pagetop(gTxt('tab_list'), $message); extract(gpsa(array('page', 'sort', 'dir', 'crit', 'search_method'))); if ($sort === '') { $sort = get_pref('article_sort_column', 'posted'); } else { if (!in_array($sort, array('id', 'title', 'expires', 'section', 'category1', 'category2', 'status', 'author', 'comments', 'lastmod'))) { $sort = 'posted'; } set_pref('article_sort_column', $sort, 'list', 2, '', 0, PREF_PRIVATE); } if ($dir === '') { $dir = get_pref('article_sort_dir', 'desc'); } else { $dir = $dir == 'asc' ? "asc" : "desc"; set_pref('article_sort_dir', $dir, 'list', 2, '', 0, PREF_PRIVATE); } $sesutats = array_flip($statuses); switch ($sort) { case 'id': $sort_sql = "textpattern.ID {$dir}"; break; case 'title': $sort_sql = "textpattern.Title {$dir}, textpattern.Posted DESC"; break; case 'expires': $sort_sql = "textpattern.Expires {$dir}"; break; case 'section': $sort_sql = "section.title {$dir}, textpattern.Posted DESC"; break; case 'category1': $sort_sql = "category1.title {$dir}, textpattern.Posted DESC"; break; case 'category2': $sort_sql = "category2.title {$dir}, textpattern.Posted DESC"; break; case 'status': $sort_sql = "textpattern.Status {$dir}, textpattern.Posted DESC"; break; case 'author': $sort_sql = "user.RealName {$dir}, textpattern.Posted DESC"; break; case 'comments': $sort_sql = "textpattern.comments_count {$dir}, textpattern.Posted DESC"; break; case 'lastmod': $sort_sql = "textpattern.LastMod {$dir}, textpattern.Posted DESC"; break; default: $sort = 'posted'; $sort_sql = "textpattern.Posted {$dir}"; break; } $switch_dir = $dir == 'desc' ? 'asc' : 'desc'; $search = new Filter($event, array('id' => array('column' => 'textpattern.ID', 'label' => gTxt('ID'), 'type' => 'integer'), 'title_body_excerpt' => array('column' => array('textpattern.Title', 'textpattern.Body', 'textpattern.Excerpt'), 'label' => gTxt('title_body_excerpt')), 'section' => array('column' => array('textpattern.Section', 'section.title'), 'label' => gTxt('section')), 'keywords' => array('column' => 'textpattern.Keywords', 'label' => gTxt('keywords'), 'type' => 'find_in_set'), 'categories' => array('column' => array('textpattern.Category1', 'textpattern.Category2', 'category1.title', 'category2.title'), 'label' => gTxt('categories')), 'status' => array('column' => array('textpattern.Status'), 'label' => gTxt('status'), 'type' => 'boolean'), 'author' => array('column' => array('textpattern.AuthorID', 'user.RealName'), 'label' => gTxt('author')), 'article_image' => array('column' => array('textpattern.Image'), 'label' => gTxt('article_image'), 'type' => 'integer'), 'posted' => array('column' => array('textpattern.Posted'), 'label' => gTxt('posted')), 'lastmod' => array('column' => array('textpattern.LastMod'), 'label' => gTxt('article_modified')))); $search->setAliases('status', $statuses); list($criteria, $crit, $search_method) = $search->getFilter(array('id' => array('can_list' => true), 'article_image' => array('can_list' => true), 'title_body_excerpt' => array('always_like' => true))); $search_render_options = array('placeholder' => 'search_articles'); $sql_from = safe_pfx('textpattern') . " textpattern\n LEFT JOIN " . safe_pfx('txp_category') . " category1 ON category1.name = textpattern.Category1 AND category1.type = 'article'\n LEFT JOIN " . safe_pfx('txp_category') . " category2 ON category2.name = textpattern.Category2 AND category2.type = 'article'\n LEFT JOIN " . safe_pfx('txp_section') . " section ON section.name = textpattern.Section\n LEFT JOIN " . safe_pfx('txp_users') . " user ON user.name = textpattern.AuthorID"; if ($criteria === 1) { $total = safe_count('textpattern', $criteria); } else { $total = getThing("SELECT COUNT(*) FROM {$sql_from} WHERE {$criteria}"); } echo n . tag(hed(gTxt('tab_list'), 1, array('class' => 'txp-heading')), 'div', array('class' => 'txp-layout-2col-cell-1')); $searchBlock = n . tag($search->renderForm('list', $search_render_options), 'div', array('class' => 'txp-layout-2col-cell-2', 'id' => $event . '_control')); $createBlock = array(); if (has_privs('article.edit')) { $createBlock[] = n . tag(sLink('article', '', gTxt('add_new_article'), 'txp-button'), 'div', array('class' => 'txp-control-panel')); } $contentBlockStart = n . tag_start('div', array('class' => 'txp-layout-1col', 'id' => $event . '_container')); $createBlock = implode(n, $createBlock); if ($total < 1) { if ($criteria != 1) { echo $searchBlock . $contentBlockStart . $createBlock . graf(span(null, array('class' => 'ui-icon ui-icon-info')) . ' ' . gTxt('no_results_found'), array('class' => 'alert-block information')); } else { echo $contentBlockStart . $createBlock . graf(span(null, array('class' => 'ui-icon ui-icon-info')) . ' ' . gTxt('no_articles_recorded'), array('class' => 'alert-block information')); } echo n . tag_end('div'); return; } $limit = max($article_list_pageby, 15); list($page, $offset, $numPages) = pager($total, $limit, $page); echo $searchBlock . $contentBlockStart . $createBlock; $rs = safe_query("SELECT\n textpattern.ID, textpattern.Title, textpattern.url_title, textpattern.Section,\n textpattern.Category1, textpattern.Category2,\n textpattern.Status, textpattern.Annotate, textpattern.AuthorID,\n UNIX_TIMESTAMP(textpattern.Posted) AS posted,\n UNIX_TIMESTAMP(textpattern.LastMod) AS lastmod,\n UNIX_TIMESTAMP(textpattern.Expires) AS expires,\n category1.title AS category1_title,\n category2.title AS category2_title,\n section.title AS section_title,\n user.RealName AS RealName,\n (SELECT COUNT(*) FROM " . safe_pfx('txp_discuss') . " WHERE parentid = textpattern.ID) AS total_comments\n FROM {$sql_from} WHERE {$criteria} ORDER BY {$sort_sql} LIMIT {$offset}, {$limit}"); if ($rs) { $show_authors = !has_single_author('textpattern', 'AuthorID'); echo n . tag(toggle_box('articles_detail'), 'div', array('class' => 'txp-list-options')) . n . tag_start('form', array('class' => 'multi_edit_form', 'id' => 'articles_form', 'name' => 'longform', 'method' => 'post', 'action' => 'index.php')) . n . tag_start('div', array('class' => 'txp-listtables')) . n . tag_start('table', array('class' => 'txp-list')) . n . tag_start('thead') . tr(hCell(fInput('checkbox', 'select_all', 0, '', '', '', '', '', 'select_all'), '', ' class="txp-list-col-multi-edit" scope="col" title="' . gTxt('toggle_all_selected') . '"') . column_head('ID', 'id', 'list', true, $switch_dir, $crit, $search_method, ('id' == $sort ? "{$dir} " : '') . 'txp-list-col-id') . column_head('title', 'title', 'list', true, $switch_dir, $crit, $search_method, ('title' == $sort ? "{$dir} " : '') . 'txp-list-col-title') . column_head('posted', 'posted', 'list', true, $switch_dir, $crit, $search_method, ('posted' == $sort ? "{$dir} " : '') . 'txp-list-col-created date') . column_head('article_modified', 'lastmod', 'list', true, $switch_dir, $crit, $search_method, ('lastmod' == $sort ? "{$dir} " : '') . 'txp-list-col-lastmod date articles_detail') . column_head('expires', 'expires', 'list', true, $switch_dir, $crit, $search_method, ('expires' == $sort ? "{$dir} " : '') . 'txp-list-col-expires date articles_detail') . column_head('section', 'section', 'list', true, $switch_dir, $crit, $search_method, ('section' == $sort ? "{$dir} " : '') . 'txp-list-col-section') . column_head('category1', 'category1', 'list', true, $switch_dir, $crit, $search_method, ('category1' == $sort ? "{$dir} " : '') . 'txp-list-col-category1 category articles_detail') . column_head('category2', 'category2', 'list', true, $switch_dir, $crit, $search_method, ('category2' == $sort ? "{$dir} " : '') . 'txp-list-col-category2 category articles_detail') . column_head('status', 'status', 'list', true, $switch_dir, $crit, $search_method, ('status' == $sort ? "{$dir} " : '') . 'txp-list-col-status') . ($show_authors ? column_head('author', 'author', 'list', true, $switch_dir, $crit, $search_method, ('author' == $sort ? "{$dir} " : '') . 'txp-list-col-author name') : '') . ($use_comments == 1 ? column_head('comments', 'comments', 'list', true, $switch_dir, $crit, $search_method, ('comments' == $sort ? "{$dir} " : '') . 'txp-list-col-comments articles_detail') : '')) . n . tag_end('thead'); include_once txpath . '/publish/taghandlers.php'; echo n . tag_start('tbody'); $validator = new Validator(); while ($a = nextRow($rs)) { extract($a); if ($Title === '') { $Title = '<em>' . eLink('article', 'edit', 'ID', $ID, gTxt('untitled')) . '</em>'; } else { $Title = eLink('article', 'edit', 'ID', $ID, $Title); } // Valid section and categories? $validator->setConstraints(array(new SectionConstraint($Section))); $vs = $validator->validate() ? '' : ' error'; $validator->setConstraints(array(new CategoryConstraint($Category1, array('type' => 'article')))); $vc[1] = $validator->validate() ? '' : ' error'; $validator->setConstraints(array(new CategoryConstraint($Category2, array('type' => 'article')))); $vc[2] = $validator->validate() ? '' : ' error'; $Category1 = $Category1 ? span(txpspecialchars($category1_title), array('title' => $Category1)) : ''; $Category2 = $Category2 ? span(txpspecialchars($category2_title), array('title' => $Category2)) : ''; if ($Status != STATUS_LIVE and $Status != STATUS_STICKY) { $view_url = '?txpreview=' . intval($ID) . '.' . time(); } else { $view_url = permlinkurl($a); } if (isset($statuses[$Status])) { $Status = $statuses[$Status]; } $comments = '(' . $total_comments . ')'; if ($total_comments) { $comments = href($comments, array('event' => 'discuss', 'step' => 'list', 'search_method' => 'parent', 'crit' => $ID), array('title' => gTxt('manage'))); } $comment_status = $Annotate ? gTxt('on') : gTxt('off'); if ($comments_disabled_after) { $lifespan = $comments_disabled_after * 86400; $time_since = time() - $posted; if ($time_since > $lifespan) { $comment_status = gTxt('expired'); } } $comments = tag($comment_status, 'span', array('class' => 'comments-status')) . ' ' . tag($comments, 'span', array('class' => 'comments-manage')); echo tr(td(($a['Status'] >= STATUS_LIVE and has_privs('article.edit.published') or $a['Status'] >= STATUS_LIVE and $AuthorID === $txp_user and has_privs('article.edit.own.published') or $a['Status'] < STATUS_LIVE and has_privs('article.edit') or $a['Status'] < STATUS_LIVE and $AuthorID === $txp_user and has_privs('article.edit.own')) ? fInput('checkbox', 'selected[]', $ID, 'checkbox') : '', '', 'txp-list-col-multi-edit') . hCell(eLink('article', 'edit', 'ID', $ID, $ID) . sp . span(span('[', array('aria-hidden' => 'true')) . href(gTxt('view'), $view_url) . span(']', array('aria-hidden' => 'true')), array('class' => 'txp-option-link articles_detail')), '', ' class="txp-list-col-id" scope="row"') . td($Title, '', 'txp-list-col-title') . td(gTime($posted), '', 'txp-list-col-created date' . ($posted < time() ? '' : ' unpublished')) . td(gTime($lastmod), '', 'txp-list-col-lastmod date articles_detail' . ($posted === $lastmod ? ' not-modified' : '')) . td($expires ? gTime($expires) : '', '', 'txp-list-col-expires date articles_detail') . td(span(txpspecialchars($section_title), array('title' => $Section)), '', 'txp-list-col-section' . $vs) . td($Category1, '', 'txp-list-col-category1 category articles_detail' . $vc[1]) . td($Category2, '', 'txp-list-col-category2 category articles_detail' . $vc[2]) . td(href($Status, $view_url, join_atts(array('title' => gTxt('view')))), '', 'txp-list-col-status') . ($show_authors ? td(span(txpspecialchars($RealName), array('title' => $AuthorID)), '', 'txp-list-col-author name') : '') . ($use_comments ? td($comments, '', 'txp-list-col-comments articles_detail') : '')); } echo n . tag_end('tbody') . n . tag_end('table') . n . tag_end('div') . list_multiedit_form($page, $sort, $dir, $crit, $search_method) . tInput() . n . tag_end('form') . n . tag_start('div', array('class' => 'txp-navigation', 'id' => $event . '_navigation')) . pageby_form('list', $article_list_pageby) . nav_form('list', $page, $numPages, $sort, $dir, $crit, $search_method, $total, $limit) . n . tag_end('div'); } echo n . tag_end('div'); }
/** * The main panel listing all images. * * @param string|array $message The activity message */ function image_list($message = '') { global $txpcfg, $extensions, $img_dir, $file_max_upload_size, $image_list_pageby, $txp_user, $event; pagetop(gTxt('tab_image'), $message); extract($txpcfg); extract(gpsa(array('page', 'sort', 'dir', 'crit', 'search_method'))); if ($sort === '') { $sort = get_pref('image_sort_column', 'id'); } else { if (!in_array($sort, array('name', 'thumbnail', 'category', 'date', 'author'))) { $sort = 'id'; } set_pref('image_sort_column', $sort, 'image', 2, '', 0, PREF_PRIVATE); } if ($dir === '') { $dir = get_pref('image_sort_dir', 'desc'); } else { $dir = $dir == 'asc' ? "asc" : "desc"; set_pref('image_sort_dir', $dir, 'image', 2, '', 0, PREF_PRIVATE); } switch ($sort) { case 'name': $sort_sql = "txp_image.name {$dir}"; break; case 'thumbnail': $sort_sql = "txp_image.thumbnail {$dir}, txp_image.id ASC"; break; case 'category': $sort_sql = "txp_category.title {$dir}, txp_image.id ASC"; break; case 'date': $sort_sql = "txp_image.date {$dir}, txp_image.id ASC"; break; case 'author': $sort_sql = "txp_users.RealName {$dir}, txp_image.id ASC"; break; default: $sort = 'id'; $sort_sql = "txp_image.id {$dir}"; break; } $switch_dir = $dir == 'desc' ? 'asc' : 'desc'; $search = new Filter($event, array('id' => array('column' => 'txp_image.id', 'label' => gTxt('ID'), 'type' => 'integer'), 'name' => array('column' => 'txp_image.name', 'label' => gTxt('name')), 'alt' => array('column' => 'txp_image.alt', 'label' => gTxt('alt_text')), 'caption' => array('column' => 'txp_image.caption', 'label' => gTxt('caption')), 'category' => array('column' => array('txp_image.category', 'txp_category.title'), 'label' => gTxt('image_category')), 'ext' => array('column' => 'txp_image.ext', 'label' => gTxt('extension')), 'author' => array('column' => array('txp_image.author', 'txp_users.RealName'), 'label' => gTxt('author')), 'thumbnail' => array('column' => array('txp_image.thumbnail'), 'label' => gTxt('thumbnail'), 'type' => 'boolean'))); $alias_yes = '1, Yes'; $alias_no = '0, No'; $search->setAliases('thumbnail', array($alias_no, $alias_yes)); list($criteria, $crit, $search_method) = $search->getFilter(array('id' => array('can_list' => true))); $search_render_options = array('placeholder' => 'search_images'); $sql_from = safe_pfx_j('txp_image') . "\n LEFT JOIN " . safe_pfx_j('txp_category') . " ON txp_category.name = txp_image.category AND txp_category.type = 'image'\n LEFT JOIN " . safe_pfx_j('txp_users') . " ON txp_users.name = txp_image.author"; if ($criteria === 1) { $total = getCount('txp_image', $criteria); } else { $total = getThing("SELECT COUNT(*) FROM {$sql_from} WHERE {$criteria}"); } echo n . tag(hed(gTxt('tab_image'), 1, array('class' => 'txp-heading')), 'div', array('class' => 'txp-layout-2col-cell-1')); $searchBlock = n . tag($search->renderForm('image_list', $search_render_options), 'div', array('class' => 'txp-layout-2col-cell-2', 'id' => $event . '_control')); $createBlock = array(); if (!is_dir(IMPATH) or !is_writeable(IMPATH)) { $createBlock[] = graf(span(null, array('class' => 'ui-icon ui-icon-alert')) . ' ' . gTxt('img_dir_not_writeable', array('{imgdir}' => IMPATH)), array('class' => 'alert-block warning')); } elseif (has_privs('image.edit.own')) { $createBlock[] = n . tag(n . upload_form('upload_image', 'upload_image', 'image_insert', 'image', '', $file_max_upload_size, '', '', ''), 'div', array('class' => 'txp-control-panel')); } $contentBlockStart = n . tag_start('div', array('class' => 'txp-layout-1col', 'id' => $event . '_container')); $createBlock = implode(n, $createBlock); if ($total < 1) { if ($criteria != 1) { echo $searchBlock . $contentBlockStart . $createBlock . graf(span(null, array('class' => 'ui-icon ui-icon-info')) . ' ' . gTxt('no_results_found'), array('class' => 'alert-block information')); } else { echo $contentBlockStart . $createBlock . graf(span(null, array('class' => 'ui-icon ui-icon-info')) . ' ' . gTxt('no_images_recorded'), array('class' => 'alert-block information')); } echo n . tag_end('div'); return; } $limit = max($image_list_pageby, 15); list($page, $offset, $numPages) = pager($total, $limit, $page); echo $searchBlock . $contentBlockStart . $createBlock; $rs = safe_query("SELECT\n txp_image.id,\n txp_image.name,\n txp_image.category,\n txp_image.ext,\n txp_image.w,\n txp_image.h,\n txp_image.alt,\n txp_image.caption,\n UNIX_TIMESTAMP(txp_image.date) AS uDate,\n txp_image.author,\n txp_image.thumbnail,\n txp_image.thumb_w,\n txp_image.thumb_h,\n txp_users.RealName AS realname,\n txp_category.Title AS category_title\n FROM {$sql_from} WHERE {$criteria} ORDER BY {$sort_sql} LIMIT {$offset}, {$limit}"); echo pluggable_ui('image_ui', 'extend_controls', '', $rs); if ($rs && numRows($rs)) { $show_authors = !has_single_author('txp_image'); echo n . tag(toggle_box('images_detail'), 'div', array('class' => 'txp-list-options')) . n . tag_start('form', array('class' => 'multi_edit_form', 'id' => 'images_form', 'name' => 'longform', 'method' => 'post', 'action' => 'index.php')) . n . tag_start('div', array('class' => 'txp-listtables')) . n . tag_start('table', array('class' => 'txp-list')) . n . tag_start('thead') . tr(hCell(fInput('checkbox', 'select_all', 0, '', '', '', '', '', 'select_all'), '', ' class="txp-list-col-multi-edit" scope="col" title="' . gTxt('toggle_all_selected') . '"') . column_head('ID', 'id', 'image', true, $switch_dir, $crit, $search_method, ('id' == $sort ? "{$dir} " : '') . 'txp-list-col-id') . column_head('name', 'name', 'image', true, $switch_dir, $crit, $search_method, ('name' == $sort ? "{$dir} " : '') . 'txp-list-col-name') . column_head('date', 'date', 'image', true, $switch_dir, $crit, $search_method, ('date' == $sort ? "{$dir} " : '') . 'txp-list-col-created date images_detail') . column_head('thumbnail', 'thumbnail', 'image', true, $switch_dir, $crit, $search_method, ('thumbnail' == $sort ? "{$dir} " : '') . 'txp-list-col-thumbnail') . hCell(gTxt('tags'), '', ' class="txp-list-col-tag-build images_detail" scope="col"') . column_head('image_category', 'category', 'image', true, $switch_dir, $crit, $search_method, ('category' == $sort ? "{$dir} " : '') . 'txp-list-col-category category') . ($show_authors ? column_head('author', 'author', 'image', true, $switch_dir, $crit, $search_method, ('author' == $sort ? "{$dir} " : '') . 'txp-list-col-author name') : '')) . n . tag_end('thead') . n . tag_start('tbody'); $validator = new Validator(); while ($a = nextRow($rs)) { extract($a); $edit_url = array('event' => 'image', 'step' => 'image_edit', 'id' => $id, 'sort' => $sort, 'dir' => $dir, 'page' => $page, 'search_method' => $search_method, 'crit' => $crit); $name = empty($name) ? gTxt('unnamed') : txpspecialchars($name); if ($thumbnail) { if ($ext != '.swf') { $thumbnail = '<img class="content-image" src="' . imagesrcurl($id, $ext, true) . "?{$uDate}" . '" alt="" ' . "title='{$id}{$ext} ({$w} × {$h})'" . ($thumb_w ? " width='{$thumb_w}' height='{$thumb_h}'" : '') . ' />'; } else { $thumbnail = ''; } } else { $thumbnail = gTxt('no'); } if ($ext != '.swf') { $tag_url = '?event=tag' . a . 'tag_name=image' . a . 'id=' . $id . a . 'ext=' . $ext . a . 'w=' . $w . a . 'h=' . $h . a . 'alt=' . urlencode($alt) . a . 'caption=' . urlencode($caption); $tagbuilder = href('Textile', $tag_url . a . 'type=textile', ' target="_blank" onclick="popWin(this.href); return false;"') . sp . span('|', array('role' => 'separator')) . sp . href('Textpattern', $tag_url . a . 'type=textpattern', ' target="_blank" onclick="popWin(this.href); return false;"') . sp . span('|', array('role' => 'separator')) . sp . href('HTML', $tag_url . a . 'type=html', ' target="_blank" onclick="popWin(this.href); return false;"'); } else { $tagbuilder = sp; } $validator->setConstraints(array(new CategoryConstraint($category, array('type' => 'image')))); $vc = $validator->validate() ? '' : ' error'; if ($category) { $category = span(txpspecialchars($category_title), array('title' => $category)); } $can_edit = has_privs('image.edit') || $author === $txp_user && has_privs('image.edit.own'); echo tr(td($can_edit ? fInput('checkbox', 'selected[]', $id) : ' ', '', 'txp-list-col-multi-edit') . hCell(($can_edit ? href($id, $edit_url, array('title' => gTxt('edit'))) : $id) . sp . span(span('[', array('aria-hidden' => 'true')) . href(gTxt('view'), imagesrcurl($id, $ext)) . span(']', array('aria-hidden' => 'true')), array('class' => 'txp-option-link images_detail')), '', ' class="txp-list-col-id" scope="row"') . td($can_edit ? href($name, $edit_url, ' title="' . gTxt('edit') . '"') : $name, '', 'txp-list-col-name') . td(gTime($uDate), '', 'txp-list-col-created date images_detail') . td(pluggable_ui('image_ui', 'thumbnail', $can_edit ? href($thumbnail, $edit_url) : $thumbnail, $a), '', 'txp-list-col-thumbnail') . td($tagbuilder, '', 'txp-list-col-tag-build images_detail') . td($category, '', 'txp-list-col-category category' . $vc) . ($show_authors ? td(span(txpspecialchars($realname), array('title' => $author)), '', 'txp-list-col-author name') : '')); } echo n . tag_end('tbody') . n . tag_end('table') . n . tag_end('div') . image_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('image', $image_list_pageby) . nav_form('image', $page, $numPages, $sort, $dir, $crit, $search_method, $total, $limit) . n . tag_end('div'); } }
function ipban_list($message = '') { global $event; pageTop(gTxt('list_banned_ips'), $message); echo hed(gTxt('banned_ips'), 1, array('class' => 'txp-heading')); echo n . '<div id="' . $event . '_banned_control" class="txp-control-panel">' . graf(sLink('discuss', 'discuss_list', gTxt('list_discussions')), ' class="txp-buttons"') . n . '</div>'; $rs = safe_rows_start('*, unix_timestamp(date_banned) as uBanned', 'txp_discuss_ipban', "1 = 1 order by date_banned desc"); if ($rs and numRows($rs) > 0) { echo n . tag_start('div', array('id' => $event . '_ban_container', 'class' => 'txp-container')) . n . tag_start('div', array('class' => 'txp-listtables')) . n . tag_start('table', array('class' => 'txp-list')) . n . tag_start('thead') . tr(hCell(gTxt('date_banned'), '', ' scope="col" class="txp-list-col-banned date"') . hCell(gTxt('IP'), '', ' scope="col" class="txp-list-col-ip"') . hCell(gTxt('name_used'), '', ' scope="col" class="txp-list-col-name"') . hCell(gTxt('banned_for'), '', ' scope="col" class="txp-list-col-id"')) . n . tag_end('thead') . n . tag_start('tbody'); while ($a = nextRow($rs)) { extract($a); echo tr(hCell(gTime($uBanned), '', ' scope="row" class="txp-list-col-banned date"') . td(txpspecialchars($ip) . sp . span('[', array('aria-hidden' => 'true')) . href(gTxt('unban'), array('event' => 'discuss', 'step' => 'ipban_unban', 'ip' => $ip, '_txp_token' => form_token()), array('class' => 'action-ban')) . span(']', array('aria-hidden' => 'true')), '', 'txp-list-col-ip') . td(txpspecialchars($name_used), '', 'txp-list-col-name') . td(href($banned_on_message, '?event=discuss' . a . 'step=discuss_edit' . a . 'discussid=' . $banned_on_message), '', 'txp-list-col-id')); } echo n . tag_end('tbody') . n . tag_end('table') . n . tag_end('div') . n . tag_end('div'); } else { echo graf(gTxt('no_ips_banned'), ' class="indicator"'); } }
/** * The main panel listing all log hits. * * @param string|array $message The activity message */ function log_list($message = '') { global $event, $log_list_pageby, $expire_logs_after; pagetop(gTxt('tab_logs'), $message); extract(gpsa(array('page', 'sort', 'dir', 'crit', 'search_method'))); if ($sort === '') { $sort = get_pref('log_sort_column', 'time'); } if ($dir === '') { $dir = get_pref('log_sort_dir', 'desc'); } $dir = $dir == 'asc' ? 'asc' : 'desc'; $expire_logs_after = assert_int($expire_logs_after); safe_delete('txp_log', "time < date_sub(now(), interval {$expire_logs_after} day)"); switch ($sort) { case 'ip': $sort_sql = 'ip ' . $dir; break; case 'host': $sort_sql = 'host ' . $dir; break; case 'page': $sort_sql = 'page ' . $dir; break; case 'refer': $sort_sql = 'refer ' . $dir; break; case 'method': $sort_sql = 'method ' . $dir; break; case 'status': $sort_sql = 'status ' . $dir; break; default: $sort = 'time'; $sort_sql = 'time ' . $dir; break; } set_pref('log_sort_column', $sort, 'log', 2, '', 0, PREF_PRIVATE); set_pref('log_sort_dir', $dir, 'log', 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('ip' => "ip = '{$crit_escaped}'", 'host' => "host = '{$crit_escaped}'", 'page' => "page = '{$crit_escaped}'", 'refer' => "refer = '{$crit_escaped}'", 'method' => "method = '{$crit_escaped}'", 'status' => "status = '{$crit_escaped}'") : array('ip' => "ip like '%{$crit_escaped}%'", 'host' => "host like '%{$crit_escaped}%'", 'page' => "page like '%{$crit_escaped}%'", 'refer' => "refer like '%{$crit_escaped}%'", 'method' => "method like '%{$crit_escaped}%'", 'status' => "status like '%{$crit_escaped}%'"); if (array_key_exists($search_method, $critsql)) { $criteria = $critsql[$search_method]; $limit = 500; } else { $search_method = ''; $crit = ''; } } else { $search_method = ''; $crit = ''; } $criteria .= callback_event('admin_criteria', 'log_list', 0, $criteria); $total = safe_count('txp_log', "{$criteria}"); echo hed(gTxt('tab_logs'), 1, array('class' => 'txp-heading')); echo n . '<div id="' . $event . '_control" class="txp-control-panel">'; if ($total < 1) { if ($criteria != 1) { echo log_search_form($crit, $search_method) . graf(gTxt('no_results_found'), ' class="indicator"') . '</div>'; } else { echo graf(gTxt('no_refers_recorded'), ' class="indicator"') . '</div>'; } return; } $limit = max($log_list_pageby, 15); list($page, $offset, $numPages) = pager($total, $limit, $page); echo log_search_form($crit, $search_method) . '</div>'; $rs = safe_rows_start('*, unix_timestamp(time) as uTime', 'txp_log', "{$criteria} order by {$sort_sql} limit {$offset}, {$limit}"); if ($rs) { echo n . tag_start('div', array('id' => $event . '_container', 'class' => 'txp-container')) . n . tag_start('form', array('action' => 'index.php', 'id' => 'log_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(hCell(fInput('checkbox', 'select_all', 0, '', '', '', '', '', 'select_all'), '', ' scope="col" title="' . gTxt('toggle_all_selected') . '" class="txp-list-col-multi-edit"') . column_head('time', 'time', 'log', true, $switch_dir, $crit, $search_method, ('time' == $sort ? "{$dir} " : '') . 'txp-list-col-time') . column_head('IP', 'ip', 'log', true, $switch_dir, $crit, $search_method, ('ip' == $sort ? "{$dir} " : '') . 'txp-list-col-ip') . column_head('host', 'host', 'log', true, $switch_dir, $crit, $search_method, ('host' == $sort ? "{$dir} " : '') . 'txp-list-col-host log_detail') . column_head('page', 'page', 'log', true, $switch_dir, $crit, $search_method, ('page' == $sort ? "{$dir} " : '') . 'txp-list-col-page') . column_head('referrer', 'refer', 'log', true, $switch_dir, $crit, $search_method, ('refer' == $sort ? "{$dir} " : '') . 'txp-list-col-refer') . column_head('method', 'method', 'log', true, $switch_dir, $crit, $search_method, ('method' == $sort ? "{$dir} " : '') . 'txp-list-col-method log_detail') . column_head('status', 'status', 'log', true, $switch_dir, $crit, $search_method, ('status' == $sort ? "{$dir} " : '') . 'txp-list-col-status log_detail')) . n . tag_end('thead') . n . tag_start('tbody'); while ($a = nextRow($rs)) { extract($a, EXTR_PREFIX_ALL, 'log'); if ($log_refer) { $log_refer = href(txpspecialchars(soft_wrap(preg_replace('#^http://#', '', $log_refer), 30)), txpspecialchars($log_refer), ' target="_blank"'); } if ($log_page) { $log_anchor = preg_replace('/\\/$/', '', $log_page); $log_anchor = soft_wrap(substr($log_anchor, 1), 30); $log_page = href(txpspecialchars($log_anchor), txpspecialchars($log_page), ' target="_blank"'); if ($log_method == 'POST') { $log_page = strong($log_page); } } echo tr(td(fInput('checkbox', 'selected[]', $log_id), '', 'txp-list-col-multi-edit') . hCell(gTime($log_uTime), '', ' scope="row" class="txp-list-col-time"') . td(href(txpspecialchars($log_ip), 'https://whois.domaintools.com/' . rawurlencode($log_ip), array('rel' => 'external', 'target' => '_blank')), '', 'txp-list-col-ip') . td(txpspecialchars($log_host), '', 'txp-list-col-host log_detail') . td($log_page, '', 'txp-list-col-page') . td($log_refer, '', 'txp-list-col-refer') . td(txpspecialchars($log_method), '', 'txp-list-col-method log_detail') . td($log_status, '', 'txp-list-col-status log_detail')); } echo n . tag_end('tbody') . n . tag_end('table') . n . tag_end('div') . log_multiedit_form($page, $sort, $dir, $crit, $search_method) . tInput() . n . tag_end('form') . graf(toggle_box('log_detail'), array('class' => 'detail-toggle')) . n . tag_start('div', array('id' => $event . '_navigation', 'class' => 'txp-navigation')) . pageby_form('log', $log_list_pageby) . nav_form('log', $page, $numPages, $sort, $dir, $crit, $search_method, $total, $limit) . n . tag_end('div') . n . tag_end('div'); } }
/** * Outputs a diagnostics report. * * This is the main panel. */ function doDiagnostics() { global $prefs, $files, $txpcfg, $event, $step, $theme, $DB, $txp_using_svn; extract(get_prefs()); $urlparts = parse_url(hu); $mydomain = $urlparts['host']; $is_apache = stristr(serverSet('SERVER_SOFTWARE'), 'Apache') || is_callable('apache_get_version'); $real_doc_root = isset($_SERVER['DOCUMENT_ROOT']) ? realpath($_SERVER['DOCUMENT_ROOT']) : ''; // ini_get() returns string values passed via php_value as a string, // not boolean. $is_register_globals = (strcasecmp(ini_get('register_globals'), 'on') === 0 or ini_get('register_globals') === '1'); $fail = array(); $now = time(); if (!$txp_using_svn) { // Check for Textpattern updates, at most once every 24 hours. $updateInfo = unserialize(get_pref('last_update_check', '')); if (!$updateInfo || $now > $updateInfo['when'] + 60 * 60 * 24) { $updates = checkUpdates(); $updateInfo['msg'] = $updates ? gTxt($updates['msg'], array('{version}' => $updates['version'])) : ''; $updateInfo['when'] = $now; set_pref('last_update_check', serialize($updateInfo), 'publish', PREF_HIDDEN, 'text_input'); } if (!empty($updateInfo['msg'])) { $fail['textpattern_version_update'] = diag_msg_wrap($updateInfo['msg'], 'information'); } } if (!is_callable('version_compare') || version_compare(PHP_VERSION, REQUIRED_PHP_VERSION, '<')) { $fail['php_version_required'] = diag_msg_wrap(gTxt('php_version_required', array('{version}' => REQUIRED_PHP_VERSION))); } if (@gethostbyname($mydomain) === $mydomain) { $fail['dns_lookup_fails'] = diag_msg_wrap(gTxt('dns_lookup_fails') . cs . $mydomain, 'warning'); } if (!@is_dir($path_to_site)) { $fail['path_to_site_inacc'] = diag_msg_wrap(gTxt('path_to_site_inacc') . cs . $path_to_site); } if (rtrim($siteurl, '/') != $siteurl) { $fail['site_trailing_slash'] = diag_msg_wrap(gTxt('site_trailing_slash') . cs . $path_to_site, 'warning'); } if (!@is_file($path_to_site . "/index.php") || !@is_readable($path_to_site . "/index.php")) { $fail['index_inaccessible'] = diag_msg_wrap("{$path_to_site}/index.php " . gTxt('is_inaccessible')); } $not_readable = array(); if (!@is_writable($path_to_site . '/' . $img_dir)) { $not_readable[] = diag_msg_wrap(str_replace('{dirtype}', gTxt('img_dir'), gTxt('dir_not_writable')) . ": {$path_to_site}/{$img_dir}", 'warning'); } if (!@is_writable($file_base_path)) { $not_readable[] = diag_msg_wrap(str_replace('{dirtype}', gTxt('file_base_path'), gTxt('dir_not_writable')) . ": {$file_base_path}", 'warning'); } if (!@is_writable($tempdir)) { $not_readable[] = diag_msg_wrap(str_replace('{dirtype}', gTxt('tempdir'), gTxt('dir_not_writable')) . ": {$tempdir}", 'warning'); } if ($not_readable) { $fail['dir_not_writable'] = join(n, $not_readable); } if ($permlink_mode != 'messy' && !$is_apache) { $fail['cleanurl_only_apache'] = diag_msg_wrap(gTxt('cleanurl_only_apache'), 'information'); } if ($permlink_mode != 'messy' and !@is_readable($path_to_site . '/.htaccess')) { $fail['htaccess_missing'] = diag_msg_wrap(gTxt('htaccess_missing')); } if ($permlink_mode != 'messy' and is_callable('apache_get_modules') and !apache_module('mod_rewrite')) { $fail['mod_rewrite_missing'] = diag_msg_wrap(gTxt('mod_rewrite_missing')); } if (!ini_get('file_uploads')) { $fail['file_uploads_disabled'] = diag_msg_wrap(gTxt('file_uploads_disabled'), 'information'); } if (@is_dir(txpath . DS . 'setup')) { $fail['setup_still_exists'] = diag_msg_wrap(txpath . DS . "setup" . DS . ' ' . gTxt('still_exists'), 'warning'); } if (empty($tempdir)) { $fail['no_temp_dir'] = diag_msg_wrap(gTxt('no_temp_dir'), 'warning'); } if (is_disabled('mail')) { $fail['warn_mail_unavailable'] = diag_msg_wrap(gTxt('warn_mail_unavailable'), 'warning'); } if ($is_register_globals) { $fail['warn_register_globals_or_update'] = diag_msg_wrap(gTxt('warn_register_globals_or_update'), 'warning'); } if ($permlink_mode != 'messy') { $rs = safe_column("name", 'txp_section', "1 = 1"); foreach ($rs as $name) { if ($name and @file_exists($path_to_site . '/' . $name)) { $fail['old_placeholder_exists'] = diag_msg_wrap(gTxt('old_placeholder') . ": {$path_to_site}/{$name}"); } } } $cs = check_file_integrity(INTEGRITY_REALPATH); if (!$cs) { $cs = array(); } // Files that don't match their checksums. if (!$txp_using_svn and $modified_files = array_keys($cs, INTEGRITY_MODIFIED)) { $fail['modified_files'] = diag_msg_wrap(gTxt('modified_files') . cs . n . t . join(', ' . n . t, $modified_files), 'warning'); } // Running development code in live mode is not recommended. if (preg_match('/-dev$/', txp_version) and $production_status == 'live') { $fail['dev_version_live'] = diag_msg_wrap(gTxt('dev_version_live'), 'warning'); } // Missing files. if ($missing = array_merge(array_keys($cs, INTEGRITY_MISSING), array_keys($cs, INTEGRITY_NOT_FILE), array_keys($cs, INTEGRITY_NOT_READABLE))) { $fail['missing_files'] = diag_msg_wrap(gTxt('missing_files') . cs . n . t . join(', ' . n . t, $missing)); } // Anything might break if arbitrary functions are disabled. if (ini_get('disable_functions')) { $disabled_funcs = array_map('trim', explode(',', ini_get('disable_functions'))); // Commonly disabled functions that we don't need. $disabled_funcs = array_diff($disabled_funcs, array('imagefilltoborder', 'escapeshellarg', 'escapeshellcmd', 'exec', 'passthru', 'proc_close', 'proc_get_status', 'proc_nice', 'proc_open', 'proc_terminate', 'shell_exec', 'system', 'popen', 'dl', 'chown')); if ($disabled_funcs) { $fail['some_php_functions_disabled'] = diag_msg_wrap(gTxt('some_php_functions_disabled') . cs . join(', ', $disabled_funcs), 'warning'); } } // Not sure about this one. // if (strncmp(php_sapi_name(), 'cgi', 3) == 0 and ini_get('cgi.rfc2616_headers')) // $fail['cgi_header_config'] = gTxt('cgi_header_config'); $guess_site_url = $_SERVER['HTTP_HOST'] . preg_replace('#[/\\\\]$#', '', dirname(dirname($_SERVER['SCRIPT_NAME']))); if ($siteurl and strip_prefix($siteurl, 'www.') != strip_prefix($guess_site_url, 'www.')) { $fail['site_url_mismatch'] = diag_msg_wrap(gTxt('site_url_mismatch') . cs . $guess_site_url, 'warning'); } // Test clean URL server vars. if (hu) { if (ini_get('allow_url_fopen') and $permlink_mode != 'messy') { $s = md5(uniqid(rand(), true)); ini_set('default_socket_timeout', 10); $pretext_data = @file(hu . $s . '/?txpcleantest=1'); if ($pretext_data) { $pretext_req = trim(@$pretext_data[0]); if ($pretext_req != md5('/' . $s . '/?txpcleantest=1')) { $fail['clean_url_data_failed'] = diag_msg_wrap(gTxt('clean_url_data_failed') . cs . txpspecialchars($pretext_req), 'warning'); } } else { $fail['clean_url_test_failed'] = diag_msg_wrap(gTxt('clean_url_test_failed'), 'warning'); } } } if ($tables = list_txp_tables()) { $table_errors = check_tables($tables); if ($table_errors) { $fail['mysql_table_errors'] = diag_msg_wrap(gTxt('mysql_table_errors') . cs . n . t . join(', ' . n . t, $table_errors)); } } $active_plugins = array(); if ($rows = safe_rows("name, version, code_md5, MD5(code) AS md5", 'txp_plugin', "status > 0")) { foreach ($rows as $row) { $n = $row['name'] . '-' . $row['version']; if (strtolower($row['md5']) != strtolower($row['code_md5'])) { $n .= 'm'; } $active_plugins[] = $n; } } $theme_manifest = $theme->manifest(); // Check GD info. if (function_exists('gd_info')) { $gd_info = gd_info(); $gd_support = array(); if ($gd_info['GIF Create Support']) { $gd_support[] = 'GIF'; } // Aside: In PHP 5.3, they chose to add a previously unemployed capital // "E" to the array key. if (!empty($gd_info['JPEG Support']) || !empty($gd_info['JPG Support'])) { $gd_support[] = 'JPG'; } if ($gd_info['PNG Support']) { $gd_support[] = 'PNG'; } if ($gd_support) { $gd_support = join(', ', $gd_support); } else { $gd_support = gTxt('none'); } $gd = gTxt('gd_info', array('{version}' => $gd_info['GD Version'], '{supported}' => $gd_support)); } else { $gd = gTxt('gd_unavailable'); } if (realpath($prefs['tempdir']) === realpath($prefs['plugin_cache_dir'])) { $fail['tmp_plugin_paths_match'] = diag_msg_wrap(gTxt('tmp_plugin_paths_match')); } // Database server time. extract(doSpecial(getRow("SELECT @@global.time_zone AS db_global_timezone, @@session.time_zone AS db_session_timezone, NOW() AS db_server_time, UNIX_TIMESTAMP(NOW()) AS db_server_timestamp"))); $db_server_timeoffset = $db_server_timestamp - $now; echo pagetop(gTxt('tab_diagnostics'), ''); echo hed(gTxt('tab_diagnostics'), 1, array('class' => 'txp-heading')) . n . tag_start('div', array('class' => 'txp-layout-1col', 'id' => $event . '_container')) . n . tag_start('div', array('id' => 'pre_flight_check')) . hed(gTxt('preflight_check'), 2); if ($fail) { foreach ($fail as $help => $message) { echo graf(nl2br($message) . popHelp($help)); } } else { echo graf(diag_msg_wrap(gTxt('all_checks_passed'), 'success')); } echo n . tag_end('div') . n . tag_start('div', array('id' => 'diagnostics')) . hed(gTxt('diagnostic_info'), 2); $fmt_date = '%Y-%m-%d %H:%M:%S'; $dets = array('low' => gTxt('low'), 'high' => gTxt('high')); $out = array(form(eInput('diag') . inputLabel('diag_detail_level', selectInput('step', $dets, $step, 0, 1, 'diag_detail_level'), 'detail', '', array('class' => 'txp-form-field diagnostic-details-level'), '')), '<textarea class="code" id="diagnostics-detail" cols="' . INPUT_LARGE . '" rows="' . TEXTAREA_HEIGHT_LARGE . '" dir="ltr" readonly>', gTxt('txp_version') . cs . txp_version . ' (' . check_file_integrity(INTEGRITY_DIGEST) . ')' . n, gTxt('last_update') . cs . gmstrftime($fmt_date, $dbupdatetime) . '/' . gmstrftime($fmt_date, @filemtime(txpath . '/update/_update.php')) . n, gTxt('document_root') . cs . @$_SERVER['DOCUMENT_ROOT'] . ($real_doc_root != @$_SERVER['DOCUMENT_ROOT'] ? ' (' . $real_doc_root . ')' : '') . n, '$path_to_site' . cs . $path_to_site . n, gTxt('txp_path') . cs . txpath . n, gTxt('permlink_mode') . cs . $permlink_mode . n, ini_get('open_basedir') ? 'open_basedir: ' . ini_get('open_basedir') . n : '', ini_get('upload_tmp_dir') ? 'upload_tmp_dir: ' . ini_get('upload_tmp_dir') . n : '', gTxt('tempdir') . cs . $tempdir . n, gTxt('web_domain') . cs . $siteurl . n, gTxt('php_version') . cs . phpversion() . n, $is_register_globals ? gTxt('register_globals') . cs . $is_register_globals . n : '', gTxt('gd_library') . cs . $gd . n, gTxt('server') . ' TZ: ' . Txp::get('\\Textpattern\\Date\\Timezone')->getTimeZone() . n, gTxt('server_time') . cs . strftime('%Y-%m-%d %H:%M:%S') . n, strip_tags(gTxt('is_dst')) . cs . $is_dst . n, strip_tags(gTxt('auto_dst')) . cs . $auto_dst . n, strip_tags(gTxt('gmtoffset')) . cs . $timezone_key . sp . "({$gmtoffset})" . n, 'MySQL' . cs . mysqli_get_server_info($DB->link) . n, gTxt('db_server_time') . cs . $db_server_time . n, gTxt('db_server_timeoffset') . cs . $db_server_timeoffset . ' s' . n, gTxt('db_global_timezone') . cs . $db_global_timezone . n, gTxt('db_session_timezone') . cs . $db_session_timezone . n, gTxt('locale') . cs . $locale . n, isset($_SERVER['SERVER_SOFTWARE']) ? gTxt('server') . cs . $_SERVER['SERVER_SOFTWARE'] . n : '', is_callable('apache_get_version') ? gTxt('apache_version') . cs . @apache_get_version() . n : '', gTxt('php_sapi_mode') . cs . PHP_SAPI . n, gTxt('rfc2616_headers') . cs . ini_get('cgi.rfc2616_headers') . n, gTxt('os_version') . cs . php_uname('s') . ' ' . php_uname('r') . n, $active_plugins ? gTxt('active_plugins') . cs . join(', ', $active_plugins) . n : '', gTxt('theme_name') . cs . $theme_name . sp . $theme_manifest['version'] . n, $fail ? n . gTxt('preflight_check') . cs . n . ln . join("\n", doStripTags($fail)) . n . ln : '', is_readable($path_to_site . '/.htaccess') ? n . gTxt('htaccess_contents') . cs . n . ln . txpspecialchars(join('', file($path_to_site . '/.htaccess'))) . n . ln : ''); if ($step == 'high') { $out[] = n . 'Charset (default/config)' . cs . $DB->default_charset . '/' . $DB->charset . n; $result = safe_query("SHOW variables LIKE 'character_se%'"); while ($row = mysqli_fetch_row($result)) { $out[] = $row[0] . cs . $row[1] . n; if ($row[0] == 'character_set_connection') { $conn_char = $row[1]; } } $table_names = array(PFX . 'textpattern'); $result = safe_query("SHOW TABLES LIKE '" . PFX . "txp\\_%'"); while ($row = mysqli_fetch_row($result)) { $table_names[] = $row[0]; } $table_msg = array(); foreach ($table_names as $table) { $ctr = safe_query("SHOW CREATE TABLE {$table}"); if (!$ctr) { unset($table_names[$table]); continue; } $row = mysqli_fetch_assoc($ctr); $ctcharset = preg_replace('#^CREATE TABLE.*SET=([^ ]+)[^)]*$#is', '\\1', $row['Create Table']); if (isset($conn_char) && !stristr($ctcharset, 'CREATE') && $conn_char != $ctcharset) { $table_msg[] = "{$table} is {$ctcharset}"; } $ctr = safe_query("CHECK TABLE {$table}"); $row = mysqli_fetch_assoc($ctr); if (in_array($row['Msg_type'], array('error', 'warning'))) { $table_msg[] = $table . cs . $row['Msg_Text']; } } if ($table_msg == array()) { $table_msg = count($table_names) < 17 ? array('-') : array('OK'); } $out[] = count($table_names) . ' Tables' . cs . implode(', ', $table_msg) . n; $cf = preg_grep('/^custom_\\d+/', getThings("DESCRIBE `" . PFX . "textpattern`")); $out[] = n . get_pref('max_custom_fields', 10) . sp . gTxt('custom') . cs . implode(', ', $cf) . sp . '(' . count($cf) . ')' . n; $extns = get_loaded_extensions(); $extv = array(); foreach ($extns as $e) { $extv[] = $e . (phpversion($e) ? '/' . phpversion($e) : ''); } $out[] = n . gTxt('php_extensions') . cs . join(', ', $extv) . n; if (is_callable('apache_get_modules')) { $out[] = n . gTxt('apache_modules') . cs . join(', ', apache_get_modules()) . n; } if (@is_array($pretext_data) and count($pretext_data) > 1) { $out[] = n . gTxt('pretext_data') . cs . txpspecialchars(join('', array_slice($pretext_data, 1, 20))) . n; } $out[] = n; if ($md5s = check_file_integrity(INTEGRITY_MD5)) { foreach ($md5s as $f => $checksum) { $out[] = $f . cs . n . t . (!$checksum ? gTxt('unknown') : $checksum) . n; } } $out[] = n . ln; } $out[] = callback_event('diag_results', $step) . n; $out[] = '</textarea>'; echo join('', $out), n . tag_end('div') . n . tag_end('div'); }
/** * The main panel listing all links. * * @param string|array $message The activity message */ function link_list($message = '') { global $event, $step, $link_list_pageby, $txp_user; pagetop(gTxt('tab_link'), $message); extract(gpsa(array('page', 'sort', 'dir', 'crit', 'search_method'))); if ($sort === '') { $sort = get_pref('link_sort_column', 'name'); } else { if (!in_array($sort, array('id', 'description', 'url', 'category', 'date', 'author'))) { $sort = 'name'; } set_pref('link_sort_column', $sort, 'link', 2, '', 0, PREF_PRIVATE); } if ($dir === '') { $dir = get_pref('link_sort_dir', 'asc'); } else { $dir = $dir == 'desc' ? "desc" : "asc"; set_pref('link_sort_dir', $dir, 'link', 2, '', 0, PREF_PRIVATE); } switch ($sort) { case 'id': $sort_sql = "txp_link.id {$dir}"; break; case 'description': $sort_sql = "txp_link.description {$dir}, txp_link.id ASC"; break; case 'url': $sort_sql = "txp_link.url {$dir}, txp_link.id ASC"; break; case 'category': $sort_sql = "txp_category.title {$dir}, txp_link.id ASC"; break; case 'date': $sort_sql = "txp_link.date {$dir}, txp_link.id ASC"; break; case 'author': $sort_sql = "txp_users.RealName {$dir}, txp_link.id ASC"; break; default: $sort = 'name'; $sort_sql = "txp_link.linksort {$dir}, txp_link.id ASC"; break; } $switch_dir = $dir == 'desc' ? 'asc' : 'desc'; $search = new Filter($event, array('id' => array('column' => 'txp_link.id', 'label' => gTxt('ID'), 'type' => 'integer'), 'name' => array('column' => 'txp_link.linkname', 'label' => gTxt('link_name')), 'url' => array('column' => 'txp_link.url', 'label' => gTxt('url')), 'description' => array('column' => 'txp_link.description', 'label' => gTxt('description')), 'category' => array('column' => array('txp_link.category', 'txp_category.title'), 'label' => gTxt('link_category')), 'author' => array('column' => array('txp_link.author', 'txp_users.RealName'), 'label' => gTxt('author')), 'linksort' => array('column' => 'txp_link.linksort', 'label' => gTxt('sort_value')))); list($criteria, $crit, $search_method) = $search->getFilter(array('id' => array('can_list' => true))); $search_render_options = array('placeholder' => 'search_links'); $sql_from = safe_pfx_j('txp_link') . "\n LEFT JOIN " . safe_pfx_j('txp_category') . " ON txp_category.name = txp_link.category AND txp_category.type = 'link'\n LEFT JOIN " . safe_pfx_j('txp_users') . " ON txp_users.name = txp_link.author"; if ($criteria === 1) { $total = safe_count('txp_link', $criteria); } else { $total = getThing("SELECT COUNT(*) FROM {$sql_from} WHERE {$criteria}"); } echo n . tag(hed(gTxt('tab_link'), 1, array('class' => 'txp-heading')), 'div', array('class' => 'txp-layout-2col-cell-1')); $searchBlock = n . tag($search->renderForm('link_list', $search_render_options), 'div', array('class' => 'txp-layout-2col-cell-2', 'id' => $event . '_control')); $createBlock = array(); if (has_privs('link.edit')) { $createBlock[] = n . tag(sLink('link', 'link_edit', gTxt('add_new_link'), 'txp-button'), 'div', array('class' => 'txp-control-panel')); } $contentBlockStart = n . tag_start('div', array('class' => 'txp-layout-1col', 'id' => $event . '_container')); $createBlock = implode(n, $createBlock); if ($total < 1) { if ($criteria != 1) { echo $searchBlock . $contentBlockStart . $createBlock . graf(span(null, array('class' => 'ui-icon ui-icon-info')) . ' ' . gTxt('no_results_found'), array('class' => 'alert-block information')); } else { echo $contentBlockStart . $createBlock . graf(span(null, array('class' => 'ui-icon ui-icon-info')) . ' ' . gTxt('no_links_recorded'), array('class' => 'alert-block information')); } echo n . tag_end('div'); return; } $limit = max($link_list_pageby, 15); list($page, $offset, $numPages) = pager($total, $limit, $page); echo $searchBlock . $contentBlockStart . $createBlock; $rs = safe_query("SELECT\n txp_link.id,\n UNIX_TIMESTAMP(txp_link.date) AS uDate,\n txp_link.category,\n txp_link.url,\n txp_link.linkname,\n txp_link.description,\n txp_link.author,\n txp_users.RealName AS realname,\n txp_category.Title AS category_title\n FROM {$sql_from} WHERE {$criteria} ORDER BY {$sort_sql} LIMIT {$offset}, {$limit}"); if ($rs && numRows($rs)) { $show_authors = !has_single_author('txp_link'); echo n . tag(toggle_box('links_detail'), 'div', array('class' => 'txp-list-options')) . n . tag_start('form', array('class' => 'multi_edit_form', 'id' => 'links_form', 'name' => 'longform', 'method' => 'post', 'action' => 'index.php')) . n . tag_start('div', array('class' => 'txp-listtables')) . n . tag_start('table', array('class' => 'txp-list')) . n . tag_start('thead') . tr(hCell(fInput('checkbox', 'select_all', 0, '', '', '', '', '', 'select_all'), '', ' class="txp-list-col-multi-edit" scope="col" title="' . gTxt('toggle_all_selected') . '"') . column_head('ID', 'id', 'link', true, $switch_dir, $crit, $search_method, ('id' == $sort ? "{$dir} " : '') . 'txp-list-col-id') . column_head('link_name', 'name', 'link', true, $switch_dir, $crit, $search_method, ('name' == $sort ? "{$dir} " : '') . 'txp-list-col-name') . column_head('description', 'description', 'link', true, $switch_dir, $crit, $search_method, ('description' == $sort ? "{$dir} " : '') . 'txp-list-col-description links_detail') . column_head('link_category', 'category', 'link', true, $switch_dir, $crit, $search_method, ('category' == $sort ? "{$dir} " : '') . 'txp-list-col-category category') . column_head('url', 'url', 'link', true, $switch_dir, $crit, $search_method, ('url' == $sort ? "{$dir} " : '') . 'txp-list-col-url') . column_head('date', 'date', 'link', true, $switch_dir, $crit, $search_method, ('date' == $sort ? "{$dir} " : '') . 'txp-list-col-created date links_detail') . ($show_authors ? column_head('author', 'author', 'link', true, $switch_dir, $crit, $search_method, ('author' == $sort ? "{$dir} " : '') . 'txp-list-col-author name') : '')) . n . tag_end('thead') . n . tag_start('tbody'); $validator = new Validator(); while ($a = nextRow($rs)) { extract($a, EXTR_PREFIX_ALL, 'link'); $edit_url = array('event' => 'link', 'step' => 'link_edit', 'id' => $link_id, 'sort' => $sort, 'dir' => $dir, 'page' => $page, 'search_method' => $search_method, 'crit' => $crit); $validator->setConstraints(array(new CategoryConstraint($link_category, array('type' => 'link')))); $vc = $validator->validate() ? '' : ' error'; if ($link_category) { $link_category = span(txpspecialchars($link_category_title), array('title' => $link_category)); } $can_edit = has_privs('link.edit') || $link_author === $txp_user && has_privs('link.edit.own'); $view_url = txpspecialchars($link_url); echo tr(td(fInput('checkbox', 'selected[]', $link_id), '', 'txp-list-col-multi-edit') . hCell($can_edit ? href($link_id, $edit_url, ' title="' . gTxt('edit') . '"') : $link_id, '', ' class="txp-list-col-id" scope="row"') . td($can_edit ? href(txpspecialchars($link_linkname), $edit_url, ' title="' . gTxt('edit') . '"') : txpspecialchars($link_linkname), '', 'txp-list-col-name') . td(txpspecialchars($link_description), '', 'txp-list-col-description links_detail') . td($link_category, '', 'txp-list-col-category category' . $vc) . td(href($view_url, $view_url, ' rel="external" target="_blank"'), '', 'txp-list-col-url') . td(gTime($link_uDate), '', 'txp-list-col-created date links_detail') . ($show_authors ? td(span(txpspecialchars($link_realname), array('title' => $link_author)), '', 'txp-list-col-author name') : '')); } echo n . tag_end('tbody') . n . tag_end('table') . n . tag_end('div') . link_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('link', $link_list_pageby) . nav_form('link', $page, $numPages, $sort, $dir, $crit, $search_method, $total, $limit) . n . tag_end('div'); } echo n . tag_end('div'); }
/** * 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'); }
function link_list($message = '') { global $event, $step, $link_list_pageby, $txp_user; pagetop(gTxt('tab_link'), $message); extract(gpsa(array('page', 'sort', 'dir', 'crit', 'search_method'))); if ($sort === '') { $sort = get_pref('link_sort_column', 'name'); } if ($dir === '') { $dir = get_pref('link_sort_dir', 'asc'); } $dir = $dir == 'desc' ? 'desc' : 'asc'; switch ($sort) { case 'id': $sort_sql = 'id ' . $dir; break; case 'description': $sort_sql = 'description ' . $dir . ', id asc'; break; case 'url': $sort_sql = 'url ' . $dir . ', id asc'; break; case 'category': $sort_sql = 'category ' . $dir . ', id asc'; break; case 'date': $sort_sql = 'date ' . $dir . ', id asc'; break; case 'author': $sort_sql = 'author ' . $dir . ', id asc'; break; default: $sort = 'name'; $sort_sql = 'linksort ' . $dir . ', id asc'; break; } set_pref('link_sort_column', $sort, 'link', 2, '', 0, PREF_PRIVATE); set_pref('link_sort_dir', $dir, 'link', 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' => "ID in ('" . join("','", do_list($crit_escaped)) . "')", 'name' => "linkname = '{$crit_escaped}'", 'description' => "description = '{$crit_escaped}'", 'url' => "url = '{$crit_escaped}'", 'category' => "category = '{$crit_escaped}'", 'author' => "author = '{$crit_escaped}'") : array('id' => "ID in ('" . join("','", do_list($crit_escaped)) . "')", 'name' => "linkname like '%{$crit_escaped}%'", 'description' => "description like '%{$crit_escaped}%'", 'url' => "url like '%{$crit_escaped}%'", 'category' => "category like '%{$crit_escaped}%'", 'author' => "author like '%{$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', 'link_list', 0, $criteria); $total = getCount('txp_link', $criteria); echo hed(gTxt('tab_link'), 1, array('class' => 'txp-heading')); echo n . '<div id="' . $event . '_control" class="txp-control-panel">'; if (has_privs('link.edit')) { echo graf(sLink('link', 'link_edit', gTxt('add_new_link')), ' class="txp-buttons"'); } if ($total < 1) { if ($criteria != 1) { echo link_search_form($crit, $search_method) . graf(gTxt('no_results_found'), ' class="indicator"') . '</div>'; } else { echo graf(gTxt('no_links_recorded'), ' class="indicator"') . '</div>'; } return; } $limit = max($link_list_pageby, 15); list($page, $offset, $numPages) = pager($total, $limit, $page); echo link_search_form($crit, $search_method) . '</div>'; $rs = safe_rows_start('*, unix_timestamp(date) as uDate', 'txp_link', "{$criteria} order by {$sort_sql} limit {$offset}, {$limit}"); if ($rs) { $show_authors = !has_single_author('txp_link'); echo n . tag_start('div', array('id' => $event . '_container', 'class' => 'txp-container')) . n . tag_start('form', array('action' => 'index.php', 'id' => 'links_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(hCell(fInput('checkbox', 'select_all', 0, '', '', '', '', '', 'select_all'), '', ' scope="col" title="' . gTxt('toggle_all_selected') . '" class="txp-list-col-multi-edit"') . column_head('ID', 'id', 'link', true, $switch_dir, $crit, $search_method, ('id' == $sort ? "{$dir} " : '') . 'txp-list-col-id') . column_head('link_name', 'name', 'link', true, $switch_dir, $crit, $search_method, ('name' == $sort ? "{$dir} " : '') . 'txp-list-col-name') . column_head('description', 'description', 'link', true, $switch_dir, $crit, $search_method, ('description' == $sort ? "{$dir} " : '') . 'txp-list-col-description links_detail') . column_head('link_category', 'category', 'link', true, $switch_dir, $crit, $search_method, ('category' == $sort ? "{$dir} " : '') . 'txp-list-col-category category') . column_head('url', 'url', 'link', true, $switch_dir, $crit, $search_method, ('url' == $sort ? "{$dir} " : '') . 'txp-list-col-url') . column_head('date', 'date', 'link', true, $switch_dir, $crit, $search_method, ('date' == $sort ? "{$dir} " : '') . 'txp-list-col-created date links_detail') . ($show_authors ? column_head('author', 'author', 'link', true, $switch_dir, $crit, $search_method, ('author' == $sort ? "{$dir} " : '') . 'txp-list-col-author name') : '')) . n . tag_end('thead') . n . tag_start('tbody'); $validator = new Validator(); while ($a = nextRow($rs)) { extract($a, EXTR_PREFIX_ALL, 'link'); $edit_url = array('event' => 'link', 'step' => 'link_edit', 'id' => $link_id, 'sort' => $sort, 'dir' => $dir, 'page' => $page, 'search_method' => $search_method, 'crit' => $crit); $validator->setConstraints(array(new CategoryConstraint($link_category, array('type' => 'link')))); $vc = $validator->validate() ? '' : ' error'; $can_edit = has_privs('link.edit') || $link_author === $txp_user && has_privs('link.edit.own'); $view_url = txpspecialchars($link_url); echo tr(td(fInput('checkbox', 'selected[]', $link_id), '', 'txp-list-col-multi-edit') . hCell($can_edit ? href($link_id, $edit_url, ' title="' . gTxt('edit') . '"') : $link_id, '', ' scope="row" class="txp-list-col-id"') . td($can_edit ? href(txpspecialchars($link_linkname), $edit_url, ' title="' . gTxt('edit') . '"') : txpspecialchars($link_linkname), '', 'txp-list-col-name') . td(txpspecialchars($link_description), '', 'txp-list-col-description links_detail') . td(span($link_category, array('title' => fetch_category_title($link_category, 'link'))), '', 'txp-list-col-category category' . $vc) . td(href($view_url, $view_url, ' rel="external" target="_blank"'), '', 'txp-list-col-url') . td(gTime($link_uDate), '', 'txp-list-col-created date links_detail') . ($show_authors ? td(span(txpspecialchars($link_author), array('title' => get_author_name($link_author))), '', 'txp-list-col-author name') : '')); } echo n . tag_end('tbody') . n . tag_end('table') . n . tag_end('div') . link_multiedit_form($page, $sort, $dir, $crit, $search_method) . tInput() . n . tag_end('form') . graf(toggle_box('links_detail'), array('class' => 'detail-toggle')) . n . tag_start('div', array('id' => $event . '_navigation', 'class' => 'txp-navigation')) . pageby_form('link', $link_list_pageby) . nav_form('link', $page, $numPages, $sort, $dir, $crit, $search_method, $total, $limit) . n . tag_end('div') . n . tag_end('div'); } }
/** * The editor for sections. */ function section_edit() { global $event, $step, $all_pages, $all_styles; require_privs('section.edit'); extract(gpsa(array('page', 'sort', 'dir', 'crit', 'search_method', 'name'))); $is_edit = $name && $step == 'section_edit'; $caption = gTxt('create_section'); $is_default_section = false; if ($is_edit) { $rs = safe_row('*', 'txp_section', "name = '" . doSlash($name) . "'"); if ($name == 'default') { $caption = gTxt('edit_default_section'); $is_default_section = true; } else { $caption = gTxt('edit_section'); } } else { // Pulls defaults for the new section from the 'default'. $rs = safe_row('*', 'txp_section', "name = 'default'"); if ($rs) { $rs['name'] = $rs['title'] = ''; } } if (!$rs) { sec_section_list(array(gTxt('unknown_section'), E_ERROR)); return; } extract($rs, EXTR_PREFIX_ALL, 'sec'); pagetop(gTxt('tab_sections')); $out = array(); $out[] = n . tag_start('section', array('class' => 'txp-edit')) . hed($caption, 2); if ($is_default_section) { $out[] = hInput('name', 'default'); } else { $out[] = inputLabel('section_name', fInput('text', 'name', $sec_name, '', '', '', INPUT_REGULAR, '', 'section_name'), 'section_name') . inputLabel('section_title', fInput('text', 'title', $sec_title, '', '', '', INPUT_REGULAR, '', 'section_title'), 'section_longtitle'); } $out[] = inputLabel('section_description', text_area('description', 0, 0, $sec_description, 'section_description', TEXTAREA_HEIGHT_SMALL, INPUT_LARGE), 'section_description'); $out[] = 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'); if (!$is_default_section) { $out[] = inputLabel('on_front_page', yesnoradio('on_frontpage', $sec_on_frontpage, '', $sec_name), '', 'section_on_frontpage') . inputLabel('syndicate', yesnoradio('in_rss', $sec_in_rss, '', $sec_name), '', 'section_syndicate') . inputLabel('include_in_search', yesnoradio('searchable', $sec_searchable, '', $sec_name), '', 'section_searchable'); } $out[] = 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) . n . tag_end('section'); echo n . tag_start('div', array('id' => $event . '_container', 'class' => 'txp-container')) . form(join('', $out), '', '', 'post', 'edit-form', '', 'section_details') . n . tag_end('div'); }
/** * Renders and outputs the file editor panel. * * @param string|array $message The activity message * @param int $id The file ID */ function file_edit($message = '', $id = '') { global $file_base_path, $levels, $file_statuses, $txp_user, $event, $all_file_cats; extract(gpsa(array('name', 'title', 'category', 'permissions', 'description', 'sort', 'dir', 'page', 'crit', 'search_method', 'publish_now'))); if (!$id) { $id = gps('id'); } $id = assert_int($id); $rs = safe_row("*, UNIX_TIMESTAMP(created) AS created, UNIX_TIMESTAMP(modified) AS modified", 'txp_file', "id = {$id}"); if ($rs) { extract($rs); $filename = sanitizeForFile($filename); if (!has_privs('file.edit') && !($author === $txp_user && has_privs('file.edit.own'))) { require_privs(); } pagetop(gTxt('edit_file'), $message); if ($permissions == '') { $permissions = '-1'; } if (!has_privs('file.publish') && $status >= STATUS_LIVE) { $status = STATUS_PENDING; } $file_exists = file_exists(build_file_path($file_base_path, $filename)); $existing_files = get_filenames(); $replace = $file_exists ? file_upload_form('replace_file', 'file_replace', 'file_replace', $id, 'file_replace', ' replace-file') : file_upload_form('file_relink', 'file_reassign', 'file_replace', $id, 'file_reassign', ' upload-file'); $condition = span($file_exists ? gTxt('file_status_ok') : gTxt('file_status_missing'), array('class' => $file_exists ? 'success' : 'error')); $downloadlink = $file_exists ? make_download_link($id, txpspecialchars($filename), $filename) : txpspecialchars($filename); $created = inputLabel('year', tsi('year', '%Y', $rs['created'], '', 'year') . ' <span role="separator">/</span> ' . tsi('month', '%m', $rs['created'], '', 'month') . ' <span role="separator">/</span> ' . tsi('day', '%d', $rs['created'], '', 'day'), 'publish_date', array('timestamp_file', 'instructions_file_date'), array('class' => 'txp-form-field date posted')) . inputLabel('hour', tsi('hour', '%H', $rs['created'], '', 'hour') . ' <span role="separator">:</span> ' . tsi('minute', '%M', $rs['created'], '', 'minute') . ' <span role="separator">:</span> ' . tsi('second', '%S', $rs['created'], '', 'second'), 'publish_time', array('', 'instructions_file_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')); echo n . tag_start('div', array('class' => 'txp-edit')) . hed(gTxt('edit_file'), 2) . $replace . inputLabel('condition', $condition, '', '', array('class' => 'txp-form-field edit-file-condition')) . inputLabel('name', $downloadlink, '', '', array('class' => 'txp-form-field edit-file-name')) . inputLabel('download_count', $downloads, '', '', array('class' => 'txp-form-field edit-file-download-count')) . form(($file_exists ? inputLabel('file_status', selectInput('status', $file_statuses, $status, false, '', 'file_status'), 'file_status', '', array('class' => 'txp-form-field edit-file-status')) . $created . inputLabel('file_title', fInput('text', 'title', $title, '', '', '', INPUT_REGULAR, '', 'file_title'), 'title', '', array('class' => 'txp-form-field edit-file-title')) . inputLabel('file_category', event_category_popup('file', $category, 'file_category') . n . eLink('category', 'list', '', '', gTxt('edit'), '', '', '', 'txp-option-link'), 'file_category', '', array('class' => 'txp-form-field edit-file-category')) . inputLabel('file_description', '<textarea id="file_description" name="description" cols="' . INPUT_LARGE . '" rows="' . TEXTAREA_HEIGHT_SMALL . '">' . $description . '</textarea>', 'description', '', array('class' => 'txp-form-field txp-form-field-textarea edit-file-description')) . pluggable_ui('file_ui', 'extend_detail_form', '', $rs) . graf(sLink('file', '', gTxt('cancel'), 'txp-button') . fInput('submit', '', gTxt('save'), 'publish'), array('class' => 'txp-edit-actions')) . hInput('filename', $filename) : (empty($existing_files) ? '' : gTxt('existing_file') . selectInput('filename', $existing_files, '', 1)) . pluggable_ui('file_ui', 'extend_detail_form', '', $rs) . graf(sLink('file', '', gTxt('cancel'), 'txp-button') . fInput('submit', '', gTxt('save'), 'publish'), array('class' => 'txp-edit-actions')) . hInput('category', $category) . hInput('perms', $permissions == '-1' ? '' : $permissions) . hInput('title', $title) . hInput('description', $description) . hInput('status', $status)) . eInput('file') . sInput('file_save') . hInput('id', $id) . hInput('sort', $sort) . hInput('dir', $dir) . hInput('page', $page) . hInput('crit', $crit) . hInput('search_method', $search_method), '', '', 'post', 'file-detail ' . ($file_exists ? '' : 'not-') . 'exists', '', $file_exists ? 'file_details' : 'assign_file') . n . tag_end('div'); } }
/** * 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'); } }
/** * Renders a page navigation form. * * @param string $event Event * @param int $page Current page number * @param int $numPages Total pages * @param string $sort Sort criterion * @param string $dir Sort direction, either "asc" or "desc" * @param string $crit Search criterion * @param string $search_method Search method * @param int $total Total search term hit count [0] * @param int $limit First visible search term hit number [0] * @param string $step Step * @param int $list Number of displayed page links discounting jump links, previous and next * @return string HTML */ function nav_form($event, $page, $numPages, $sort = '', $dir = '', $crit = '', $search_method = '', $total = 0, $limit = 0, $step = 'list', $list = 5) { $out = array(); if ($crit != '' && $total > 1) { $out[] = announce(gTxt('showing_search_results', array('{from}' => ($page - 1) * $limit + 1, '{to}' => min($total, $page * $limit), '{total}' => $total)), TEXTPATTERN_ANNOUNCE_REGULAR); } if ($numPages > 1) { $nav = array(); $list--; $page = max(min($page, $numPages), 1); $start = max(1, min($numPages - $list, $page - floor($list / 2))); $end = min($numPages, $start + $list); $parameters = array('event' => $event, 'step' => $step, 'dir' => $dir, 'crit' => $crit, 'search_method' => $search_method); // Previous page. if ($page > 1) { $nav[] = PrevNextLink($event, $page - 1, gTxt('prev'), 'prev', $sort, $dir, $crit, $search_method, $step); } else { $nav[] = span(gTxt('prev'), array('class' => 'navlink-disabled', 'aria-disabled' => 'true')); } // Jump to the first page. if ($start > 1) { $nav[] = href(1, $parameters + array('page' => 1), array('class' => 'navlink')); } // Jump to mid. if ($start > 2) { $between = ceil($start / 2); $nav[] = href('…', $parameters + array('page' => $between), array('class' => 'navlink', 'title' => $between)); } // Page links. for ($i = $start; $i <= $end; $i++) { if ($i == $page) { $class = 'navlink-active'; } else { $class = 'navlink'; } $nav[] = href($i, $parameters + array('page' => $i), array('class' => $class)); } // Jump to mid. if ($end < $numPages - 1) { $between = $end + floor(($numPages - $end) / 2); $nav[] = href('…', $parameters + array('page' => $between), array('class' => 'navlink', 'title' => $between)); } // Jump to the last page. if ($end < $numPages) { $nav[] = href($numPages, $parameters + array('page' => $numPages), array('class' => 'navlink')); } // Next page. if ($page < $numPages) { $nav[] = PrevNextLink($event, $page + 1, gTxt('next'), 'next', $sort, $dir, $crit, $search_method, $step); } else { $nav[] = span(gTxt('next'), array('class' => 'navlink-disabled', 'aria-disabled' => 'true')); } $out[] = n . tag(tag(join(tag_end('li') . tag_start('li'), $nav), 'li'), 'ul', array('class' => 'nav-tertiary prev-next')); } return join('', $out); }
/** * Generates a <table> of every language that Textpattern supports. * * If requested with HTTP POST parameter 'force' set anything other than 'file', * outputs any errors in RPC server connection. * * @param string|array $message The activity message */ function list_languages($message = '') { require_once txpath . '/lib/IXRClass.php'; $active_lang = safe_field("val", 'txp_prefs', "name = 'language'"); $lang_form = tag(form(tag(gTxt('active_language'), 'label', array('for' => 'language')) . languages('language', $active_lang) . eInput('lang') . sInput('save_language')), 'div', array('class' => 'txp-control-panel')); $client = new IXR_Client(RPC_SERVER); // $client->debug = true; $available_lang = array(); $rpc_connect = false; $show_files = false; // Get items from RPC. @set_time_limit(90); // TODO: 90 seconds: seriously? if ($client->query('tups.listLanguages', get_pref('blog_uid'))) { $rpc_connect = true; $response = $client->getResponse(); foreach ($response as $language) { $available_lang[$language['language']]['rpc_lastmod'] = gmmktime($language['lastmodified']->hour, $language['lastmodified']->minute, $language['lastmodified']->second, $language['lastmodified']->month, $language['lastmodified']->day, $language['lastmodified']->year); } } elseif (gps('force') != 'file') { $msg = gTxt('rpc_connect_error') . "<!--" . $client->getErrorCode() . ' ' . $client->getErrorMessage() . "-->"; } // Get items from Filesystem. $files = get_lang_files(); if (is_array($files) && !empty($files)) { foreach ($files as $file) { if ($fp = @fopen(txpath . DS . 'lang' . DS . $file, 'r')) { $name = preg_replace('/\\.(txt|textpack)$/i', '', $file); $firstline = fgets($fp, 4069); fclose($fp); if (strpos($firstline, '#@version') !== false) { @(list($fversion, $ftime) = explode(';', trim(substr($firstline, strpos($firstline, ' ', 1))))); } else { $fversion = $ftime = null; } $available_lang[$name]['file_note'] = isset($fversion) ? $fversion : 0; $available_lang[$name]['file_lastmod'] = isset($ftime) ? $ftime : 0; } } } // Get installed items from the database. // We need a value here for the language itself, not for each one of the rows. $rows = safe_rows("lang, UNIX_TIMESTAMP(MAX(lastmod)) AS lastmod", 'txp_lang', "1 = 1 GROUP BY lang ORDER BY lastmod DESC"); $installed_lang = array(); foreach ($rows as $language) { $available_lang[$language['lang']]['db_lastmod'] = $language['lastmod']; if ($language['lang'] != $active_lang) { $installed_lang[] = $language['lang']; } } $list = ''; // Create the language table components. foreach ($available_lang as $langname => $langdat) { $file_updated = isset($langdat['db_lastmod']) && @$langdat['file_lastmod'] > $langdat['db_lastmod']; $rpc_updated = @$langdat['rpc_lastmod'] > @$langdat['db_lastmod']; $rpc_install = tda($rpc_updated ? strong(eLink('lang', 'get_language', 'lang_code', $langname, isset($langdat['db_lastmod']) ? gTxt('update') : gTxt('install'), 'updating', isset($langdat['db_lastmod']), '')) . n . span(safe_strftime('%d %b %Y %X', @$langdat['rpc_lastmod']), array('class' => 'date modified')) : (isset($langdat['rpc_lastmod']) ? gTxt('up_to_date') : '-') . (isset($langdat['db_lastmod']) ? n . span(safe_strftime('%d %b %Y %X', $langdat['db_lastmod']), array('class' => 'date modified')) : ''), isset($langdat['db_lastmod']) && $rpc_updated ? ' class="highlight lang-value"' : ' class="lang-value"'); $lang_file = tda(isset($langdat['file_lastmod']) ? strong(eLink('lang', 'get_language', 'lang_code', $langname, $file_updated ? gTxt('update') : gTxt('install'), 'force', 'file', '')) . n . span(safe_strftime(get_pref('archive_dateformat'), $langdat['file_lastmod']), array('class' => 'date ' . ($file_updated ? 'created' : 'modified'))) : '-', ' class="lang-value languages_detail' . (isset($langdat['db_lastmod']) && $rpc_updated ? ' highlight' : '') . '"'); $list .= tr(hCell(gTxt($langname), '', isset($langdat['db_lastmod']) && $rpc_updated ? ' class="highlight lang-label" scope="row"' : ' class="lang-label" scope="row"') . n . $rpc_install . n . $lang_file . tda(in_array($langname, $installed_lang) ? dLink('lang', 'remove_language', 'lang_code', $langname, 1) : '-', ' class="languages_detail' . (isset($langdat['db_lastmod']) && $rpc_updated ? ' highlight' : '') . '"')) . n; } // Output table and content. pagetop(gTxt('tab_languages'), $message); echo n . tag(hed(gTxt('tab_languages'), 1, array('class' => 'txp-heading')), 'div', array('class' => 'txp-layout-2col-cell-1')) . n . tag_start('div', array('class' => 'txp-layout-1col', 'id' => 'language_container')); if (isset($msg) && $msg) { echo graf('<span class="ui-icon ui-icon-closethick"></span> ' . $msg, array('class' => 'alert-block error')); } echo $lang_form, n . tag(toggle_box('languages_detail'), 'div', array('class' => 'txp-list-options')) . n . tag_start('div', array('class' => 'txp-listtables')) . n . tag_start('table', array('class' => 'txp-list')) . n . tag_start('thead') . tr(hCell(gTxt('language'), '', ' scope="col"') . hCell(gTxt('from_server') . popHelp('install_lang_from_server'), '', ' scope="col"') . hCell(gTxt('from_file') . popHelp('install_lang_from_file'), '', ' class="languages_detail" scope="col"') . hCell(gTxt('remove_lang') . popHelp('remove_lang'), '', ' class="languages_detail" scope="col"')) . n . tag_end('thead') . n . tag_start('tbody') . $list . n . tag_end('tbody') . n . tag_end('table') . n . tag_end('div') . hed(gTxt('install_from_textpack'), 2) . n . tag(form('<label for="textpack-install">' . gTxt('install_textpack') . '</label>' . popHelp('get_textpack') . n . '<textarea class="code" id="textpack-install" name="textpack" cols="' . INPUT_LARGE . '" rows="' . TEXTAREA_HEIGHT_SMALL . '" dir="ltr"></textarea>' . fInput('submit', 'install_new', gTxt('upload')) . eInput('lang') . sInput('get_textpack'), '', '', 'post', '', '', 'text_uploader'), 'div', array('class' => 'txp-control-panel')) . n . tag_end('div'); }
/** * Outputs the main panel listing all articles. * * @param string|array $message The activity message * @param string $post Not used */ function list_list($message = '', $post = '') { global $statuses, $use_comments, $comments_disabled_after, $step, $txp_user, $article_list_pageby, $event; pagetop(gTxt('tab_list'), $message); extract(gpsa(array('page', 'sort', 'dir', 'crit', 'search_method'))); if ($sort === '') { $sort = get_pref('article_sort_column', 'posted'); } if ($dir === '') { $dir = get_pref('article_sort_dir', 'desc'); } $dir = $dir == 'asc' ? 'asc' : 'desc'; $sesutats = array_flip($statuses); switch ($sort) { case 'id': $sort_sql = 'textpattern.ID ' . $dir; break; case 'title': $sort_sql = 'textpattern.Title ' . $dir . ', textpattern.Posted desc'; break; case 'expires': $sort_sql = 'textpattern.Expires ' . $dir; break; case 'section': $sort_sql = 'section.title ' . $dir . ', textpattern.Posted desc'; break; case 'category1': $sort_sql = 'category1.title ' . $dir . ', textpattern.Posted desc'; break; case 'category2': $sort_sql = 'category2.title ' . $dir . ', textpattern.Posted desc'; break; case 'status': $sort_sql = 'textpattern.Status ' . $dir . ', textpattern.Posted desc'; break; case 'author': $sort_sql = 'user.RealName ' . $dir . ', textpattern.Posted desc'; break; case 'comments': $sort_sql = 'textpattern.comments_count ' . $dir . ', textpattern.Posted desc'; break; case 'lastmod': $sort_sql = 'textpattern.LastMod ' . $dir . ', textpattern.Posted desc'; break; default: $sort = 'posted'; $sort_sql = 'textpattern.Posted ' . $dir; break; } set_pref('article_sort_column', $sort, 'list', 2, '', 0, PREF_PRIVATE); set_pref('article_sort_dir', $dir, 'list', 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' => "textpattern.ID in ('" . join("','", do_list($crit_escaped)) . "')", 'title_body_excerpt' => "textpattern.Title = '{$crit_escaped}' or textpattern.Body = '{$crit_escaped}' or textpattern.Excerpt = '{$crit_escaped}'", 'section' => "textpattern.Section = '{$crit_escaped}' or section.title = '{$crit_escaped}'", 'keywords' => "FIND_IN_SET('" . $crit_escaped . "',textpattern.Keywords)", 'categories' => "textpattern.Category1 = '{$crit_escaped}' or textpattern.Category2 = '{$crit_escaped}' or category1.title = '{$crit_escaped}' or category2.title = '{$crit_escaped}'", 'status' => "textpattern.Status = '" . @$sesutats[gTxt($crit_escaped)] . "'", 'author' => "textpattern.AuthorID = '{$crit_escaped}' or user.RealName = '{$crit_escaped}'", 'article_image' => "textpattern.Image in ('" . join("','", do_list($crit_escaped)) . "')", 'posted' => "textpattern.Posted = '{$crit_escaped}'", 'lastmod' => "textpattern.LastMod = '{$crit_escaped}'") : array('id' => "textpattern.ID in ('" . join("','", do_list($crit_escaped)) . "')", 'title_body_excerpt' => "textpattern.Title like '%{$crit_escaped}%' or textpattern.Body like '%{$crit_escaped}%' or textpattern.Excerpt like '%{$crit_escaped}%'", 'section' => "textpattern.Section like '%{$crit_escaped}%' or section.title like '%{$crit_escaped}%'", 'keywords' => "FIND_IN_SET('" . $crit_escaped . "',textpattern.Keywords)", 'categories' => "textpattern.Category1 like '%{$crit_escaped}%' or textpattern.Category2 like '%{$crit_escaped}%' or category1.title like '%{$crit_escaped}%' or category2.title like '%{$crit_escaped}%'", 'status' => "textpattern.Status = '" . @$sesutats[gTxt($crit_escaped)] . "'", 'author' => "textpattern.AuthorID like '%{$crit_escaped}%' or user.RealName like '%{$crit_escaped}%'", 'article_image' => "textpattern.Image in ('" . join("','", do_list($crit_escaped)) . "')", 'posted' => "textpattern.Posted like '{$crit_escaped}%'", 'lastmod' => "textpattern.LastMod like '{$crit_escaped}%'"); if (array_key_exists($search_method, $critsql)) { $criteria = $critsql[$search_method]; $limit = 500; } else { $search_method = ''; $crit = ''; } } else { $search_method = ''; $crit = ''; } $criteria .= callback_event('admin_criteria', 'list_list', 0, $criteria); $sql_from = safe_pfx('textpattern') . " textpattern\n left join " . safe_pfx('txp_category') . " category1 on category1.name = textpattern.Category1 and category1.type = 'article'\n left join " . safe_pfx('txp_category') . " category2 on category2.name = textpattern.Category2 and category2.type = 'article'\n left join " . safe_pfx('txp_section') . " section on section.name = textpattern.Section\n left join " . safe_pfx('txp_users') . " user on user.name = textpattern.AuthorID"; if ($criteria === 1) { $total = safe_count('textpattern', $criteria); } else { $total = getThing('select count(*) from ' . $sql_from . ' where ' . $criteria); } echo hed(gTxt('tab_list'), 1, array('class' => 'txp-heading')); echo n . '<div id="' . $event . '_control" class="txp-control-panel">'; if ($total < 1) { if ($criteria != 1) { echo list_search_form($crit, $search_method) . graf(gTxt('no_results_found'), ' class="indicator"') . '</div>'; } else { echo graf(gTxt('no_articles_recorded'), ' class="indicator"') . '</div>'; } return; } $limit = max($article_list_pageby, 15); list($page, $offset, $numPages) = pager($total, $limit, $page); echo list_search_form($crit, $search_method) . '</div>'; $rs = safe_query("select\n textpattern.ID, textpattern.Title, textpattern.url_title, textpattern.Section,\n textpattern.Category1, textpattern.Category2,\n textpattern.Status, textpattern.Annotate, textpattern.AuthorID,\n unix_timestamp(textpattern.Posted) as posted,\n unix_timestamp(textpattern.LastMod) as lastmod,\n unix_timestamp(textpattern.Expires) as expires,\n category1.title as category1_title,\n category2.title as category2_title,\n section.title as section_title,\n user.RealName as RealName,\n (select count(*) from " . safe_pfx('txp_discuss') . " where parentid = textpattern.ID) as total_comments\n from {$sql_from} where {$criteria} order by {$sort_sql} limit {$offset}, {$limit}"); if ($rs) { $show_authors = !has_single_author('textpattern', 'AuthorID'); echo n . tag_start('div', array('id' => $event . '_container', 'class' => 'txp-container')) . n . tag_start('form', array('action' => 'index.php', 'id' => 'articles_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(hCell(fInput('checkbox', 'select_all', 0, '', '', '', '', '', 'select_all'), '', ' scope="col" title="' . gTxt('toggle_all_selected') . '" class="txp-list-col-multi-edit"') . column_head('ID', 'id', 'list', true, $switch_dir, $crit, $search_method, ('id' == $sort ? "{$dir} " : '') . 'txp-list-col-id') . column_head('title', 'title', 'list', true, $switch_dir, $crit, $search_method, ('title' == $sort ? "{$dir} " : '') . 'txp-list-col-title') . column_head('posted', 'posted', 'list', true, $switch_dir, $crit, $search_method, ('posted' == $sort ? "{$dir} " : '') . 'txp-list-col-created date') . column_head('article_modified', 'lastmod', 'list', true, $switch_dir, $crit, $search_method, ('lastmod' == $sort ? "{$dir} " : '') . 'txp-list-col-lastmod date articles_detail') . column_head('expires', 'expires', 'list', true, $switch_dir, $crit, $search_method, ('expires' == $sort ? "{$dir} " : '') . 'txp-list-col-expires date articles_detail') . column_head('section', 'section', 'list', true, $switch_dir, $crit, $search_method, ('section' == $sort ? "{$dir} " : '') . 'txp-list-col-section') . column_head('category1', 'category1', 'list', true, $switch_dir, $crit, $search_method, ('category1' == $sort ? "{$dir} " : '') . 'txp-list-col-category1 category articles_detail') . column_head('category2', 'category2', 'list', true, $switch_dir, $crit, $search_method, ('category2' == $sort ? "{$dir} " : '') . 'txp-list-col-category2 category articles_detail') . column_head('status', 'status', 'list', true, $switch_dir, $crit, $search_method, ('status' == $sort ? "{$dir} " : '') . 'txp-list-col-status') . ($show_authors ? column_head('author', 'author', 'list', true, $switch_dir, $crit, $search_method, ('author' == $sort ? "{$dir} " : '') . 'txp-list-col-author name') : '') . ($use_comments == 1 ? column_head('comments', 'comments', 'list', true, $switch_dir, $crit, $search_method, ('comments' == $sort ? "{$dir} " : '') . 'txp-list-col-comments articles_detail') : '')) . n . tag_end('thead'); include_once txpath . '/publish/taghandlers.php'; echo n . tag_start('tbody'); $validator = new Validator(); while ($a = nextRow($rs)) { extract($a); if ($Title === '') { $Title = '<em>' . eLink('article', 'edit', 'ID', $ID, gTxt('untitled')) . '</em>'; } else { $Title = eLink('article', 'edit', 'ID', $ID, $Title); } // Valid section and categories? $validator->setConstraints(array(new SectionConstraint($Section))); $vs = $validator->validate() ? '' : ' error'; $validator->setConstraints(array(new CategoryConstraint($Category1, array('type' => 'article')))); $vc[1] = $validator->validate() ? '' : ' error'; $validator->setConstraints(array(new CategoryConstraint($Category2, array('type' => 'article')))); $vc[2] = $validator->validate() ? '' : ' error'; $Category1 = $Category1 ? span(txpspecialchars($category1_title), array('title' => $Category1)) : ''; $Category2 = $Category2 ? span(txpspecialchars($category2_title), array('title' => $Category2)) : ''; if ($Status != STATUS_LIVE and $Status != STATUS_STICKY) { $view_url = '?txpreview=' . intval($ID) . '.' . time(); } else { $view_url = permlinkurl($a); } if (isset($statuses[$Status])) { $Status = $statuses[$Status]; } $comments = '(' . $total_comments . ')'; if ($total_comments) { $comments = href($comments, array('event' => 'discuss', 'step' => 'list', 'search_method' => 'parent', 'crit' => $ID), array('title' => gTxt('manage'))); } $comment_status = $Annotate ? gTxt('on') : gTxt('off'); if ($comments_disabled_after) { $lifespan = $comments_disabled_after * 86400; $time_since = time() - $posted; if ($time_since > $lifespan) { $comment_status = gTxt('expired'); } } $comments = tag($comment_status, 'span', array('class' => 'comments-status')) . ' ' . tag($comments, 'span', array('class' => 'comments-manage')); echo tr(td(($a['Status'] >= STATUS_LIVE and has_privs('article.edit.published') or $a['Status'] >= STATUS_LIVE and $AuthorID === $txp_user and has_privs('article.edit.own.published') or $a['Status'] < STATUS_LIVE and has_privs('article.edit') or $a['Status'] < STATUS_LIVE and $AuthorID === $txp_user and has_privs('article.edit.own')) ? fInput('checkbox', 'selected[]', $ID, 'checkbox') : '', '', 'txp-list-col-multi-edit') . hCell(eLink('article', 'edit', 'ID', $ID, $ID) . tag(sp . tag('[', 'span', array('aria-hidden' => 'true')) . href(gTxt('view'), $view_url) . tag(']', 'span', array('aria-hidden' => 'true')), 'span', array('class' => 'articles_detail')), '', ' scope="row" class="txp-list-col-id"') . td($Title, '', 'txp-list-col-title') . td(gTime($posted), '', 'txp-list-col-created date' . ($posted < time() ? '' : ' unpublished')) . td(gTime($lastmod), '', 'txp-list-col-lastmod date articles_detail' . ($posted === $lastmod ? ' not-modified' : '')) . td($expires ? gTime($expires) : '', '', 'txp-list-col-expires date articles_detail') . td(span(txpspecialchars($section_title), array('title' => $Section)), '', 'txp-list-col-section' . $vs) . td($Category1, '', 'txp-list-col-category1 category articles_detail' . $vc[1]) . td($Category2, '', 'txp-list-col-category2 category articles_detail' . $vc[2]) . td(href($Status, $view_url, join_atts(array('title' => gTxt('view')))), '', 'txp-list-col-status') . ($show_authors ? td(span(txpspecialchars($RealName), array('title' => $AuthorID)), '', 'txp-list-col-author name') : '') . ($use_comments ? td($comments, '', 'txp-list-col-comments articles_detail') : '')); } echo n . tag_end('tbody') . n . tag_end('table') . n . tag_end('div') . list_multiedit_form($page, $sort, $dir, $crit, $search_method) . tInput() . n . tag_end('form') . graf(toggle_box('articles_detail'), array('class' => 'detail-toggle')) . n . tag_start('div', array('id' => $event . '_navigation', 'class' => 'txp-navigation')) . pageby_form('list', $article_list_pageby) . nav_form('list', $page, $numPages, $sort, $dir, $crit, $search_method, $total, $limit) . n . tag_end('div') . n . tag_end('div'); } }