diff --git a/chapter09/plg_finder_song/plugins/finder/song/song.php b/chapter09/plg_finder_song/plugins/finder/song/song.php index 0a2ab0d..1cd759c 100644 --- a/chapter09/plg_finder_song/plugins/finder/song/song.php +++ b/chapter09/plg_finder_song/plugins/finder/song/song.php @@ -2,99 +2,161 @@ /** * Finder Plugin for Joomla! - Song * - * @author Jisse Reitsma (jisse@yireo.com) - * @copyright Copyright 2014 Jisse Reitsma - * @license GNU Public License version 3 or later - * @link http://www.yireo.com/books/ + * @author Jisse Reitsma + * @copyright Copyright 2014 Jisse Reitsma + * @license GNU Public License version 3 or later + * @link http://www.yireo.com/books/ */ defined('_JEXEC') or die; require_once JPATH_ADMINISTRATOR . '/components/com_finder/helpers/indexer/adapter.php'; +/** + * Class PlgFinderSong + * + * @since September 2014 + */ class PlgFinderSong extends FinderIndexerAdapter { + /** + * @var string + */ protected $context = 'Song'; + /** + * @var string + */ protected $extension = 'com_music'; + /** + * @var string + */ protected $layout = 'song'; + /** + * @var string + */ protected $type_title = 'Song'; + /** + * @var string + */ protected $table = '#__music_songs'; + /** + * @var bool + */ protected $autoloadLanguage = true; + /** + * Override method to index a certain result + * + * @param FinderIndexerResult $item Finder item + * @param string $format Formatting (html or text) + * + * @return null + */ protected function index(FinderIndexerResult $item, $format = 'html') - { - //if (JComponentHelper::isEnabled($this->extension) == false) - //{ - // return; - //} - - // Prepare the item - $item->access = 1; - - // Define these items as songs - $item->addTaxonomy('Type', 'Song'); - - // Add artist information - $item->addInstruction(FinderIndexer::META_CONTEXT, 'artist'); - $item->addTaxonomy('Artist', $item->artist); - - // Set language + { + /* + if (JComponentHelper::isEnabled($this->extension) == false) + { + return; + } + */ + + // Prepare the item + $item->access = 1; + + // Define these items as songs + $item->addTaxonomy('Type', 'Song'); + + // Add artist information + $item->addInstruction(FinderIndexer::META_CONTEXT, 'artist'); + $item->addTaxonomy('Artist', $item->artist); + + // Set language //$item->setLanguage(); //$item->addTaxonomy('Language', $item->language); - // Set URLs - $item->route = 'index.php?option=com_music&view=song&id='.$item->id; + // Set URLs + $item->route = 'index.php?option=com_music&view=song&id=' . $item->id; $item->url = $item->route; $item->path = FinderIndexerHelper::getContentPath($item->route); - // Allow others to hook into our $item as well + // Allow others to hook into our $item as well FinderIndexerHelper::getContentExtras($item); - $this->indexer->index($item); - } + $this->indexer->index($item); + } + /** + * Override method to setup the entire plugin process + * + * @return bool + */ protected function setup() - { - //require_once JPATH_SITE.'/components/com_music/helpers/route.php'; + { + //require_once JPATH_SITE.'/components/com_music/helpers/route.php'; - return true; - } + return true; + } + /** + * Override method to return the list query + * + * @param mixed $query JDatabaseQuery object or null + * + * @return null + */ protected function getListQuery($query = null) - { - $db = JFactory::getDbo(); - $query = $db->getQuery(true); - $query->select('a.*'); - $query->select('p.name AS artist'); - $query->from($db->quoteName('#__music_songs', 'a')); - $query->innerJoin($db->quoteName('#__music_artists', 'p') - .' ON ('.$db->quoteName('a.artist_id').'='.$db->quoteName('p.id').')' - ); - - $debugQuery = str_replace('#__', $db->getPrefix(), trim($query)); - echo "[SONGS]\n".$debugQuery."\n[/SONGS]\n"; - return $query; - } + { + $db = JFactory::getDbo(); + + $query = $db->getQuery(true); + $query->select('a.*'); + $query->select('p.name AS artist'); + $query->from($db->quoteName('#__music_songs', 'a')); + $query->innerJoin($db->quoteName('#__music_artists', 'p') + . ' ON (' . $db->quoteName('a.artist_id') . '=' . $db->quoteName('p.id') . ')'); + + $debugQuery = str_replace('#__', $db->getPrefix(), trim($query)); + echo "[SONGS]\n" . $debugQuery . "\n[/SONGS]\n"; + return $query; + } + + /** + * Override method to return the state query + * + * @return mixed + */ protected function getStateQuery() { $query = $this->db->getQuery(true); $query->select('a.id'); - $query->select('a.'.$this->state_field.' AS state'); + $query->select('a.' . $this->state_field . ' AS state'); $query->from($this->table . ' AS a'); - jimport('joomla.log.log'); - JLog::add($query, JLog::WARNING, 'jerror'); + + jimport('joomla.log.log'); + JLog::add($query, JLog::WARNING, 'jerror'); + return $query; } + /** + * Event method to run when the item state changes + * + * @param text $context String describing the current context + * @param array $pks List of primary keys + * @param mixed $value State value (likely either 0 or 1) + * + * @return null + */ public function onFinderChangeState($context, $pks, $value) - { + { if ($context == 'com_music.song') { $this->itemStateChange($pks, $value); @@ -104,18 +166,35 @@ public function onFinderChangeState($context, $pks, $value) { $this->pluginDisable($pks); } - } + } + /** + * Event method run when the category state changes + * + * @param string $extension String pointing to the component + * @param array $pks Array of primary keys + * @param mixed $value State value + * + * @return null + */ public function onFinderCategoryChangeState($extension, $pks, $value) - { + { if ($extension == 'com_music') { $this->categoryStateChange($pks, $value); } - } + } + /** + * Event method run when the item is deleted + * + * @param string $context String describing the current context + * @param JTable $table JTable instance of the content item + * + * @return bool + */ public function onFinderAfterDelete($context, $table) - { + { if ($context == 'com_music.song') { $id = $table->id; @@ -126,39 +205,57 @@ public function onFinderAfterDelete($context, $table) } return $this->remove($id); - } + } - public function onFinderAfterSave($context, $row, $isNew) - { + /** + * Event method run after the item is saved + * + * @param string $context String describing the current context + * @param object $item Content item that is being saved + * @param bool $isNew Flag determining whether this item is new or not + * + * @return null + */ + public function onFinderAfterSave($context, $item, $isNew) + { if ($context == 'com_music.song') { - if (!$isNew && $this->old_access != $row->access) + if (!$isNew && $this->old_access != $item->access) { - $this->itemAccessChange($row); + $this->itemAccessChange($item); } - $this->reindex($row->id); + $this->reindex($item->id); } if ($context == 'com_categories.category') { - if (!$isNew && $this->old_cataccess != $row->access) + if (!$isNew && $this->old_cataccess != $item->access) { - $this->categoryAccessChange($row); + $this->categoryAccessChange($item); } } - } + } - public function onFinderBeforeSave($context, $row, $isNew) - { + /** + * Event method run before the item is saved + * + * @param string $context String describing the current context + * @param object $item Content item that is being saved + * @param bool $isNew Flag determining whether this item is new or not + * + * @return null + */ + public function onFinderBeforeSave($context, $item, $isNew) + { if ($context == 'com_music.song' && $isNew == false) { - $this->checkItemAccess($row); + $this->checkItemAccess($item); } if ($context == 'com_categories.category' && $isNew == false) { - $this->checkCategoryAccess($row); + $this->checkCategoryAccess($item); } - } + } } diff --git a/chapter09/plg_search_music/plugins/search/music/music.php b/chapter09/plg_search_music/plugins/search/music/music.php index c389b07..92880eb 100644 --- a/chapter09/plg_search_music/plugins/search/music/music.php +++ b/chapter09/plg_search_music/plugins/search/music/music.php @@ -2,168 +2,223 @@ /** * Search Plugin for Joomla! - Music * - * @author Jisse Reitsma (jisse@yireo.com) - * @copyright Copyright 2014 Jisse Reitsma - * @license GNU Public License version 3 or later - * @link http://www.yireo.com/books/ + * @author Jisse Reitsma + * @copyright Copyright 2014 Jisse Reitsma + * @license GNU Public License version 3 or later + * @link http://www.yireo.com/books/ */ defined('_JEXEC') or die; jimport('joomla.plugin.plugin'); +/** + * Class PlgSearchMusic + * + * @since September 2014 + */ class PlgSearchMusic extends JPlugin { - public function onContentSearch($text, $phrase='', $ordering='', $areas=null) - { - if (empty($text)) - { - return array(); - } - - if (is_array($areas)) - { - if (!array_intersect($areas, array_keys($this->onContentSearchAreas()))) - { - return array(); - } - } - - $results = array(); - - if (empty($areas) || in_array('songs', $areas)) - { - $songs = $this->getSongs($text, $phrase, $ordering); - if (!empty($songs)) - { - $results = array_merge($results, $songs); - } - } - - if (empty($areas) || in_array('artists', $areas)) - { - $artists = $this->getArtists($text, $phrase, $ordering); - if (!empty($artists)) - { - $results = array_merge($results, $artists); - } - } - - - return $results; - } - - public function onContentSearchAreas() - { + /** + * Event method onContentSearchAreas + * + * @return array + */ + public function onContentSearchAreas() + { static $areas = array( 'songs' => 'PLG_SEARCH_MUSIC_AREA_SONGS', 'artists' => 'PLG_SEARCH_MUSIC_AREA_ARTISTS', ); + return $areas; - } - - protected function getSongs($text, $phrase='', $ordering='') - { - $db = JFactory::getDbo(); - $query = $db->getQuery(true); - $query->select('s.*'); - $query->from($db->quoteName('#__music_songs').' AS s'); - $query->where('s.'.$db->quoteName('state') . ' = 1'); - - $words = explode(' ', $text); - foreach($words as $wordIndex => $word) - { - $words[$wordIndex] = trim($word); - } - - $searchFields = array('title', 'text'); - $where = array(); - switch($phrase) - { - case 'exact': - foreach($searchFields as $searchField) - { - $search = $db->Quote('%'.$text.'%'); - $searchField = $db->quoteName($searchField); - $where[] = 's.'.$searchField.' LIKE '.$search; - } - break; - - case 'all': - foreach($searchFields as $searchField) - { - $searchField = $db->quoteName($searchField); - $wordWhere = array(); - foreach($words as $word) { - $search = $db->Quote('%'.$word.'%'); - $wordWhere[] = 's.'.$searchField.' LIKE '.$search; - } - $where[] = '('.implode(' AND ', $wordWhere).')'; - } - break; - - case 'any': - default: - foreach($searchFields as $searchField) - { - $searchField = $db->quoteName($searchField); - $wordWhere = array(); - foreach($words as $word) { - $search = $db->Quote('%'.$word.'%'); - $wordWhere[] = 's.'.$searchField.' LIKE '.$search; - } - $where[] = '('.implode(' OR ', $wordWhere).')'; - } - break; - } - - $query->where('('.implode(' OR ', $where).')'); - - switch($ordering) - { - case 'alpha': - $query->order('title ASC'); - break; - - case 'popular': - case 'category': - case 'oldest': - case 'newest': - default: - break; - } - $db->setQuery($query); - echo str_replace('#_', $db->getPrefix(), $db->getQuery()).'
'; - $results = $db->loadObjectList(); - - foreach($results as $result) { - $result->href = 'index.php?option=com_music&view=song&id='.$result->id; - $result->section = JText::_('PLG_SEARCH_MUSIC_AREA_SONGS'); - $result->created = 'today'; - } - - return $results; - } - - protected function getArtists($text, $phrase='', $ordering='') - { - $db = JFactory::getDbo(); - $query = $db->getQuery(true); - $query->select('a.*'); - $query->from($db->quoteName('#__music_artists').' AS a'); - $query->where('a.'.$db->quoteName('name') . ' LIKE '. $db->quote('%'.$text.'%')); - $db->setQuery($query); - echo str_replace('#_', $db->getPrefix(), $db->getQuery()); - $results = $db->loadObjectList(); - - foreach($results as $result) { - $result->title = $result->name; - $result->text = $result->name; - $result->href = 'index.php?option=com_music&view=article&id='.$result->id; - $result->section = JText::_('PLG_SEARCH_MUSIC_AREA_ARTISTS'); - $result->created = 'today'; - } - - return $results; - } + } + + /** + * Event method onContentSearch + * + * @param string $text The search phrase + * @param string $phrase String how to match the phrase + * @param string $ordering String describing the ordering + * @param mixed $areas Array of search areas or null + * + * @return null + */ + public function onContentSearch($text, $phrase = '', $ordering = '', $areas = null) + { + if (empty($text)) + { + return array(); + } + + if (is_array($areas)) + { + if (!array_intersect($areas, array_keys($this->onContentSearchAreas()))) + { + return array(); + } + } + + $results = array(); + + if (empty($areas) || in_array('songs', $areas)) + { + $songs = $this->getSongs($text, $phrase, $ordering); + + if (!empty($songs)) + { + $results = array_merge($results, $songs); + } + } + + if (empty($areas) || in_array('artists', $areas)) + { + $artists = $this->getArtists($text, $phrase, $ordering); + + if (!empty($artists)) + { + $results = array_merge($results, $artists); + } + } + + + return $results; + } + + /** + * Method to fetch all songs matching a certain search phrase + * + * @param string $text The search phrase + * @param string $phrase String how to match the phrase + * @param string $ordering String describing the ordering + * + * @return array + */ + protected function getSongs($text, $phrase='', $ordering='') + { + $db = JFactory::getDbo(); + $query = $db->getQuery(true); + $query->select('s.*'); + $query->from($db->quoteName('#__music_songs') . ' AS s'); + $query->where('s.' . $db->quoteName('state') . ' = 1'); + + $words = explode(' ', $text); + + foreach ($words as $wordIndex => $word) + { + $words[$wordIndex] = trim($word); + } + + $searchFields = array('title', 'text'); + $where = array(); + + switch ($phrase) + { + case 'exact': + + foreach ($searchFields as $searchField) + { + $search = $db->Quote('%' . $text . '%'); + $searchField = $db->quoteName($searchField); + $where[] = 's.' . $searchField . ' LIKE ' . $search; + } + break; + + case 'all': + foreach ($searchFields as $searchField) + { + $searchField = $db->quoteName($searchField); + $wordWhere = array(); + + foreach ($words as $word) + { + $search = $db->Quote('%' . $word . '%'); + $wordWhere[] = 's.' . $searchField . ' LIKE ' . $search; + } + + $where[] = '(' . implode(' AND ', $wordWhere) . ')'; + } + break; + + case 'any': + default: + foreach ($searchFields as $searchField) + { + $searchField = $db->quoteName($searchField); + $wordWhere = array(); + + foreach ($words as $word) + { + $search = $db->Quote('%' . $word . '%'); + $wordWhere[] = 's.' . $searchField . ' LIKE ' . $search; + } + + $where[] = '(' . implode(' OR ', $wordWhere) . ')'; + } + break; + } + + $query->where('(' . implode(' OR ', $where) . ')'); + + switch ($ordering) + { + case 'alpha': + $query->order('title ASC'); + break; + + case 'popular': + case 'category': + case 'oldest': + case 'newest': + default: + break; + } + + $db->setQuery($query); + echo str_replace('#_', $db->getPrefix(), $db->getQuery()) . '
'; + $results = $db->loadObjectList(); + + foreach ($results as $result) + { + $result->href = 'index.php?option=com_music&view=song&id=' . $result->id; + $result->section = JText::_('PLG_SEARCH_MUSIC_AREA_SONGS'); + $result->created = 'today'; + } + + return $results; + } + + /** + * Method to fetch all artists matching a certain search phrase + * + * @param string $text The search phrase + * @param string $phrase String how to match the phrase + * @param string $ordering String describing the ordering + * + * @return array + */ + protected function getArtists($text, $phrase = '', $ordering = '') + { + $db = JFactory::getDbo(); + + $query = $db->getQuery(true); + $query->select('a.*'); + $query->from($db->quoteName('#__music_artists') . ' AS a'); + $query->where('a.' . $db->quoteName('name') . ' LIKE ' . $db->quote('%' . $text . '%')); + + $db->setQuery($query); + echo str_replace('#_', $db->getPrefix(), $db->getQuery()); + $results = $db->loadObjectList(); + + foreach ($results as $result) + { + $result->title = $result->name; + $result->text = $result->name; + $result->href = 'index.php?option=com_music&view=article&id=' . $result->id; + $result->section = JText::_('PLG_SEARCH_MUSIC_AREA_ARTISTS'); + $result->created = 'today'; + } + + return $results; + } } diff --git a/chapter09/plg_search_sphinx/plugins/search/sphinx/sphinx.php b/chapter09/plg_search_sphinx/plugins/search/sphinx/sphinx.php index 02937ba..ca8adc4 100644 --- a/chapter09/plg_search_sphinx/plugins/search/sphinx/sphinx.php +++ b/chapter09/plg_search_sphinx/plugins/search/sphinx/sphinx.php @@ -1,10 +1,35 @@ + * @copyright Copyright 2014 Jisse Reitsma + * @license GNU Public License version 3 or later + * @link http://www.yireo.com/books/ + */ + defined('_JEXEC') or die; +/** + * Class PlgSearchSphinx + * + * @since September 2014 + */ class PlgSearchSphinx extends JPlugin { + /** + * Load the language file on instantiation (for Joomla! 3.X only) + * + * @var boolean + * @since 3.3 + */ protected $autoloadLanguage = true; + /** + * Event method onContentSearchAreas + * + * @return array + */ public function onContentSearchAreas() { static $areas = array( @@ -14,6 +39,16 @@ public function onContentSearchAreas() return $areas; } + /** + * Event method onContentSearch + * + * @param string $text The search phrase + * @param string $phrase String how to match the phrase + * @param string $ordering String describing the ordering + * @param mixed $areas Array of search areas or null + * + * @return null + */ public function onContentSearch($text, $phrase = '', $ordering = '', $areas = null) { if (is_array($areas)) @@ -25,54 +60,75 @@ public function onContentSearch($text, $phrase = '', $ordering = '', $areas = nu } $text = trim($text); - $results = $this->getSphinxResults($text, $phrase, $ordering); - if (empty($results['matches'])) - { - return array(); - } - - $ids = array(); - foreach ($results['matches'] as $resultId => $result) - { - $ids[] = $resultId; - } - - $results = $this->getArticles($ids); - return $results; - } - - protected function getSphinxResults($text, $phrase = '', $ordering = '') - { - $host = $this->params->get('host', 'localhost'); - $port = $this->params->get('port', 9312); - $index = $this->params->get('index'); - - switch($phrase) - { - case 'exact': - $matchMode = SPH_MATCH_PHRASE; - break; - - case 'all': - $matchMode = SPH_MATCH_ALL; - break; - - case 'any': - default: - $matchMode = SPH_MATCH_ANY; - break; - } - - $s = new SphinxClient(); - $s->setServer($host, $port); - $s->setMatchMode($matchMode); - $s->setLimits(50); - $result = $s->query($text, $index); - return $result; - } - - protected function getArticles($ids) - { + $results = $this->getSphinxResults($text, $phrase, $ordering); + + if (empty($results['matches'])) + { + return array(); + } + + $ids = array(); + + foreach ($results['matches'] as $resultId => $result) + { + $ids[] = $resultId; + } + + $results = $this->getArticles($ids); + + return $results; + } + + /** + * Method to fetch all Sphinx results for a certain search phrase + * + * @param string $text The search phrase + * @param string $phrase String how to match the phrase + * @param string $ordering String describing the ordering + * + * @return array + */ + protected function getSphinxResults($text, $phrase = '', $ordering = '') + { + $host = $this->params->get('host', 'localhost'); + $port = $this->params->get('port', 9312); + $index = $this->params->get('index'); + + switch ($phrase) + { + case 'exact': + $matchMode = SPH_MATCH_PHRASE; + break; + + case 'all': + $matchMode = SPH_MATCH_ALL; + break; + + case 'any': + default: + $matchMode = SPH_MATCH_ANY; + break; + } + + $s = new SphinxClient; + $s->setServer($host, $port); + $s->setMatchMode($matchMode); + $s->setLimits(50); + + $result = $s->query($text, $index); + + return $result; + } + + /** + * Method to load all articles by ID + * + * @param array $ids Array of primary keys + * + * @return array + */ + protected function getArticles($ids) + { $db = JFactory::getDbo(); $app = JFactory::getApplication(); $user = JFactory::getUser(); @@ -83,41 +139,42 @@ protected function getArticles($ids) $date = JFactory::getDate(); $now = $date->toSql(); - $query = $db->getQuery(true); - $query->select(array('a.id, a.catid, a.title, a.alias, a.created')) + $query = $db->getQuery(true); + $query->select(array('a.id, a.catid, a.title, a.alias, a.created')) ->select($query->concatenate(array('a.introtext', 'a.fulltext')) . ' AS text') - ->select(array('c.title AS section', 'c.alias AS catalias')) - ->from('#__content AS a') + ->select(array('c.title AS section', 'c.alias AS catalias')) + ->from('#__content AS a') ->join('INNER', '#__categories AS c ON c.id=a.catid') - ->where('a.id IN ('.implode(',', $ids).') ' - . 'AND a.state=1 AND c.published = 1 AND a.access IN ('.$groups.') ' + ->where('a.id IN ('.implode(',', $ids).') ' + . 'AND a.state=1 AND c.published = 1 AND a.access IN ('.$groups.') ' . 'AND c.access IN ('.$groups .') ' . 'AND (a.publish_up = '.$db->quote($nullDate).' OR a.publish_up <= '.$db->quote($now).') ' . 'AND (a.publish_down = '.$db->quote($nullDate).' OR a.publish_down >= '.$db->quote($now).')' - ) - ; + ) + ; if ($app->isSite() && JLanguageMultilang::isEnabled()) { - $query->where('a.language in ('.$db->quote($tag).','.$db->quote('*') . ')') - ->where('c.language in ('.$db->quote($tag).','.$db->quote('*') . ')'); + $query->where('a.language in (' . $db->quote($tag) . ',' . $db->quote('*') . ')') + ->where('c.language in (' . $db->quote($tag) . ',' . $db->quote('*') . ')'); } $db->setQuery($query, 0, $limit); $items = $db->loadObjectList(); if (isset($items)) - { - require_once JPATH_SITE . '/components/com_content/helpers/route.php'; - foreach ($items as $key => $item) - { - $item->slug = $item->id.':'.$item->alias; - $item->catslug = $item->catid.':'.$item->catalias; - $item->href = ContentHelperRoute::getArticleRoute($item->slug, $item->catslug); - $items[$key] = $item; - } - } - - return $items; - } + { + require_once JPATH_SITE . '/components/com_content/helpers/route.php'; + + foreach ($items as $key => $item) + { + $item->slug = $item->id . ':' . $item->alias; + $item->catslug = $item->catid . ':' . $item->catalias; + $item->href = ContentHelperRoute::getArticleRoute($item->slug, $item->catslug); + $items[$key] = $item; + } + } + + return $items; + } } diff --git a/chapter10/plg_captcha_example/plugins/captcha/example/example.php b/chapter10/plg_captcha_example/plugins/captcha/example/example.php index 9272420..b4c438b 100644 --- a/chapter10/plg_captcha_example/plugins/captcha/example/example.php +++ b/chapter10/plg_captcha_example/plugins/captcha/example/example.php @@ -2,120 +2,189 @@ /** * Example CAPTCHA Plugin for Joomla! * - * @author Jisse Reitsma (jisse@yireo.com) - * @copyright Copyright 2014 Jisse Reitsma - * @license GNU Public License version 3 or later - * @link http://www.yireo.com/books/ + * @author Jisse Reitsma + * @copyright Copyright 2014 Jisse Reitsma + * @license GNU Public License version 3 or later + * @link http://www.yireo.com/books/ */ defined('_JEXEC') or die; jimport('joomla.plugin.plugin'); -class plgCaptchaExample extends JPlugin + +/** + * Class PlgCaptchaExample + * + * @since September 2014 + */ +class PlgCaptchaExample extends JPlugin { + /** + * Load the language file on instantiation (for Joomla! 3.X only) + * + * @var boolean + * @since 3.3 + */ protected $autoloadLanguage = true; - protected $question_types = array( - 'vowels' => 'PLG_CAPTCHA_EXAMPLE_FIELD_QUESTION_VOWELS', - 'consonants' => 'PLG_CAPTCHA_EXAMPLE_FIELD_QUESTION_CONSONANTS', - 'capitals' => 'PLG_CAPTCHA_EXAMPLE_FIELD_QUESTION_CAPITALS', - ); - + /** + * Listing of question types + * + * @var array + */ + protected $question_types = array( + 'vowels' => 'PLG_CAPTCHA_EXAMPLE_FIELD_QUESTION_VOWELS', + 'consonants' => 'PLG_CAPTCHA_EXAMPLE_FIELD_QUESTION_CONSONANTS', + 'capitals' => 'PLG_CAPTCHA_EXAMPLE_FIELD_QUESTION_CAPITALS', + ); + + /** + * Event method loaded on CAPTCHA initialization + * + * @param mixed $id HTML identifier + * + * @return null + */ public function onInit($id) - { - $this->question_word = $this->generateRandomString(); - $this->question_type = array_rand($this->question_types, 1); - - $session = JFactory::getSession(); - $session->set('captcha.example.word', $this->question_word); - $session->set('captcha.example.type', $this->question_type); - } - + { + $this->question_word = $this->generateRandomString(); + $this->question_type = array_rand($this->question_types, 1); + + $session = JFactory::getSession(); + $session->set('captcha.example.word', $this->question_word); + $session->set('captcha.example.type', $this->question_type); + } + + /** + * Event method run when the CAPTCHA needs to be displayed + * + * @param string $name HTML name + * @param mixed $id HTML identifier + * @param string $class HTML class + * + * @return string + */ public function onDisplay($name, $id, $class) { - $html = JText::_($this->question_types[$this->question_type]); - $html .= '
'.$this->question_word.'
'; - $html .= '
'; - $html .= JText::_('PLG_CAPTCHA_EXAMPLE_FIELD_ANSWER').': '; - $html .= ''; - return $html; - } - + $html = JText::_($this->question_types[$this->question_type]); + $html .= '
' . $this->question_word . '
'; + $html .= '
'; + $html .= JText::_('PLG_CAPTCHA_EXAMPLE_FIELD_ANSWER') . ': '; + $html .= ''; + + return $html; + } + + /** + * Event method run to check the CAPTCHA response given by the user + * + * @param string $answer Text inputted by the user + * + * @return bool + */ public function onCheckAnswer($answer) { - $answer = (int)trim($answer); - if (!$answer > 0) - { + $answer = (int) trim($answer); + + if (!$answer > 0) + { $this->_subject->setError(JText::_('PLG_CAPTCHA_EXAMPLE_ERROR_NO_RESPONSE')); + return false; - } + } + + $session = JFactory::getSession(); + $question_type = $session->get('captcha.example.type'); + $question_word = $session->get('captcha.example.word'); - $session = JFactory::getSession(); - $question_type = $session->get('captcha.example.type'); - $question_word = $session->get('captcha.example.word'); - if ($this->matchAnswer($answer, $question_type, $question_word) == false) - { + if ($this->matchAnswer($answer, $question_type, $question_word) == false) + { $this->_subject->setError(JText::sprintf('PLG_CAPTCHA_EXAMPLE_ERROR_INCORRECT', $answer)); + return false; - } - - return true; - } - - protected function matchAnswer($answer, $question_type, $question_word) - { - $validAnswer = 0; - switch($question_type) - { - case 'capitals': - preg_match_all('/[ABCDEFGHIJKLMNOPQRSTUVWXYZ]/', $question_word, $matches); - $validAnswer = count($matches[0]); - break; - - case 'vowels': - preg_match_all('/[aouie]/i', $question_word, $matches); - $validAnswer = count($matches[0]); - break; - - case 'consonants': - preg_match_all('/[bcdfghjklmnpqrstvwxyz]/i', $question_word, $matches); - $validAnswer = count($matches[0]); - break; - } - - if ($answer == $validAnswer) - { - return true; - } - - return false; - } - - protected function generateRandomString() - { - $characters = array(); - - $ranges = array( - 'abcdefghijklmnopqrstuvwxyz', - 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', - '0123456789', - 'aAeEiIoOuU', - 'bBcCdDfFgGhHjJkKlLmMnNpPqQrRsStTvVwWxXyYzZ', - ); - - foreach ($ranges as $range) - { - $length = rand(2, 4); - $rangeCharacters = $this->generateRandomStringFromRange($length, $range); - $characters = array_merge($characters, $rangeCharacters); - } - - shuffle($characters); - return implode('', $characters); - } - - protected function generateRandomStringFromRange($length, $range) - { + } + + return true; + } + + /** + * Method to match the answer with a certain question + * + * @param string $answer String of the answer + * @param string $question_type Question type + * @param string $question_word Question word + * + * @return bool + */ + protected function matchAnswer($answer, $question_type, $question_word) + { + $validAnswer = 0; + + switch ($question_type) + { + case 'capitals': + preg_match_all('/[ABCDEFGHIJKLMNOPQRSTUVWXYZ]/', $question_word, $matches); + $validAnswer = count($matches[0]); + break; + + case 'vowels': + preg_match_all('/[aouie]/i', $question_word, $matches); + $validAnswer = count($matches[0]); + break; + + case 'consonants': + preg_match_all('/[bcdfghjklmnpqrstvwxyz]/i', $question_word, $matches); + $validAnswer = count($matches[0]); + break; + } + + if ($answer == $validAnswer) + { + return true; + } + + return false; + } + + /** + * Method to generate a random string + * + * @return string + */ + protected function generateRandomString() + { + $characters = array(); + + $ranges = array( + 'abcdefghijklmnopqrstuvwxyz', + 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', + '0123456789', + 'aAeEiIoOuU', + 'bBcCdDfFgGhHjJkKlLmMnNpPqQrRsStTvVwWxXyYzZ', + ); + + foreach ($ranges as $range) + { + $length = rand(2, 4); + $rangeCharacters = $this->generateRandomStringFromRange($length, $range); + $characters = array_merge($characters, $rangeCharacters); + } + + shuffle($characters); + + return implode('', $characters); + } + + /** + * Method to generate a random string from a certain range of characters + * + * @param int $length Length of the required string + * @param string $range Characters containing the range + * + * @return array + */ + protected function generateRandomStringFromRange($length, $range) + { $base = strlen($range); $randomChars = array(); @@ -128,6 +197,6 @@ protected function generateRandomStringFromRange($length, $range) $shift += ord($random[$i]); } - return $randomChars; - } + return $randomChars; + } } diff --git a/chapter11/plg_extension_custom/plugins/extension/custom/custom.php b/chapter11/plg_extension_custom/plugins/extension/custom/custom.php index 60d86f4..473f237 100644 --- a/chapter11/plg_extension_custom/plugins/extension/custom/custom.php +++ b/chapter11/plg_extension_custom/plugins/extension/custom/custom.php @@ -2,34 +2,70 @@ /** * Extension Plugin for Joomla! - Custom * - * @author Jisse Reitsma (jisse@yireo.com) - * @copyright Copyright 2014 Jisse Reitsma - * @license GNU Public License version 3 or later - * @link http://www.yireo.com/books/ + * @author Jisse Reitsma + * @copyright Copyright 2014 Jisse Reitsma + * @license GNU Public License version 3 or later + * @link http://www.yireo.com/books/ */ defined('_JEXEC') or die; jimport('joomla.plugin.plugin'); -class plgExtensionCustom extends JPlugin + +/** + * Class PlgExtensionCustom + * + * @since September 2014 + */ +class PlgExtensionCustom extends JPlugin { - public function onExtensionBeforeSave($context, $table, $isNew) - { - $this->debug('[onExtensionBeforeSave] context', $context); - $this->debug('[onExtensionBeforeSave] table', get_class($table)); - } + /** + * Event method onExtensionBeforeSave + * + * @param string $context Current context + * @param JTable $table JTable instance + * @param bool $isNew Flag to determine whether this is a new extension + * + * @return void + */ + public function onExtensionBeforeSave($context, $table, $isNew) + { + $this->debug('[onExtensionBeforeSave] context', $context); + $this->debug('[onExtensionBeforeSave] table', get_class($table)); + } + + /** + * Event method onExtensionAfterSave + * + * @param string $context Current context + * @param JTable $table JTable instance + * @param bool $isNew Flag to determine whether this is a new extension + * + * @return void + */ + public function onExtensionAfterSave($context, $table, $isNew) + { + $this->debug('[onExtensionAfterSave] context', $context); + $this->debug('[onExtensionAfterSave] table', get_class($table)); + } - public function onExtensionAfterSave($context, $table, $isNew) - { - $this->debug('[onExtensionAfterSave] context', $context); - $this->debug('[onExtensionAfterSave] table', get_class($table)); - } + /** + * Method to log something + * + * @param string $message Message to log + * @param mixed $variable Optional variable to add to the message + * + * @return void + */ + protected function debug($message, $variable = null) + { + if (!empty($variable)) + { + $message .= var_export($variable, true); + } - protected function debug($message, $variable) - { - if (!empty($variable)) $message .= var_export($variable, true); - $message .= "\n"; + $message .= "\n"; - JLog::add($message, JLog::NOTICE, 'plg_extension_custom'); - } + JLog::add($message, JLog::NOTICE, 'plg_extension_custom'); + } } diff --git a/chapter13/plg_system_eventlog/plugins/system/eventlog/eventlog.php b/chapter13/plg_system_eventlog/plugins/system/eventlog/eventlog.php index e2a55b1..2855ca8 100644 --- a/chapter13/plg_system_eventlog/plugins/system/eventlog/eventlog.php +++ b/chapter13/plg_system_eventlog/plugins/system/eventlog/eventlog.php @@ -2,47 +2,196 @@ /** * System Plugin for Joomla! - Event Log * - * @author Jisse Reitsma (jisse@yireo.com) - * @copyright Copyright 2014 Jisse Reitsma - * @license GNU Public License version 3 or later - * @link http://www.yireo.com/books/ + * @author Jisse Reitsma + * @copyright Copyright 2014 Jisse Reitsma + * @license GNU Public License version 3 or later + * @link http://www.yireo.com/books/ */ defined('_JEXEC') or die; jimport('joomla.plugin.plugin'); -class plgSystemEventlog extends JPlugin + +/** + * Class PlgSystemEventlog + * + * @since September 2014 + */ +class PlgSystemEventlog extends JPlugin { + /** + * Constructor. + * + * @param object &$subject The object to observe. + * @param array $config An optional associative array of configuration settings. + */ public function __construct(& $subject, $config) { parent::__construct($subject, $config); - jimport('joomla.log.log'); - JLog::addLogger(array('text_file' => 'plg_system_eventlog.log.php'), JLog::ALL, array('plg_system_eventlog')); - } - - public function onAfterInitialise() { $this->log('onAfterInitialise'); } - public function onAfterSessionStart() { $this->log('onAfterSessionStart'); } - public function onAfterRoute() { $this->log('onAfterRoute'); } - public function onAfterDispatch() { $this->log('onAfterDispatch'); } - public function onAfterExecute() { $this->log('onAfterExecute'); } - public function onAfterRespond() { $this->log('onAfterRespond'); } - public function onBeforeCompileHead() { $this->log('onBeforeCompileHead'); } - public function onBeforeExecute() { $this->log('onBeforeExecute'); } - public function onBeforeRender() { $this->log('onBeforeRender'); } - public function onBeforeRespond() { $this->log('onBeforeRespond'); } - public function onFork() { $this->log('onFork'); } - public function onReceiveSignal() { $this->log('onReceiveSignal'); } - - protected function log($event) - { - $request = null; - if(isset($_SERVER['REQUEST_URI'])) $request .= $_SERVER['REQUEST_URI']; - if(isset($_SERVER['HTTP_HOST'])) $request .= $_SERVER['HTTP_HOST']; - if(isset($_SERVER['REMOTE_ADDR'])) $request .= $_SERVER['REMOTE_ADDR']; - $id = md5($request); - - $log = '['.$id.'] '.$event; - JLog::add($event, JLog::NOTICE, 'plg_system_eventlog'); - } + jimport('joomla.log.log'); + JLog::addLogger(array('text_file' => 'plg_system_eventlog.log.php'), JLog::ALL, array('plg_system_eventlog')); + } + + /** + * Event method onAfterInitialise + * + * @return null + */ + public function onAfterInitialise() + { + $this->log('onAfterInitialise'); + } + + /** + * Event method onAfterSessionStart + * + * @return null + */ + public function onAfterSessionStart() + { + $this->log('onAfterSessionStart'); + } + + /** + * Event method onAfterRoute + * + * @return null + */ + public function onAfterRoute() + { + $this->log('onAfterRoute'); + } + + /** + * Event method onAfterDispatch + * + * @return null + */ + public function onAfterDispatch() + { + $this->log('onAfterDispatch'); + } + + /** + * Event method onAfterRender + * + * @return null + */ + public function onAfterRender() + { + $this->log('onAfterRender'); + } + + /** + * Event method onAfterExecute + * + * @return null + */ + public function onAfterExecute() + { + $this->log('onAfterExecute'); + } + + /** + * Event method onAfterRespond + * + * @return null + */ + public function onAfterRespond() + { + $this->log('onAfterRespond'); + } + + /** + * Event method onBeforeCompileHead + * + * @return null + */ + public function onBeforeCompileHead() + { + $this->log('onBeforeCompileHead'); + } + + /** + * Event method onBeforeExecute + * + * @return null + */ + public function onBeforeExecute() + { + $this->log('onBeforeExecute'); + } + + /** + * Event method onBeforeRender + * + * @return null + */ + public function onBeforeRender() + { + $this->log('onBeforeRender'); + } + + /** + * Event method onBeforeRespond + * + * @return null + */ + public function onBeforeRespond() + { + $this->log('onBeforeRespond'); + } + + /** + * Event method onFork + * + * @return null + */ + public function onFork() + { + $this->log('onFork'); + } + + /** + * Event method onReceiveSignal + * + * @return null + */ + public function onReceiveSignal() + { + $this->log('onReceiveSignal'); + } + + /** + * Method to log an event + * + * @param string $event Name of the event + * + * @return null + */ + protected function log($event) + { + $request = null; + + if (isset($_SERVER['REQUEST_URI'])) + { + $request .= $_SERVER['REQUEST_URI']; + } + + if (isset($_SERVER['HTTP_HOST'])) + { + $request .= $_SERVER['HTTP_HOST']; + } + + if (isset($_SERVER['REMOTE_ADDR'])) + { + $request .= $_SERVER['REMOTE_ADDR']; + } + + $id = md5($request); + + $log = '[' . $id . '] ' . $event; + JLog::add($event, JLog::NOTICE, 'plg_system_eventlog'); + } } diff --git a/chapter14/plg_system_custom/plugins/system/custom/custom.php b/chapter14/plg_system_custom/plugins/system/custom/custom.php index 01fe5d8..350fe35 100644 --- a/chapter14/plg_system_custom/plugins/system/custom/custom.php +++ b/chapter14/plg_system_custom/plugins/system/custom/custom.php @@ -1,39 +1,65 @@ + * @copyright Copyright 2014 Jisse Reitsma + * @license GNU Public License version 3 or later + * @link http://www.yireo.com/books/ */ defined('_JEXEC') or die; jimport('joomla.plugin.plugin'); -class plgSystemCustom extends JPlugin + +/** + * Class PlgSystemCustom + * + * @since September 2014 + */ +class PlgSystemCustom extends JPlugin { - protected $replacementStrings = array( - ); - - public function onAfterRender() - { - $app = JFactory::getApplication(); - if($app->isAdmin()) { - return; - } - - $this->replaceStrings(); - } - - protected function replaceStrings() - { - $body = JResponse::getBody(); - if(!empty($this->replacementStrings)) { - foreach($this->replacementStrings as $original => $replacement) { - $body = str_replace($original, $replacement, $body); - } - } - JResponse::setBody($body); - } + /* + * Array of replacement strings (original => replacement) + */ + protected $replacementStrings = array( + 'exapmle' => 'example', + ); + + /** + * Event method onAfterRender + * + * @return null + */ + public function onAfterRender() + { + $app = JFactory::getApplication(); + + if ($app->isAdmin()) + { + return; + } + + $this->replaceStrings(); + } + + /** + * Method to replace strings into strings + * + * @return null + */ + protected function replaceStrings() + { + $body = JResponse::getBody(); + + if (!empty($this->replacementStrings)) + { + foreach ($this->replacementStrings as $original => $replacement) + { + $body = str_replace($original, $replacement, $body); + } + } + + JResponse::setBody($body); + } } diff --git a/chapter14/plugin-tests/plgSystemArticletext.php b/chapter14/plugin-tests/plgSystemArticletext.php index b54c877..b28faf3 100644 --- a/chapter14/plugin-tests/plgSystemArticletext.php +++ b/chapter14/plugin-tests/plgSystemArticletext.php @@ -1,61 +1,91 @@ + * @copyright Copyright 2014 Jisse Reitsma + * @license GNU Public License version 3 or later + * @link http://www.yireo.com/books/ + */ -class plgSystemArticletextTest extends PHPUnit_Framework_TestCase +/** + * Class PlgSystemArticletextTest + * + * @since September 2014 + */ +class PlgSystemArticletextTest extends PHPUnit_Framework_TestCase { - public function initJoomla() - { - $_SERVER['HTTP_HOST'] = null; - - // Neccessary definitions - define('_JEXEC', 1); - define('DOCUMENT_ROOT', dirname(dirname(__FILE__)).'/'); - define('JPATH_BASE', DOCUMENT_ROOT); - - if(!is_file(JPATH_BASE.'/includes/framework.php')) { - die('Incorrect Joomla! base-path'); - } - chdir(JPATH_BASE); - - // Include the framework - require_once(JPATH_BASE.'/includes/defines.php'); - require_once(JPATH_BASE.'/includes/framework.php'); - - jimport('joomla.environment.request'); - jimport('joomla.database.database'); - - $app = JFactory::getApplication('site'); - $app->initialise(); - - jimport('joomla.plugin.helper'); - JPluginHelper::importPlugin('system'); - } - - public function testReplaceTags() - { - $this->initJoomla(); - $dispatcher = JEventDispatcher::getInstance(); - $plugin = new plgSystemArticletext($dispatcher, array()); - - $tests = array(); - $tests[] = array( - 'text' => 'test without articletext', - 'articletext' => false, - ); - $tests[] = array( - 'text' => 'test with articletext: {articletext id=2}', - 'articletext' => true, - ); - - foreach($tests as $test) { - $textBefore = $test['text']; - $textAfter = $plugin->replaceTags($testBefore); - - if($test['articletext'] == true) { - $this->assertNotEquals($testBefore, $textAfter); - } else { - $this->assertEquals($testBefore, $textAfter); - } - } - } + /** + * Method to initialize Joomla application + * + * @return null + */ + public function initJoomla() + { + $_SERVER['HTTP_HOST'] = null; + + // Neccessary definitions + define('_JEXEC', 1); + define('DOCUMENT_ROOT', dirname(dirname(__FILE__)) . '/'); + define('JPATH_BASE', DOCUMENT_ROOT); + + if (!is_file(JPATH_BASE . '/includes/framework.php')) + { + die('Incorrect Joomla! base-path'); + } + + chdir(JPATH_BASE); + + // Include the framework + require_once JPATH_BASE . '/includes/defines.php'; + require_once JPATH_BASE . '/includes/framework.php'; + + jimport('joomla.environment.request'); + jimport('joomla.database.database'); + + $app = JFactory::getApplication('site'); + $app->initialise(); + + jimport('joomla.plugin.helper'); + JPluginHelper::importPlugin('system'); + } + + /** + * PHPUnit test for replacing tags + * + * @return null + */ + public function testReplaceTags() + { + $this->initJoomla(); + + $dispatcher = JEventDispatcher::getInstance(); + $plugin = new plgSystemArticletext($dispatcher, array()); + + $tests = array(); + $tests[] = array( + 'text' => 'test without articletext', + 'articletext' => false, + ); + $tests[] = array( + 'text' => 'test with articletext: {articletext id=2}', + 'articletext' => true, + ); + + foreach ($tests as $test) + { + $textBefore = $test['text']; + $textAfter = $plugin->replaceTags($testBefore); + + if ($test['articletext'] == true) + { + $this->assertNotEquals($testBefore, $textAfter); + } + else + { + $this->assertEquals($testBefore, $textAfter); + } + } + } }