Assembla home | Assembla project page
 

root/trunk/Phergie/Plugin/Tld.php

Revision 273, 8.7 kB (checked in by Seldaek, 4 months ago)

* Plugins that can't load now return error messages to say why
fixes #35

Line 
1 <?php
2
3 /**
4  * Responds to a request for a TLD (formatted as .tld where tld is the TLD to
5  * be looked up) with its corresponding description.
6  */
7 class Phergie_Plugin_Tld extends Phergie_Plugin_Abstract_Base
8 {
9     /**
10      * Indicates that a local directory is required for this plugin
11      *
12      * @var bool
13      */
14     protected $needsDir = true;
15
16     /**
17      * PDO resource for a SQLite database containing the TLDs
18      *
19      * @var resource
20      */
21     protected $db = null;
22
23     /**
24      * Some fixed TLD values, keys must be lowercase
25      *
26      * @var array
27      */
28     protected static $fixedTlds;
29
30     /**
31      * Prepared statement to retrieve TLD records
32      *
33      * @var PDOStatement
34      */
35     protected $select;
36     protected $selectAll;
37
38     /**
39      * Static instance of the Tld class
40      *
41      * @var Phergie_Plugin_Tld
42      */
43     protected static $instance;
44
45     /**
46      * Connects to the database and populates tables where needed.
47      *
48      * @return void
49      */
50     public function onInit()
51     {
52         self::$fixedTlds = array(
53             'phergie' => 'You can find Phergie at http://www.phergie.org',
54             'spoon' => 'Don\'t you know? There is no spoon!',
55             'poo' => 'Do you really think that\'s funny?',
56             'root' => 'Diagnostic marker to indicate a root zone load was not truncated.'
57         );
58
59         try {
60             // Initialize the database connection
61             $this->db = new PDO('sqlite:' . $this->dir . 'tld.db');
62             if (!$this->db) {
63                 return;
64             }
65
66             // Check to see if the TLD table needs to be created
67             $table = $this->db->query('SELECT COUNT(*) FROM sqlite_master WHERE name = ' . $this->db->quote('tld'))->fetchColumn();
68
69             // Get the list of columns from the table
70             $columns = array();
71             if ($table) {
72                 $pragma = $this->db->query('PRAGMA table_info(' . $this->db->quote('tld') . ')')->fetchAll();
73
74                 foreach($pragma as $key => $column) {
75                     $columns[] = trim(strtolower($column['name']));
76                 }
77                 unset($pragma);
78             }
79
80             // Create and populate the table if needed
81             if (!$table || !in_array('type', $columns)) {
82                 if ($table && !in_array('type', $columns)) {
83                     $this->debug('Removing the current database schema');
84                     $this->db->exec('DROP TABLE tld');
85                 }
86                 $this->debug('Creating the database schema');
87                 $this->db->exec('CREATE TABLE tld (tld VARCHAR(20), type VARCHAR(20), description VARCHAR(255))');
88
89                 $insert = $this->db->prepare('INSERT INTO tld (tld, type, description) VALUES (:tld, :type, :description)');
90
91                 $contents = file_get_contents('http://www.iana.org/domains/root/db/');
92                 preg_match_all('{<tr class="iana-group[^>]*><td><a[^>]*>\s*\.?([^<]+)\s*(?:<br/><span[^>]*>[^<]*</span>)?</a></td><td>\s*([^<]+)\s*</td><td>\s*([^<]+)\s*}i',
93                                $contents, $matches, PREG_SET_ORDER);
94
95                 foreach($matches as $match) {
96                     list(, $tld, $type, $description) = array_pad($match, 4, null);
97                     $type = trim(strtolower($type));
98                     if ($type != 'test') {
99                         $tld = trim(strtolower($tld));
100                         $description = trim($description);
101
102                         switch ($tld) {
103                             case 'com':
104                                 $description = 'Commercial';
105                             break;
106
107                             case 'info':
108                                 $description = 'Information';
109                             break;
110
111                             case 'net':
112                                 $description = 'Network';
113                             break;
114
115                             case 'org':
116                                 $description = 'Organization';
117                             break;
118
119                             case 'edu':
120                                 $description = 'Educational';
121                             break;
122
123                             case 'name':
124                                 $description = 'Individuals, by name';
125                             break;
126                         }
127
128                         if (empty($tld) || empty($description)) {
129                             continue;
130                         }
131
132                         $description = preg_replace('{(^(?:Reserved|Restricted)\s*(?:exclusively\s*)?(?:for|to)\s*(?:members of\s*)?(?:the|support)?\s*|\s*as advised.*$)}i', '', $description);
133                         $description = ucfirst(trim($description));
134
135                         $data = array_map('html_entity_decode', array(
136                             'tld' => $tld,
137                             'type' => $type,
138                             'description' => $description
139                         ));
140
141                         $insert->execute($data);
142                         $this->debug('Inserted TLD: ' . $tld . ' = ' . '(' . $type . ') ' . $description);
143                     }
144                 }
145                 unset($insert, $matches, $match, $tld, $type, $description, $data);
146             }
147
148             // Create a prepared statement for retrieving TLDs
149             $this->select = $this->db->prepare('SELECT type, description FROM tld WHERE LOWER(tld) = LOWER(:tld)');
150             $this->selectAll = $this->db->prepare('SELECT tld, type, description FROM tld');
151         } catch (PDOException $e) { }
152
153         // Create a static instance of the class
154         self::$instance = $this;
155     }
156
157     /**
158      * Returns whether or not the plugin's dependencies are met.
159      *
160      * @param Phergie_Driver_Abstract $client Client instance
161      * @param array $plugins List of short names for plugins that the
162      *                       bootstrap file intends to instantiate
163      * @see Phergie_Plugin_Abstract_Base::checkDependencies()
164      * @return bool TRUE if dependencies are met, FALSE otherwise
165      */
166     public static function checkDependencies(Phergie_Driver_Abstract $client, array $plugins)
167     {
168         $errors = array();
169
170         if (!extension_loaded('PDO')) {
171             $errors[] = 'PDO php extension is required';
172         }
173         if (!extension_loaded('pdo_sqlite')) {
174             $errors[] = 'pdo_sqlite php extension is required';
175         }
176
177         return empty($errors) ? true : $errors;
178     }
179
180     /**
181      * Performs a lookup on the internal TLD table and sends the description
182      * corresponding to a given TLD back to the sender if it exists.
183      *
184      * @return void
185      */
186     public function onPrivmsg()
187     {
188         if (!$this->db) {
189             return;
190         }
191
192         $target = $this->event->getNick();
193
194         // Command prefix check
195         $prefix = preg_quote(trim($this->getIni('command_prefix')));
196         $bot = preg_quote($this->getIni('nick'));
197         $exp = '(?:(?:' . $bot . '\s*[:,>]?\s+(?:' . $prefix . ')?)|(?:' . $prefix . '))';
198
199         if (preg_match('#^(?:' . $exp . 'tld\s+\.?([a-z]{2,10})$|' . $exp . '?\.([a-z]{2,10}))$#i', $this->event->getArgument(1), $m) &&
200             $description = self::getTld((!empty($m[1]) ? $m[1] : $m[2]))) {
201             $this->doPrivmsg($this->event->getSource(),
202             $target . ': .' . (!empty($m[1]) ? $m[1] : $m[2]) . ' -> ' . ($description ? ucfirst($description) : 'Unknown TLD'));
203         }
204     }
205
206     /**
207      * Retrieves the definition for a given TLD if it exists
208      *
209      * @param string $tld TLD to search for
210      * @return string Defination of the given TLD
211      */
212     public static function getTld($tld)
213     {
214         $tld = trim(strtolower($tld));
215         if (isset(self::$fixedTlds[$tld])) {
216             return self::$fixedTlds[$tld];
217         }
218         else if (self::$instance->db && self::$instance->select->execute(array('tld' => $tld))) {
219             $tlds = self::$instance->select->fetch();
220             if (is_array($tlds)) {
221                 return '(' . $tlds['type'] . ') ' . $tlds['description'];
222             }
223         }
224         return false;
225     }
226
227     /**
228      * Retrieves a list of all the TLDs and their definations
229      *
230      * @return array Array of all the TLDs and their definations
231      */
232     public static function getTlds()
233     {
234         if (self::$instance->db && self::$instance->selectAll->execute()) {
235             $tlds = self::$instance->selectAll->fetchAll();
236             if (is_array($tlds)) {
237                 $tldinfo = array();
238                 foreach($tlds as $key => $tld) {
239                     if (!empty($tld['tld'])) {
240                         $tldinfo[$tld['tld']] = '(' . $tld['type'] . ') ' . $tld['description'];
241                     }
242                 }
243                 unset($tlds);
244                 return $tldinfo;
245             }
246         }
247         return false;
248     }
249 }
250
Note: See TracBrowser for help on using the browser.