if (@txpinterface == 'admin') { global $smd_featured_event; $smd_featured_event = 'smd_featured'; $smd_featured_privs = get_pref('smd_featured_privs', '1,2'); add_privs($smd_featured_event, $smd_featured_privs); register_tab("content", $smd_featured_event, smd_featured_gTxt('tab_name')); register_callback('smd_featured_manage', $smd_featured_event); register_callback('smd_featured_welcome', 'plugin_lifecycle.smd_featured'); } if (!defined('SMD_FEAT')) { define("SMD_FEAT", 'smd_featured'); } // ********** // ADMIN SIDE // ********** // ------------------------ function smd_featured_manage($evt, $stp) { if ($stp == 'save_pane_state') { smd_featured_save_pane_state(); } else { if(!$stp or !in_array($stp, array( 'smd_featured_table_install', 'smd_featured_table_remove', 'smd_featured_save', 'smd_featured_tagit', ))) { smd_featured_list(''); } else $stp(); } } // ------------------------ function smd_featured_welcome($evt, $stp) { $msg = ''; switch ($stp) { case 'installed': smd_featured_table_install(0); $msg = 'Thanks for installing smd_featured. Please read the docs :-)'; break; case 'deleted': smd_featured_table_remove(0); break; } return $msg; } // ------------------------ function smd_featured_list($msg='') { global $smd_featured_event; pagetop(smd_featured_gTxt('tab_name'), $msg); extract(gpsa(array('smd_feat_id', 'smd_feat_label', 'smd_feat_searchkeep', 'smd_feat_filtkeep'))); if (smd_featured_table_exist()) { $featlist = safe_rows('*', SMD_FEAT, '1=1'); $featlist = empty($featlist) ? array() : $featlist; $editname = $feat_label = $feat_desc = ''; $ftypes = $flist = array(); $ftypes['smd_unlabelled'] = smd_featured_gTxt('unlabelled'); foreach ($featlist as $item) { if (isset($item['label']) && !empty($item['label'])) { $ftypes[$item['label']] = $item['label']; } $flist[$item['id']] = array('label' => $item['label'], 'description' => $item['description'], 'desc_html' => $item['desc_html']); } $featlist = $flist; // Get additional filtering from hidden prefs $where = array('1=1'); $seclist = get_pref('smd_featured_section_list', ''); if ($seclist) { $where[] = "Section IN ('".join("','", do_list($seclist))."')"; } $where[] = "Status IN (4,5)"; $orderby = get_pref('smd_featured_sort', 'Posted desc'); $rs = safe_rows('*', 'textpattern', join(' AND ', $where). ' ORDER BY '.$orderby); foreach ($rs as $row) { $ftype = isset($featlist[$row['ID']]['label']) ? $featlist[$row['ID']]['label'] : ''; $out[] = array($row['ID'], $row['Title'], $ftype); if ($smd_feat_id && $row['ID'] == $smd_feat_id) { $editname = $row['Title']; $feat_label = $featlist[$smd_feat_id]['label']; $feat_desc = doStrip(str_replace('\r\n',' ', $featlist[$smd_feat_id]['description'])); } } echo ''; echo '
'; echo hInput('smd_feat_searchkeep', ''). hInput('smd_feat_filtkeep', ''). hInput('smd_feat_id', ''). eInput($smd_featured_event). sInput('smd_featured_list'); echo '
'; echo '
'; echo startTable('control','','','3'); if ($smd_feat_id) { echo tr( td(' ').tdcs(gTxt('edit').sp.strong($editname), 2) ); echo tr( fLabelCell(gTxt('label'), '', 'smd_feat_label'). td(fInput('text', 'smd_feat_label', $feat_label, '', '', '', '', '', 'smd_feat_label')) ); echo tr( fLabelCell(gTxt('description'), '', 'smd_feat_desc'). td(text_area('smd_feat_desc', 80, 400, $feat_desc, 'smd_feat_desc')). td(fInput('submit', '', gTxt('save'), 'smallerbox')). hInput('smd_feat_searchkeep', ''). hInput('smd_feat_filtkeep', ''). hInput('smd_feat_id', $smd_feat_id). eInput($smd_featured_event). sInput('smd_featured_save') ); } echo endTable(); echo '
'; $edbtn = small('['.gTxt('edit').']'); if ($out) { $sizes = do_list(get_pref('smd_featured_box_size', '150x40'), 'x'); $sizes[0] = (isset($sizes[0]) && is_numeric($sizes[0])) ? $sizes[0] : '150'; $sizes[1] = (isset($sizes[1]) && is_numeric($sizes[1])) ? $sizes[1] : '40'; $rows = count($rs); $tblout = array(); $atts = ' class="smd_featured_table smd_clear" id="list" align="center"'; $tblout[] = hed(smd_featured_gTxt('manage_lbl', array(), 'raw'), 3, ' class="smd_clear"'); for ($idx = 0; $idx < $rows; $idx++) { $isfeat = (isset($out[$idx]) && array_key_exists($out[$idx][0], $featlist)); $cellclass = $isfeat ? ' class="smd_featured"' : ''; $edlink = $isfeat ? ''.$edbtn.''.sp : ''; $rowdata = (isset($out[$idx])) ? ''.$out[$idx][1].'' : ''; $rowdata .= $isfeat ? ''.$out[$idx][2].'' : ''; $tblout[] = (isset($out[$idx])) ? ''.$edlink.''.$out[$idx][1].''.$rowdata.'' : '
'; } echo tag(join("",$tblout), 'div', $atts); echo '
'; } $qs = array( "event" => $smd_featured_event, ); $qsVars = "index.php".join_qs($qs); $verifyTxt = smd_featured_gTxt('unfeature_confirm'); echo << function smd_featured_select(obj, id) { obj = jQuery(obj).parent(); // N.B. Negative logic used here because we're checking the class _before_ it's been toggled var action = ((obj).hasClass("smd_featured")) ? 'remove' : 'add'; if (action == 'remove') { var ret = confirm('{$verifyTxt}'); if (ret == false) { return false; } } jQuery.post('{$qsVars}', { step: "smd_featured_tagit", smd_feat_id: id, smd_feat_action: action }, function(data) { obj.toggleClass('smd_featured'); if (action == 'add') { obj.prepend('{$edbtn} '); obj.append(''); } else { obj.find('a.edlink').remove(); obj.find('span.extra').remove(); if (jQuery("#smd_feat_search").val() != '') jQuery("#smd_feat_search").keyup(); if (jQuery("#smd_feat_filt").val() != '') jQuery("#smd_feat_filt").change(); } } ); return false; } function smd_featured_editkeep(id) { jQuery("#smd_feat_editform [name='smd_feat_searchkeep']").val(jQuery("#smd_feat_search").val()); jQuery("#smd_feat_editform [name='smd_feat_filtkeep']").val(jQuery("#smd_featured_bylabel #smd_feat_filt option:selected").val()); jQuery("#smd_feat_editform [name='smd_feat_id']").val(id); jQuery("#smd_feat_editform").submit(); } function smd_featured_savekeep() { jQuery("#smd_feat_saveform [name='smd_feat_searchkeep']").val(jQuery("#smd_feat_search").val()); jQuery("#smd_feat_saveform [name='smd_feat_filtkeep']").val(jQuery("#smd_featured_bylabel #smd_feat_filt option:selected").val()); } function smd_feat_filter(selector, query, nam, csense) { var query = jQuery.trim(query); csense = (csense) ? "" : "i"; query = query.replace(/ /gi, '|'); // add OR for regex query var re = new RegExp(query, csense); jQuery(selector).each(function() { sel = (typeof nam=="undefined" || nam=='') ? jQuery(this) : jQuery(this).find("span[name='"+nam+"']"); if (query == '') { if (sel.length == 1 && sel.text() == '') { jQuery(this).show(); } else { jQuery(this).hide(); } } else { if (sel.text().search(re) < 0) { jQuery(this).hide(); } else { jQuery(this).show(); } } }); } jQuery(function() { jQuery("#smd_feat_search").keyup(function(event) { jQuery("#smd_feat_filt").val('0'); // Clear the filter dropdown // if esc is pressed or nothing is entered if (event.keyCode == 27 || jQuery(this).val() == '') { jQuery(this).val(''); jQuery(".smd_featured_table div:not(.tblhead)").show(); } else { smd_feat_filter('.smd_featured_table div:not(.tblhead)', jQuery(this).val(), 'smd_feat_name', 0); } }); if ('{$smd_feat_searchkeep}' != '') { jQuery("#smd_feat_search").keyup(); } jQuery("#smd_feat_filt").change(function(event) { jQuery("#smd_feat_search").val(''); // Empty the search box if (jQuery(this).val() == '') { jQuery('.smd_featured_table div:not(.tblhead)').show(); } else if (jQuery(this).val() == 'smd_unlabelled') { smd_feat_filter('.smd_featured_table div:not(.tblhead)', '', 'smd_feat_label', 0); } else { smd_feat_filter('.smd_featured_table div:not(.tblhead)', jQuery(this).val(), 'smd_feat_label', 1); } }); if ('{$smd_feat_filtkeep}' != '') { jQuery("#smd_feat_filt").change(); } if ('{$smd_feat_id}' != '') { jQuery("#smd_feat_label").focus(); } }); EOS; } else { // Table not installed $btnInstall = '
'.fInput('submit', 'submit', smd_featured_gTxt('tbl_install_lbl'), 'smallerbox').'
'; $btnStyle = ' style="border:0;height:25px"'; echo startTable('list'); echo tr(tda($btnInstall, $btnStyle)); echo endTable(); } } // ------------------------ // Update the passed record in the featured table function smd_featured_save() { global $smd_featured_event; extract(gpsa(array('smd_feat_id', 'smd_feat_label', 'smd_feat_desc'))); assert_int($smd_feat_id); $smd_feat_desctile = $smd_feat_desc; $smd_feat_label = doSlash($smd_feat_label); if (smd_featured_table_exist()) { @include_once txpath.'/lib/classTextile.php'; @include_once txpath.'/publish.php'; if (class_exists('Textile')) { $textile = new Textile(); $smd_feat_desctile = doSlash($textile->TextileThis(parse($smd_feat_desc))); } $smd_feat_desc = doSlash($smd_feat_desc); $ret = safe_upsert(SMD_FEAT, "label='$smd_feat_label', description='$smd_feat_desc', desc_html='$smd_feat_desctile'", "id='$smd_feat_id'"); unset($_POST['smd_feat_id']); } smd_featured_list(smd_featured_gTxt('saved')); } // ------------------------ // Create an empty entry in the featured table or destroy it function smd_featured_tagit() { global $smd_featured_event; extract(doSlash(gpsa(array('smd_feat_id', 'smd_feat_action')))); assert_int($smd_feat_id); if ($smd_feat_action == 'add') { $ret = safe_upsert(SMD_FEAT, "label=''", "id='$smd_feat_id'"); } else if ($smd_feat_action == 'remove') { $ret = safe_delete(SMD_FEAT, "id='$smd_feat_id'"); } } // ------------------------------------------------------------- function smd_featured_save_pane_state() { $panes = array('smd_featured_filters'); $pane = gps('pane'); if (in_array($pane, $panes)) { set_pref("pane_{$pane}_visible", (gps('visible') == 'true' ? '1' : '0'), 'smd_featured', PREF_HIDDEN, 'yesnoradio', 0, PREF_PRIVATE); send_xml_response(); } else { send_xml_response(array('http-status' => '400 Bad Request')); } } // ------------------------ // Add featured table if not already installed function smd_featured_table_install($showpane='1') { $GLOBALS['txp_err_count'] = 0; $ret = ''; $sql = array(); $sql[] = "CREATE TABLE IF NOT EXISTS `".PFX.SMD_FEAT."` ( `id` int(8) NOT NULL, `label` varchar(32) NULL default '', `description` text NULL default '', `desc_html` text NULL default '', PRIMARY KEY (`id`) ) ENGINE=MyISAM"; if(gps('debug')) { dmp($sql); } foreach ($sql as $qry) { $ret = safe_query($qry); if ($ret===false) { $GLOBALS['txp_err_count']++; echo "".$GLOBALS['txp_err_count'].". ".mysql_error()."
\n"; echo "\n"; } } if ($GLOBALS['txp_err_count'] == 0) { $message = smd_featured_gTxt('tbl_installed'); } else { if ($showpane) { $message = smd_featured_gTxt('tbl_not_installed'); smd_featured_list($message); } } } // ------------------------ // Drop table if in database function smd_featured_table_remove() { $ret = ''; $sql = array(); $GLOBALS['txp_err_count'] = 0; if (smd_featured_table_exist()) { $sql[] = "DROP TABLE IF EXISTS " .PFX.SMD_FEAT. "; "; if(gps('debug')) { dmp($sql); } foreach ($sql as $qry) { $ret = safe_query($qry); if ($ret===false) { $GLOBALS['txp_err_count']++; echo "".$GLOBALS['txp_err_count'].". ".mysql_error()."
\n"; echo "\n"; } } } if ($GLOBALS['txp_err_count'] == 0) { $message = smd_featured_gTxt('tbl_removed'); } else { $message = smd_featured_gTxt('tbl_not_removed'); smd_featured_list($message); } } // ------------------------ function smd_featured_table_exist($all='') { if ($all) { $tbls = array(SMD_FEAT => 4); $out = count($tbls); foreach ($tbls as $tbl => $cols) { if (gps('debug')) { echo "++ TABLE ".$tbl." HAS ".count(@safe_show('columns', $tbl))." COLUMNS; REQUIRES ".$cols." ++".br; } if (count(@safe_show('columns', $tbl)) == $cols) { $out--; } } return ($out===0) ? 1 : 0; } else { if (gps('debug')) { echo "++ TABLE ".SMD_FEAT." HAS ".count(@safe_show('columns', SMD_FEAT))." COLUMNS;"; } return(@safe_show('columns', SMD_FEAT)); } } // **************** // PUBLIC SIDE TAGS // **************** // ------------------------ function smd_featured($atts, $thing) { global $smd_featured_info, $smd_prior_featured, $prefs; extract(lAtts(array( 'label' => '', 'unlabel' => 'Featured', 'labeltag' => '', 'time' => 'past', 'status' => '4,5', 'section' => '', 'limit' => '', 'sort' => '', 'form' => '', 'wraptag' => '', 'break' => '', 'class' => '', 'html_id' => '', ),$atts)); if (isset($atts['label'])) { if ($label) { $where = "BINARY label REGEXP '".$atts['label']."'"; } else { $where = "label=''"; } unset($atts['label']); } else { $where = "1=1"; } // Exclude previously seen articles if (!empty($smd_prior_featured)) { $where .= ' AND smdfeat.id NOT IN(' . join(',', $smd_prior_featured) . ')'; } if ($time) { switch ($time) { case 'any': break; case 'future': $where .= " AND Posted > now()"; break; default: $where .= " AND Posted <= now()"; } if (!$prefs['publish_expired_articles']) { $where .= " AND (now() <= Expires OR Expires = ".NULLDATETIME.")"; } unset($atts['time']); } if ($status) { $where .= ' AND Status in ('.join(',', do_list($status)).')'; unset($atts['status']); } if ($section) { $where .= " AND Section in ('".join("','", do_list($section))."')"; unset($atts['section']); } if ($sort) { $where .=' ORDER BY '.$sort; unset($atts['sort']); } if ($limit) { $where .=' LIMIT '.$limit; unset($atts['limit']); } // Don't pass the remaining attributes we've already handled onto the article tag unset( $atts['label'], $atts['unlabel'], $atts['labeltag'], $atts['wraptag'], $atts['break'], $atts['class'], $atts['html_id'] ); $rs = getRows('SELECT *, unix_timestamp(Posted) as uPosted, unix_timestamp(Expires) as uExpires, unix_timestamp(LastMod) as uLastMod FROM '.PFX.'textpattern AS txp LEFT JOIN '.PFX.'smd_featured AS smdfeat ON txp.ID=smdfeat.id WHERE '.$where); $out = array(); if ($rs) { foreach ($rs as $row) { $smd_featured_info['label'] = $row['label']; $smd_featured_info['description'] = $row['desc_html']; $atts['id'] = $row['ID']; $artout = article($atts, $thing); if ($artout) { $smd_prior_featured[] = $row['ID']; $out[] = $artout; } } } if ($out) { return (($labeltag) ? doLabel( ( ($label == '') ? $unlabel : $label), $labeltag ) : '') .doWrap($out, $wraptag, $break, $class, '', '', '', $html_id); } return ''; } // ------------------------ function smd_unfeatured($atts, $thing) { global $smd_prior_featured; $where = "1=1"; // Exclude previously seen articles if (!empty($smd_prior_featured)) { $where .= ' AND id NOT IN(' . join(',', $smd_prior_featured) . ')'; } $rs = safe_column('ID', 'textpattern', $where); $atts['id'] = join(',', $rs); $out = article($atts, $thing); return $out; } // ------------------------ function smd_featured_info($atts) { global $smd_featured_info; extract(lAtts(array( 'item' => '', ),$atts)); return (isset($smd_featured_info[$item]) ? $smd_featured_info[$item] : ''); } // ------------------------ // Plugin-specific replacement strings - localise as required // TODO: make these into a textpack when plugin composer supports them function smd_featured_gTxt($what, $atts = array()) { $lang = array( 'by_label' => 'By label: ', 'by_name' => 'By name: ', 'live_search' => 'Article live search', 'manage_lbl' => 'Click to select featured articles, which will be shown highlighted.', 'saved' => 'Article info updated', 'tab_name' => 'Featured articles', 'tbl_install_lbl' => 'Install table', 'tbl_installed' => 'Table installed', 'tbl_not_installed' => 'Table not installed', 'tbl_removed' => 'Table removed', 'tbl_not_removed' => 'Table not removed', 'unfeature_confirm' => 'Sure to unfeature this article?', 'unlabelled' => '[unlabelled]', ); return strtr($lang[$what], $atts); }