soo_txp_obj API Documentation
soo_txp_obj.php
00001 <?php 00020 $plugin['name'] = 'soo_txp_obj'; 00021 $plugin['description'] = 'Support library for Txp plugins'; 00022 $plugin['version'] = '1.1.0'; 00023 $plugin['author'] = 'Jeff Soo'; 00024 $plugin['author_uri'] = 'http://ipsedixit.net/txp/'; 00025 $plugin['type'] = 2; 00026 @include_once('zem_tpl.php'); 00027 00028 # --- BEGIN PLUGIN CODE --- 00029 00031 abstract class soo_obj 00032 { 00036 public function __get( $property ) 00037 { 00038 return isset($this->$property) ? $this->$property : null; 00039 } 00040 00045 public function __call( $request, $args ) 00046 { 00047 if ( isset($this->$request) ) 00048 $this->$request = array_shift($args); 00049 return $this; 00050 } 00051 00056 public function __toString() 00057 { 00058 return get_class($this); 00059 } 00060 00066 public function properties() 00067 { 00068 return get_object_vars($this); 00069 } 00070 00074 public function property_names() 00075 { 00076 return array_keys($this->properties()); 00077 } 00078 00079 } 00080 00082 abstract class soo_txp_query extends soo_obj 00083 { 00085 protected $table = ''; 00087 protected $where = array(); 00089 protected $order_by = array(); 00091 protected $limit = 0; 00093 protected $offset = 0; 00094 00102 public function __construct( $table, $key = null ) 00103 { 00104 $this->table = trim($table); 00105 if ( is_array($key) ) 00106 $this->where(key($key), current($key)); 00107 elseif ( $key ) 00108 $this->where($this->key_column($key), $key); 00109 } 00110 00117 public function where( $column, $value, $operator = '=', $join = '' ) 00118 { 00119 $join = $this->andor($join); 00120 00121 if ( is_array($value) ) 00122 $value = '(' . implode(',', quote_list(doSlash($value))) . ')'; 00123 elseif ( $value instanceof soo_txp_select ) 00124 $value = '(' . $value->sql() . ')'; 00125 else 00126 $value = "'$value'"; 00127 00128 $this->where[] = ( $join ? "$join " : '' ) . 00129 self::quote($column) . " $operator $value"; 00130 return $this; 00131 } 00132 00138 public function where_clause( $clause, $join = '' ) 00139 { 00140 $join = $this->andor($join); 00141 $this->where[] = ( $join ? "$join " : '' ) . $clause; 00142 return $this; 00143 } 00144 00151 public function in( $column, $list, $join = '', $in = true ) 00152 { 00153 $in = ( $in ? '' : ' not' ) . ' in'; 00154 if ( is_string($list) ) 00155 $list = do_list($list); 00156 return $this->where($column, $list, $in, $join); 00157 } 00158 00164 public function not_in( $column, $list, $join = '' ) 00165 { 00166 return $this->in( $column , $list , $join , false ); 00167 } 00168 00174 public function regexp( $pattern, $subject, $join = '' ) 00175 { 00176 return $this->where($subject, $pattern, 'regexp', $join); 00177 } 00178 00179 protected function andor( $join = 'and' ) 00180 { 00181 $join = strtolower($join); 00182 return count($this->where) ? 00183 ( in_list($join, 'and,or') ? $join : 'and' ) : ''; 00184 } 00185 00191 public static function quote( $identifier ) 00192 { 00193 return preg_match('/^[a-z_$\d]+$/i', $identifier) ? 00194 "`$identifier`" : $identifier; 00195 } 00196 00202 public function order_by( $expr, $direction = '' ) 00203 { 00204 if ( $expr ) 00205 { 00206 if ( ! is_array($expr) ) $expr = do_list($expr); 00207 foreach ( $expr as $x ) 00208 { 00209 if ( preg_match('/(\S+)\s+(\S+)/', $x, $match) ) 00210 list( , $column, $direction) = $match; 00211 else 00212 $column = $x; 00213 if ( in_array(strtolower($column), array('random', 'rand', 'rand()')) ) 00214 $column = 'rand()'; 00215 else 00216 $direction = in_array(strtolower($direction), array('asc', 'desc')) ? $direction : ''; 00217 $this->order_by[] = $column . ( $direction ? ' ' . $direction : ''); 00218 } 00219 } 00220 return $this; 00221 } 00222 00226 public function asc( $col ) 00227 { 00228 return $this->order_by($col, 'asc'); 00229 } 00230 00234 public function desc( $col ) 00235 { 00236 return $this->order_by($col, 'desc'); 00237 } 00238 00245 public function order_by_field( $field, $list ) 00246 { 00247 if ( is_string($list) ) $list = do_list($list); 00248 if ( count($list) ) 00249 $this->order_by[] = 'field(' . self::quote($field) . ', ' . 00250 implode(', ', quote_list(doSlash($list))) . ')'; 00251 return $this; 00252 } 00253 00257 public function limit( $limit ) 00258 { 00259 if ( $limit = intval($limit) ) 00260 $this->limit = ' limit ' . $limit; 00261 return $this; 00262 } 00263 00267 public function offset( $offset ) 00268 { 00269 if ( $offset = intval($offset) ) 00270 $this->offset = ' offset ' . $offset; 00271 return $this; 00272 } 00273 00277 protected function clause_string() 00278 { 00279 return implode(' ', $this->where) . 00280 ( count($this->order_by) ? ' order by ' . implode(', ', $this->order_by) : '' ) . 00281 ( $this->limit ? $this->limit : '' ) . ( $this->offset ? $this->offset : '' ); 00282 } 00283 00288 public function count() 00289 { 00290 return getCount($this->table, $this->clause_string() ? $this->clause_string() : '1=1'); 00291 } 00292 00300 public function key_column( $key_value = null ) 00301 { 00302 $numeric_index = array( 00303 'textpattern' => 'ID', 00304 'txp_category' => 'id', 00305 'txp_discuss' => 'discussid', 00306 'txp_file' => 'id', 00307 'txp_image' => 'id', 00308 'txp_lang' => 'id', 00309 'txp_link' => 'id', 00310 'txp_log' => 'id', 00311 'txp_users' => 'user_id', 00312 ); 00313 $string_index = array( 00314 'textpattern' => 'Title', 00315 'txp_category' => 'name', 00316 'txp_css' => 'name', 00317 'txp_discuss_ipban' => 'ip', 00318 'txp_discuss_nonce' => 'nonce', 00319 'txp_file' => 'filename', 00320 'txp_form' => 'name', 00321 'txp_image' => 'name', 00322 'txp_lang' => 'lang', 00323 'txp_page' => 'name', 00324 'txp_plugin' => 'name', 00325 'txp_prefs' => 'name', 00326 'txp_section' => 'name', 00327 'txp_users' => 'name', 00328 ); 00329 if ( isset($numeric_index[$this->table]) ) 00330 $nx = $numeric_index[$this->table]; 00331 if ( isset($string_index[$this->table]) ) 00332 $sx = $string_index[$this->table]; 00333 00334 if ( is_numeric($key_value) ) 00335 return isset($nx) ? $nx : null; 00336 if ( is_string($key_value) ) 00337 return isset($sx) ? $sx : null; 00338 return isset($nx) ? $nx : ( isset($sx) ? $sx : null ); 00339 } 00340 00341 } 00342 00344 class soo_txp_select extends soo_txp_query 00345 { 00346 00348 protected $select = array(); 00350 protected $distinct = false; 00351 00357 public function __construct( $table, $key = null, $select = null ) 00358 { 00359 parent::__construct($table, $key); 00360 if ( $select ) $this->select($select); 00361 } 00362 00366 public function select( $list = '*' ) 00367 { 00368 if ( is_string($list) ) $list = do_list($list); 00369 foreach ( $list as $col ) $this->select[] = parent::quote($col); 00370 return $this; 00371 } 00372 00376 public function distinct( ) 00377 { 00378 $this->distinct = true; 00379 return $this; 00380 } 00381 00382 protected function init_query() 00383 { 00384 if ( ! count($this->select) ) $this->select(); 00385 if ( ! count($this->where) ) $this->where[] = '1 = 1'; 00386 } 00387 00391 public function row() 00392 { 00393 $this->init_query(); 00394 return safe_row(implode(',', $this->select), $this->table, 00395 $this->clause_string()); 00396 } 00397 00401 public function rows() 00402 { 00403 $this->init_query(); 00404 return safe_rows( ( $this->distinct ? 'distinct ' : '') . 00405 implode(',', $this->select), $this->table, $this->clause_string()); 00406 } 00407 00411 public function sql() 00412 { 00413 $this->init_query(); 00414 return 'select ' . implode(',', $this->select) . ' from ' . safe_pfx($this->table) . ' where ' . $this->clause_string(); 00415 } 00416 00417 } 00418 00422 class soo_txp_left_join extends soo_txp_select 00423 { 00425 protected $left_join; 00427 protected $join_on; 00429 const t1 = 't1'; 00431 const t2 = 't2'; 00432 00439 public function __construct ( $table, $left_join, $col1, $col2 ) 00440 { 00441 parent::__construct($table); 00442 $this->left_join = $left_join; 00443 $this->join_on = self::t1 . '.' . self::quote($col1) . ' = ' . self::t2 . '.' . self::quote($col2); 00444 } 00445 00450 public static function quote( $identifier, $prefix = '' ) 00451 { 00452 return ( $prefix ? $prefix . '.' : '' ) . parent::quote($identifier); 00453 } 00454 00458 public function select( $list = '*' ) 00459 { 00460 return self::select_from($list, self::t1); 00461 } 00462 00466 public function select_join( $list = '*' ) 00467 { 00468 return self::select_from($list, self::t2); 00469 } 00470 00471 private function select_from( $list, $table ) 00472 { 00473 if ( is_string($list) ) $list = do_list($list); 00474 foreach ( $list as $col ) $this->select[] = self::quote($col, $table); 00475 return $this; 00476 } 00477 00484 public function where( $column, $value, $operator = '=', $join = '' ) 00485 { 00486 return parent::where(self::quote($column, self::t1), $value, $operator, $join); 00487 } 00488 00495 public function where_join( $column, $value, $operator = '=', $join = '' ) 00496 { 00497 return parent::where(self::quote($column, self::t2), $value, $operator, $join); 00498 } 00499 00503 public function where_join_null( $column ) 00504 { 00505 $join = parent::andor(''); 00506 $this->where[] = ( $join ? $join . ' ' : '' ) . self::quote($column, self::t2) . ' is null'; 00507 return $this; 00508 } 00509 00514 public function order_by( $cols, $direction = '' ) 00515 { 00516 $direction = in_array(strtolower($direction), array('asc', 'desc')) ? $direction : ''; 00517 if ( is_string($cols) ) $cols = do_list($cols); 00518 foreach ( $cols as $col ) 00519 { 00520 if ( $col == 'random' or $col == 'rand' or $col == 'rand()' ) 00521 { 00522 $col = 'rand()'; 00523 $direction = ''; 00524 } 00525 $this->order_by[] = self::quote($col, self::t1) . ( $direction ? ' ' . $direction : ''); 00526 } 00527 return $this; 00528 } 00529 00533 public function row() 00534 { 00535 return getRow($this->sql()); 00536 } 00537 00541 public function rows() 00542 { 00543 return getRows($this->sql()); 00544 } 00545 00549 public function sql() 00550 { 00551 parent::init_query(); 00552 return 'select ' . implode(',', $this->select) . ' from ' . self::quote(safe_pfx($this->table)) . ' as ' . self::t1 . ' left join ' . self::quote(safe_pfx($this->left_join)) . ' as ' . self::t2 . ' on ' . $this->join_on . ' where ' . $this->clause_string(); 00553 } 00554 00558 public function count() 00559 { 00560 $select = $this->select; 00561 $this->select = array('count(*)'); 00562 $r = safe_query($this->sql()); 00563 $this->select = $select; 00564 if ( $r ) 00565 return mysql_result($r, 0); 00566 } 00567 } 00568 00570 class soo_txp_upsert extends soo_txp_query 00571 { 00572 // For use with VALUES() syntax 00574 public $columns = array(); 00576 public $values = array(); 00578 protected $values_clause = ''; 00579 00580 // For use with SET col_name=value syntax 00582 public $set = array(); 00584 protected $set_clause = ''; 00585 00592 public function __construct( $init, $col = null ) 00593 { 00594 if ( is_scalar($init) ) 00595 parent::__construct($init, $col); 00596 elseif ( $init instanceof soo_txp_rowset ) 00597 { 00598 $this->table = $init->table; 00599 if ( $col ) 00600 $this->columns = is_array($col) ? $col : do_list($col); 00601 else 00602 $this->columns = array_keys(current($init->data)); 00603 foreach ( $init->rows as $r ) 00604 $this->values[] = $r->data; 00605 } 00606 elseif ( $init instanceof soo_txp_row ) 00607 { 00608 $this->table = $init->table; 00609 if ( $col ) 00610 $this->columns = is_array($col) ? $col : do_list($col); 00611 else 00612 $this->columns = array_keys($init->data); 00613 $this->values[] = $init->data; 00614 } 00615 } 00616 00621 public function set( $column, $value ) 00622 { 00623 $this->set[$column] = $value; 00624 return $this; 00625 } 00626 00627 private function init_query() 00628 { 00629 if ( count($this->set) ) 00630 { 00631 foreach ( $this->set as $col => $val ) 00632 { 00633 $val = is_numeric($val) ? $val : "'$val'"; 00634 $set_pairs[] = "$col = $val"; 00635 } 00636 $this->set_clause = implode(',', $set_pairs); 00637 } 00638 elseif ( count($this->values) ) 00639 { 00640 if ( count($this->columns) ) 00641 $this->values_clause = '(`' . implode('`,`', $this->columns) . '`) '; 00642 $this->values_clause .= ' values '; 00643 foreach ( $this->values as $vs ) 00644 { 00645 $this->values_clause .= '('; 00646 foreach ( $vs as $v ) 00647 $this->values_clause .= ( is_numeric($v) ? $v : "'$v'" ) . ','; 00648 $this->values_clause = rtrim($this->values_clause, ',') . '),'; 00649 } 00650 $this->values_clause = rtrim($this->values_clause, ',') . ';'; 00651 } 00652 } 00653 00658 public function upsert() 00659 { 00660 $this->init_query(); 00661 if ( count($this->where) ) 00662 return safe_upsert($this->table, $this->set_clause, $this->clause_string()); 00663 if ( $this->set_clause ) 00664 return safe_insert($this->table, $this->set_clause); 00665 if ( $this->values_clause ) 00666 return safe_query('insert into ' . safe_pfx($this->table) . $this->values_clause); 00667 } 00668 } 00669 00671 class soo_txp_delete extends soo_txp_query 00672 { 00676 public function delete() 00677 { 00678 if ( count($this->where) ) 00679 return safe_delete($this->table, $this->clause_string()); 00680 } 00681 } 00682 00684 class soo_txp_rowset extends soo_obj 00685 { 00686 00688 protected $table = ''; 00689 00691 public $rows = array(); 00692 00701 public function __construct( $init = array(), $table = '', $index = null ) 00702 { 00703 if ( $init instanceof soo_txp_select ) 00704 { 00705 $table = $init->table; 00706 $index = $init->key_column(); 00707 $init = $init->rows(); 00708 } 00709 if ( is_resource($init) and mysql_num_rows($init) ) 00710 { 00711 while ( $r = mysql_fetch_assoc($init) ) 00712 $data[] = $r; 00713 mysql_free_result($init); 00714 $init = $data; 00715 } 00716 $this->table = $table; 00717 if ( is_array($init) and count($init) ) 00718 { 00719 foreach ( $init as $r ) 00720 if ( $index ) 00721 $this->add_row($r, $table, $r[$index]); 00722 else 00723 $this->add_row($r, $table); 00724 } 00725 } 00726 00732 public function __get( $property ) 00733 { 00734 if ( property_exists($this, $property) ) 00735 return $this->$property; 00736 if ( array_key_exists($property, $this->rows) ) 00737 return $this->rows[$property]; 00738 } 00739 00746 public function field_vals( $field, $key = null ) 00747 { 00748 foreach ( $this->rows as $r ) 00749 if ( ! is_null($key) ) 00750 $out[$r->$key] = $r->$field; 00751 else 00752 $out[] = $r->$field; 00753 return isset($out) ? $out : array(); 00754 } 00755 00761 public function add_row( $data, $table = null, $i = null ) 00762 { 00763 $table = is_null($table) ? $this->table : $table; 00764 $r = $data instanceof soo_txp_row ? 00765 $data : ( $table == 'txp_image' ? 00766 new soo_txp_img($data) : new soo_txp_row($data, $table) ); 00767 if ( is_null($i) ) 00768 $this->rows[] = $r; 00769 else 00770 $this->rows[$i] = $r; 00771 return $this; 00772 } 00773 00780 public function subset( $key, $value, $index = null ) 00781 { 00782 $out = new self; 00783 foreach ( $this->rows as $row ) 00784 if ( $row->$key == $value ) 00785 $out->add_row($row, null, is_null($index) ? null : $row->$index); 00786 return $out; 00787 } 00788 } 00789 00791 class soo_nested_set extends soo_txp_rowset 00792 { 00799 public function __construct( $init = array(), $table = '', $index = null ) 00800 { 00801 if ( $init instanceof soo_txp_rowset ) 00802 { 00803 $this->table = $init->table; 00804 $this->rows = $init->rows; 00805 } 00806 else 00807 parent::__construct($init, $table); 00808 } 00809 00818 public function as_object_array( &$rows = null, $rgt = null ) 00819 { 00820 if ( is_null($rows) ) 00821 { 00822 $rows = $this->rows; 00823 $root = current($rows); 00824 $rgt = $root->rgt; 00825 } 00826 while ( $out[] = $node = array_shift($rows) and $node->rgt <= $rgt ) 00827 if ( $node->rgt > $node->lft + 1 ) 00828 $out[] = $this->as_object_array($rows, $node->rgt); 00829 if ( $node and $node->rgt > $rgt ) 00830 array_unshift($rows, array_pop($out)); 00831 if ( is_null($out[count($out) - 1]) ) 00832 array_pop($out); 00833 return $out; 00834 } 00835 00847 public function as_array( $index_column, $value_column, &$rows = null, $rgt = null ) 00848 { 00849 if ( is_null($rows) ) 00850 { 00851 $rows = $this->rows; 00852 $root = current($rows); 00853 $rgt = $root->rgt; 00854 } 00855 while ( $node = array_shift($rows) and $node->rgt <= $rgt ) 00856 { 00857 $out[$node->$index_column] = $node->$value_column; 00858 if ( $node->rgt > $node->lft + 1 ) 00859 $out[$node->$index_column . '_c'] = $this->as_array($index_column, $value_column, $rows, $node->rgt); 00860 } 00861 if ( $node and $node->rgt > $rgt ) 00862 array_unshift($rows, $node); 00863 return $out; 00864 } 00865 00870 public function subtree( $root, $index = null ) 00871 { 00872 $out = new self; 00873 $root = $this->rows[$root]; 00874 foreach ( $this->rows as $row ) 00875 if ( $row->lft >= $root->lft and $row->rgt <= $root->rgt ) 00876 $out->add_row($row, null, is_null($index) ? null : $row->$index); 00877 return $out; 00878 } 00879 } 00880 00882 class soo_txp_row extends soo_obj 00883 { 00885 protected $table = ''; 00887 protected $data = array(); 00888 00893 public function __construct( $init = array(), $table = '' ) 00894 { 00895 if ( is_scalar($init) and $table ) 00896 $init = new soo_txp_select($table, $init); 00897 if ( $init instanceof soo_txp_select ) 00898 { 00899 $table = $init->table; 00900 $init = $init->row(); 00901 } 00902 if ( is_array($init) ) 00903 foreach ( $init as $k => $v ) 00904 $this->data[$k] = $v; 00905 $this->table = $table; 00906 } 00907 00913 public function __get( $property ) 00914 { 00915 return isset($this->data[$property]) ? $this->data[$property] 00916 : parent::__get($property); 00917 } 00918 00920 public function data( ) 00921 { 00922 return; 00923 } 00924 00926 public function properties( ) 00927 { 00928 return $this->data; 00929 } 00930 } 00931 00933 class soo_txp_img extends soo_txp_row 00934 { 00936 protected $full_url = ''; 00938 protected $thumb_url = ''; 00939 00943 public function __construct( $init ) 00944 { 00945 global $img_dir; 00946 parent::__construct($init, 'txp_image'); 00947 $this->full_url = hu . $img_dir . '/' . $this->id . $this->ext; 00948 if ( $this->thumbnail ) 00949 $this->thumb_url = hu . $img_dir . '/' . $this->id . 't' . $this->ext; 00950 } 00951 } 00952 00954 abstract class soo_html extends soo_obj 00955 { 00956 // HTML element class. Instantiation takes a required 'name' argument and an 00957 // optional 'atts' array: items with keys matching HTML attributes 00958 // will be transferred to the new object. 00959 // 00960 // See the soo_html_img class for an example of how to extend this class. 00961 00963 00964 00965 protected $element_name = ''; 00967 protected $is_empty = 0; 00969 protected $contents = array(); 00971 00973 00974 protected $class = ''; 00975 protected $dir = ''; 00976 protected $id = ''; 00977 protected $lang = ''; 00978 protected $onclick = ''; 00979 protected $ondblclick = ''; 00980 protected $onkeydown = ''; 00981 protected $onkeypress = ''; 00982 protected $onkeyup = ''; 00983 protected $onmousedown = ''; 00984 protected $onmousemove = ''; 00985 protected $onmouseout = ''; 00986 protected $onmouseover = ''; 00987 protected $onmouseup = ''; 00988 protected $style = ''; 00989 protected $title = ''; 00991 00997 public function __construct($element_name, $atts, $content = null, $is_empty = 0) 00998 { 00999 $this->element_name($element_name)->is_empty($is_empty); 01000 if ( empty($atts) ) 01001 $atts = array(); 01002 foreach ( $this as $property => $value ) 01003 if ( in_array($property, array_keys($atts)) ) 01004 $this->$property($atts[$property]); 01005 if ( $content ) 01006 $this->contents($content); 01007 } 01008 01013 public function id($id) 01014 { 01015 if ( $id and !preg_match('/^[a-z]/', strtolower(trim($id))) ) 01016 { 01017 $this->id = 'invalid_HTML_ID_value_from_Soo_Txp_Obj'; 01018 return false; 01019 } 01020 $this->id = $id; 01021 return $this; 01022 } 01023 01027 public function contents($content) 01028 { 01029 if ( ! $this->is_empty ) 01030 { 01031 $content = is_array($content) ? $content : array($content); 01032 foreach ( $content as $i => $item ) 01033 if ( is_null($item) ) 01034 unset($content[$i]); 01035 $this->contents = array_merge($this->contents, $content); 01036 } 01037 return $this; 01038 } 01039 01045 private function html_attributes() 01046 { 01047 return array_diff_key($this->properties(), array_flip(array('element_name', 'is_empty', 'contents'))); 01048 } 01049 01054 public function tag() 01055 { 01056 $out = '<' . $this->element_name; 01057 01058 foreach ( $this->html_attributes() as $property => $value ) 01059 if ( $value or $property == 'alt' ) 01060 $out .= " $property=\"$value\""; 01061 01062 if ( $this->is_empty ) 01063 return $out . ' />'; 01064 01065 $out .= '>' . $this->newline(); 01066 01067 foreach ( $this->contents as $item ) 01068 01069 if ( $item instanceof soo_html ) 01070 $out .= $item->tag(); 01071 else 01072 $out .= $item; 01073 01074 return $out . $this->newline() . "</$this->element_name>" . $this->newline(); 01075 } 01076 01081 protected function html_escape( $property ) 01082 { 01083 $this->$property = htmlspecialchars($this->$property); 01084 return $this; 01085 } 01086 01087 private function newline() 01088 { 01089 return ( ! $this->is_empty and count($this->contents) > 1 ) ? n : ''; 01090 } 01091 } 01092 01094 class soo_html_anchor extends soo_html 01095 { 01097 01098 protected $href = ''; 01099 protected $name = ''; 01100 protected $rel = ''; 01101 protected $rev = ''; 01102 protected $type = ''; 01103 protected $hreflang = ''; 01104 protected $charset = ''; 01105 protected $accesskey = ''; 01106 protected $tabindex = ''; 01107 protected $shape = ''; 01108 protected $coords = ''; 01109 protected $onfocus = ''; 01110 protected $onblur = ''; 01112 01116 public function __construct ( $atts = array(), $content = '' ) 01117 { 01118 if ( ! is_array($atts) ) 01119 $atts = array('href' => $atts); 01120 parent::__construct( 'a', $atts, $content ); 01121 } 01122 01123 } 01124 01126 class soo_html_br extends soo_html 01127 { 01131 public function __construct ( $atts = array() ) 01132 { 01133 parent::__construct('br', $atts, null, true); 01134 } 01135 } 01136 01138 class soo_html_form extends soo_html 01139 { 01141 01142 protected $action = ''; 01143 protected $method = ''; 01144 protected $enctype = ''; 01145 protected $accept_charset = ''; 01146 protected $onsubmit = ''; 01147 protected $onreset = ''; 01149 01154 public function __construct ( $init = array(), $content = '' ) 01155 { 01156 $atts = is_string($init) ? array('action' => $init) : $init; 01157 if ( ! isset($atts['method']) ) 01158 $atts['method'] = 'post'; 01159 if ( is_array($atts['action']) ) 01160 { 01161 foreach ( $atts['action'] as $k => $v ) 01162 $atts['action'][$k] = "$k=$v"; 01163 $atts['action'] = '?' . implode(a, $atts['action']); 01164 } 01165 parent::__construct('form', $atts, $content ); 01166 } 01167 } 01168 01170 class soo_html_label extends soo_html 01171 { 01173 01174 protected $for = ''; 01175 protected $onfocus = ''; 01176 protected $onblur = ''; 01178 01183 public function __construct ( $init = array(), $content = '' ) 01184 { 01185 if ( is_string($init) ) 01186 $init = array('for' => $init); 01187 parent::__construct('label', $init, $content); 01188 } 01189 } 01190 01192 abstract class soo_html_form_control extends soo_html 01193 { 01195 01196 protected $name = ''; 01197 protected $disabled = ''; 01198 protected $tabindex = ''; 01199 protected $onfocus = ''; 01200 protected $onblur = ''; 01202 } 01203 01205 class soo_html_input extends soo_html_form_control 01206 { 01207 01209 01210 protected $type = ''; 01211 protected $value = ''; 01212 protected $checked = ''; 01213 protected $size = ''; 01214 protected $maxlength = ''; 01215 protected $src = ''; 01216 protected $alt = ''; 01217 protected $usemap = ''; 01218 protected $readonly = ''; 01219 protected $accept = ''; 01220 protected $onselect = ''; 01221 protected $onchange = ''; 01223 01228 public function __construct ( $type = 'text', $atts = array() ) 01229 { 01230 $this->type($type); 01231 parent::__construct('input', $atts, null, true); 01232 } 01233 } 01234 01236 class soo_html_select extends soo_html_form_control 01237 { 01239 01240 protected $multiple = ''; 01241 protected $size = ''; 01242 protected $onchange = ''; 01244 01251 public function __construct ( $atts = array(), $content = array() ) 01252 { 01253 parent::__construct('select', $atts); 01254 if ( ! is_array($content) ) $content = array($content); 01255 foreach ( $content as $i => $item ) 01256 { 01257 if ( $item instanceof soo_html_option ) 01258 $this->contents($item); 01259 else 01260 $this->contents(new soo_html_option(array('value' => $i), $item)); 01261 } 01262 } 01263 } 01264 01266 class soo_html_option extends soo_html_form_control 01267 { 01269 01270 protected $value = ''; 01271 protected $selected = ''; 01272 protected $label = ''; 01274 01279 public function __construct ( $atts = array(), $content = array() ) 01280 { 01281 parent::__construct('option', $atts, $content); 01282 } 01283 } 01284 01286 class soo_html_textarea extends soo_html_form_control 01287 { 01289 01290 protected $rows = ''; 01291 protected $cols = ''; 01292 protected $readonly = ''; 01293 protected $onselect = ''; 01294 protected $onchange = ''; 01296 01301 public function __construct ( $atts = array(), $content = '' ) 01302 { 01303 parent::__construct('textarea', $atts, $content); 01304 } 01305 } 01306 01308 class soo_html_img extends soo_html 01309 { 01311 01312 protected $alt = ''; 01313 protected $src = ''; 01314 protected $width = ''; 01315 protected $height = ''; 01317 01323 public function __construct ( $init = array(), $thumbnail = false, $escape = true ) 01324 { 01325 if ( $init instanceof soo_txp_img ) 01326 { 01327 $src = $thumbnail ? $init->thumb_url : $init->full_url; 01328 $init = $init->properties(); 01329 if ( $thumbnail ) 01330 { 01331 if ( ! empty($init['thumb_h']) ) 01332 { // pre Txp 4.2 compatibility 01333 $init['h'] = $init['thumb_h']; 01334 $init['w'] = $init['thumb_w']; 01335 } 01336 else $init['h'] = ( $init['w'] = 0 ); 01337 } 01338 $init['height'] = $init['h']; 01339 $init['width'] = $init['w']; 01340 $init['title'] = $init['caption']; 01341 $init['src'] = $src; 01342 unset($init['id']); // don't want database id as HTML id! 01343 } 01344 elseif ( ! is_array($init) ) 01345 $init['src'] = $init; 01346 01347 parent::__construct('img', $init, null, true); 01348 if ( $escape ) 01349 $this->html_escape('title')->html_escape('alt'); 01350 } 01351 01352 } 01353 01355 class soo_html_p extends soo_html 01356 { 01361 public function __construct ( $atts = array(), $content = '' ) 01362 { 01363 parent::__construct('p', $atts, $content); 01364 } 01365 } 01366 01368 class soo_html_table extends soo_html 01369 { 01371 01372 protected $summary = ''; 01373 protected $width = ''; 01374 protected $border = ''; 01375 protected $frame = ''; 01376 protected $rules = ''; 01377 protected $cellspacing = ''; 01378 protected $cellpadding = ''; 01380 01386 public function __construct ( $atts = array(), $content = null ) 01387 { 01388 $this->contents($content); 01389 parent::__construct( 'table', $atts ); 01390 } 01391 01399 public function contents($content) 01400 { 01401 if ( is_null($content) ) return $this; 01402 01403 $content = is_array($content) ? $content : array($content); 01404 foreach ( $content as $item ) 01405 { 01406 if ( is_object($item) and ( $item instanceof soo_html_table_component or $item instanceof soo_html_caption) ) 01407 $this->contents[] = $item; 01408 else 01409 { 01410 $item = is_array($item) ? $item : array($item); 01411 foreach ( $item as $i => $cell ) 01412 if ( ! $cell instanceof soo_html_table_component ) 01413 $item[$i] = new soo_html_td(array(), $cell); 01414 $this->contents[] = new soo_html_tr(array(), $item); 01415 } 01416 } 01417 return $this; 01418 } 01419 } 01420 01422 class soo_html_caption extends soo_html_table_component 01423 { 01424 public function __construct ( $atts = array(), $content ) 01425 { 01426 parent::__construct( 'caption', $atts, $content ); 01427 } 01428 } 01429 01431 abstract class soo_html_table_component extends soo_html 01432 { 01434 01435 protected $align = ''; 01436 protected $char = ''; 01437 protected $charoff = ''; 01438 protected $valign = ''; 01440 01446 public function __construct ( $component, $atts = array(), $content = '' ) 01447 { 01448 parent::__construct( $component, $atts, $content ); 01449 } 01450 } 01451 01453 class soo_html_thead extends soo_html_table_component 01454 { 01459 public function __construct ( $atts = array(), $content = '' ) 01460 { 01461 parent::__construct( 'thead', $atts, $content ); 01462 } 01463 } 01464 01466 class soo_html_tbody extends soo_html_table_component 01467 { 01472 public function __construct ( $atts = array(), $content = '' ) 01473 { 01474 parent::__construct( 'tbody', $atts, $content ); 01475 } 01476 } 01477 01479 class soo_html_tfoot extends soo_html_table_component 01480 { 01485 public function __construct ( $atts = array(), $content = '' ) 01486 { 01487 parent::__construct( 'tfoot', $atts, $content ); 01488 } 01489 } 01490 01492 class soo_html_tr extends soo_html_table_component 01493 { 01494 01499 public function __construct ( $atts = array(), $content = '' ) 01500 { 01501 parent::__construct( 'tr', $atts, $content ); 01502 } 01503 } 01504 01506 abstract class soo_html_table_cell extends soo_html_table_component 01507 { 01509 01510 protected $rowspan = ''; 01511 protected $colspan = ''; 01512 protected $headers = ''; 01513 protected $abbr = ''; 01514 protected $scope = ''; 01515 protected $axis = ''; 01517 01523 public function __construct ( $cell_type, $atts = array(), $content = '' ) 01524 { 01525 parent::__construct( $cell_type, $atts, $content ); 01526 } 01527 } 01528 01530 class soo_html_th extends soo_html_table_cell 01531 { 01536 public function __construct ( $atts = array(), $content = '' ) 01537 { 01538 parent::__construct( 'th', $atts, $content ); 01539 } 01540 } 01541 01543 class soo_html_td extends soo_html_table_cell 01544 { 01549 public function __construct ( $atts = array(), $content = '' ) 01550 { 01551 parent::__construct( 'td', $atts, $content ); 01552 } 01553 01554 } 01555 01557 abstract class soo_html_list extends soo_html 01558 { 01569 public function __construct ( $element_name, $atts, $content, $class ) 01570 { 01571 if ( ! is_array($content) ) 01572 $content = array($content); 01573 $prev = null; 01574 foreach ( $content as $i => &$item ) 01575 { 01576 if ( is_array($item) ) 01577 { 01578 if ( ! is_null($prev) and $content[$prev] instanceof soo_html_li ) 01579 { 01580 $content[$prev]->contents(new $class($atts, $item)); 01581 unset($content[$i]); 01582 } 01583 else foreach ( $item as &$li ) 01584 $li = new soo_html_li(array(), $li); 01585 } 01586 elseif ( ! $item instanceof soo_html_li ) 01587 $item = new soo_html_li(array(), $item); 01588 $prev = $i; 01589 } 01590 parent::__construct($element_name, $atts, $content); 01591 } 01592 } 01593 01595 class soo_html_ol extends soo_html_list 01596 { 01601 public function __construct ( $atts = array(), $content = '' ) 01602 { 01603 parent::__construct('ol', $atts, $content, __CLASS__); 01604 } 01605 } 01606 01608 class soo_html_ul extends soo_html_list 01609 { 01614 public function __construct ( $atts = array(), $content = '' ) 01615 { 01616 parent::__construct('ul', $atts, $content, __CLASS__); 01617 } 01618 } 01619 01621 class soo_html_li extends soo_html 01622 { 01627 public function __construct ( $atts = array(), $content = '' ) 01628 { 01629 parent::__construct('li', $atts, $content); 01630 } 01631 } 01632 01634 class soo_html_span extends soo_html 01635 { 01640 public function __construct ( $atts = array(), $content = '' ) 01641 { 01642 parent::__construct('span', $atts, $content); 01643 } 01644 } 01645 01647 // MLP Pack manipulates $_SERVER['REQUEST_URI'], so grab it first 01648 01649 global $plugin_callback; 01650 if( is_array($plugin_callback) 01651 and $plugin_callback[0]['function'] == '_l10n_pretext' ) 01652 array_unshift($plugin_callback, array( 01653 'function' => 'soo_uri_mlp', 01654 'event' => 'pretext', 01655 'step' => '', 01656 'pre' => 0 ) 01657 ); 01658 01659 function soo_uri_mlp() 01660 { 01661 global $soo_request_uri; 01662 $soo_request_uri = $_SERVER['REQUEST_URI']; 01663 } 01665 01666 01668 class soo_uri extends soo_obj 01669 { 01671 protected $full; 01672 01674 protected $request_uri; 01675 01677 protected $query_string; 01678 01680 protected $query_params; 01681 01686 public function __construct ( ) 01687 { 01688 global $soo_request_uri; // MLP Pack compatibility 01689 $this->request_uri = $soo_request_uri ? $soo_request_uri : 01690 $_SERVER['REQUEST_URI']; 01691 $this->query_string = $_SERVER['QUERY_STRING']; 01692 $this->full = preg_replace('/\/$/', '', hu) . $this->request_uri(); 01693 parse_str($this->query_string, $this->query_params); 01694 } 01695 01697 public function __call( $request, $args ) 01698 { 01699 return false; 01700 } 01701 01708 public function set_query_param ( $name, $value = null ) 01709 { 01710 if ( is_null($value) ) 01711 unset($this->query_params[$name]); 01712 else 01713 $this->query_params[$name] = $value; 01714 $this->update_from_params(); 01715 return $this; 01716 } 01717 01721 private function update_from_params ( ) 01722 { 01723 $this->query_string = http_build_query($this->query_params); 01724 $this->request_uri = self::strip_query($this->request_uri) . 01725 ( $this->query_string ? '?' . $this->query_string : '' ); 01726 $this->full = preg_replace('/\/$/', '', hu) . $this->request_uri(); 01727 $_SERVER['QUERY_STRING'] = $this->query_string; 01728 $_SERVER['REQUEST_URI'] = $this->request_uri; 01729 } 01730 01734 public function strip_query ( $uri ) 01735 { 01736 return preg_replace ('/(.+)\?.+/', '$1', $uri); 01737 } 01738 01743 private function request_uri ( ) 01744 { 01745 if ( preg_match('&://[^/]+(/.+)/$&', hu, $match) ) 01746 { 01747 $sub_dir = $match[1]; 01748 return substr($this->request_uri, strlen($sub_dir)); 01749 } 01750 return $this->request_uri; 01751 } 01752 01753 } 01754 01756 class soo_util 01757 { 01764 public static function txp_tag ( $func, $atts = array(), $thing = null ) 01765 { 01766 $a = ''; 01767 foreach ( $atts as $k => $v ) 01768 $a .= " $k=\"$v\""; 01769 return "<txp:$func$a" . ( is_null($thing) ? ' />' : ">$thing</txp:$func>" ); 01770 } 01771 01781 public static function secondpass ( $func, $atts = array(), $thing = null ) 01782 { 01783 global $pretext; 01784 if ( $pretext['secondpass'] ) return; // you only live twice 01785 return self::txp_tag($func, $atts, $thing); 01786 } 01787 01788 } 01789 01790 # --- END PLUGIN CODE --- 01791 01792 if (0) { 01793 ?> 01794 <!-- CSS & HELP 01795 # --- BEGIN PLUGIN CSS --- 01796 <style type="text/css"> 01797 div#sed_help pre {padding: 0.5em 1em; background: #eee; border: 1px dashed #ccc;} 01798 div#sed_help h1, div#sed_help h2, div#sed_help h3, div#sed_help h3 code {font-family: sans-serif; font-weight: bold;} 01799 div#sed_help h1, div#sed_help h2, div#sed_help h3 {margin-left: -1em;} 01800 div#sed_help h2, div#sed_help h3 {margin-top: 2em;} 01801 div#sed_help h1 {font-size: 2.4em;} 01802 div#sed_help h2 {font-size: 1.8em;} 01803 div#sed_help h3 {font-size: 1.4em;} 01804 div#sed_help h4 {font-size: 1.2em;} 01805 div#sed_help h5 {font-size: 1em;margin-left:1em;font-style:oblique;} 01806 div#sed_help ul li {list-style-type: disc;} 01807 div#sed_help ul li li {list-style-type: circle;} 01808 div#sed_help ul li li li {list-style-type: square;} 01809 div#sed_help li a code {font-weight: normal;} 01810 div#sed_help li code:first-child {background: #ddd;padding:0 .3em;margin-left:-.3em;} 01811 div#sed_help li li code:first-child {background:none;padding:0;margin-left:0;} 01812 div#sed_help dfn {font-weight:bold;font-style:oblique;} 01813 div#sed_help .required, div#sed_help .warning {color:red;} 01814 div#sed_help .default {color:green;} 01815 div#sed_help sup {line-height:0;} 01816 </style> 01817 # --- END PLUGIN CSS --- 01818 # --- BEGIN PLUGIN HELP --- 01819 <div id="sed_help"> 01820 01821 h1. soo_txp_obj 01822 01823 A support library for Textpattern plugins. 01824 01825 * "Information and examples":http://ipsedixit.net/txp/21/soo-txp-obj 01826 * "API Documentation":http://ipsedixit.net/api/soo_txp_obj/ 01827 01828 h2(#history). Version history 01829 01830 h3(#1_1_0). 1.1.0 01831 01832 2011/01/07 01833 01834 * soo_txp_select::distinct() for @SELECT DISTINCT@ queries 01835 * Bugfix: soo_txp_left_join now works with database table prefixes 01836 01837 h3(#b9). 1.1.b.1 01838 01839 9/12/2010 01840 01841 _Note: this changelist includes items from the 1.0.b.9 and 1.0.b.10 releases_ 01842 01843 * New class, *soo_txp_left_join*, for @SELECT ... LEFT JOIN@ queries 01844 * *soo_txp_upsert* new features: 01845 ** properties and methods for @VALUES()@ syntax 01846 ** can be initialized with a *soo_txp_rowset* or *soo_txp_row* object 01847 * *soo_txp_rowset* new features: 01848 ** can be initialized with a query result resource 01849 ** new function @subset()@ to create a new rowset object from an existing one 01850 * New class, *soo_nested_set*, for Celko nested sets (modified preorder tree) 01851 * *soo_html_form*, new features and related classes: 01852 ** Constructor's @atts@ argument can include an @action@ array for adding query parameters to the form's @action@ attribute 01853 ** New classes: 01854 *** *soo_html_label* for labeling form controls 01855 *** *soo_html_input* for input elements 01856 *** *soo_html_select* for select elements (can be initialized with an array which will auto-create appropriate @option@ elements) 01857 *** *soo_html_option* (see above) 01858 *** *soo_html_textarea* for textarea elements 01859 * *soo_html_img* bugfix for pre Txp 4.2 compatibility 01860 * *soo_html_table* can now be initialized with an array of values or table cells; these will automatically be formatted into rows and cells appropriately 01861 * New class, *soo_html_caption*, for table captions 01862 * *soo_html_ol* and *soo_html_ul* can be initialized with nested arrays, automatically generating nested lists (see *soo_nested_set* for a possible source of the nested array) 01863 01864 h3(#b8). 1.0.b.8 01865 01866 7/9/2010 01867 01868 * Documentation updates (DoxyGen compatibility) 01869 01870 h3(#b7). 1.0.b.7 01871 01872 7/4/2010 01873 01874 * *soo_html_img* now adds thumbnail @height@ and @width@ attributes (Txp 4.2.0 or later) 01875 01876 h3(#b6). 1.0.b.6 01877 01878 7/1/2010 01879 01880 * New class: soo_util, for static utility methods 01881 01882 h3(#b5). 1.0.b.5 01883 01884 1/27/2010 01885 01886 * new method: @where_clause()@ in *soo_txp_query*, a catch-all for complex clauses 01887 * minor HTML formatting change to @tag()@ method in *soo_html* 01888 01889 h3(#b4). 1.0.b.4 01890 01891 10/3/2009 01892 01893 * *soo_uri* updated for correct behavior in Txp sub-dir installations 01894 01895 h3(#b3). 1.0.b.3 01896 01897 9/22/2009 01898 01899 * *soo_uri* now gets query params by parsing $_SERVER['QUERY_STRING'] instead of $_GET 01900 01901 h3(#b2). 1.0.b.2 01902 01903 9/16/2009 01904 01905 * New callback function for MLP Pack compatibility with *soo_uri* 01906 * New classes: 01907 ** soo_txp_upsert for SQL insert/update statements 01908 ** soo_txp_delete for SQL delete statements 01909 ** soo_html_form for form elements 01910 * soo_txp_rowset overrides parent::__get() method 01911 01912 h3(#b1). 1.0.b.1 01913 01914 * Major re-organization and re-write of most classes. 01915 ** The old *Soo_Txp_Data* family has been divided into separate classes for queries and data. 01916 ** There are no longer separate classes for each Txp table. 01917 ** All class names now lowercase (these aren't case sensitive anyway). 01918 ** Generic setting is now in the form @obj->property()@ instead of @obj->set_property()@. 01919 ** Various renaming, code cleaning, etc. 01920 01921 h3(#a6). 1.0.a.6 01922 01923 6/2/2009 01924 01925 What the heck, time to use the same naming convention I'm using with other plugins. 01926 01927 * Added *Soo_Txp_Uri* class, for URI query string manipulation 01928 * *Soo_Html_P* and *soo_html_th* can now have contents set during instantiation. Note that this will break compatibility with some previous uses, e.g. @new Soo_Html_P($atts)@. 01929 * Added @$in@ argument to @where_in()@ method (*Soo_Txp_Data*) to allow "NOT IN" queries 01930 01931 h3(#a5). 1.0.a5 01932 01933 5/13/2009 01934 01935 * Corrected SQL syntax in @order_by_field()@ function of @Soo_Txp_Data@ class 01936 * Modified @tag()@ function of @Soo_Html@ class to handle a PHP 5.2.0 bug 01937 01938 h3(#a4). 1.0.a4 01939 01940 5/1/2009 01941 01942 Added @count()@ and @field()@ methods to the abstract @Soo_Txp_Data@ class. 01943 01944 h3(#a3). 1.0.a3 01945 01946 2/19/2009 01947 01948 Added "Expires" property to @Soo_Txp_Article@ and "load_order" property to @Soo_Txp_Plugin@. These fields were added in Textpattern version 4.0.7. 01949 01950 h3(#a2). 1.0.a2 01951 01952 2/5/2009 01953 01954 No significant changes, but added generic getters and setters (thanks to *jm* for the hint), making the file about 35% smaller. 01955 01956 h3(#a1). 1.0.a1 01957 01958 2/4/2009 01959 01960 01961 </div> 01962 # --- END PLUGIN HELP --- 01963 --> 01964 <?php 01965 } 01966 ?>
Generated on Fri Jan 7 2011 14:35:01 for soo_txp_obj by Doxygen 1.7.1