00001 <?php
00002
00017 namespace Habari;
00018
00023 class Term extends QueryRecord
00024 {
00025 protected $inforecords = null;
00026
00027 public $unsetfields = array(
00028 'object_id' => 'object_id',
00029 'type' => 'type',
00030 );
00031
00036 public static function default_fields()
00037 {
00038 return array(
00039 'id' => 0,
00040 'term' => '',
00041 'term_display' => '',
00042 'vocabulary_id' => 0,
00043 'mptt_left' => 0,
00044 'mptt_right' => 0
00045 );
00046 }
00047
00054 public function __construct( $paramarray = array() )
00055 {
00056
00057 $this->fields = array_merge(
00058 self::default_fields(),
00059 $this->fields
00060 );
00061
00062 if ( is_string( $paramarray ) ) {
00063 $paramarray = array(
00064 'term_display' => $paramarray,
00065 'term' => Utils::slugify( $paramarray ),
00066 );
00067 }
00068
00069 parent::__construct( $paramarray );
00070
00071
00072
00073
00074
00075 if ( $this->term == '' ) {
00076 $this->fields[ 'term' ] = Utils::slugify( $this->fields[ 'term_display' ] );
00077 }
00078
00079 $this->exclude_fields( 'id' );
00080 }
00081
00087 protected function setslug()
00088 {
00089 $value = '';
00090
00091
00092 if ( isset( $this->newfields[ 'term' ] ) && $this->newfields[ 'term' ] != '' ) {
00093 $value = $this->newfields[ 'term' ];
00094 }
00095
00096 elseif ( $this->fields[ 'term' ] != '' ) {
00097 $value = $this->fields[ 'term' ];
00098 }
00099
00100 elseif ( isset( $this->newfields[ 'term_display' ] ) && $this->newfields[ 'term_display' ] != '' ) {
00101 $value = $this->newfields[ 'term_display' ];
00102 }
00103
00104 elseif ( $this->fields[ 'term_display' ] != '' ) {
00105 $value = $this->fields[ 'term_display' ];
00106 }
00107
00108
00109 $slug = Plugins::filter( 'term_setslug', $value );
00110 $slug = Utils::slugify( $slug );
00111 $postfix = '';
00112 $postfixcount = 0;
00113 do {
00114 if ( ! $slugcount = DB::get_row( 'SELECT COUNT(term) AS ct FROM {terms} WHERE term = ? AND vocabulary_id = ?;', array( $slug . $postfix, $this->fields['vocabulary_id'] ) ) ) {
00115 Utils::debug( DB::get_errors() );
00116 exit;
00117 }
00118 if ( $slugcount->ct != 0 ) {
00119 $postfix = "-" . ( ++$postfixcount );
00120 }
00121 } while ( $slugcount->ct != 0 );
00122
00123 return $this->newfields[ 'term' ] = $slug . $postfix;
00124 }
00125
00130 public function insert()
00131 {
00132 $this->setslug();
00133
00134
00135 $allow = true;
00136 $allow = Plugins::filter( 'term_insert_allow', $allow, $this );
00137 $allow = $this->is_valid();
00138 if ( !$allow ) {
00139 return $allow;
00140 }
00141 Plugins::act( 'term_insert_before', $this );
00142
00143 $result = parent::insertRecord( DB::table( 'terms' ) );
00144
00145
00146 $this->newfields[ 'id' ] = DB::last_insert_id();
00147
00148
00149 $this->fields = array_merge( $this->fields, $this->newfields );
00150
00151
00152 $this->newfields = array();
00153
00154
00155 $this->info->commit( $this->fields['id'] );
00156
00157 EventLog::log( _t( 'New term %1$s: %2$s', array( $this->id, $this->term_display ) ), 'info', 'content', 'habari' );
00158
00159
00160 Plugins::act( 'term_insert_after', $this );
00161
00162 return $result;
00163 }
00164
00169 public function update()
00170 {
00171
00172 $allow = true;
00173 $allow = Plugins::filter( 'term_update_allow', $allow, $this );
00174 $allow = $this->is_valid();
00175 if ( !$allow ) {
00176 return;
00177 }
00178 Plugins::act( 'term_update_before', $this );
00179
00180
00181 if ( isset( $this->newfields[ 'term' ] ) && $this->newfields[ 'term' ] != '' ) {
00182 if ( $this->fields[ 'term' ] != $this->newfields[ 'term' ] ) {
00183 $this->setslug();
00184 }
00185 }
00186
00187 $result = parent::updateRecord( '{terms}', array( 'id' => $this->id ) );
00188 $this->fields = array_merge( $this->fields, $this->newfields );
00189
00190 $this->info->commit();
00191
00192
00193 Plugins::act( 'term_update_after', $this );
00194
00195 return $result;
00196 }
00197
00201 public function delete()
00202 {
00203
00204 $allow = true;
00205 $allow = Plugins::filter( 'term_delete_allow', $allow, $this );
00206 if ( !$allow ) {
00207 return false;
00208 }
00209 Plugins::act( 'term_delete_before', $this );
00210
00211
00212 $this->info->delete_all();
00213
00214 DB::query( 'DELETE FROM {object_terms} WHERE term_id = :id', array( 'id' => $this->id ) );
00215
00216 $result = parent::deleteRecord( '{terms}', array( 'id'=>$this->id ) );
00217 EventLog::log( _t( 'Term %1$s (%2$s) deleted.', array( $this->id, $this->term_display ) ), 'info', 'content', 'habari' );
00218
00219
00220 Plugins::act( 'term_delete_after', $this );
00221 return $result;
00222 }
00223
00228 public function ancestors()
00229 {
00230 $params = array( 'vocab_id' => $this->vocabulary_id, 'left' => $this->mptt_left, 'right' => $this->mptt_right );
00231 $query = 'SELECT * FROM {terms} WHERE vocabulary_id=:vocab_id AND mptt_left<:left AND mptt_right>:right ORDER BY mptt_left ASC';
00232 return DB::get_results( $query, $params, 'Term' );
00233 }
00234
00239 public function not_ancestors()
00240 {
00241 $params = array( 'vocab_id' => $this->vocabulary_id, 'left' => $this->mptt_left, 'right' => $this->mptt_right );
00242 $query = 'SELECT * FROM {terms} WHERE vocabulary_id=:vocab_id AND (mptt_left>:left OR mptt_right<:right) ORDER BY mptt_left ASC';
00243 return DB::get_results( $query, $params, 'Term' );
00244 }
00245
00250 public function descendants()
00251 {
00252 $params = array( 'vocab_id' => $this->vocabulary_id, 'left' => $this->mptt_left, 'right' => $this->mptt_right );
00253 $query = 'SELECT * FROM {terms} WHERE vocabulary_id=:vocab_id AND mptt_left>:left AND mptt_right<:right ORDER BY mptt_left ASC';
00254 return DB::get_results( $query, $params, 'Term' );
00255 }
00256
00261 public function not_descendants()
00262 {
00263 $params = array( 'vocab_id' => $this->vocabulary_id, 'left' => $this->mptt_left, 'right' => $this->mptt_right );
00264 $query = 'SELECT * FROM {terms} WHERE vocabulary_id=:vocab_id AND mptt_left NOT BETWEEN :left AND :right ORDER BY mptt_left ASC';
00265 return DB::get_results( $query, $params, 'Term' );
00266 }
00267
00272 public function is_descendant_of( Term $term )
00273 {
00274 if ( $this->vocabulary_id != $term->vocabulary_id ) {
00275 return false;
00276 }
00277 if ( ( $this->mptt_left > $term->mptt_left ) && ( $this->mptt_right < $term->mptt_right ) ) {
00278 return true;
00279 }
00280 return false;
00281 }
00282
00287 public function is_ancestor_of( Term $term )
00288 {
00289 if ( $this->vocabulary_id != $term->vocabulary_id ) {
00290 return false;
00291 }
00292 if ( ( $this->mptt_left < $term->mptt_left ) && ( $this->mptt_right > $term->mptt_right ) ) {
00293 return true;
00294 }
00295 return false;
00296 }
00297
00302 public function parent()
00303 {
00304 $params = array( 'vocab_id' => $this->vocabulary_id, 'left' => $this->mptt_left, 'right' => $this->mptt_right );
00305 $query = 'SELECT * FROM {terms} WHERE vocabulary_id=:vocab_id AND mptt_left<:left AND mptt_right>:right ORDER BY mptt_left DESC LIMIT 1';
00306 return DB::get_row( $query, $params, 'Term' );
00307 }
00308
00313 public function siblings()
00314 {
00315 $parent = $this->parent();
00316 if ( $parent ) {
00317 return $parent->children();
00318 }
00319 else {
00320 return $this->vocabulary->get_root_terms();
00321 }
00322 }
00323
00328 public function children()
00329 {
00330 $params = array( 'vocab' => $this->vocabulary_id,
00331 'left' => $this->mptt_left,
00332 'right' => $this->mptt_right
00333 );
00340 $query = <<<SQL
00341 SELECT child.term as term,
00342 child.term_display as term_display,
00343 child.mptt_left as mptt_left,
00344 child.mptt_right as mptt_right,
00345 child.vocabulary_id as vocabulary_id,
00346 child.id as id
00347 FROM {terms} as parent
00348 INNER JOIN {terms} as child
00349 ON child.mptt_left BETWEEN parent.mptt_left AND parent.mptt_right
00350 AND child.vocabulary_id = parent.vocabulary_id
00351 WHERE parent.mptt_left > :left AND parent.mptt_right < :right
00352 AND parent.vocabulary_id = :vocab
00353 GROUP BY child.term
00354 HAVING COUNT(child.term)=1
00355 ORDER BY mptt_left
00356 SQL;
00357 return new Terms(DB::get_results( $query, $params, 'Term' ));
00358 }
00359
00366 public function objects( $type )
00367 {
00368 $type_id = Vocabulary::object_type_id( $type );
00369 $results = DB::get_column( "SELECT object_id FROM {object_terms} WHERE term_id = ? AND object_type_id = ?", array( $this->id, $type_id ) );
00370 return $results;
00371 }
00372
00378 public function object_types()
00379 {
00380 $results = DB::get_results( 'SELECT terms.object_id, types.name as `type` FROM {object_terms} terms, {object_types} types WHERE terms.object_type_id = types.id and term_id = :term_id', array( 'term_id' => $this->id ) );
00381 return $results;
00382 }
00383
00390 public function object_count( $type )
00391 {
00392 $type_id = Vocabulary::object_type_id( $type );
00393 $result = DB::get_value( "SELECT count(object_id) FROM {object_terms} WHERE term_id = ? AND object_type_id = ?", array( $this->id, $type_id ) );
00394 return $result;
00395 }
00396
00403 public function associate( $type, $id )
00404 {
00405 $result = true;
00406 $type_id = Vocabulary::object_type_id( $type );
00407
00408 Plugins::act( 'term_associate_to_object_before', $this->id, $id, $type_id );
00409
00410 if ( ! DB::exists( "{object_terms}", array( 'term_id' => $this->id, 'object_id' => $id, 'object_type_id' => $type_id ) ) ) {
00411 $result = DB::insert( "{object_terms}", array( 'term_id' => $this->id, 'object_id' => $id, 'object_type_id' => $type_id ) );
00412 }
00413
00414 Plugins::act( 'term_associate_to_object_after', $this->id, $id, $type_id );
00415
00416 return $result;
00417 }
00418
00425 public function dissociate( $type = null, $id = null )
00426 {
00427 $result = true;
00428
00429 $type_id = Vocabulary::object_type_id( $type );
00430 Plugins::act( 'term_dissociate_from_object_before', $this->id, $id, $type_id );
00431
00432 $result = DB::query( "DELETE FROM {object_terms} WHERE term_id = ? AND object_id = ? AND object_type_id = ?", array( $this->id, $id, $type_id ) );
00433
00434 Plugins::act( 'term_dissociate_from_object_after', $this->id, $id, $type_id, $result );
00435
00436 return $result;
00437 }
00438
00444 public function __tostring()
00445 {
00446 return $this->term_display;
00447 }
00448
00455 public function __get( $name )
00456 {
00457 switch ( $name ) {
00458 case 'vocabulary':
00459 $out = Vocabulary::get_by_id( $this->vocabulary_id );
00460 break;
00461 case 'tag_text_searchable':
00462
00463 if ( strpos( $this->term_display, ' ' ) !== false || strpos( $this->term_display, ',' ) !== false ) {
00464 $out = '\'' . str_replace( "'", "\'", $this->term_display ) . '\'';
00465 }
00466 else {
00467 $out = $this->term_display;
00468 }
00469 break;
00470 case 'count':
00471 $out = (int)$this->count();
00472 break;
00473 case 'id':
00474 return (int)parent::__get( $name );
00475 case 'info':
00476 return $this->get_info();
00477 default:
00478 $out = parent::__get( $name );
00479 break;
00480 }
00481 return $out;
00482 }
00483
00489 protected function get_info()
00490 {
00491 if ( ! $this->inforecords ) {
00492 if ( 0 == $this->id ) {
00493 $this->inforecords = new TermInfo();
00494 }
00495 else {
00496 $this->inforecords = new TermInfo( $this->id );
00497 }
00498 }
00499 return $this->inforecords;
00500 }
00501
00507 public function count( $object_type = 'post' )
00508 {
00509 return $this->object_count( $object_type );
00510 }
00511
00518 public function __call( $name, $args )
00519 {
00520 array_unshift( $args, 'term_call_' . $name, null, $this );
00521 return call_user_func_array( Method::create( '\\Habari\\Plugins', 'filter' ), $args );
00522 }
00523
00531 public static function get( $term, $term_class = 'Term' )
00532 {
00533 $query = '';
00534 if ( $term instanceof Term ) {
00535
00536
00537 $params[ 'term_id' ] = $term->id;
00538 $query = 'SELECT * FROM {terms} WHERE id = ABS(:term_id)';
00539 }
00540 elseif ( is_string( $term ) ) {
00541 $params[ 'term' ] = $term;
00542 $query = 'SELECT * FROM {terms} WHERE (term = :term OR term_display = :term) ORDER BY term <> :term';
00543 }
00544 elseif ( is_int( $term ) ) {
00545 $params[ 'term_id' ] = $term;
00546 $query = 'SELECT * FROM {terms} WHERE id = ABS(:term_id)';
00547 }
00548 return DB::get_row( $query, $params, $term_class );
00549 }
00550
00555 protected function is_valid()
00556 {
00557 if( strlen( trim( $this->term_display ) ) && strlen( trim( $this->term ) ) && $this->vocabulary_id != 0 ) {
00558 return true;
00559 }
00560 else {
00561 return false;
00562 }
00563 }
00564 }
00565
00566 ?>