1: <?php
2:
3: namespace RedBeanPHP;
4:
5: use RedBeanPHP\ToolBox as ToolBox;
6: use RedBeanPHP\AssociationManager as AssociationManager;
7: use RedBeanPHP\OODBBean as OODBBean;
8:
9: /**
10: * RedBeanPHP Tag Manager.
11: *
12: * The tag manager offers an easy way to quickly implement basic tagging
13: * functionality.
14: *
15: * Provides methods to tag beans and perform tag-based searches in the
16: * bean database.
17: *
18: * @file RedBeanPHP/TagManager.php
19: * @author Gabor de Mooij and the RedBeanPHP community
20: * @license BSD/GPLv2
21: *
22: * @copyright
23: * copyright (c) G.J.G.T. (Gabor) de Mooij and the RedBeanPHP Community
24: * This source file is subject to the BSD/GPLv2 License that is bundled
25: * with this source code in the file license.txt.
26: */
27: class TagManager
28: {
29: /**
30: * @var ToolBox
31: */
32: protected $toolbox;
33:
34: /**
35: * @var AssociationManager
36: */
37: protected $associationManager;
38:
39: /**
40: * @var OODBBean
41: */
42: protected $redbean;
43:
44: /**
45: * Checks if the argument is a comma separated string, in this case
46: * it will split the string into words and return an array instead.
47: * In case of an array the argument will be returned 'as is'.
48: *
49: * @param array|string $tagList list of tags
50: *
51: * @return array
52: */
53: private function extractTagsIfNeeded( $tagList )
54: {
55: if ( $tagList !== FALSE && !is_array( $tagList ) ) {
56: $tags = explode( ',', (string) $tagList );
57: } else {
58: $tags = $tagList;
59: }
60:
61: return $tags;
62: }
63:
64: /**
65: * Finds a tag bean by it's title.
66: * Internal method.
67: *
68: * @param string $title title to search for
69: *
70: * @return OODBBean
71: */
72: protected function findTagByTitle( $title )
73: {
74: $beans = $this->redbean->find( 'tag', array( 'title' => array( $title ) ) );
75:
76: if ( $beans ) {
77: $bean = reset( $beans );
78:
79: return $bean;
80: }
81:
82: return NULL;
83: }
84:
85: /**
86: * Constructor.
87: * The tag manager offers an easy way to quickly implement basic tagging
88: * functionality.
89: *
90: * @param ToolBox $toolbox toolbox object
91: */
92: public function __construct( ToolBox $toolbox )
93: {
94: $this->toolbox = $toolbox;
95: $this->redbean = $toolbox->getRedBean();
96:
97: $this->associationManager = $this->redbean->getAssociationManager();
98: }
99:
100: /**
101: * Tests whether a bean has been associated with one ore more
102: * of the listed tags. If the third parameter is TRUE this method
103: * will return TRUE only if all tags that have been specified are indeed
104: * associated with the given bean, otherwise FALSE.
105: * If the third parameter is FALSE this
106: * method will return TRUE if one of the tags matches, FALSE if none
107: * match.
108: *
109: * Tag list can be either an array with tag names or a comma separated list
110: * of tag names.
111: *
112: * @param OODBBean $bean bean to check for tags
113: * @param array|string $tags list of tags
114: * @param boolean $all whether they must all match or just some
115: *
116: * @return boolean
117: */
118: public function hasTag( $bean, $tags, $all = FALSE )
119: {
120: $foundtags = $this->tag( $bean );
121:
122: $tags = $this->extractTagsIfNeeded( $tags );
123: $same = array_intersect( $tags, $foundtags );
124:
125: if ( $all ) {
126: return ( implode( ',', $same ) === implode( ',', $tags ) );
127: }
128:
129: return (bool) ( count( $same ) > 0 );
130: }
131:
132: /**
133: * Removes all sepcified tags from the bean. The tags specified in
134: * the second parameter will no longer be associated with the bean.
135: *
136: * Tag list can be either an array with tag names or a comma separated list
137: * of tag names.
138: *
139: * @param OODBBean $bean tagged bean
140: * @param array|string $tagList list of tags (names)
141: *
142: * @return void
143: */
144: public function untag( $bean, $tagList )
145: {
146: $tags = $this->extractTagsIfNeeded( $tagList );
147:
148: foreach ( $tags as $tag ) {
149: if ( $t = $this->findTagByTitle( $tag ) ) {
150: $this->associationManager->unassociate( $bean, $t );
151: }
152: }
153: }
154:
155: /**
156: * Tags a bean or returns tags associated with a bean.
157: * If $tagList is NULL or omitted this method will return a
158: * comma separated list of tags associated with the bean provided.
159: * If $tagList is a comma separated list (string) of tags all tags will
160: * be associated with the bean.
161: * You may also pass an array instead of a string.
162: *
163: * Tag list can be either an array with tag names or a comma separated list
164: * of tag names.
165: *
166: * @param OODBBean $bean bean to be tagged
167: * @param array|string $tagList a list of tags
168: *
169: * @return array
170: */
171: public function tag( OODBBean $bean, $tagList = NULL )
172: {
173: if ( is_null( $tagList ) ) {
174:
175: $tags = $bean->sharedTag;
176: $foundTags = array();
177:
178: foreach ( $tags as $tag ) {
179: $foundTags[] = $tag->title;
180: }
181:
182: return $foundTags;
183: }
184:
185: $this->associationManager->clearRelations( $bean, 'tag' );
186: $this->addTags( $bean, $tagList );
187:
188: return $tagList;
189: }
190:
191: /**
192: * Adds tags to a bean.
193: * If $tagList is a comma separated list of tags all tags will
194: * be associated with the bean.
195: * You may also pass an array instead of a string.
196: *
197: * Tag list can be either an array with tag names or a comma separated list
198: * of tag names.
199: *
200: * @param OODBBean $bean bean to add tags to
201: * @param array|string $tagList list of tags to add to bean
202: *
203: * @return void
204: */
205: public function addTags( OODBBean $bean, $tagList )
206: {
207: $tags = $this->extractTagsIfNeeded( $tagList );
208:
209: if ( $tagList === FALSE ) {
210: return;
211: }
212:
213: foreach ( $tags as $tag ) {
214: if ( !$t = $this->findTagByTitle( $tag ) ) {
215: $t = $this->redbean->dispense( 'tag' );
216: $t->title = $tag;
217:
218: $this->redbean->store( $t );
219: }
220:
221: $this->associationManager->associate( $bean, $t );
222: }
223: }
224:
225: /**
226: * Returns all beans that have been tagged with one or more
227: * of the specified tags.
228: *
229: * Tag list can be either an array with tag names or a comma separated list
230: * of tag names.
231: *
232: * @param string $beanType type of bean you are looking for
233: * @param array|string $tagList list of tags to match
234: * @param string $sql additional SQL (use only for pagination)
235: * @param array $bindings bindings
236: *
237: * @return array
238: */
239: public function tagged( $beanType, $tagList, $sql = '', $bindings = array() )
240: {
241: $tags = $this->extractTagsIfNeeded( $tagList );
242: $records = $this->toolbox->getWriter()->queryTagged( $beanType, $tags, FALSE, $sql, $bindings );
243:
244: return $this->redbean->convertToBeans( $beanType, $records );
245: }
246:
247: /**
248: * Returns all beans that have been tagged with ALL of the tags given.
249: *
250: * Tag list can be either an array with tag names or a comma separated list
251: * of tag names.
252: *
253: * @param string $beanType type of bean you are looking for
254: * @param array|string $tagList list of tags to match
255: *
256: * @return array
257: */
258: public function taggedAll( $beanType, $tagList, $sql = '', $bindings = array() )
259: {
260: $tags = $this->extractTagsIfNeeded( $tagList );
261: $records = $this->toolbox->getWriter()->queryTagged( $beanType, $tags, TRUE, $sql, $bindings );
262:
263: return $this->redbean->convertToBeans( $beanType, $records );
264: }
265: }
266: