OPiQuotations  v.02.00.00 — October 26, 2015
 All Classes Namespaces Files Functions Variables Pages
OPiQuotations.inc
Go to the documentation of this file.
1 <?php /* -*- coding: utf-8 -*- */
2 
3 /** \file OPiQuotations.inc
4  * (October 26, 2015)
5  *
6  * \brief
7  * Main class.
8  *
9  * PHP package to deal quotations (text, author…) and maxims (text, nation…)
10  * from a MySQL database.
11  *
12  * Piece of OPiQuotations.
13  * https://bitbucket.org/OPiMedia/opiquotations
14  *
15  * GPL3 --- Copyright (C) 2014, 2015 Olivier Pirson
16  * http://www.opimedia.be/
17  *
18  * @version 02.00.00 --- October 26, 2015
19  * @author Olivier Pirson <olivier_pirson_opi@yahoo.fr>
20  * @package OPiQuotations
21  *
22  * \mainpage OPiQuotations
23  * PHP package to deal quotations (text, author…) and maxims (text, nation…)
24  * from a MySQL database.
25  *
26  * <ul>
27  * <li>Complete sources (and MySQL quotations file) on Bitbucket: <a href="https://bitbucket.org/OPiMedia/opiquotations" target="_blank"><tt>https://bitbucket.org/OPiMedia/opiquotations</tt></a></li>
28  * <li><a href="http://www.opimedia.be/DS/webdev/PHP/OPiQuotations/docs/index.html">Online HTML documentation</a></li>
29  * </ul>
30  *
31  * <img src="OPiQuotations-64x64-t.png" width="64" height="64" border="0" alt="[OPiQuotations]" />
32  *
33  * My personal use of this package:
34  *
35  * \htmlonly
36  * <a href="http://www.opimedia.be/OPiCitations/" target="_blank"><img src="OPiCitation-banner--577x100.jpg" width="577" height="100" border="0" alt="[OPiCitations]" /></a>
37  * <ul>
38  * <li><a href="http://www.opimedia.be/OPiCitations/" target="_blank">OPiCitations <img src="OPiQuotations-16x16-t.png" width="16" height="16" border="0" alt="" /></a>: Web application containing over 3000 French quotes</li>
39  * <li><a href="http://www.opimedia.be/OPiCitations/uneOPiCitation.php" target="_blank">une O<span class="small-caps">Pi</span>Citation <img src="oneOPiQuotation-16x16-t.png" width="16" height="16" border="0" alt="" /></a>: Little Web application to display one OPiCitation (may be used in an iframe to include in another Web page)</li>
40  * <li><a href="https://twitter.com/OPiCitationJour" target="_blank">@OPiCitationJour</a>: Twitter account with an OPiCitation by day</li>
41  * <li><a href="https://www.facebook.com/1OPiCitationParJour" target="_blank">1OPiCitationParJour</a>: Page Facebook with another OPiCitation by day</li>
42  * </ul>
43  * \endhtmlonly
44  *
45  * \htmlonly
46  * <hr />
47  * <div>
48  * One quotation randomly chosen from the dictionary of French quotes:
49  * <a href="http://www.opimedia.be/OPiCitations/uneOPiCitation.php" target="_blank"><strong>une O<span class="small-caps">Pi</span>Citations</strong> <img src="oneOPiQuotation-16x16-t.png" width="16" height="16" border="0" alt="" /></a>.
50  * <iframe src="http://www.opimedia.be/OPiCitations/uneOPiCitation.php?no-link-OPiQuotations" width="100%" height="200" scrolling="auto" frameborder="0" onload="this.height=this.contentWindow.document.getElementsByTagName('body')[0].clientHeight;">[Your browser does not support iframe.]</iframe>
51  * </div>
52  * <hr />
53  * \endhtmlonly
54  *
55  * <div>
56  * GPLv3
57  * ------
58  * Copyright (C) 2014, 2015 Olivier Pirson
59  *
60  * This program is free software: you can redistribute it and/or modify
61  * it under the terms of the GNU General Public License as published by
62  * the Free Software Foundation, either version 3 of the License, or
63  * (at your option) any later version.
64  *
65  * This program is distributed in the hope that it will be useful,
66  * but WITHOUT ANY WARRANTY; without even the implied warranty of
67  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
68  * GNU General Public License for more details.
69  *
70  * You should have received a copy of the GNU General Public License
71  * along with this program. If not, see <http://www.gnu.org/licenses/>.
72  * </div>
73  * <hr>
74  *
75  * \htmlonly
76  * <div align="center">
77  * <a class="net" href="http://www.opimedia.be/donate/" target="_blank"><img src="Donate-92x26-t.png" width="92" height="26" border="0" alt="[Donate]" /></a>
78  * </div>
79  * \endhtmlonly
80  *
81  * <div align="right">
82  * &copy; Olivier <span style="font-variant:small-caps">Pirson</span>\n
83  * <a class="net" href="http://www.opimedia.be/" target="_blank"><tt>www.opimedia.be</tt></a>\n
84  * <a class="mail" href="mailto:olivier_pirson_opi@yahoo.fr?subject=[OPiQuotations]"><tt>olivier_pirson_opi@yahoo.fr</tt></a>
85  * </div>
86  */
87 
88 namespace OPiQuotations;
89 
90 
91 /**
92  * \brief
93  * If length of $html_text <= $max_length characters
94  * then return $html_text,
95  * else return $html_text cutted added of $hellip to not be longer than $max_length characters.
96  *
97  * If a cutting is required and $reduce then reduce contiguous whitespaces.
98  *
99  * If the cutting cut a HTML entity
100  * then remove it.
101  *
102  * @param string $html_text
103  * @param int $max_length (must be >= length of $hellip)
104  * @param string $hellip; (must not containt the & character)
105  * @param bool $reduce
106  *
107  * @return string
108  */
109 function html_text_cut($html_text, $max_length, $hellip='…', $reduce=true) {
110  #DEBUG
111  assert('is_string($html_text)');
112  assert('is_int($max_length)');
113  assert('is_string($hellip)');
114  assert('$max_length >= mb_strlen($hellip)');
115  assert('is_bool($reduce)');
116  #DEBUG_END
117 
118  if (mb_strlen($html_text) > $max_length) {
119  $html_text = text_cut($html_text, $max_length, $hellip, $reduce);
120 
121  $i = mb_strrpos($html_text, '&');
122  if (($i !== false) && (mb_strrpos($html_text, ';', $i + 1) === false)) {
123  // Remove partial HTML entity like &quot;
124  $html_text = mb_substr($html_text, 0, $i).$hellip;
125  }
126  }
127 
128  return $html_text;
129 }
130 
131 
132 /**
133  * \brief
134  * If length of $text <= $max_length characters
135  * then return $text,
136  * else return $text cutted added of $hellip to be length of $max_length characters.
137  *
138  * If a cutting is required and $reduce then reduce contiguous whitespaces.
139  *
140  * @param string $text
141  * @param int $max_length (must be >= length of $hellip)
142  * @param string $hellip;
143  * @param bool $reduce
144  *
145  * @return string
146  */
147 function text_cut($text, $max_length, $hellip='…', $reduce=true) {
148  #DEBUG
149  assert('is_string($text)');
150  assert('is_int($max_length)');
151  assert('is_string($hellip)');
152  assert('$max_length >= mb_strlen($hellip)');
153  assert('is_bool($reduce)');
154  #DEBUG_END
155 
156  if (mb_strlen($text) > $max_length) {
157  if ($reduce) {
158  // Reduce contiguous whitespaces with break line
159  $text = preg_replace('/\s*\n\s*/', '
160 ', $text);
161 
162  // Reduce other contiguous whitespaces (\v is ignored because confusion with \n)
163  $text = preg_replace('/[ \t\r\f]+/', ' ', $text);
164  }
165 
166  $text = mb_substr($text, 0, $max_length - mb_strlen($hellip)).$hellip;
167  }
168 
169  return $text;
170 }
171 
172 
173 
174 /**
175  * \brief
176  * Class to get OPiQuotation and informations from the databse.
177  */
179  /**
180  * \brief
181  * Connect to the database.
182  * See the Db class.
183  */
184  public function __construct() {
185  require_once 'OPiQuotations/Db.inc';
186  require_once 'OPiQuotations/.private/db_login.inc';
187 
188  $this->db = new Db($db_host, $db_user, $db_password, $db_name);
189  }
190 
191 
192  /**
193  * \brief
194  * Return a associative table id => array(name, number of use)
195  * of elements of the table author.
196  *
197  * @return array[array]
198  */
199  public function list_authors() {
200  return $this->db->list_to_assoc('author');
201  }
202 
203 
204  /**
205  * \brief
206  * Return a associative table id => array(name, number of use)
207  * of elements of the table nation.
208  *
209  * @return array[array]
210  */
211  public function list_nations() {
212  return $this->db->list_to_assoc('nation');
213  }
214 
215 
216  /**
217  * Return a associative table id => array(name, number of use)
218  * of elements of the table subject.
219  *
220  * @return array[array]
221  */
222  public function list_subjects() {
223  return $this->db->list_to_assoc('subject');
224  }
225 
226 
227  /**
228  * \brief
229  * Return a associative table id => array(name, number of use)
230  * of elements of the table work.
231  *
232  * @return array[array]
233  */
234  public function list_works() {
235  return $this->db->list_to_assoc('work');
236  }
237 
238 
239  /**
240  * \brief
241  * If $is_maxim === null then return the numbers of quotations/maxims,
242  * if $is_maxim === false then return the numbers of quotations,
243  * if $is_maxim === true then return the numbers of maxims.
244  *
245  * @param null|bool $is_maxim
246  *
247  * @return int >= 0
248  */
249  public function nb($is_maxim=null) {
250  #DEBUG
251  assert('($is_maxim === null) || is_bool($is_maxim)');
252  #DEBUG_END
253 
254  return $this->db->nb($is_maxim);
255  }
256 
257 
258  /**
259  * \brief
260  * Return the unique quotation/maxim of id $id.
261  *
262  * If this id doesn't exist
263  * then return null.
264  *
265  * @param int $id
266  *
267  * @return null|OPiQuotation
268  */
269  public function quotation_by_id($id) {
270  #DEBUG
271  assert('is_int($id)');
272  #DEBUG_END
273 
274  if ($id <= 0) {
275  return null;
276  }
277 
278  $quots = $this->db->query_quotations('WHERE `id`='.(int)$id.'');
279 
280  return (empty($quots)
281  ? null
282  : $quots[0]);
283  }
284 
285 
286  /**
287  * \brief
288  * Return the complete list of quotations/maxims.
289  *
290  * @return OPiQuotation[]
291  */
292  public function quotations_all() {
293  return $this->db->query_quotations('',
294  'ORDER BY `text_stripped` COLLATE utf8_unicode_ci');
295  }
296 
297 
298  /**
299  * \brief
300  * Return the list of quotations/maxims that are marked.
301  *
302  * @return OPiQuotation[]
303  */
304  public function quotations_all_marked() {
305  return $this->db->query_quotations('WHERE `is_marked`',
306  'ORDER BY `text_stripped` COLLATE utf8_unicode_ci');
307  }
308 
309 
310  /**
311  * \brief
312  * Return the list of quotations that are writed by author $author.
313  *
314  * @param string $author
315  *
316  * @return OPiQuotation[]
317  */
318  public function quotations_by_author($author) {
319  #DEBUG
320  assert('is_string($author)');
321  #DEBUG_END
322 
323  return $this->db->query_quotations('WHERE NOT `is_maxim` AND `author` LIKE \'%'.$this->db->escape($author).'%\' COLLATE utf8_unicode_ci',
324  'ORDER BY `author`, `text_stripped` COLLATE utf8_unicode_ci');
325  }
326 
327 
328  /**
329  * \brief
330  * Return the list of quotations/maxims of id among $ids.
331  *
332  * @param int[] $ids (each int > 0)
333  *
334  * @return OPiQuotation[]
335  */
336  public function quotations_by_ids($ids) {
337  #DEBUG
338  assert('is_array($ids)');
339  #DEBUG_END
340 
341  foreach($ids as &$id) {
342  #DEBUG
343  assert('is_int($id)');
344  assert('$id > 0');
345  #DEBUG_END
346 
347  settype($id, 'int');
348  }
349 
350  return (empty($ids)
351  ? array()
352  : $this->db->query_quotations('WHERE `id` IN ('.implode(',', $ids).')'));
353  }
354 
355 
356  /**
357  * \brief
358  * Return the list of maxims of nationality $nation.
359  *
360  * @param string $nation
361  *
362  * @return OPiQuotation[]
363  */
364  public function quotations_by_nation($nation) {
365  #DEBUG
366  assert('is_string($nation)');
367  #DEBUG_END
368 
369  return $this->db->query_quotations('WHERE `is_maxim` AND `nation` LIKE \'%'.$this->db->escape($nation).'%\' COLLATE utf8_unicode_ci',
370  'ORDER BY `nation`, `text_stripped` COLLATE utf8_unicode_ci');
371  }
372 
373 
374  /**
375  * \brief
376  * Return a list of $nb different quotations choose at random.
377  *
378  * If $label !== null
379  * then choose quotations not already chosen with this label
380  * and set the chosen quotations with this $label.
381  *
382  * @param int $nb (must be >= 0)
383  * @param null|string $label
384  *
385  * @return OPiQuotation[]
386  */
387  public function quotations_by_random($nb=1, $label=null) {
388  #DEBUG
389  assert('is_int($nb)');
390  assert('$nb >= 0');
391  assert('($label === null) || is_string($label)');
392  #DEBUG_END
393 
394  if ($label === null) {
395  return $this->db->query_quotations('',
396  'ORDER BY RAND() LIMIT '.(int)$nb);
397  }
398  else {
399  $label = $this->db->escape($label);
400  $quots = $this->db->query_quotations('WHERE `id` NOT IN (SELECT `quotation_id` FROM `_selected_label` WHERE `label` = \''.$label.'\')',
401  'ORDER BY RAND() LIMIT '.(int)$nb);
402 
403  if (!empty($quots)) {
404  $query = array();
405  foreach ($quots as $quot) {
406  $query[] = '('.$quot->id().', \''.$label.'\', UTC_TIMESTAMP())';
407  }
408  $query = 'INSERT INTO `_selected_label` (`quotation_id`, `label`, `datetime_utc`) VALUES
409 '.implode(',
410 ', $query).';';
411 
412  $this->db->query_insert($query);
413  }
414 
415  return $quots;
416  }
417  }
418 
419 
420  /**
421  * \brief
422  * Return the list of quotations/maxims of subject $subject
423  *
424  * @param string $subject
425  *
426  * @return OPiQuotation[]
427  */
428  public function quotations_by_subject($subject) {
429  #DEBUG
430  assert('is_string($subject)');
431  #DEBUG_END
432 
433  return $this->db->query_quotations('WHERE `subject` LIKE \'%'.$this->db->escape($subject).'%\' COLLATE utf8_unicode_ci',
434  'ORDER BY `subject`, `text_stripped` COLLATE utf8_unicode_ci');
435  }
436 
437 
438  /**
439  * \brief
440  * Return the list of quotations/maxims that contains the text $text.
441  *
442  * @param string $text
443  *
444  * @return OPiQuotation[]
445  */
446  public function quotations_by_text($text) {
447  #DEBUG
448  assert('is_string($text)');
449  #DEBUG_END
450 
451  return $this->db->query_quotations('WHERE `text` LIKE \'%'.$this->db->escape($text).'%\' COLLATE utf8_unicode_ci',
452  'ORDER BY `text_stripped` COLLATE utf8_unicode_ci');
453  }
454 
455 
456  /**
457  * \brief
458  * Return the list of quotations/maxims with a translation that contains the text $translation.
459  *
460  * @param string $translation
461  *
462  * @return OPiQuotation[]
463  */
464  public function quotations_by_translation($translation) {
465  #DEBUG
466  assert('is_string($translation)');
467  #DEBUG_END
468 
469  return $this->db->query_quotations('WHERE `translation` LIKE \'%'.$this->db->escape($translation).'%\' COLLATE utf8_unicode_ci',
470  'ORDER BY `translation_stripped` COLLATE utf8_unicode_ci');
471  }
472 
473 
474  /**
475  * \brief
476  * Return the list of quotations/maxims that are writed in work $work.
477  *
478  * @param string $work
479  *
480  * @return OPiQuotation[]
481  */
482  public function quotations_by_work($work) {
483  #DEBUG
484  assert('is_string($work)');
485  #DEBUG_END
486 
487  return $this->db->query_quotations('WHERE NOT `is_maxim` AND `work` LIKE \'%'.$this->db->escape($work).'%\' COLLATE utf8_unicode_ci',
488  'ORDER BY `work`, `text_stripped` COLLATE utf8_unicode_ci');
489  }
490 
491 
492 
493  /** @var Db $db
494  * \brief
495  * Link to the database
496  */
497  protected $db;
498 }
499 
500 
501 return TRUE;
502 
503 ?>