| 1 |
<?php
|
| 2 |
// $Id: itunes.module,v 1.9 2009/07/31 22:45:06 drewish Exp $
|
| 3 |
|
| 4 |
define('ITUNES_EXPLICIT_YES', 1);
|
| 5 |
define('ITUNES_EXPLICIT_CLEAN', 2);
|
| 6 |
|
| 7 |
/**
|
| 8 |
* @file
|
| 9 |
* Provides an iTunes view style for feeds.
|
| 10 |
*/
|
| 11 |
|
| 12 |
/**
|
| 13 |
* Implementation of hook_menu().
|
| 14 |
*/
|
| 15 |
function itunes_menu() {
|
| 16 |
$items = array();
|
| 17 |
$items['admin/settings/itunes'] = array(
|
| 18 |
'title' => 'iTunes',
|
| 19 |
'page callback' => 'drupal_get_form',
|
| 20 |
'page arguments' => array('itunes_admin_settings'),
|
| 21 |
'access arguments' => array('administer site configuration'),
|
| 22 |
'file' => 'itunes.admin.inc',
|
| 23 |
'description' => 'Determine which node types can track iTunes information.'
|
| 24 |
);
|
| 25 |
return $items;
|
| 26 |
}
|
| 27 |
|
| 28 |
/**
|
| 29 |
* Implementation of hook_theme().
|
| 30 |
*/
|
| 31 |
function itunes_theme() {
|
| 32 |
return array(
|
| 33 |
'itunes_admin_settings' => array(
|
| 34 |
'arguments' => array('form'),
|
| 35 |
'file' => 'itunes.admin.inc',
|
| 36 |
),
|
| 37 |
);
|
| 38 |
}
|
| 39 |
|
| 40 |
/**
|
| 41 |
* Implementation of hook_views_api().
|
| 42 |
*/
|
| 43 |
function itunes_views_api() {
|
| 44 |
return array(
|
| 45 |
'api' => 2,
|
| 46 |
);
|
| 47 |
}
|
| 48 |
|
| 49 |
/**
|
| 50 |
* Implementation of hook_help().
|
| 51 |
*/
|
| 52 |
function itunes_help($section, $arg) {
|
| 53 |
switch ($section) {
|
| 54 |
case 'admin/settings/itunes':
|
| 55 |
return '<p>'. t("This form allows you to determine which content types need to be have the iTunes feed item data fields added to them.") .'<br />'
|
| 56 |
. t("If the <a href='!filefield-url'>FileField</a> module is installed then you can choose which field to include as an enclosure in RSS feeds.", array('!filefield-url' => url('http://drupal.org/project/filefield'))) .'</p>';
|
| 57 |
}
|
| 58 |
}
|
| 59 |
|
| 60 |
/**
|
| 61 |
* Implementation of hook_form_alter().
|
| 62 |
*
|
| 63 |
* We add in extra iTunes specific information to the node edit forms.
|
| 64 |
*/
|
| 65 |
function itunes_form_alter(&$form, &$form_state, $form_id) {
|
| 66 |
// We only alter the selected node edit forms
|
| 67 |
if (isset($form['#id']) && $form['#id'] == 'node-form') {
|
| 68 |
$types = variable_get('itunes_types', array('audio'));
|
| 69 |
if (isset($form['#node']->type) && in_array($form['#node']->type, $types)) {
|
| 70 |
$node = $form['#node'];
|
| 71 |
$form['itunes'] = array(
|
| 72 |
'#type' => 'fieldset',
|
| 73 |
'#title' => t('iTunes feed information'),
|
| 74 |
'#collapsible' => TRUE,
|
| 75 |
'#description' => t('iTunes specific information.'),
|
| 76 |
'#weight' => 0,
|
| 77 |
'#tree' => TRUE,
|
| 78 |
);
|
| 79 |
$form['itunes']['subtitle'] = array(
|
| 80 |
'#type' => 'textfield',
|
| 81 |
'#title' => t('Subtitle'),
|
| 82 |
'#default_value' => isset($node->itunes['subtitle']) ? $node->itunes['subtitle'] : '',
|
| 83 |
'#maxlength' => 255,
|
| 84 |
'#description' => t("The contents of this tag are shown in the Description column in iTunes. The subtitle displays best if it is only a few words long."),
|
| 85 |
);
|
| 86 |
$form['itunes']['summary'] = array(
|
| 87 |
'#type' => 'textarea',
|
| 88 |
'#title' => t('Summary'),
|
| 89 |
'#default_value' => isset($node->itunes['summary']) ? $node->itunes['summary'] : '',
|
| 90 |
'#maxlength' => 4000,
|
| 91 |
'#rows' => 5,
|
| 92 |
'#description' => t('The contents of this tag are shown in a separate window that appears when the "circled i" in the Description column is clicked. It also appears on the iTunes page for your podcast.'),
|
| 93 |
);
|
| 94 |
$form['itunes']['explicit'] = array(
|
| 95 |
'#type' => 'select', '#title' => t('Explicit'),
|
| 96 |
'#options' => array(0 => 'Unspecified', ITUNES_EXPLICIT_YES => 'Yes', ITUNES_EXPLICIT_CLEAN => 'Clean'),
|
| 97 |
'#default_value' => isset($node->itunes['explicit']) ? $node->itunes['explicit'] : 0,
|
| 98 |
'#description' => t('If select "yes", an "explicit" parental advisory graphic will appear next to your podcast artwork on the iTunes Music Store, and in the Name column in iTunes. If you select "clean", the parental advisory type is considered Clean, meaning that no explicit language or adult content is included anywhere in the episode, and a "clean" graphic will appear.'),
|
| 99 |
);
|
| 100 |
$form['itunes']['block'] = array(
|
| 101 |
'#type' => 'checkbox', '#title' => t('Block'),
|
| 102 |
'#default_value' => isset($node->itunes['block']) ? $node->itunes['block'] : 0,
|
| 103 |
'#description' => t('Check this to prevent this episode from appearing in the iTunes Podcast directory. For example, you may want a specific episode blocked from iTunes if its content might cause the feed to be removed from iTunes.'),
|
| 104 |
);
|
| 105 |
}
|
| 106 |
}
|
| 107 |
}
|
| 108 |
|
| 109 |
/**
|
| 110 |
* Implements hook_content_extra_fields()
|
| 111 |
*
|
| 112 |
* CCK hook to allow moving the iTunes field set around in the node edit form.
|
| 113 |
*/
|
| 114 |
function itunes_content_extra_fields($type_name) {
|
| 115 |
return array(
|
| 116 |
'itunes' => array(
|
| 117 |
'label' => t('iTunes feed information'),
|
| 118 |
'description' => t('iTunes specific information.'),
|
| 119 |
'weight' => 0,
|
| 120 |
),
|
| 121 |
);
|
| 122 |
}
|
| 123 |
|
| 124 |
/**
|
| 125 |
* Implementation of hook_nodeapi().
|
| 126 |
*/
|
| 127 |
function itunes_nodeapi(&$node, $op, $arg) {
|
| 128 |
$types = variable_get('itunes_types', array('audio'));
|
| 129 |
if (in_array($node->type, $types)) {
|
| 130 |
switch ($op) {
|
| 131 |
case 'load':
|
| 132 |
$result = db_query("SELECT * FROM {itunes_item} WHERE vid = %d", $node->vid);
|
| 133 |
if ($result) {
|
| 134 |
return array('itunes' => db_fetch_array($result));
|
| 135 |
}
|
| 136 |
break;
|
| 137 |
|
| 138 |
case 'update':
|
| 139 |
// Delete and insert rather than updating in case the node doesn't have
|
| 140 |
// an existing record.
|
| 141 |
db_query("DELETE FROM {itunes_item} WHERE vid = %d", $node->vid);
|
| 142 |
// INTENTIONALLY NO BREAK HERE.
|
| 143 |
case 'insert':
|
| 144 |
if (!empty($node->itunes)) {
|
| 145 |
$record = array_merge($node->itunes, array('nid' => $node->nid, 'vid' => $node->vid));
|
| 146 |
drupal_write_record('itunes_item', $record);
|
| 147 |
}
|
| 148 |
break;
|
| 149 |
|
| 150 |
case 'delete':
|
| 151 |
db_query("DELETE FROM {itunes_item} WHERE nid = %d", $node->nid);
|
| 152 |
break;
|
| 153 |
|
| 154 |
case 'delete revision':
|
| 155 |
db_query("DELETE FROM {itunes_item} WHERE vid = %d", $node->vid);
|
| 156 |
break;
|
| 157 |
|
| 158 |
case 'rss item':
|
| 159 |
$ret = array();
|
| 160 |
|
| 161 |
// File enclosure.
|
| 162 |
$fields = variable_get('itunes_enclosure_source', array());
|
| 163 |
if (!empty($fields[$node->type]) && !empty($node->{$fields[$node->type]}[0]['fid'])) {
|
| 164 |
$file = (array) $node->{$fields[$node->type]}[0];
|
| 165 |
$ret[] = array(
|
| 166 |
'key' => 'enclosure',
|
| 167 |
'value' => '',
|
| 168 |
'attributes' => array(
|
| 169 |
'url' => file_create_url($file['filepath']),
|
| 170 |
'length' => $file['filesize'],
|
| 171 |
'type' => $file['filemime'],
|
| 172 |
)
|
| 173 |
);
|
| 174 |
if (!empty($file['data']['duration'])) {
|
| 175 |
$ret[] = array(
|
| 176 |
'namespace' => array('xmlns:itunes' => 'http://www.itunes.com/dtds/podcast-1.0.dtd'),
|
| 177 |
'key' => 'itunes:duration',
|
| 178 |
'value' => (int) $file['data']['duration'],
|
| 179 |
);
|
| 180 |
}
|
| 181 |
}
|
| 182 |
|
| 183 |
// Keyword tags.
|
| 184 |
$vocabs = variable_get('itunes_keyword_source', array());
|
| 185 |
if (!empty($vocabs[$node->type])) {
|
| 186 |
$keywords = array();
|
| 187 |
foreach ($node->taxonomy as $tid => $term) {
|
| 188 |
if ($term->vid == $vocabs[$node->type]) {
|
| 189 |
$keywords[] = $term->name;
|
| 190 |
}
|
| 191 |
}
|
| 192 |
if (!empty($keywords)) {
|
| 193 |
$ret[] = array(
|
| 194 |
'namespace' => array('xmlns:itunes' => 'http://www.itunes.com/dtds/podcast-1.0.dtd'),
|
| 195 |
'key' => 'itunes:keywords',
|
| 196 |
'value' => implode(',', array_slice($keywords, 0, 12)),
|
| 197 |
);
|
| 198 |
}
|
| 199 |
}
|
| 200 |
|
| 201 |
// Author.
|
| 202 |
$author_source = variable_get('itunes_author_source', array());
|
| 203 |
if (!empty($author_source[$node->type])) {
|
| 204 |
if ($author_source[$node->type] == 'node_author') {
|
| 205 |
$author = strip_tags(theme('username', $node));
|
| 206 |
}
|
| 207 |
else {
|
| 208 |
$author_field = $node->$author_source[$node->type];
|
| 209 |
if (!empty($author_field[0]['safe'])) {
|
| 210 |
$author = $author_field[0]['view'];
|
| 211 |
}
|
| 212 |
elseif (!empty($author_field[0]['view'])) {
|
| 213 |
foreach ($author_field as $authors) {
|
| 214 |
$authors_view[] = strip_tags(($authors['view']));
|
| 215 |
}
|
| 216 |
$author = implode($authors_view, ', ');
|
| 217 |
}
|
| 218 |
}
|
| 219 |
if ($author) {
|
| 220 |
$ret[] = array(
|
| 221 |
'namespace' => array('xmlns:itunes' => 'http://www.itunes.com/dtds/podcast-1.0.dtd'),
|
| 222 |
'key' => 'itunes:author',
|
| 223 |
'value' => $author,
|
| 224 |
);
|
| 225 |
}
|
| 226 |
}
|
| 227 |
|
| 228 |
// Remaining elements.
|
| 229 |
if (!empty($node->itunes)) {
|
| 230 |
$ret[] = array(
|
| 231 |
'namespace' => array('xmlns:itunes' => 'http://www.itunes.com/dtds/podcast-1.0.dtd'),
|
| 232 |
'key' => 'itunes:summary',
|
| 233 |
'value' => $node->itunes['summary'],
|
| 234 |
);
|
| 235 |
$ret[] = array(
|
| 236 |
'namespace' => array('xmlns:itunes' => 'http://www.itunes.com/dtds/podcast-1.0.dtd'),
|
| 237 |
'key' => 'itunes:subtitle',
|
| 238 |
'value' => $node->itunes['subtitle'],
|
| 239 |
);
|
| 240 |
if ($node->itunes['block']) {
|
| 241 |
$ret[] = array(
|
| 242 |
'namespace' => array('xmlns:itunes' => 'http://www.itunes.com/dtds/podcast-1.0.dtd'),
|
| 243 |
'key' => 'itunes:block',
|
| 244 |
'value' => 'yes',
|
| 245 |
);
|
| 246 |
}
|
| 247 |
$ret[] = array(
|
| 248 |
'namespace' => array('xmlns:itunes' => 'http://www.itunes.com/dtds/podcast-1.0.dtd'),
|
| 249 |
'key' => 'itunes:explicit',
|
| 250 |
'value' => itunes_explicit($node->itunes['explicit']),
|
| 251 |
);
|
| 252 |
}
|
| 253 |
return $ret;
|
| 254 |
}
|
| 255 |
}
|
| 256 |
}
|
| 257 |
|
| 258 |
function itunes_explicit($value) {
|
| 259 |
if ($value == ITUNES_EXPLICIT_YES) {
|
| 260 |
return 'yes';
|
| 261 |
}
|
| 262 |
if ($value == ITUNES_EXPLICIT_CLEAN) {
|
| 263 |
return 'clean';
|
| 264 |
}
|
| 265 |
return 'no';
|
| 266 |
}
|
| 267 |
|
| 268 |
/**
|
| 269 |
* Get an array with the iTunes podcast categories.
|
| 270 |
*
|
| 271 |
* @see http://www.apple.com/itunes/whatson/podcasts/specs.html#categories
|
| 272 |
*/
|
| 273 |
function itunes_categories() {
|
| 274 |
return array(
|
| 275 |
'Arts' => array(
|
| 276 |
'Design',
|
| 277 |
'Fashion & Beauty',
|
| 278 |
'Food',
|
| 279 |
'Literature',
|
| 280 |
'Performing Arts',
|
| 281 |
'Visual Arts',
|
| 282 |
),
|
| 283 |
'Business' => array(
|
| 284 |
'Business News',
|
| 285 |
'Careers',
|
| 286 |
'Investing',
|
| 287 |
'Management & Marketing',
|
| 288 |
'Shopping',
|
| 289 |
),
|
| 290 |
'Comedy' => array(),
|
| 291 |
'Education' => array(
|
| 292 |
'Education Technology',
|
| 293 |
'Higher Education',
|
| 294 |
'K-12',
|
| 295 |
'Language Courses',
|
| 296 |
'Training',
|
| 297 |
),
|
| 298 |
'Games & Hobbies' => array(
|
| 299 |
'Automotive',
|
| 300 |
'Aviation',
|
| 301 |
'Hobbies',
|
| 302 |
'Other Games',
|
| 303 |
'Video Games',
|
| 304 |
),
|
| 305 |
'Government & Organizations' => array(
|
| 306 |
'Local',
|
| 307 |
'National',
|
| 308 |
'Non-Profit',
|
| 309 |
'Regional',
|
| 310 |
),
|
| 311 |
'Health' => array(
|
| 312 |
'Alternative Health',
|
| 313 |
'Fitness & Nutrition',
|
| 314 |
'Self-Help',
|
| 315 |
'Sexuality',
|
| 316 |
),
|
| 317 |
'Kids & Family' => array(),
|
| 318 |
'Music' => array(),
|
| 319 |
'News & Politics' => array(),
|
| 320 |
'Religion & Spirituality' => array(
|
| 321 |
'Buddhism',
|
| 322 |
'Christianity',
|
| 323 |
'Hinduism',
|
| 324 |
'Islam',
|
| 325 |
'Judaism',
|
| 326 |
'Other',
|
| 327 |
'Spirituality',
|
| 328 |
),
|
| 329 |
'Science & Medicine' => array(
|
| 330 |
'Medicine',
|
| 331 |
'Natural Sciences',
|
| 332 |
'Social Sciences',
|
| 333 |
),
|
| 334 |
'Society & Culture' => array(
|
| 335 |
'History',
|
| 336 |
'Personal Journals',
|
| 337 |
'Philosophy',
|
| 338 |
'Places & Travel',
|
| 339 |
),
|
| 340 |
'Sports & Recreation' => array(
|
| 341 |
'Amateur',
|
| 342 |
'College & High School',
|
| 343 |
'Outdoor',
|
| 344 |
'Professional',
|
| 345 |
),
|
| 346 |
'Technology' => array(
|
| 347 |
'Gadgets',
|
| 348 |
'Tech News',
|
| 349 |
'Podcasting',
|
| 350 |
'Software How-To',
|
| 351 |
),
|
| 352 |
'TV & Film' => array(),
|
| 353 |
);
|
| 354 |
}
|