1: <?php
2:
3: /**
4: * Sort by the comic's name.
5: */
6: define('KLUTZ_SORT_NAME', 201);
7:
8: /**
9: * Sort by the comic's author.
10: */
11: define('KLUTZ_SORT_AUTHOR', 202);
12:
13: /**
14: * Don't bother sorting.
15: */
16: define('KLUTZ_SORT_NOSORT', 203);
17:
18: /**
19: * Width (integer).
20: */
21: define('KLUTZ_FLD_WIDTH', 0);
22:
23: /**
24: * Height (integer).
25: */
26: define('KLUTZ_FLD_HEIGHT', 1);
27:
28: /**
29: * Type (integer).
30: */
31: define('KLUTZ_FLD_TYPE', 2);
32:
33: /**
34: * IMG-appropriate HTML.
35: */
36: define('KLUTZ_FLD_HTML', 3);
37:
38: /**
39: * Klutz Base Class.
40: *
41: * Copyright 2002-2012 Horde LLC (http://www.horde.org/)
42: *
43: * @author Marcus I. Ryan <marcus@riboflavin.net>
44: * @package Klutz
45: */
46: class Klutz
47: {
48: /**
49: * Used to translate between literal dow and numeric dow (sun = 0, 7)
50: *
51: * @var array
52: */
53: var $days = array('sun', 'mon', 'tue', 'wed',
54: 'thu', 'fri', 'sat', 'sun');
55:
56: /**
57: * MIME types for images based on the return value from getimagesize
58: *
59: * @var array
60: */
61: var $image_types = array(1 => 'image/gif',
62: 2 => 'image/jpg',
63: 3 => 'image/png',
64: 6 => 'image/bmp',
65: 7 => 'image/tiff',
66: 8 => 'image/tiff',
67: );
68:
69: /**
70: * Array of comics and their associated attributes
71: *
72: * @var array
73: */
74: var $comics = array();
75:
76: /**
77: * Sorting method to use. Options are KLUTZ_SORT_NAME (sort by comic
78: * title), KLUTZ_SORT_AUTHOR (sort by Author's last name), and
79: * KLUTZ_SORT_NOSORT (don't promise any given sorting order).
80: *
81: * @var integer
82: */
83: var $sort = null;
84:
85: /**
86: * Constructor - Parse the /config/comics.php config file and store
87: * the results in $comic. Also tries to validate all the data it can
88: * and adjust case, etc., to more predictible consistency than humans
89: * editing config files can give. :)
90: *
91: * @param integer $sort Sorting method to use
92: */
93: function Klutz($sort = KLUTZ_SORT_NAME)
94: {
95: $this->sort = $sort;
96:
97: // Load the list of comics from the config file.
98: include_once KLUTZ_BASE . '/config/comics.php';
99:
100: if (isset($comics)) {
101: $this->comics = $comics;
102: }
103:
104: if ($this->sort != KLUTZ_SORT_NOSORT) {
105: uksort($this->comics, array($this, '_sortComics'));
106: }
107:
108: foreach (array_keys($this->comics) as $index) {
109: if (empty($this->comics[$index]['days'])) {
110: $this->comics[$index]['days'] = array_unique($this->days);
111: } else {
112: if (!is_array($this->comics[$index]['days'])) {
113: if (Horde_String::lower($this->comics[$index]['days']) == 'random') {
114: $this->comics[$index]['days'] = 'random';
115: } else {
116: $this->comics[$index]['days'] =
117: array($this->comics[$index]['days']);
118: }
119: }
120:
121: if (is_array($this->comics[$index]['days'])) {
122: $this->comics[$index]['days'] = array_map(array($this, '_convertDay'),
123: $this->comics[$index]['days']);
124: }
125: }
126: if (empty($this->comics[$index]['nohistory'])) {
127: $this->comics[$index]['nohistory'] = false;
128: }
129: }
130: }
131:
132: /**
133: * Convert a user-passed string into a three-letter, lowercased day abbr.
134: *
135: * @param string $a The string to convert
136: *
137: * @return string A three-letter abbreviation for the
138: * requested day, or the first three letters
139: * of the passed string lowercased.
140: */
141: function _convertDay($a)
142: {
143: $a = Horde_String::lower(substr($a,0,3));
144: if (!in_array($a, $this->days)) {
145: switch ($a) {
146: case 'm':
147: case 'mo':
148: $a = 'mon';
149: break;
150:
151: case 't':
152: case 'tu':
153: $a = 'tue';
154: break;
155:
156: case 'w':
157: case 'we':
158: $a = 'wed';
159: break;
160:
161: case 'r':
162: case 'th':
163: $a = 'thu';
164: break;
165:
166: case 'f':
167: case 'fr':
168: $a = 'fri';
169: break;
170:
171: case 's':
172: case 'su':
173: $a = 'sat';
174: break;
175:
176: case 'u':
177: case 'su':
178: $a = 'sun';
179: break;
180: }
181: }
182:
183: return $a;
184: }
185:
186: /**
187: * Comparse two comics and return -1, 0, or 1 based on the $sort member
188: * variable
189: *
190: * @param string $a The index of the first comic
191: * @param string $b The index of the second comic
192: *
193: * @return integer @see strcmp
194: */
195: function _sortComics($a, $b)
196: {
197: switch ($this->sort) {
198: case KLUTZ_SORT_NAME:
199: $namea = preg_replace("/^(A|An|The)\s+/i", '', $this->comics[$a]['name']);
200: $nameb = preg_replace("/^(A|An|The)\s+/i", '', $this->comics[$b]['name']);
201:
202: return strcmp($namea, $nameb);
203:
204: case KLUTZ_SORT_AUTHOR:
205: $authora = preg_replace("/^.*?\s+/", '', $this->comics[$a]['author']);
206: $authorb = preg_replace("/^.*?\s+/", '', $this->comics[$b]['author']);
207: $authora = preg_replace("/^\s*and\s+.*?\s+/", '', $authora);
208: $authorb = preg_replace("/^\s*and\s+.*?\s+/", '', $authorb);
209:
210: return strcmp($authora, $authorb);
211: }
212: }
213:
214: /**
215: * Return a list of comics that are marked as enabled, and that should
216: * appear on a given day if a date is passed in.
217: *
218: * @param array $list The list to extract from (default is all comics,
219: * but smaller arrays are okay).
220: * @param timestamp $date If passed in, check the $days array to make sure
221: * the comic should appear today.
222: *
223: * @return array A list of comic indecies
224: */
225: function listEnabled($list = null, $date = null)
226: {
227: if (is_null($list)) {
228: $list = array_keys($this->comics);
229: }
230:
231: $day = null;
232: if (!is_null($date)) {
233: $day = Horde_String::lower(date('D', $date));
234: }
235:
236: $return = array();
237: foreach ($list as $index) {
238: if (!isset($this->comics[$index])) continue;
239: if ($this->comics[$index]['enabled']) {
240: if (is_null($day) || $this->comics[$index]['days'] == 'random'
241: || in_array($day, $this->comics[$index]['days'])) {
242: $return[] = $index;
243: }
244: }
245: }
246: return $return;
247: }
248:
249: /**
250: * Return a list of comics that use the given fetch driver
251: *
252: * @param string $driver The driver to check for
253: * @param array $list The list to filter by driver (default all comics)
254: *
255: * @return array A list of the comics passed in that have been filtered
256: * based on driver
257: */
258: function listByDriver($driver, $list = null)
259: {
260: if (is_null($list)) { $list = array_keys($this->comics); }
261:
262: $return = array();
263: foreach ($list as $index) {
264: if ($this->comics[$index]['method'] == $driver) {
265: $return[] = $index;
266: }
267: }
268: return $return;
269: }
270:
271: /**
272: * Return a Klutz_Comic for the given index
273: *
274: * @param string $index The index key for the desired comic
275: *
276: * @return object A Klutz_Comic object for the given index
277: */
278: function comicObject($index)
279: {
280: if (empty($this->comics[$index])) {
281: return null;
282: }
283:
284: $driver = ucfirst($this->comics[$index]['method']);
285: $class = 'Klutz_Comic_' . $driver;
286: if (class_exists($class)) {
287: return new $class($this->comics[$index]);
288: } else {
289: return null;
290: }
291: }
292:
293: /**
294: * Return the requested property for the requested comic
295: *
296: * @param string $index The index key for the desired comic
297: * @param string $property The desired property
298: *
299: * @return mixed The value of $property for $index
300: */
301: function getProperty($index, $property)
302: {
303: if (!is_array($index) && is_array($property)) {
304: $return = array();
305: foreach ($property as $p) {
306: $return[$p] = $this->comics[$index][$p];
307: }
308: return $return;
309: }
310:
311: if (is_array($index)) {
312: $return = array();
313: foreach ($index as $i) {
314: $return[$i] = $this->getProperty($i, $property);
315: }
316: return $return;
317: }
318:
319: if (isset($this->comics[$index][$property])) {
320: return $this->comics[$index][$property];
321: } else {
322: return null;
323: }
324: }
325: }
326: