ignatia has proposed merging lp:~gregfr/phpdevshell/TablesAndFilters-v1.0.0-trunk into lp:phpdevshell.
Requested reviews: TitanKing (titan-phpdevshell) For more details, see: https://code.launchpad.net/~gregfr/phpdevshell/TablesAndFilters-v1.0.0-trunk/+merge/163637 -- https://code.launchpad.net/~gregfr/phpdevshell/TablesAndFilters-v1.0.0-trunk/+merge/163637 Your team PHPDevShell is subscribed to branch lp:~gregfr/phpdevshell/TablesAndFilters-v1.0.0-trunk.
=== added directory 'TablesAndFilters' === added directory 'TablesAndFilters/config' === added file 'TablesAndFilters/config/plugin.config.xml' --- TablesAndFilters/config/plugin.config.xml 1970-01-01 00:00:00 +0000 +++ TablesAndFilters/config/plugin.config.xml 2013-05-14 05:06:25 +0000 @@ -0,0 +1,116 @@ +<?xml version="1.0" encoding="UTF-8" standalone="yes" ?> +<!-- Please see http://phpdevshell.org for documentation on plugin config xml files. --> +<config type="plugin"> + + <!-- Use a proper plugin name without using special characters. --> + <name>TablesAndFilters</name> + + <!-- Human readable version number of your plugin. --> + <version>3.0</version> + + <!-- a Short description of your plugin. --> + <description>This plugin provides easy to use tables based on query results.</description> + + <!-- If the plugin/script is modification by you, place the original authors names here. --> + <founder>Greg Reitter</founder> + + <!-- Name of the developer for this plugin. --> + <author>Greg Reitter</author> + + <!-- Email address of the developer for this plugin. --> + <email>[email protected]</email> + + <!-- Plugin developers web address. --> + <homepage>http://www.phpdevshell.org</homepage> + + <!-- Date the plugin was developed, modified etc, this is up to you. --> + <date>July 2010</date> + + <!-- Copyright notice you would like to amend to your plugin. --> + <copyright>Copyright 2010 PHPDevShell.org All rights reserved.</copyright> + + <!-- License this plugin is released under. --> + <license>http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html GNU/LGPL</license> + <!-- Code Version XML URL check. --> + <!-- Version (current) below is used to check for new releases and has little to do with database version. --> + <versionurl current="3000">http://version.phpdevshell.org/TablesAndFilters.xml</versionurl> + + <!-- Detailed information and help for this plugin. --> + <info> + <![CDATA[ + <p> + This plugin provides easy to use tables based on query results. + </p> + ]]> + </info> + <!-- Version here represents the database version that should be install. --> + <!-- If your database version needs no update, this number can stay the same. --> + <!-- Upgrades further down will only be executed up to this number. --> + <!-- This is the current database version that will be installed. --> + <!-- Below is a series of example upgrade procedures. --> + <install version="3000"> + <!-- + [contains][All query, menu, hooks, settings installation tags.] + [param][version][int][mandatory][The latest database version in numbers only.] + [note][This is how the plugin manager will know to what version upgrade scripts should be executed.] + [note][Always keep install maintained to the latest menu, query, hooks and setting versions.] + --> + <menus> + <!-- + [contains][All types of menu items that needs to be installed.] + [note][Tags inside menus can be nested and repeated.] + --> + <menu name="testTable" type="1" link="scripts/tableTest.php" hide="0" rank="last" newwindow="" plugin="TablesAndFilters" > + <!-- + [contains][Menu items can be contained in itself, this will create a menu tree.] + [param][name][string][not-mandatory][The name of the menu item, if empty the pluginName.menu.lang.php will be used.] + [param][type][int][not-mandatory][There are 8 menu types, 1 is the default if left empty.] + [1][Plugin script] normal plugin menu item in your plugin folder. + [2][Link existing menu] item while staying in its own menu group when clicked. + [3][Link existing menu] item while jumping to original scripts menu group when clicked. + [4][External file] Include external PHP web applications into PHPDevShell. + [5][HTTP URL] Normal url to outside web. + [6][Empty Place Holder] This item will only serve as a unclickable menu place holder. + [7][iFrame] Link url to both external url or onsite url. + [8][Cronjob Menu Type] The same as a plugin script but is set as cronjob. + [param][link][string][mandatory][The url, script location or symlink holder will be entered here depending on type.] + [param][hide][int][not-mandatory][There are 4 hide types, 0 is the default if left empty.] + [0] Do not hide menu item. + [1] Hide menu item from both Menu System and Control Panel. + [2] Hide menu item from Control Panel only. + [3] Hide menu item from Menu System only. + [4] Hide menu only when inactive. + [param][rank][string][not-mandatory][If you want to ensure ranking positions, will auto rank if left empty.] + [int] Can be ranked with integer. + [last] Will be ranked last in a menu group. + [first] Will be ranked first in a menu group. + [param][newwindow][int][not-mandatory][To make item open in new window set to 1, will not open in new if left empty.] + [param][plugin][string][not-mandatory][Plugin name, use to install menu item to a different plugins menu structure.] + [param][alias][string][not-mandatory][When switching on friendly urls in the settings and renaming rename.htaccess in the root, sef url will use this alias.] + [param][parentlink][string][not-mandatory][Use with [param][plugin] or without to install in different structure.] + [param][symlink][string][not-mandatory][Url or location with [param][plugin] or without to link to another menu item duplicating its use.] + [note][Symlink is mandatory for menu types 1,2,6] + [param][template][string][not-mandatory][Set template to use with plugin, if template is unavailable it will be installed.] + [param][template][string][not-mandatory][Set the height of an iframe menu type.] + [note][Height is mandatory for menu types 7] + [param][layout][string][not-mandatory][Set a custom template.tpl location for a certain script.] + [param][noautopermission][int][not-mandatory][Set to 1 to not add the installer of the plugin to permit menu item access.] + --> + </menu> + </menus> + <classes> + <class name="TaF_table" alias="TaF_table" plugin="TablesAndFilters" rank="last" /> + <class name="TaF_html_table@TaF_table" alias="TaF_table" plugin="TablesAndFilters" rank="last" /> + + <class name="TaF_filteredQuery" alias="TaF_filteredQuery" plugin="TablesAndFilters" rank="last" /> + <class name="TaF_html_filteredQuery@TaF_filteredQuery" alias="TaF_html_filteredQuery" plugin="TablesAndFilters" rank="last" /> + <class name="TaF_html_filteredTable@TaF_filteredQuery" alias="TaF_html_filteredTable" plugin="TablesAndFilters" rank="last" /> + <class name="TaF_html_queryFilter@TaF_filteredQuery" alias="TaF_html_filteredTable" plugin="TablesAndFilters" rank="last" /> + <class name="TaF_list_queryFilter@TaF_filteredQuery" alias="TaF_html_filteredTable" plugin="TablesAndFilters" rank="last" /> + <class name="TaF_queryFilter@TaF_filteredQuery" alias="TaF_html_filteredTable" plugin="TablesAndFilters" rank="last" /> + <class name="TaF_radio_queryFilter@TaF_filteredQuery" alias="TaF_html_filteredTable" plugin="TablesAndFilters" rank="last" /> + <class name="TaF_select_queryFilter@TaF_filteredQuery" alias="TaF_html_filteredTable" plugin="TablesAndFilters" rank="last" /> + + </classes> + </install> +</config> === added directory 'TablesAndFilters/controllers' === added file 'TablesAndFilters/controllers/index.php' --- TablesAndFilters/controllers/index.php 1970-01-01 00:00:00 +0000 +++ TablesAndFilters/controllers/index.php 2013-05-14 05:06:25 +0000 @@ -0,0 +1,16 @@ +<?php +/** + * PHPDevShell is a RAD Framework aimed at developing administrative applications. + * + * @package PHPDevShell + * @link http://www.phpdevshell.org + * @copyright Copyright (C) 2007 Jason Schoeman, All rights reserved. + * @license GNU/LGPL, see readme/licensed_under_lgpl or http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html + * @author Jason Schoeman, Contact: titan [at] phpdevshell [dot] org. + * + * Copyright notice: See readme/notice + * By using PHPDevShell you agree to notice and license, if you dont agree to this notice/license you are not allowed to use PHPDevShell. + */ +// Directory listing not allowed. +exit('Access Denied!'); +?> \ No newline at end of file === added directory 'TablesAndFilters/includes' === added file 'TablesAndFilters/includes/TaF_excerpt.class.php' --- TablesAndFilters/includes/TaF_excerpt.class.php 1970-01-01 00:00:00 +0000 +++ TablesAndFilters/includes/TaF_excerpt.class.php 2013-05-14 05:06:25 +0000 @@ -0,0 +1,32 @@ +<?php + + + + class TaF_excerpt extends PHPDS_dependant + { + protected $data = array(); + protected $strip = true; + + + public function addArray(array $query_result) + { + //$strip = empty($options['strip']) ? $this->strip : true; + foreach($query_result as $key => $value) { + $this->data[$key] = $this->strip ? true : $value; + } + } + + public function addResult($query_name) + { + $params = func_get_args(); + array_shift($params); // first parameter of this function is $query_name + $query = $this->db->makeQuery($query_name); + $result = $query->invoke($params); + if (is_array($result)) return $this->addArray($result); else return false; + } + + public function dump() + { + print_r($this->data); + } + } \ No newline at end of file === added file 'TablesAndFilters/includes/TaF_filteredQuery.class.php' --- TablesAndFilters/includes/TaF_filteredQuery.class.php 1970-01-01 00:00:00 +0000 +++ TablesAndFilters/includes/TaF_filteredQuery.class.php 2013-05-14 05:06:25 +0000 @@ -0,0 +1,398 @@ +<?php + + + + /** + * FILTERED QUERIES AND TABLE - EXPERIMENTAL + * + * The basic idea is to take the winning couple PHPDS_query + PHPDS_table and add multilayers of user-provided constraints (ie filters) to it + * + * @author greg completly stolen ideas from Jason + * + */ + + class TaF_queryFilter extends PHPDS_dependant + { + protected $table; // TaF_html_filteredTable + protected $sql = ''; // a snipet in include into the WHERE clause + + protected $field = ''; // filters are usualy (but not always) in the form: "field operator value" (ie. "age > 18") + protected $value = ''; + protected $operator = '='; + + public function __construct(TaF_html_filteredTable $table, TaF_filteredQuery $dependance) + { + parent::__construct($dependance); // our dependancy is the query + $this->table = $table; + + $this->init(); + } + + /** + * Give the filter a chance to alter the given query to do its job + * + * @param PHPDS_query $query + * @param unknown_type $mode + * @return unknown_type + */ + public function alterQuery(PHPDS_query $query, $mode) + { + $sql = $this->sql(); + if ($sql) $query->addWhere($this->sql, $mode); + return true; + } + + /** + * return a piece of sql to be added to the WHERE clause + * + * @param unknown_type $sql + * @return unknown_type + */ + public function sql($sql = null) + { + if (!empty($sql)) $this->sql = $sql; + if (empty($this->sql) && !empty($this->field) && !empty($this->value)) $this->sql = $this->field.' '.$this->operator.' '.$this->value; + return $this->sql; + } + + public function init() + { + return true; + } + } + + + + /** + * Add an html presentation layer to a filter + * + * @author greg + * + */ + class TaF_html_queryFilter extends TaF_queryFilter + { + protected $id = ''; + protected $label = ''; + + public function __construct(TaF_html_filteredTable $table, TaF_filteredQuery $dependance) + { + if (empty($this->id)) $this->id = $table->id().'_'.get_class($this); + parent::__construct($table, $dependance); + } + + public function label($label = null) + { + if (!empty($label)) $this->label = $label; + return $this->label; + } + + public function id() + { + return $this->id; + } + + /** + * This should ouput some html to be added before the table + * + * @return unknown_type + */ + public function toHTML() + { + return '<p>'.$this->sql.'</p>'; + } + + /** + * Support for dynamic reload: bind the javascript function in a way you want it to be called for reloading the table + * + * @return javascript code to add inside a <script> clause + */ + public function toJSbind() + { + return ''; + } + + /** + * + * This should return a pair key=value to add to the request to ensure the filtering + * + * @return string in the form " key=value " suitable for html request (such as GET or POST) + */ + public function toJSdata() + { + return ''; + } + } + + + + + + /** + * A filter based on a list of key=>value pairs, possibly from a secondary query + * + * @author greg + * + */ + class TaF_list_queryFilter extends TaF_html_queryFilter + { + protected $list = array(); + protected $listQuery; + + public function init () + { + if (!empty($this->listQuery)) { + $dep = array_pop(func_get_args()); + + $this->list = $this->buildList(); + } + + //if ($this->select($this->select) != $this->select) + $select = isset($_POST[$this->id()]) ? $_POST[$this->id()] : $this->defValue(); + // $this->select(VeM_GetFromRequest($this->id, $this->defValue())); + $this->value($select); + //TODO: get parameter is a nicer way + } + + public function buildList() + { + return is_a($this->listQuery, PHPDS_query) ? $dep->db->invokeQuery($this->listQuery): array(); + } + + public function value($value = null) + { + if (!is_null($value)) { + if (is_array($this->list) && isset($this->list[$value])) $this->value = $value; + } + return $this->value; + } + + public function defValue() + { + if (!empty($this->value)) return $this->value; + + $a = array_keys($this->list); + $b = array_shift(array_keys($this->list)); + if (is_array($this->list)) return array_shift(array_keys($this->list)); + } + } + + + + /** + * + * @author greg + * + */ + class TaF_select_queryFilter extends TaF_list_queryFilter + { + public function toHTML() + { + $fct_name = $this->table->makeName('js_reload'); + $html = "<label for=\"{$this->id}\">".$this->label()."</label>"; + $html .= "<select id=\"{$this->id}\" name=\"{$this->id}\" onChange=\"$fct_name()\" >"; + foreach($this->list as $key => $value) $html .= "<option value=\"$key\"".($this->value == $key ? 'selected' : '').">$value</option>"; + $html .= '</select>'; + + return $html; + } + + /*public function toJSbind() + { + $js = "$('#{$this->id}').change(function() { alert('toto'); $fct_name });"; + return $js; + }*/ + + /*public function toJSdata() + { + return "'&{$this->id}=' + $('#{$this->id}').val()"; + }*/ + + } + + + + + + + + class TaF_radio_queryFilter extends TaF_list_queryFilter + + { + protected $classes = array('line' => 'filterline', 'input' => 'filterinput'); + + public function toHTML() + { + $html = '<div class="'.$this->classes['line'].'">'; + $html .= '<label>'.$this->label().'</label>'; + foreach($this->list as $key => $value) { + $name = $this->id; + $id = $name.'_'.$value; + $html .= "<input type=\"radio\" id=\"$id\" name=\"$name\" class=\"{$this->classes['input']}\" value=\"$key\" "; + if ($key == $this->value) $html .= 'checked '; + $html .= "/><label for=\"$id\">$value</label>"; + } + $html .= '</div>'; + return $html; + } + + public function toJSbind($fct_name = '') + { + return "$('input[name={$this->id}]').click(function() { $fct_name; });"; + } + + public function toJSdata() + { + return "'&{$this->id}=' + $('input:radio[name={$this->id}]:checked').val()"; + } + } + + + + + + + + class TaF_filteredQuery extends PHPDS_query + { + + protected $filters = array(); + protected $mode = 'AND'; + + /* + * filter can be a TaF_queryFilter object or a TaF_queryFilter-descendant class name + */ + public function addFilter($filter, TaF_html_filteredTable $table) + { + if (is_a($filter, 'TaF_queryFilter')) $this->filters[] = $filter; + else { + $params = func_get_args(); + array_shift($params); // shift-off $filter class name + $this->filters[] = $this->_factory($filter, $params); + } + return $this; + } + + /** + * Construct the extra part of the query (WHERE ... GROUP BY ... ORDER BY...) + * Doesn't change $this->sql but DOES alter the query (our local clone) + * + * @param array $parameters + * @return string (sql) + */ + public function extra_build($parameters = null) + { + foreach ($this->filters as $filter) $filter->alterQuery($this, $this->mode); + + return parent::extra_build($parameters); + } + } + + + + + + + + class TaF_html_filteredQuery extends TaF_filteredQuery + { + public function filtersAsHTML() + { + $html = ''; + foreach($this->filters as $filter) $html .= $filter->toHTML(); + return $html; + } + + public function filtersAsJSbind() + { + $js = ''; + foreach($this->filters as $filter) $js .= $filter->toJSbind()."\n"; + return $js; + } + + public function filtersAsJSdata() + { + $js = array(); + foreach($this->filters as $filter) $js[] = $filter->toJSdata(); + return implode(' + ', $js); + } + + } + + + + + + + + + + + + + class TaF_html_filteredTable extends TaF_html_table + { + /* + * filter can be a TaF_queryFilter object or a TaF_queryFilter-descendant class name + */ + public function addFilter($filter) + { + if (is_a($this->query, 'TaF_html_filteredQuery')) $this->query->addFilter($filter, $this); + } + + public function makeName($action) + { + switch ($action) { + case 'js_reload': return 'TaFReload_'.$this->id; + } + } + + public function make_html($forceLoad = false) + { + // first fetch the data + $data_html = parent::make_html($forceLoad); + + // then add some headers + $html = $this->make_tag('div', $this->id.'_container', array('class' => 'slidingTable')); + $url = PU_BuildURL(); + $html .= $this->make_tag('form', $this->id.'_form', array('action' => $url)); + if (is_a($this->query, 'TaF_html_filteredQuery')) $html .= $this->filtersAsHTML($this); // this is actually calling the query's method "filtersAsHTML()", at least if it's not overriden by the table + $html .= $data_html; + + //and some footers + $html .= $this->make_tag(); // _form + $html .= $this->make_tag(); // _container + if (is_a($this->query, 'TaF_html_filteredQuery')) $html .= $this->make_js($this); + + return $html; + } + + public function make_js() + { + $fct_name = $this->makeName('js_reload'); + + if ($js_filters = $this->query->filtersASJSdata()) $js_filters .= ' + '.$js_filters; + + $js = '<script type="text/javascript" language="javascript">'; + $js .= "\n//<![CDATA[\n"; + $js .= <<<EndOfJavascript + + + function $fct_name(opt) + { + url = $('#{$this->id}_form').attr('action'); + params = $('#{$this->id}_form').serializeArray(); // so it's sent as POST + if (opt) params[params.length] = opt; + $('#{$this->id}_container').load(url + ' #{$this->id}_form', params); + } + + +EndOfJavascript; + + $js .= $this->query->filtersAsJSbind($fct_name); + + $js .= "\n//]]>\n</script>"; + + return $js; + } + } + === added file 'TablesAndFilters/includes/TaF_table.class.php' --- TablesAndFilters/includes/TaF_table.class.php 1970-01-01 00:00:00 +0000 +++ TablesAndFilters/includes/TaF_table.class.php 2013-05-14 05:06:25 +0000 @@ -0,0 +1,302 @@ +<?php + + + +/** + * Basic class to link a table (i.e. tabular data) to a query result + * + * Usage 1 (implict instanciation of the class given its name): + * $params = array( + * 'query' => 'my_query_class', + * 'showHeaders' => true, + * 'headers' => array('ref' => 'Reference', 'name' => 'User name') + * ); + * $t = $this->factory('TaF_table', $params); + * + * Usage 2 (you already have instanciated the class, you pass the object): + * $query = $this->db->makeQuery('my_query_class', $query_parameters); + * $params = array( + * 'query' => 'my_query_class', + * 'showHeaders' => true, + * 'headers' => array('ref' => 'Reference', 'name' => 'User name') + * ); + * $t = $this->factory($query, $params); + * + * Note: all unknown method class are routed to the query so you can actually do something like: $t->sql('SELECT * FROM mytable'); + * + * @author greg + * + */ +class TaF_table extends PHPDS_dependant +{ + /** + * These are the parameters used to customize the table: + * - query (optional): name of the query to instanciate or query object to use; if blank a useless empty PHPDS_query is created + * - query_parameters (optional): parameters to pass on to the query when it's actually invokated + * @var unknown_type + */ + protected $parameters; // array + + protected $parent = 'query'; + protected $query; // PHPDS_query + protected $data; // array + + protected $request; + + protected $headers; + protected $classes; + + protected static $defaults = array('showHeaders' => false); + + + public function construct ($parameters = null) + { + $this->parameters = is_array($parameters) ? array_merge(self::$defaults, $parameters) : self::$defaults; + + $query = empty($this->parameters['query']) ? 'PHPDS_query' : $this->parameters['query']; + $this->query = (is_a($query, 'PHPDS_query')) ? clone $query : $this->db->makeQuery($query); + // TODO: is "clone" enough??? + + if (!empty($this->parameters->sql)) $this->query->sql($this->parameters->sql); + } + + + /** + * Use the query to load all data into memory + * + * Unless forced, if the data is already in memory, do nothing + * + * @version 1.1 + * @date 20100528 (greg) (v1.1) use the query parameters taken from the table parameters array, if any + * + * @param boolean $force + * @return array the data + */ + public function load($force = false) + { + if (empty($this->data) || $force) { + $this->data = empty($this->parameters['query_parameters']) ? $this->query->invoke() : $this->query->invoke($this->parameters['query_parameters']); + + $this->purge(); + } + + return $this->data; + } + + public function make_request() + { + $this->request = $this->query->query(); + } + + public function purge() + { + } + + public function next() + { + } + + public function count() + { + if (empty($data)) return $this->query->count(); + else return count($this->data); + } + + public function scan($line) + { + return $line; + + } + + /*public function __call($name, $arguments) + { + if (method_exists($this->query, $name)) return call_user_func_array(array($this->query, $name), $arguments); + else trigger_error("Table's query doesn't have a \"$name\"() method."); + }*/ + + public function data($data = null) + { + if (is_array($data)) $this->data = $data; + return $this->data; + } +} + + +/** + * An easy way to turn a query into a flexible HTML table + * + * @author greg + * + */ +class TaF_html_table extends TaF_table +{ + protected $alternate_styles = array('alt1', 'alt1', 'alt1', 'alt2', 'alt2', 'alt2'); + protected $tag_styles = array( + 'table' => 'inside_table', 'tr'=> 'highlight', 'th' => 'head' + ); + protected $id = ''; + + protected $tag_stack = array(); + + protected $empty_content = ' '; // default value in case we have to value to display + + + public function construct ($parameters = null) + { + if (empty($this->id)) $this->id = get_class($this); + //call_user_func_array(array($this, 'parent::__construct'), func_get_args()); + parent::construct ($parameters); + } + + public function id() + { + return $this->id; + } + + /** + * Creates an array with the key and the labels of the headers + * + * @date 20100428 (v1.0) (greg) + * @version 1.0 + * @author greg + * @param array $data an row of data + * @return array + */ + public function build_headers($data) + { + $result = array(); + + if (!empty($this->parameters['headers'])) { + // field list is given as a parameter + $result = $this->parameters['headers']; + /*foreach ($this->parameters['headers'] as $key => $value) { + $result .= $this->make_tag('th'); + $result .= $value; + $result .= $this->make_tag(); + }*/ + } elseif (!empty($this->query->fields)) { + // fields are explicitly listed + foreach ($this->query->fields as $key => $value) { + // $key is column field name (from the DB point of view, $value is what's displayed + $result[$key] = $value; + } + } elseif (is_array($data)) { + // we're on our own, so we try to get the field names from the database result + $first_line = $data[array_shift(array_keys($data))]; + if (is_array($first_line)) { + $keys = array_keys($first_line); + $result = array_combine($keys, $keys); + } else $result = array('#', '_'); + } + + return $result; + } + + /** + * Takes a header array and make an html string out of it + * + * @date 20100428 (v1.0) (greg) + * @version 1.0 + * @author greg + * @param array $headers + * @return string + */ + public function make_headers($headers) + { + $result = ''; + if (!empty($this->parameters['showHeaders'])) { + $result .= $this->make_tag('thead'); + $result .= $this->make_tag('tr'); + + if(is_array($headers)) { + foreach ($headers as $key => $value) { + // $key is column field name (from the DB point of view, $value is what's displayed + $result .= $this->make_tag('th'); + $result .= $value; + $result .= $this->make_tag(); // th + } + } + $result .= $this->make_tag(); //tr + $result .= $this->make_tag(); //theader + } + return $result; + } + + + public function make_html($forceLoad = false) + { + $this->load($forceLoad); + $result = $this->make_tag('table', $this->id.'_table'); + + if (is_array($this->data) && count($this->data) > 0) { + $headers = $this->build_headers($this->data); + $result .= $this->make_headers($headers); + + $line_index = 0; + + $result .= $this->make_tag('tbody'); + foreach($this->data as $idx => $line) { + $style = $this->alternate_styles[$line_index % count($this->alternate_styles)]; + $result .= $this->make_tag('tr', '', array('class' => $style)); + + foreach($headers as $key => $value) $result .= $this->make_cell($key, $line_index, $line, $idx); + $result .= $this->make_tag(); // tr + $line_index++; + } + $result .= $this->make_tag(); // tbody + } + + $result .= $this->make_tag(); // table + + return $result; + } + + + public function make_cell($key, $line_index, $line, $idx) + { + $result = $this->make_tag('td'); + $matches = array(); + if (preg_match('/.+ as (?<alias>.+)/', $key, $matches)) $key = $matches['alias']; + if (is_array($line)) { + $value = empty($line[$key]) ? '' : $line[$key]; + } else $value = $line; + $content = $this->chew($key, $line_index, $line, $value, $idx); + if (empty($content)) $content = $this->empty_content; + $result .= $content; + $result .= $this->make_tag(); + return $result; + } + + /** + * Placeholder to give you the opportunity to alter a cell content before it's displayed + * + * @param string $column_key + * @param integer $line_index + * @param array $line + * @param mixed $value + * @return striing + */ + public function chew($column_key, $line_index, $line, $value) + { + return $value; + } + + public function make_tag($tag = null, $id = '', array $attributes = array(), $single = false) + { + if (empty($tag)) { + $html = '</'.array_pop($this->tag_stack).'>'; + } else { + $class_tag = empty($this->tag_styles[$tag]) ? array() : array('class' => $this->tag_styles[$tag]); + $attr = PU_BuildAttrString(array_merge($class_tag, $attributes)); + if ($id) $id = " id=\"$id\" "; + if ($single) { + $html ="<$tag$id$attr />"; + }else { + array_push($this->tag_stack, $tag); + $html ="<$tag$id$attr>"; + } + } + + return $html; + } +} \ No newline at end of file === added directory 'TablesAndFilters/models' === added file 'TablesAndFilters/models/tableTest.query.php' --- TablesAndFilters/models/tableTest.query.php 1970-01-01 00:00:00 +0000 +++ TablesAndFilters/models/tableTest.query.php 2013-05-14 05:06:25 +0000 @@ -0,0 +1,12 @@ +<?php + //require_once 'includes/query.class.php'; + + class testTableQuery extends TaF_html_filteredQuery + { + protected $sql = 'SELECT SQL_CALC_FOUND_ROWS * FROM _db_core_menu_items'; + protected $keyField = 'user_name'; + + } + + + === added directory 'TablesAndFilters/scripts' === added file 'TablesAndFilters/scripts/tableTest.php' --- TablesAndFilters/scripts/tableTest.php 1970-01-01 00:00:00 +0000 +++ TablesAndFilters/scripts/tableTest.php 2013-05-14 05:06:25 +0000 @@ -0,0 +1,158 @@ +<?php + + //(is_object($security)) ? $this->security->load_security(true) : exit('Access Denied!'); //////////////////////////////////////// + + ?> + + <style type="text/css"> + .navigBtn { + padding: 3px; + outline: 1px solid black; + } + </style> + + <?php + + + class_exists('TaF_table'); + class_exists('TaF_filteredQuery'); + class_exists('PHPDS_user'); + + + + + class pagingFilter extends TaF_html_queryFilter + { + protected $pageSize = 10; + protected $pageNumber = 1; + + protected $foundRows = 0; + protected $numRows = 0; + protected $lastPage = 0; + + public function init() + { + $pageNo = empty($_POST['pageNo']) ? 1 :intval($_POST['pageNo']); + if ($pageNo > 0) $this->pageNumber = $pageNo; + + $pageSize = empty($_POST['pageSize']) ? 10 : intval($_POST['pageSize']); + if ($pageSize > 0) $this->pageSize = $pageSize; + } + + public function makeNavigBtn($label, $pageNo, $fct_name, $extra = '') + { + $html = '<button class="navigBtn" onClick="'.$fct_name.'({name:\'pageNo\',value:\''.$pageNo.'\'})"'; + $html .= ' type="button" value="'.$pageNo.'" name="'.$this->id().'" '.$extra.' >'.$label.'</button>'; + + return $html; + } + + public function toHTML() + { + $this->numRows = $this->count(); + $this->foundRows = mysql_result($this->db->connector->query('SELECT FOUND_ROWS()'), 0 ,0); + + $this->lastPage = intval($this->foundRows / $this->pageSize) + 1; + + $fct_name = $this->table->makeName('js_reload'); + + $html = '<p>Paging by '.$this->pageSize.' rows - '.time().'</p>'; + $html .= '<p>Rows on page '.$this->pageNumber.' (for a total of '.$this->foundRows.' rows on '.$this->lastPage.' pages)</p>'; + + $disabled = ($this->pageNumber < 2) ? 'disabled' : ''; + $html .= $this->makeNavigBtn('First', 1, $fct_name, $disabled); + $html .= $this->makeNavigBtn('Prev', $this->pageNumber - 1, $fct_name, $disabled); + + $disabled = ($this->pageNumber >= $this->lastPage) ? 'disabled' : ''; + $html .= $this->makeNavigBtn('Next', $this->pageNumber + 1, $fct_name, $disabled); + $html .= $this->makeNavigBtn('Last', $this->lastPage, $fct_name, $disabled); + + return $html; + } + + public function alterQuery(PHPDS_query $query, $mode) + { + if ($this->pageSize < 1) $this->pageSize = 1; + if ($this->pageNumber < 1) $this->pageNumber = 1; + + $query->limit($this->pageSize * ($this->pageNumber -1).', '.$this->pageSize); + return true; + } + } + + + + class testTable extends TaF_html_filteredTable + { + /*public function _make_js() + { + $fct_name = 'TaFReload_'.$this->id; + + if ($js_filters = $this->query->filtersASJSdata()) $js_filters .= ' + '.$js_filters; + + $js = '<script type="text/javascript" language="javascript">'; + $js .= "\n//<![CDATA[\n"; + $js .= <<<EOS + + + function $fct_name(url, dir) + { + if (dir < 0) { + jQuery.get(url{$js_filters} + ' #{$this->id}_div', function (data, textStatus, XMLHttpRequest) { + $('#{$this->id}_container').prepend($(data).find('#testTable_div')); + previous = $('#{$this->id}_container div:last-child'); + //previous.slideDown(function() { previous.remove(); }); + }); + } else { + jQuery.get(url{$js_filters} + ' #{$this->id}_div', function (data, textStatus, XMLHttpRequest) { + $('#{$this->id}_container').append($(data).find('#testTable_div')); + previous = $('#{$this->id}_container div:first-child'); + previous.slideUp(function() { previous.remove(); }); + }); + } + } + + +EOS; + + $js .= '$(document).ready(function() {'; + $js .= $this->query->filtersAsJSbind($fct_name.'();'); + $js .=' });'; + + $js .= "\n//]]>\n</script>"; + + return $js; + }*/ + } + + class f1 extends TaF_select_queryFilter + { + protected $field = 'user_role'; + protected $list = array(1 => 'one', 2 => 'two'); + protected $value = 2; + } + + class tableTestController extends PHPDS_controller + { + + protected $params = array( + 'query' => 'testTableQuery', + 'showHeaders' => true + ); + + public function execute() + { + $t = $this->factory('testTable', $this->params); + /*$t->addFilter('pagingFilter'); + $t->addFilter('f1');*/ + echo '<tr><td>'; + echo $t->make_html(); + echo '</td></tr>'; + } + } + + return 'tableTestController'; + + + + === added directory 'TablesAndFilters/tests' === added file 'TablesAndFilters/tests/taf.Test.php' --- TablesAndFilters/tests/taf.Test.php 1970-01-01 00:00:00 +0000 +++ TablesAndFilters/tests/taf.Test.php 2013-05-14 05:06:25 +0000 @@ -0,0 +1,82 @@ +<?php + + require_once 'mock_connector.php'; + + require_once BASEPATH.'/plugins/TablesAndFilters/includes/TaF_table.class.php'; + require_once BASEPATH.'/plugins/TablesAndFilters/includes/TaF_filteredQuery.class.php'; + require_once BASEPATH.'/plugins/TablesAndFilters/includes/TaF_excerpt.class.php'; + + class TAF_testTable extends TaF_html_filteredTable + { + + } + + class testTableQuery extends TEST_stubQuery + { + + } + + class TAF_tableTest extends PHPUnit_Framework_TestCase + { + protected $query; + protected $stub; + protected $table; + + protected function setUp() + { + $db = PHPDSlib::instance()->my_db(); + $this->query = $db->factory('TEST_stubQuery'); + $this->stub = $db->factory('TEST_mock_connector'); + $this->query->connector($this->stub); + } + + public function testDefaults() + { + $data_in = array( + array('col1' => 1, 'col2' => 'one', 'col3' => false, 'col4' => 'abc'), + ); + $this->stub->data = $data_in; + + $this->table = $this->query->factory('TAF_testTable'); + + $html = $this->table->make_html(); + $this->assertEquals('<div id="TAF_testTable_container" class="slidingTable"><form id="TAF_testTable_form" action="http://TEST/test.php"><table id="TAF_testTable_table" class="inside_table"></table></form></div>', $html); + } + + + /** + * @dataProvider tableValueProvider + * @group TaF + */ + public function testVariousData($data, $result) + { + $this->stub->data = $data; + + $params = array( + 'query' => $this->query, + 'showHeaders' => true + ); + $this->table = $this->query->factory('TAF_testTable', $params); + $html = $this->table->make_html(true); + $this->assertEquals($result, $html); + } + + public function tableValueProvider() + { + return array( + array( + array( + array('col1' => 1, 'col2' => 'one', 'col3' => false, 'col4' => 'abc'), + ), + '<div id="TAF_testTable_container" class="slidingTable"><form id="TAF_testTable_form" action="http://TEST/test.php"><table id="TAF_testTable_table" class="inside_table"><thead><tr class="highlight"><th class="head">col1</th><th class="head">col2</th><th class="head">col3</th><th class="head">col4</th></tr></thead><tbody><tr class="alt1"><td>1</td><td>one</td><td> </td><td>abc</td></tr></tbody></table></form></div>' + ), + array( + array( + array('col1' => 1, 'col2' => 'one', 'col3' => false, 'col4' => 'abc'), + array('col1' => 2, 'col2' => 'two', 'col3' => true, 'col4' => 'def'), + ), + '<div id="TAF_testTable_container" class="slidingTable"><form id="TAF_testTable_form" action="http://TEST/test.php"><table id="TAF_testTable_table" class="inside_table"><thead><tr class="highlight"><th class="head">col1</th><th class="head">col2</th><th class="head">col3</th><th class="head">col4</th></tr></thead><tbody><tr class="alt1"><td>1</td><td>one</td><td> </td><td>abc</td></tr><tr class="alt1"><td>2</td><td>two</td><td>1</td><td>def</td></tr></tbody></table></form></div>' + ), + ); + } + } \ No newline at end of file === added directory 'nbproject' === added directory 'nbproject/private' === added file 'nbproject/private/private.properties' --- nbproject/private/private.properties 1970-01-01 00:00:00 +0000 +++ nbproject/private/private.properties 2013-05-14 05:06:25 +0000 @@ -0,0 +1,2 @@ +index.file=index.php +url=http://localhost/TablesAndFilters/ === added file 'nbproject/project.properties' --- nbproject/project.properties 1970-01-01 00:00:00 +0000 +++ nbproject/project.properties 2013-05-14 05:06:25 +0000 @@ -0,0 +1,7 @@ +include.path=${php.global.include.path} +php.version=PHP_53 +source.encoding=UTF-8 +src.dir=. +tags.asp=false +tags.short=true +web.root=. === added file 'nbproject/project.xml' --- nbproject/project.xml 1970-01-01 00:00:00 +0000 +++ nbproject/project.xml 2013-05-14 05:06:25 +0000 @@ -0,0 +1,9 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project xmlns="http://www.netbeans.org/ns/project/1"> + <type>org.netbeans.modules.php.project</type> + <configuration> + <data xmlns="http://www.netbeans.org/ns/php-project/1"> + <name>TablesAndFilters</name> + </data> + </configuration> +</project>
_______________________________________________ Mailing list: https://launchpad.net/~phpdevshell Post to : [email protected] Unsubscribe : https://launchpad.net/~phpdevshell More help : https://help.launchpad.net/ListHelp

