/halogy/application/libraries/Tags.php

https://bitbucket.org/haloweb/halogy-1.0/ · PHP · 920 lines · 455 code · 142 blank · 323 comment · 58 complexity · dcc5639d53fb248525d6276297316b05 MD5 · raw file

  1. <?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
  2. /**
  3. * CodeIgniter
  4. *
  5. * An open source application development framework for PHP 4.3.2 or newer
  6. *
  7. * @package CodeIgniter
  8. * @author ExpressionEngine Dev Team
  9. * @copyright Copyright (c) 2006, EllisLab, Inc.
  10. * @license http://codeigniter.com/user_guide/license.html
  11. * @link http://codeigniter.com
  12. * @since Version 1.0
  13. * @filesource
  14. */
  15. // ------------------------------------------------------------------------
  16. /**
  17. * CX Tags Class Modified by Haloweb
  18. *
  19. * @package CXTags
  20. * @category Models
  21. * @author David Pennington <xeoncross.com>
  22. * @link http://code.google.com/p/cxtags/
  23. * @license http://www.gnu.org/copyleft/gpl.html
  24. * @version 1.1.0
  25. *
  26. * This class allows any table, and any type of system, to
  27. * add, edit, and delete tags from any object/row without
  28. * interfering with other tables that are also using tags.
  29. *
  30. *
  31. * Forexample, you have 58 articles on your blog that each
  32. * have 2-4 tags attached to them. Now you add a "Image Gallery"
  33. * to your site to showoff your photos. You want to "tag" each
  34. * photo with some key words (city, dark, night) that will help
  35. * people sort through all the images. With this class both
  36. * your articles and your images (and anything else you add) can
  37. * use the same "tags" table without interfering with each other.
  38. * Just because blog article 23 has the tag "sports" doesn't mean
  39. * that image 23 will return the tag "sports".
  40. *
  41. *
  42. *
  43. * About the variables:
  44. * (the fictitious tables "posts" and "images" used for examples)
  45. *
  46. * TABLE
  47. * The name of a table using tags (i.e. "posts", "images", etc..)
  48. * this allows us to tell the difference between a tag for row
  49. * 23 of the "images" table and row 23 of the "posts" table.
  50. *
  51. * ROW_ID
  52. * The row_id is the unique ID of a row from the table set in TABLE.
  53. * This id corasponds to a some row like "row 23" of the "posts" table.
  54. *
  55. * siteID
  56. * The ID of the user that created the tag. (for use with a "users" table)
  57. * This means that multiple users can each tag a TABLE row with their own
  58. * tags. This is optional so if you don't plan on starting another "de
  59. *
  60. * SAFE_TAG
  61. * This is a URL/file/etc. safe version of the TAG. (only [a-z0-9_])
  62. *
  63. * TAG
  64. * A cleaned (alphanumeric and spaces) catialized tag (only for display)
  65. *
  66. * TAG_ID
  67. * The Unique Id of the tag
  68. *
  69. * DATE
  70. * The date the tag was attached to a row
  71. *
  72. *
  73. * ABOUT THE CLASS FUNCTIONS
  74. * The following functions need a table name and a safe_tag
  75. * string or a tag_id to work. Never try to pass the plain "tag"
  76. * field to any of these functions as it won't work.
  77. *
  78. *
  79. /***************************** MySQL TABLES
  80. CREATE TABLE IF NOT EXISTS `ci_tags` (
  81. `id` int NOT NULL auto_increment,
  82. `safe_tag` varchar(30) NOT NULL,
  83. `tag` varchar(40) NOT NULL,
  84. PRIMARY KEY (`id`),
  85. UNIQUE KEY `safe_tag` (`safe_tag`)
  86. ) ENGINE=MyISAM ;
  87. CREATE TABLE IF NOT EXISTS `ci_tags_ref` (
  88. `tag_id` int unsigned NOT NULL,
  89. `row_id` int unsigned NOT NULL,
  90. `siteID` int unsigned NOT NULL,
  91. `date` int unsigned NOT NULL,
  92. `table` varchar(20) NOT NULL
  93. ) ENGINE=MyISAM ;
  94. ******************************************
  95. */
  96. class Tags {
  97. //The names of the tables
  98. var $CI;
  99. var $tags_ref = 'tags_ref';
  100. var $tags = 'tags';
  101. var $tags_prefix = null;
  102. var $tags_ref_prefix = null;
  103. var $siteID = null;
  104. function Tags() {
  105. $this->CI =& get_instance();
  106. //prefix the tags tables with the right thing
  107. $this->tags_prefix = $this->CI->db->dbprefix($this->tags);
  108. $this->tags_ref_prefix = $this->CI->db->dbprefix($this->tags_ref);
  109. // get siteID, if available
  110. if (defined('SITEID'))
  111. {
  112. $this->siteID = SITEID;
  113. }
  114. }
  115. /*
  116. * Fetch all tags for a given row/object and table
  117. *
  118. * $data = array(
  119. * 'table' => 'posts', //Name of the table row_id is from
  120. * 'row_id' => '1', //ID of the row that we want the tags for
  121. * 'siteID' => null, //Optional ID of a single user
  122. * 'limit' => 10, //Optional Max number of results
  123. * 'offset' => 0 //Optional Offset of results
  124. * );
  125. * @param array data about the tag(s) we are fetching
  126. * @return mixed
  127. */
  128. function fetch_tags($data) {
  129. //If there is no table
  130. if(!$data['table'] || !$data['row_id']) {
  131. return;
  132. }
  133. //Select the Tag info
  134. $this->CI->db->select('tag, safe_tag, id, date');
  135. $this->CI->db->distinct();
  136. $this->CI->db->join($this->tags,
  137. $this->tags_ref_prefix. '.tag_id = '. $this->tags_prefix. '.id', 'inner');
  138. $this->CI->db->where('table', $data['table']);
  139. $this->CI->db->where('row_id', $data['row_id']);
  140. //If a limit is implied
  141. if(isset($data['limit']) && $data['limit']) {
  142. $this->CI->db->limit($data['limit'],
  143. (isset($data['offset']) ? $data['offset'] : null)
  144. );
  145. }
  146. //If a siteID is given
  147. if(isset($data['siteID']) && $data['siteID']) {
  148. $this->CI->db->where($this->tags_ref_prefix. '.siteID', $data['siteID']);
  149. }
  150. $result = $this->CI->db->get($this->tags_ref);
  151. if ($result->num_rows())
  152. {
  153. return $result->result_array();
  154. }
  155. else
  156. {
  157. return FALSE;
  158. }
  159. }
  160. /*
  161. * Fetch the most popular/used tags
  162. *
  163. * $data = array(
  164. * 'table' => 'posts', //Name of the table row_id is from
  165. * 'siteID' => null, //Optional ID of a single user
  166. * 'limit' => 10, //Optional Max number of results
  167. * 'offset' => 0 //Optional Offset of results
  168. * );
  169. * @param array data about the tag(s) we are fetching
  170. * @return mixed
  171. */
  172. function fetch_popular_tags($data) {
  173. //If there is no table
  174. if(!$data['table']) {
  175. return;
  176. }
  177. //Select the Tag info
  178. $this->CI->db->select('tag, safe_tag, id, date, COUNT(*) as count');
  179. //$this->CI->db->distinct();
  180. $this->CI->db->join($this->tags,
  181. $this->tags_ref_prefix. '.tag_id = '. $this->tags_prefix. '.id', 'inner');
  182. $this->CI->db->where('table', $data['table']);
  183. $this->CI->db->order_by('count DESC, tag ASC');
  184. $this->CI->db->group_by('tag');
  185. //If a limit is NOT implied
  186. if(!isset($data['limit']) || !$data['limit']) {
  187. $data['limit'] = 50;
  188. }
  189. //Only fetch up to limit number of rows
  190. $this->CI->db->limit($data['limit'],
  191. (isset($data['offset']) ? $data['offset'] : null)
  192. );
  193. //If a siteID is given
  194. if(isset($data['siteID']) && $data['siteID']) {
  195. $this->CI->db->where($this->tags_ref_prefix. '.siteID', $data['siteID']);
  196. }
  197. $result = $this->CI->db->get($this->tags_ref);
  198. if ($result->num_rows())
  199. {
  200. return $result->result_array();
  201. }
  202. else
  203. {
  204. return FALSE;
  205. }
  206. }
  207. /*
  208. * Get tag data based on tag_id OR safe_tag
  209. *
  210. * @param string Name of the table to use
  211. * @param mixed Int (tag_id) or string (safe_tag)
  212. * @return mixed
  213. */
  214. function fetch_tag($piece=null) {
  215. //If no tag is given
  216. if(!$piece) { return; }
  217. //Is the $piece an ID or a TAG name?
  218. if(is_int($piece)) {
  219. $this->CI->db->where('id', $piece);
  220. } else {
  221. $this->CI->db->where('safe_tag', $piece);
  222. }
  223. $result = $this->CI->db->get($this->tags);
  224. if ($result->num_rows())
  225. {
  226. return $result->result_array();
  227. }
  228. else
  229. {
  230. return FALSE;
  231. }
  232. }
  233. /*
  234. * Fetch all rows/objects that use one or more safe_tag(s) or tag_id(s)
  235. *
  236. * $data = array(
  237. * 'table' => 'posts', //Name of the table row_id is from
  238. * 'tags' => '1', //tag_id, tag, or an array of either
  239. * 'siteID' = > null, //Optional only return rows for siteID
  240. * 'limit' => 10, //Optional Max number of results
  241. * 'offset' => 0 //Optional Offset of results
  242. * );
  243. * @param array data about the tag(s) we are fetching
  244. * @return mixed
  245. */
  246. function fetch_rows($data) {
  247. //If there is no table
  248. if(!$data['table'] || !$data['tags']) {
  249. return;
  250. }
  251. //Add the WHERE clause for the tags
  252. $this->where_tags($data['tags']);
  253. //Select the Tag info
  254. //$this->CI->db->select('tag, safe_tag, date, row_id, siteID');
  255. //Don't need tag/user info because the GROUP BY will only show 1
  256. //tag/user for each row (even if there are may)
  257. $this->CI->db->select('row_id');
  258. $this->CI->db->group_by("row_id");
  259. $this->CI->db->join($this->tags_ref,
  260. $this->tags_ref_prefix. '.tag_id = '. $this->tags_prefix. '.id', 'inner');
  261. $this->CI->db->where('table', $data['table']);
  262. //If a limit is implied
  263. if(isset($data['limit']) && $data['limit']) {
  264. $this->CI->db->limit($data['limit'],
  265. (isset($data['offset']) ? $data['offset'] : null)
  266. );
  267. }
  268. //If a siteID is given
  269. if(isset($data['siteID']) && $data['siteID']) {
  270. $this->CI->db->where($this->tags_ref_prefix. '.siteID', $data['siteID']);
  271. }
  272. $result = $this->CI->db->get($this->tags);
  273. if ($result->num_rows())
  274. {
  275. return $result->result_array();
  276. }
  277. else
  278. {
  279. return FALSE;
  280. }
  281. }
  282. /*
  283. * Count all the tags for a user and/or table
  284. *
  285. * $data = array(
  286. * 'table' => 'posts', //Name of the table row_id is from
  287. * 'siteID' => null, //Optional ID of a single user
  288. * );
  289. * @param array data about the tag(s) we are counting
  290. * @return mixed
  291. */
  292. function count_tags($data) {
  293. //If there is no table
  294. if(!$data['table']) {
  295. return;
  296. }
  297. /*
  298. * SELECT COUNT(DISTINCT `safe_tag`) as count FROM ci_tags
  299. * INNER JOIN ci_tags_ref ON (id = tag_id) WHERE `siteID` = 0 AND `table` = 'posts'
  300. */
  301. //Select the Tag info
  302. $this->CI->db->select('COUNT(*) as count');
  303. $this->CI->db->join($this->tags,
  304. $this->tags_ref_prefix. '.tag_id = '. $this->tags_prefix. '.id', 'inner');
  305. $this->CI->db->where('table', $data['table']);
  306. $this->CI->db->order_by('count DESC');
  307. //If a siteID is given
  308. if(isset($data['siteID']) && $data['siteID']) {
  309. $this->CI->db->where($this->tags_ref_prefix. '.siteID', $data['siteID']);
  310. }
  311. //fetch the number of rows
  312. $result = $this->CI->db->get($this->tags_ref);
  313. return $result->result();
  314. }
  315. /*
  316. * Insert tags for a row/object
  317. *
  318. * $data = array(
  319. * 'table' => 'posts', //Name of the table row_id is from
  320. * 'tags' => array('tag 1', 'tag 2'), //An array of tags
  321. * 'row_id' => 23,
  322. * 'siteID' = > null, //Optional only return rows for siteID
  323. * );
  324. * @param array data about the tag(s) we are creating
  325. * @return mixed
  326. */
  327. function add_tags($data=array()) {
  328. //If there is no table, row, or tags...
  329. if(!$data['table'] || !$data['tags'] || !$data['row_id']) {
  330. return;
  331. }
  332. //The array of tags -minus the $finalized_tags
  333. $tags = array();
  334. //This will store the table ID and safe_tag of each tag
  335. $finalized_tags = array();
  336. //This will store the "Cleaned" version for our where_tag() function
  337. $safe_tags = array();
  338. //STEP 1: Create the "safe" version of each tag
  339. foreach($data['tags'] as $key => $tag) {
  340. $safe_tag = $this->make_safe_tag($tag);
  341. //Add this tag to an array called $tags
  342. $tags[$safe_tag] = trim($tag);
  343. //Add it to an array of ONLY safe_tags
  344. $safe_tags[] = $safe_tag;
  345. }
  346. //STEP 2: Search DB for the tags already in there
  347. $this->CI->db->select('id, tag, safe_tag');
  348. $this->where_tags($safe_tags);
  349. $query = $this->CI->db->get($this->tags);
  350. //If some of these tags already exist
  351. if ($query->num_rows() > 0) {
  352. foreach ($query->result() as $row) {
  353. //Add this row to the finalized tags
  354. $finalized_tags[$row->safe_tag] = array(
  355. 'tag' => $row->tag,
  356. 'id' => $row->id
  357. );
  358. }
  359. /**
  360. * Now that we have an array of the tags from the DB
  361. * we can unset them from the $tags array so they aren't
  362. * added to the table a second time!
  363. */
  364. foreach($finalized_tags as $safe_tag => $tag) {
  365. if(isset($tags[$safe_tag])) {
  366. unset($tags[$safe_tag]);
  367. }
  368. }
  369. }
  370. //STEP 3: Insert each tag into our table since it isn't there already
  371. foreach($tags as $safe_tag => $tag) {
  372. // tidy tag
  373. $tag = ucwords(strtolower($tag));
  374. //Insert the tag into the database
  375. $this->CI->db->insert($this->tags, array('safe_tag' => $safe_tag, 'tag' => $tag));
  376. //Now that the tag is in the DB we need to add it to the finalized tags
  377. $finalized_tags[$safe_tag] = array('tag' => $tag, 'id' => $this->CI->db->insert_id());
  378. }
  379. //STEP 4: Attach each tag to the row
  380. //Row data that won't change doesn't need to be repeated!
  381. $row_data = array(
  382. '`table`' => $data['table'],
  383. 'row_id' => $data['row_id']
  384. );
  385. /* MOD: haloweb -- dont duplicate data in row by getting tags
  386. if ($tags_data = $this->fetch_tags($row_data))
  387. {
  388. foreach ($tags_data as $row)
  389. {
  390. $row_tags[$row['safe_tag']] = $row['tag'];
  391. }
  392. }
  393. */
  394. //If a siteID is given
  395. if(isset($data['siteID']) && $data['siteID']) {
  396. $row_data['siteID'] = $data['siteID'];
  397. }
  398. //For each tag - attach it to the row/object
  399. foreach($finalized_tags as $safe_tag => $tag) {
  400. //Data about the row
  401. $row_data['date'] = date("Y-m-d H:i:s");
  402. $row_data['tag_id'] = $tag['id'];
  403. /*
  404. if (!in_array($safe_tag, $row_tags))
  405. {
  406. $this->CI->db->insert($this->tags_ref, $row_data);
  407. }
  408. */
  409. //FINALLY INSERT THE ROW! ...(jeez)...
  410. $this->CI->db->insert($this->tags_ref, $row_data);
  411. }
  412. //return true;
  413. // Not sure why someone would need this..
  414. // but return the finalized array
  415. return $finalized_tags;
  416. }
  417. /*
  418. * Delete tag relationships to a row/object
  419. *
  420. * $data = array(
  421. * 'table' => 'posts', //Name of the table row_id is from
  422. * 'row_id' => 23,
  423. * 'siteID' => null //Optional only delete rows for siteID
  424. * );
  425. * @param array data about the tag_ref we are deleting
  426. * @return mixed
  427. */
  428. function delete_tag_ref($data) {
  429. //If there is no table or row_id
  430. if(!$data['table'] || !$data['row_id']) {
  431. return;
  432. }
  433. //If a user is set - only delete tags for that user
  434. if(isset($data['siteID']) && $data['siteID']) {
  435. $this->CI->db->where('siteID', $data['siteID']);
  436. }
  437. //Delete all tags_ref where this table and row are found
  438. $this->CI->db->where('table', $data['table']);
  439. $this->CI->db->where('row_id', $data['row_id']);
  440. $this->CI->db->delete($this->tags_ref);
  441. //return the rows deleted
  442. $rows = $this->CI->db->affected_rows();
  443. //Delete tags that are no-longer referenced by any row
  444. $this->delete_tags();
  445. return $rows;
  446. }
  447. /*
  448. * Delete all tags from a given user
  449. *
  450. * $data = array(
  451. * 'table' => 'posts', //Name of the table row_id is from
  452. * 'siteID' = > null, //Optional only delete rows for siteID
  453. * );
  454. * @param array data about the tag_ref we are deleting
  455. * @return mixed
  456. */
  457. function delete_user_tags($data) {
  458. //If there is no table or row_id
  459. if(!$data['table'] || !$data['siteID']) {
  460. return;
  461. }
  462. //Where the tag is used by this user
  463. $this->CI->db->where('siteID', $data['siteID']);
  464. //Delete all tags_ref where this table and row are found
  465. $this->CI->db->delete($this->tags_ref);
  466. //return the rows deleted
  467. $rows = $this->CI->db->affected_rows();
  468. //Delete tags that are no-longer referenced by any row
  469. $this->delete_tags();
  470. return $rows;
  471. }
  472. /*
  473. * Delete tags not referenced by any row/object.
  474. *
  475. * Because CI does NOT support DELETE...JOIN syntax
  476. * will will have to do a SELECT first and then delete
  477. * the result rows.
  478. *
  479. * @return Int
  480. */
  481. function delete_tags() {
  482. /*
  483. //Join it to the tags_ref to make sure no rows are found
  484. $this->CI->db->join('tags_ref', 'tags.id = tags_ref.tag_id');
  485. //the tag_id is NULL (not found)
  486. $this->CI->db->where('tag_id', null);
  487. $this->CI->db->delete('tags');
  488. //return the rows deleted
  489. return $this->CI->db->affected_rows();
  490. */
  491. $this->CI->db->select('id');
  492. //Join it to the tags_ref to make sure no rows are found
  493. $this->CI->db->join($this->tags_ref,
  494. $this->tags_ref_prefix. '.tag_id = '. $this->tags_prefix. '.id', 'left');
  495. //the tag_id is NULL (not found)
  496. $this->CI->db->where('tag_id', null);
  497. $result = $this->CI->db->get($this->tags);
  498. //If there are NO lost tags - just return
  499. if(!$result->num_rows()) {
  500. return 0;
  501. }
  502. //Colect the ids
  503. foreach($result->result() as $row) {
  504. $ids[] = $row->id;
  505. }
  506. //Delete all ids found in this list
  507. $this->CI->db->where_in('id', $ids);
  508. $this->CI->db->delete($this->tags);
  509. //return the rows deleted
  510. return $this->CI->db->affected_rows();
  511. }
  512. function get_tags($table, $ID)
  513. {
  514. // get tags
  515. $tags = $this->fetch_tags(array(
  516. 'table' => $table,
  517. 'row_id' => $ID
  518. ));
  519. if ($tags)
  520. {
  521. foreach($tags as $tag)
  522. {
  523. $tagsArray[] = $tag['tag'];
  524. }
  525. return $tagsArray;
  526. }
  527. else
  528. {
  529. return FALSE;
  530. }
  531. }
  532. function get_popular_tags($table, $limit = 10)
  533. {
  534. // get tags
  535. $tags = $this->fetch_popular_tags(array(
  536. 'table' => $table,
  537. 'siteID' => $this->siteID,
  538. 'limit' => $limit
  539. ));
  540. if ($tags)
  541. {
  542. return $tags;
  543. }
  544. else
  545. {
  546. return FALSE;
  547. }
  548. }
  549. function update_tags($table, $ID = '', $tags = '')
  550. {
  551. // add tags
  552. if ($tags)
  553. {
  554. $data = array(
  555. 'table' => $table,
  556. 'row_id' => $ID
  557. );
  558. if ($this->siteID)
  559. {
  560. $data['siteID'] = $this->siteID;
  561. }
  562. $this->delete_tag_ref($data);
  563. $tagsArray = explode(',', $tags);
  564. foreach($tagsArray as $key => $tag)
  565. {
  566. $tag = trim($tag);
  567. if (isset($tag) && $tags != '' && strlen($tag) > 0)
  568. {
  569. $tidyTagsArray[] = $tag;
  570. }
  571. }
  572. $tags = array(
  573. 'table' => $table,
  574. 'tags' => $tidyTagsArray,
  575. 'row_id' => $ID
  576. );
  577. if ($this->siteID)
  578. {
  579. $tags['siteID'] = $this->siteID;
  580. }
  581. $this->add_tags($tags);
  582. return TRUE;
  583. }
  584. else
  585. {
  586. return FALSE;
  587. }
  588. }
  589. function search($table, $tags = '')
  590. {
  591. $tags = explode(' ', $tags);
  592. $tagdata = array(
  593. 'table' => $table, //Name of the table row_id is from
  594. 'tags' => $tags, //tag_id, tag, or an array of either
  595. 'limit' => null, //Optional Max number of results
  596. 'offset' => null, //Optional Offset of results
  597. );
  598. if ($this->siteID)
  599. {
  600. $tagdata['siteID'] = $this->siteID;
  601. }
  602. if ($object = $this->fetch_rows($tagdata))
  603. {
  604. if ($rows = $object->result())
  605. {
  606. foreach($rows as $row => $key)
  607. {
  608. $ids[] = $key->row_id;
  609. }
  610. return $ids;
  611. }
  612. else
  613. {
  614. return FALSE;
  615. }
  616. }
  617. else
  618. {
  619. return FALSE;
  620. }
  621. }
  622. function tag_cloud($table, $limit = 10, $maxSize = 150, $minSize = 100)
  623. {
  624. // get tag data
  625. $tagdata = array(
  626. 'table' => $table,
  627. 'siteID' => $this->siteID,
  628. 'limit' => $limit
  629. );
  630. $result = $this->fetch_popular_tags($tagdata);
  631. $tags = $result->result_array();
  632. // populate tag count array
  633. if ($tags)
  634. {
  635. // get sizes of tags
  636. foreach($tags as $tag)
  637. {
  638. $tagsCount[$tag['tag']] = $tag['count'];
  639. }
  640. // get the largest and smallest array values
  641. $maxQty = max(array_values($tagsCount));
  642. $minQty = min(array_values($tagsCount));
  643. // find range of values
  644. $range = $maxQty['count'] - $minQty['count'];
  645. // don't divide by zero
  646. if (0 == $range)
  647. {
  648. $range = 1;
  649. }
  650. // determine the font-size increment
  651. $step = ($maxSize - $minSize) / ($range);
  652. // populate tag array
  653. foreach($tags as $tag)
  654. {
  655. $size = $minSize + (($tag['count'] - $minQty) * $step);
  656. $tagsArray[$tag['tag']] = array('safe_tag' => $tag['safe_tag'], 'size' => $size);
  657. }
  658. // load output vars
  659. $data['tags'] = $tagsArray;
  660. $data['step'] = $step;
  661. $data['maxQty'] = $maxQty;
  662. $data['minQty'] = $minQty;
  663. $data['maxSize'] = $maxSize;
  664. $data['minSize'] = $minSize;
  665. return $data;
  666. }
  667. else
  668. {
  669. return FALSE;
  670. }
  671. }
  672. /*
  673. * SUPPORT FUNCTIONS
  674. */
  675. /*
  676. * Turn a comma-separated string into an array of elements
  677. * @param string The string from an input box or something
  678. * @return array
  679. */
  680. function comma_to_array($string='') {
  681. /*
  682. //Can handle even the most messed-up comma strings like below:
  683. $tags = "\n\r". 'tag1, this is tag2, or tag3. but we can\'t tag4, tag5, other '. "\n".
  684. 'tag6, "plus tag7", #tag8,'. "\n\n". ',,,, ,,,,, ,,,'. "\n". ',, '.
  685. "\n\n\n". '< this is another, tag9.,, , ';
  686. */
  687. //Make the String lowercase
  688. $string = trim(strtolower($string));
  689. //Replace anything that isn't a letter, comma, space, quote, or number!
  690. $string = preg_replace("/[^a-z0-9, \"']/", '', $string);
  691. //Remove empty "," so that we don't make empty elements
  692. $string = preg_replace("/,[^a-z0-9]*,/", ',', $string);
  693. //If there is an ending comma.... kill it!
  694. $string = rtrim($string, ',');
  695. //Turn the string into an array of tags
  696. $string = explode(',', $string);
  697. //Remove extra spaces from front and back of each element and capitalize
  698. foreach($string as $key => $tag) {
  699. $string[$key] = trim(ucwords($tag));
  700. }
  701. return $string;
  702. }
  703. /*
  704. * Make a tag safe for file & URL usage
  705. * @param string the tag to clean
  706. * @return string cleaned tag
  707. */
  708. function make_safe_tag($tag='') {
  709. $tag = strtolower($tag);
  710. //remove anything not alphanumeric OR "_"
  711. $tag = preg_replace("/([^a-z0-9_\-]+)/i", '-', $tag);
  712. //remove duplicate "_"
  713. $tag = preg_replace("/(-{2,})+/", '-', $tag);
  714. //remove posible start/end "_"
  715. $tag = trim($tag, '-');
  716. return $tag;
  717. }
  718. /*
  719. * Adds a WHERE Clause to a query. Pass this function a single
  720. * tag_id/safe_tag - or an array of tag_ids/safe_tags.
  721. *
  722. * @param mixed string or array of tag_id's or safe_tags
  723. */
  724. function where_tags($tags) {
  725. //If we have been given an array of tags to match
  726. if(is_array($tags)) {
  727. $ints = null;
  728. $strings = null;
  729. //Check each tag to see if it is an ID or a name
  730. foreach($tags as $tag) {
  731. if(is_int($tag)) {
  732. $ints[] = $tag;
  733. } else {
  734. $strings[] = $tag;
  735. }
  736. }
  737. //If some ID's were given
  738. if($ints) {
  739. $this->CI->db->where_in('id', $ints);
  740. }
  741. //If some tag names where given
  742. if($strings) {
  743. //If Int's are in the query we need an OR clause
  744. if($ints) {
  745. $this->CI->db->or_where_in('safe_tag', $strings);
  746. } else {
  747. $this->CI->db->where_in('safe_tag', $strings);
  748. }
  749. }
  750. //Else we are just looking for a rows that match one tag/ID
  751. } else {
  752. if(is_int($tags)) {
  753. $this->CI->db->where('id', $tags);
  754. } else {
  755. $this->CI->db->where('safe_tag', $tags);
  756. }
  757. }
  758. }
  759. }