tweaked node validation
[radio:radio.git] / radio_custom.module
1 <?php
2
3 /**
4  * Defines SSL certificate fingerprints.
5  */
6 define('RADIO_CUSTOM_MD5', '9F:3A:95:A7:3D:93:B4:47:CF:E0:3A:05:7F:1F:3D:20');
7 define('RADIO_CUSTOM_SHA1', '79:C8:12:7E:6E:E6:EB:75:61:81:20:5C:C5:F5:2E:96:01:CD:32:2A');
8
9 /**
10  * Implements hook_block_info().
11  */
12 function radio_custom_block_info() {
13   $blocks['podcast'] = array(
14     'cache'  => DRUPAL_CACHE_GLOBAL,
15     'info'   => t('Podcast generator'),
16   );
17   return $blocks;
18 }
19
20 /**
21  * Implements hook_block_view().
22  */
23 function radio_custom_block_view($delta) {
24   switch ($delta) {
25     case 'podcast':
26       return array(
27         'subject' => t('Podcast generator'),
28         'content' => drupal_get_form('radio_custom_form_podcast'),
29       );
30   }
31 }
32
33 /**
34  * Load feed items
35  *
36  * @param $type
37  *   The filter for the items. Possible values: 'sum', 'source', 'category'
38  * @param $data
39  *   Feed or category data for filtering
40  * @return
41  *   An array of the feed items.
42  */
43 function radio_custom_feed_items_load($type, $data = NULL) {
44   $items = array();
45   $range_limit = 5;
46   switch ($type) {
47     case 'sum':
48       $result = db_query_range('SELECT i.*, f.title AS ftitle, f.link AS flink FROM {aggregator_item} i INNER JOIN {aggregator_feed} f ON i.fid = f.fid ORDER BY i.timestamp DESC, i.iid DESC', 0, $range_limit);
49       break;
50     case 'source':
51       $result = db_query_range('SELECT * FROM {aggregator_item} WHERE fid = :fid ORDER BY timestamp DESC, iid DESC', 0, $range_limit, array(':fid' => $data->fid));
52       break;
53     case 'category':
54       $result = db_query_range('SELECT i.*, f.title AS ftitle, f.link AS flink FROM {aggregator_category_item} c LEFT JOIN {aggregator_item} i ON c.iid = i.iid LEFT JOIN {aggregator_feed} f ON i.fid = f.fid WHERE cid = :cid ORDER BY timestamp DESC, i.iid DESC', 0, $range_limit, array(':cid' => $data['cid']));
55       break;
56   }
57
58   foreach ($result as $item) {
59     $item->categories = db_query('SELECT c.title, c.cid FROM {aggregator_category_item} ci LEFT JOIN {aggregator_category} c ON ci.cid = c.cid WHERE ci.iid = :iid ORDER BY c.title', array(':iid' => $item->iid))->fetchAll();
60     $summary = text_summary($item->description, NULL, variable_get('aggregator_teaser_length', 600));
61     if ($summary != $item->description) {
62       $summary .= '<p><a href="' . check_url($item->link) . '">' . t('read more') . "</a></p>\n";
63     }
64     $item->description = $summary;
65     $items[] = $item;
66   }
67
68   return $items;
69 }
70
71 /**
72  * Implements hook_form_alter().
73  */
74 function radio_custom_form_alter(&$form, $form_state, $form_id) {
75   if ($form_id == 'radio_custom_form_podcast') {
76     unset($form['form_build_id']);
77     unset($form['form_token']);
78     unset($form['form_id']);
79   }
80 }
81
82 /**
83  * Podcast form builder.
84  */
85 function radio_custom_form_podcast() {
86   $form['#method'] = 'get';
87   $form['#action'] = url('podcast');
88   $form['keys'] = array(
89     '#type' => 'textfield',
90     '#title' => t('Enter your keywords'),
91     '#size' => 20,
92     '#description' => t('Enter your search terms — for example, <em>cats OR dogs</em> — to generate a keyword-based podcast URL.'),
93   );
94   $form['submit'] = array(
95     '#type' => 'submit',
96     '#value' => t('Go'),
97     '#name' => '',
98     '#id' => 'radio-block-podcast-submit',
99   );
100   return $form;
101 }
102
103 /**
104  * Implements hook_help().
105  */
106 function radio_custom_help($path, $arg) {
107   global $is_https;
108   switch ($path) {
109     case 'publish.html':
110     case 'node/add/audio':
111       if ($is_https) {
112         return t('Your submission will be encrypted. SSL certificate fingerprints:<br />SHA-1 %sha1<br />MD5 %md5', array('%sha1' => RADIO_CUSTOM_SHA1, '%md5' => RADIO_CUSTOM_MD5));
113       }
114   }
115 }
116
117 /**
118  * Implements hook_menu().
119  */
120 function radio_custom_menu() {
121   $items = array();
122   $type = node_type_get_type('audio');
123   $items['publish.html'] = array(
124     'title' => 'Publish',
125     'page callback' => 'node_add',
126     'page arguments' => array('audio'),
127     'access callback' => 'node_access',
128     'access arguments' => array('create', 'audio'),
129     'description' => $type->description,
130     'file' => 'node.pages.inc',
131     'file path' => drupal_get_path('module', 'node'),
132   );
133   $items['index.html'] = array(
134     'title' => 'Home',
135     'page callback' => 'radio_custom_page_category',
136     'access arguments' => array('access news feeds'),
137     'file' => 'aggregator.pages.inc',
138     'file path' => drupal_get_path('module', 'aggregator'),
139   );
140   $items['about.html'] = array(
141     'title' => 'About',
142     'page callback' => 'radio_custom_page_about',
143     'access callback' => TRUE,
144   );
145   $items['cities.html'] = array(
146     'title' => 'Indymedia',
147     'page callback' => 'radio_custom_page_cities',
148     'access callback' => TRUE,
149   );
150   $items['podcast.html'] = array(
151     'title' => 'Podcast',
152     'page callback' => 'radio_custom_page_podcast',
153     'access callback' => TRUE,
154   );
155   $items['yp/icecast.html'] = array(
156     'title' => 'Add your stream',
157     'page callback' => 'radio_custom_page_icecast',
158     'access callback' => TRUE,
159     'type' => MENU_LOCAL_TASK,
160   );
161   $items['metagen.php'] = array(
162     'page callback' => 'radio_custom_page_metagen',
163     'access arguments' => array('access content'),
164     'type' => MENU_CALLBACK,
165   );
166   return $items;
167 }
168
169 /**
170  * Implements hook_node_validate().
171  */
172 function radio_custom_node_validate($node, $form, &$form_state) {
173   foreach ($node->upload as $language) {
174     foreach ($language as $delta) {
175       if ($delta['fid']) {
176         $file = file_load($delta['fid']);
177         if ($file->filemime == 'audio/mpeg' && $file->filesize < 1000000) {
178           radio_custom_set_error();
179         }
180       }
181     }
182   }
183   foreach ($node->body as $language) {
184     foreach ($language as $delta) {
185       if (substr_count(strtolower($delta['value']), 'http:') > 10) {
186         radio_custom_set_error();
187       }
188     }
189   }
190 }
191
192 /**
193  * About page callback.
194  */
195 function radio_custom_page_about() {
196   return node_page_view(node_load(2453));
197 }
198
199 /**
200  * Menu callback; displays all the items aggregated in a particular category.
201  *
202  * @param $category
203  *   The category for which to list all the aggregated items.
204  *
205  * @return
206 *   The rendered list of items for a category.
207  */
208 function radio_custom_page_category($cid = 1) {
209   // Turn off the page title for front page.
210   drupal_set_title('');
211   $category = aggregator_category_load($cid);
212   drupal_add_feed('rss.xml', variable_get('site_name', 'Drupal') . ' ' . t('RSS'));
213   drupal_add_feed('aggregator/rss/' . $category['cid'], variable_get('site_name', 'Drupal') . ' ' . t('aggregator - @title', array('@title' => $category['title'])));
214
215   // It is safe to include the cid in the query because it's loaded from the
216   // database by aggregator_category_load.
217   $items = radio_custom_feed_items_load('category', $category);
218
219   return _aggregator_page_list($items, arg(3)) . '<div id="radio-more-link">' . l(t('More'), 'aggregator/categories/1'). '</div>';
220 }
221
222 /**
223  * Cities page callback.
224  */
225 function radio_custom_page_cities() {
226   return node_page_view(node_load(18501));
227 }
228
229 /**
230  * Icecast page callback.
231  */
232 function radio_custom_page_icecast() {
233   return node_page_view(node_load(17168));
234 }
235
236 /**
237  * Metagen page callback.
238  */
239 function radio_custom_page_metagen() {
240   $url = isset($_GET['url']) ? $_GET['url'] : NULL;
241   $output = $url . "\r\n";
242   drupal_set_header('Content-Type: audio/x-mpegurl');
243   drupal_set_header('Content-Length: '. strlen($output));
244   drupal_set_header('Content-Disposition: inline; filename='. preg_replace(array(';http://;', ';[^a-z0-9];'), array('', '-'), $url) . '.m3u');
245   print $output;
246 }
247
248 /**
249  * Podcast page callback.
250  */
251 function radio_custom_page_podcast() {
252   return node_page_view(node_load(18514));
253 }
254
255 /**
256  * Node validation helper function.
257  */
258 function radio_custom_set_error() {
259   form_set_error('', t('Sorry, please try again in 30 seconds. For help please contact imc-audio@lists.indymedia.org.'));
260 }