1<?php
2/**
3 * Copyright 2008-2017 Horde LLC (http://www.horde.org/)
4 *
5 * @author     Michael J Rubinsky <mrubinsk@horde.org>
6 * @author     Chuck Hagenbuch <chuck@horde.org>
7 * @category   Horde
8 * @package    Content
9 * @subpackage UnitTests
10 */
11class Content_Test_Base extends Horde_Test_Case
12{
13    /**
14     * @static Content_Tagger
15     */
16    static $tagger;
17    static $type_mgr;
18
19    /**
20     * Primes the fixture, and tests basic tagging functionality where all
21     * bits of data are new (user, type, object, tag)..
22     *
23     */
24    protected function _create()
25    {
26
27        $this->_testEmpty();
28
29        // user alice tags an event named 'party' with the tag 'personal' and
30        // an event named 'anniversary' with the tag 'personal'
31        self::$tagger->tag('alice', array('type' => 'event', 'object' => 'party'), 'play', new Horde_Date('2008-01-01T00:10:00'));
32
33        // user alice tags an event named 'office hours' with the tag 'work'
34        self::$tagger->tag('alice', array('type' => 'event', 'object' => 'office hours'), 'work', new Horde_Date('2008-01-01T00:05:00'));
35
36        // user bob tags a blog named 'daring fireball' with the tag 'apple'
37        self::$tagger->tag('bob', array('type' => 'blog', 'object' => 'daring fireball'), 'apple', new Horde_Date('2008-01-01T00:20:00'));
38
39        // Two users have tagged the same object, with the same tag
40        self::$tagger->tag('alice', array('type' => 'event', 'object' => 'anniversary'), 'personal', new Horde_Date('2009-01-01T00:05:00'));
41        self::$tagger->tag('bob', array('type' => 'event', 'object' => 'anniversary'), 'personal', new Horde_Date('2009-01-01T00:06:00'));
42    }
43
44    protected function _testEmpty()
45    {
46        // Basic check that no data exists.
47        $this->assertEmpty(self::$tagger->getTags(array()));
48        $this->assertEmpty(self::$tagger->getRecentTags());
49        $this->assertEmpty(self::$tagger->getRecentObjects());
50    }
51
52    /**
53     * Test types
54     *
55     */
56    protected function _testEnsureTypes()
57    {
58        $this->assertEquals(array(0 => 1, 1 => 2), self::$type_mgr->ensureTypes(array('event', 'blog')));
59        $this->assertEquals(array(0 => 2, 1 => 1), self::$type_mgr->ensureTypes(array('blog', 'event')));
60        $this->assertEquals(array(0 => 3, 1 => 2), self::$type_mgr->ensureTypes(array('foo', 'blog')));
61    }
62
63    /**
64     * Test ensureTags.
65     *
66     * 1 => play
67     * 2 => work
68     * 3 => apple
69     * 4 => personal
70     */
71    protected function _testEnsureTags()
72    {
73        // Test passing tag_ids to ensureTags
74        $this->assertEquals(array(1 => 1), self::$tagger->ensureTags(1));
75        $this->assertEquals(array(1 => 1), self::$tagger->ensureTags(array(1)));
76        $this->assertEquals(array(1 => 1, 2 => 2), self::$tagger->ensureTags(array(1, 2)));
77
78        // Test passing tag names
79        $this->assertEquals(array('work' => 2), self::$tagger->ensureTags('work'));
80        $this->assertEquals(array('work' => 2), self::$tagger->ensureTags(array('work')));
81        $this->assertEquals(array('work' => 2, 'play' => 1), self::$tagger->ensureTags(array('work', 'play')));
82
83        // Test mixed
84        $this->assertEquals(array(1 => 1, 'play' => 1), self::$tagger->ensureTags(array(1, 'play')));
85        $this->assertEquals(array(2 => 2, 'work' => 2), self::$tagger->ensureTags(array('work', 2)));
86        $this->assertEquals(array(1 => 1, 'work' => 2), self::$tagger->ensureTags(array(1, 'work')));
87    }
88
89    protected function _testFullTagCloudSimple()
90    {
91        $expected = array(
92            '1' => array(
93                'tag_id' => 1,
94                'tag_name' => 'play',
95                'count' => 1
96            ),
97
98            '2' => array(
99                'tag_id' => 2,
100                'tag_name' => 'work',
101                'count' => 1
102            ),
103
104            '3' => array(
105                'tag_id' => 3,
106                'tag_name' => 'apple',
107                'count' => 1
108            ),
109
110            '4' => array(
111                'tag_id' => 4,
112                'tag_name' => 'personal',
113                'count' => 2
114            )
115        );
116
117        $cloud = self::$tagger->getTagCloud();
118        $this->assertEquals($expected, $cloud);
119    }
120
121    protected function _testTagCloudByType()
122    {
123        $expected = array(
124            '3' => array(
125                'tag_id' => 3,
126                'tag_name' => 'apple',
127                'count' => 1
128            )
129        );
130        $cloud = self::$tagger->getTagCloud(array('typeId' => 'blog'));
131        $this->assertEquals($expected, $cloud);
132    }
133
134    protected function _testTagCloudByUser()
135    {
136        $expected = array(
137            '3' => array(
138                'tag_id' => 3,
139                'tag_name' => 'apple',
140                'count' => 1
141            ),
142            '4' => array(
143                'tag_id' => 4,
144                'tag_name' => 'personal',
145                'count' => 1
146            )
147        );
148        $cloud = self::$tagger->getTagCloud(array('userId' => 'bob'));
149        $this->assertEquals($expected, $cloud);
150    }
151
152    protected function _testTagCloudByUserType()
153    {
154        $expected = array(
155            '1' => array(
156                'tag_id' => 1,
157                'tag_name' => 'play',
158                'count' => 1
159            ),
160            '2' => array(
161                'tag_id' => 2,
162                'tag_name' => 'work',
163                'count' => 1
164            ),
165            '4' => array(
166                'tag_id' => 4,
167                'tag_name' => 'personal',
168                'count' => 1
169            )
170        );
171        $cloud = self::$tagger->getTagCloud(array('userId' => 'alice', 'typeId' => 'event'));
172        $this->assertEquals($expected, $cloud);
173    }
174
175    protected function _testTagCloudByTagType()
176    {
177        $expected = array(
178            '2' => array(
179                'tag_id' => 2,
180                'tag_name' => 'work',
181                'count' => 1
182            )
183        );
184        $cloud = self::$tagger->getTagCloud(array('tagIds' => array(2), 'typeId' => 'event'));
185        $this->assertEquals($expected, $cloud);
186    }
187
188    protected function _testTagCloudByTagIds()
189    {
190        $expected = array(
191            '2' => array(
192                'tag_id' => 2,
193                'tag_name' => 'work',
194                'count' => 1
195            ),
196            '4' => array(
197                'tag_id' => 4,
198                'tag_name' => 'personal',
199                'count' => 2
200            )
201        );
202        $cloud = self::$tagger->getTagCloud(array('tagIds' => array(2, 4)));
203        $this->assertEquals($expected, $cloud);
204    }
205
206    protected function _testGetRecentTags()
207    {
208        $recent = self::$tagger->getRecentTags();
209        $this->assertEquals(4, count($recent));
210        $this->assertEquals(4, $recent[0]['tag_id']);
211        $this->assertEquals('personal', $recent[0]['tag_name']);
212        $date = new Horde_Date($recent[0]['created']);
213        $this->assertEquals(1230764760, $date->timestamp());
214    }
215
216    protected function _testGetRecentTagsByUser()
217    {
218        $recent = self::$tagger->getRecentTags(array('userId' => 1));
219        $this->assertEquals(3, count($recent));
220
221        $recent = self::$tagger->getRecentTags(array('userId' => 2));
222        $this->assertEquals(2, count($recent));
223
224        $recent = self::$tagger->getRecentTags(array('userId' => 'alice'));
225        $this->assertEquals(3, count($recent));
226    }
227
228    protected function _testGetRecentTagsByType()
229    {
230        $recent = self::$tagger->getRecentTags(array('typeId' => 'event'));
231        $this->assertEquals(3, count($recent));
232    }
233
234    protected function _testGetRecentObjects()
235    {
236        $recent = self::$tagger->getRecentObjects();
237        $this->assertEquals(4, count($recent));
238        $this->assertEquals(4, $recent[0]['object_id']);
239        $date = new Horde_Date($recent[0]['created'], 'UTC');
240        $this->assertEquals(1230764760, $date->timestamp());
241    }
242
243    protected function _testUntag()
244    {
245        self::$tagger->untag('alice', array('type' => 'event', 'object' => 'party'), 'play');
246        $count = self::$tagger->getRecentTags();
247        $this->assertEquals(3, count($count));
248
249        //readd
250        self::$tagger->tag('alice', array('type' => 'event', 'object' => 'party'), 'play', new Horde_Date('2008-01-01T00:10:00'));
251        $count = self::$tagger->getRecentTags();
252        $this->assertEquals(4, count($count));
253    }
254    /**
255     * @TODO: SHould validate the values too, not just the count.
256     */
257    protected function _testGetRecentObjectsByUser()
258    {
259        // alice has 3 recent objects
260        $recent = self::$tagger->getRecentObjects(array('userId' => 'alice'));
261        $this->assertEquals(3, count($recent));
262
263        // bob has 2
264        $recent = self::$tagger->getRecentObjects(array('userId' => 'bob'));
265        $this->assertEquals(2, count($recent));
266
267        // just for kicks, test using the user id, not name.
268        $recent = self::$tagger->getRecentObjects(array('userId' => 1));
269        $this->assertEquals(3, count($recent));
270    }
271
272    protected function _testGetRecentObjectsByType()
273    {
274        $recent = self::$tagger->getRecentObjects(array('typeId' => 1));
275        $this->assertEquals(3, count($recent));
276
277        $recent = self::$tagger->getRecentObjects(array('typeId' => 2));
278        $this->assertEquals(1, count($recent));
279    }
280
281    protected function _testGetRecentUsers()
282    {
283        $recent = self::$tagger->getRecentUsers();
284        $this->assertEquals(2, count($recent));
285    }
286
287    protected function _testGetRecentUsersByType()
288    {
289        $recent = self::$tagger->getRecentUsers(array('typeId' => 1));
290        $this->assertEquals(2, count($recent));
291
292        $recent = self::$tagger->getRecentUsers(array('typeId' => 2));
293        $this->assertEquals(1, count($recent));
294    }
295
296    /**
297     * Test obtaining objects that are tagged with the same tags as the provided
298     * object.
299     *
300     * See Bug: 10439
301     */
302    public function testGetObjectsByObjectId()
303    {
304        self::$tagger->tag('mike', array('type' => 'event', 'object' => 'irene'), 'hurricane', new Horde_Date('2011-08-28T00:01:00'));
305        self::$tagger->tag('mike', array('type' => 'event', 'object' => 'floyd'), 'hurricane', new Horde_Date('1999-09-07T00:02:00'));
306        $object = self::$tagger->getObjects(array('objectId' => array('type' => 'event', 'object' => 'irene')));
307        $this->assertEquals('floyd', current($object));
308    }
309
310    public function testDuplicateTagsByCase()
311    {
312        // These tests don't work at the moment, because SQLite sucks at
313        // non-ascii comparing.
314        /*
315        self::$tagger->tag('mike', 1, 'TYÖ');
316        self::$tagger->tag('mike', 1, 'TYÖ');
317        self::$tagger->tag('mike', 1, 'työ');
318        self::$tagger->tag('mike', 1, 'työ');
319        */
320        // Use older timestamps to avoid interfering with the later tests
321        self::$tagger->tag('mike', array('type' => 'foo', 'object' => 'xyz'), 'foo', new Horde_Date('2008-01-01T00:05:00'));
322        self::$tagger->tag('alice', array('type' => 'foo', 'object' => 'xyz'), 'FOO', new Horde_Date('2008-01-01T00:05:00'));
323        self::$tagger->tag('alice', array('type' => 'foo', 'object' => 'xyz'), array('test', 'TEST'), new Horde_Date('2008-01-01T00:05:00'));
324        $this->assertEquals(2, count(self::$tagger->getTags(array('objectId' => array('type' => 'foo', 'object' => 'xyz')))));
325    }
326
327    public function testGetRecentTagsLimit()
328    {
329        // Create 100 tags on 100 tag_ids, with tag_id = t1 being applied
330        // most recently, and so on. Prepend "t" to each tag to force the
331        // creation of tags that don't yet exist in the test database.
332        for ($i = 1; $i <= 100; $i++) {
333            self::$tagger->tag(1, 1, "t$i", new Horde_Date(strtotime('now - ' . $i . ' minutes')));
334        }
335
336        $recentLimit = self::$tagger->getRecentTags(array('limit' => 25));
337        $this->assertEquals(25, count($recentLimit));
338        $this->assertEquals('t1', $recentLimit[0]['tag_name']);
339    }
340
341    /**
342     * @depends testGetRecentTagsLimit
343     */
344    public function testGetRecentTagsOffset()
345    {
346        $recentOffset = self::$tagger->getRecentTags(array('limit' => 25, 'offset' => 25));
347        $this->assertEquals(25, count($recentOffset));
348        $this->assertEquals('t26', $recentOffset[0]['tag_name']);
349    }
350
351    public function testGetRecentObjectsLimit()
352    {
353        // Create 100 tags on 100 object_ids, with object_id = 1 being tagged
354        // most recently, and so on.
355        for ($i = 1; $i <= 100; $i++) {
356            self::$tagger->tag(1, $i, 1, new Horde_Date(strtotime('now - ' . $i . ' minutes')));
357        }
358
359        $recentLimit = self::$tagger->getRecentObjects(array('limit' => 25));
360        $this->assertEquals(25, count($recentLimit));
361        $this->assertEquals(1, $recentLimit[0]['object_id']);
362    }
363
364    /**
365     * @depend testGetRecentTagsOffset
366     */
367    public function testGetRecentObjectsOffset()
368    {
369        $recentOffset = self::$tagger->getRecentObjects(array('limit' => 25, 'offset' => 25));
370        $this->assertEquals(25, count($recentOffset));
371        $this->assertEquals(26, $recentOffset[0]['object_id']);
372    }
373
374    public function testGetRecentUsersLimit()
375    {
376        // Create 100 tags by 100 user_ids, with user_id = 1 tagging
377        // most recently, and so on.
378        for ($i = 1; $i <= 100; $i++) {
379            self::$tagger->tag($i, 1, 1, new Horde_Date(strtotime('now - ' . $i . ' minutes')));
380        }
381
382        $recentLimit = self::$tagger->getRecentUsers(array('limit' => 25));
383        $this->assertEquals(25, count($recentLimit));
384        $this->assertEquals(1, $recentLimit[0]['user_id']);
385    }
386
387    /**
388     * @depend testGetRecentUsersLimit
389     */
390    public function testGetRecentUsersOffset()
391    {
392        $recentOffset = self::$tagger->getRecentUsers(array('limit' => 25, 'offset' => 25));
393        $this->assertEquals(25, count($recentOffset));
394        $this->assertEquals(26, $recentOffset[0]['user_id']);
395    }
396
397}
398