public function was_deactivated() { $feeds = \Podlove\Model\Feed::all("WHERE `bitlove` = '1'"); foreach ($feeds as $feed) { delete_transient("podlove_bitlove_feed_url_" . $feed->id); } }
public function handle_model_change($model) { $tainting_classes = array(Model\Episode::name(), Model\Feed::name(), Model\Podcast::name(), Model\Template::name(), Model\TemplateAssignment::name()); $tainting_classes = apply_filters('podlove_cache_tainting_classes', $tainting_classes); if (in_array($model::name(), $tainting_classes)) { $this->taint(); } }
/** * Ping hub for every feed. * * @todo do it in a wp cron for more faster UX * @todo subscribe url or redirect=no url? */ public function announce_feed_changes($post_ID, $post) { if (get_post_type($post) !== 'podcast') { return; } foreach (Model\Feed::all() as $feed) { $this->send_ping($feed->get_subscribe_url()); } }
function podlove_jetpack_remove_rss_icon() { if (!method_exists('Jetpack_Site_Icon', 'init')) { return; } if (!($feed_slug = get_query_var('feed'))) { return; } if (!($feed = \Podlove\Model\Feed::find_one_by_slug($feed_slug))) { return; } remove_action('rss2_head', [Jetpack_Site_Icon::init(), 'rss2_icon']); }
public function __construct($feed_slug) { add_action('atom_ns', function () { echo 'xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd"'; }); add_filter('feed_link', function ($output, $feed) use($feed_slug) { return get_bloginfo('url') . '/feed/' . $feed_slug . '/'; }, 10, 2); $podcast = Model\Podcast::get_instance(); $feed = Model\Feed::find_one_by_slug($feed_slug); $episode_asset = $feed->episode_asset(); $file_type = $episode_asset->file_type(); add_filter('podlove_feed_enclosure', function ($enclosure, $enclosure_url, $enclosure_file_size, $mime_type) { return sprintf('<link rel="enclosure" href="%s" length="%s" type="%s"/>', $enclosure_url, $enclosure_file_size, $mime_type); }, 10, 4); mute_feed_title(); override_feed_title($feed); override_feed_language($feed); override_feed_head('atom_head', $podcast, $feed, $file_type); override_feed_entry('atom_entry', $podcast, $feed, $file_type); add_action('atom_head', function () use($podcast, $feed, $file_type) { ?> <link rel="self" type="application/atom+xml" title="<?php echo $feed->title_for_discovery(); ?> " href="<?php echo $feed->get_subscribe_url(); ?> " /> <?php $feeds = Model\Feed::all(); foreach ($feeds as $other_feed) { if ($other_feed->id !== $feed->id) { ?> <link rel="alternate" type="application/atom+xml" title="<?php echo $other_feed->title_for_discovery(); ?> " href="<?php echo $other_feed->get_subscribe_url(); ?> " /> <?php } } }, 9); $this->do_feed($feed); }
public function __construct($feed_slug) { add_action('rss2_ns', function () { echo 'xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd"'; }); $podcast = Model\Podcast::get_instance(); $feed = Model\Feed::find_one_by_slug($feed_slug); $episode_asset = $feed->episode_asset(); $file_type = $episode_asset->file_type(); add_filter('podlove_feed_enclosure', function ($enclosure, $enclosure_url, $enclosure_file_size, $mime_type) { return sprintf('<enclosure url="%s" length="%s" type="%s" />', $enclosure_url, $enclosure_file_size, $mime_type); }, 10, 4); mute_feed_title(); override_feed_title($feed); override_feed_language($feed); override_feed_head('rss2_head', $podcast, $feed, $file_type); override_feed_entry('rss2_item', $podcast, $feed, $file_type); $this->do_feed($feed); }
function override_feed_item_limit($limits) { global $wp_query; if (!is_feed()) { return $limits; } if (!($feed = \Podlove\Model\Feed::find_one_by_slug(get_query_var('feed_slug')))) { return $limits; } $custom_limit = (int) $feed->limit_items; if ($custom_limit > 0) { return "LIMIT {$custom_limit}"; } elseif ($custom_limit == 0) { return $limits; // WordPress default } else { return ''; // no limit } }
private function reset_migration() { delete_option('podlove_module_migration'); delete_option('podlove_migration'); delete_option('podlove_migration_validation_cache'); delete_option('podlove_asset_assignment'); delete_option('podlove_migrated_posts_cache'); $args = array('post_type' => 'podcast', 'posts_per_page' => -1); $query = new \WP_Query($args); while ($query->have_posts()) { $query->the_post(); wp_delete_post(get_the_ID()); } wp_reset_postdata(); foreach (Model\EpisodeAsset::all() as $asset) { $asset->delete(); } foreach (Model\Feed::all() as $feed) { $feed->delete(); } }
public function prepare_items() { // number of items per page $per_page = get_user_meta(get_current_user_id(), 'podlove_feeds_per_page', true); if (empty($per_page)) { $per_page = 10; } // define column headers $this->_column_headers = $this->get_column_info(); // retrieve data $data = \Podlove\Model\Feed::all('ORDER BY position ASC'); // get current page $current_page = $this->get_pagenum(); // get total items $total_items = count($data); // extrage page for current page only $data = array_slice($data, ($current_page - 1) * $per_page, $per_page); // add items to table $this->items = $data; // register pagination options & calculations $this->set_pagination_args(array('total_items' => $total_items, 'per_page' => $per_page, 'total_pages' => ceil($total_items / $per_page))); }
public function prepare_items() { // number of items per page $per_page = 10; // define column headers $columns = $this->get_columns(); $hidden = array(); $sortable = $this->get_sortable_columns(); $this->_column_headers = array($columns, $hidden, $sortable); // retrieve data $data = \Podlove\Model\Feed::all(); // get current page $current_page = $this->get_pagenum(); // get total items $total_items = count($data); // extrage page for current page only $data = array_slice($data, ($current_page - 1) * $per_page, $per_page); // add items to table $this->items = $data; // register pagination options & calculations $this->set_pagination_args(array('total_items' => $total_items, 'per_page' => $per_page, 'total_pages' => ceil($total_items / $per_page))); }
public function ajax_validate_feed() { $feed_id = $_REQUEST['feed_id']; $redirect = $_REQUEST['redirect'] == '0' ? FALSE : TRUE; $feed = \Podlove\Model\Feed::find_by_id($feed_id); // Delete feed source transient $errors_and_warnings = \Podlove\Modules\FeedValidation\Model\FeedValidator::getValidationErrorsandWarnings($feed->id, $redirect); // renew transients set_transient('podlove_dashboard_feed_validation_' . $feed->id, \Podlove\Modules\FeedValidation\Model\FeedValidator::getValidationIcon($feed->id, $redirect), 3600 * 24); set_transient('podlove_dashboard_feed_information_' . $feed->id, \Podlove\Modules\FeedValidation\Model\FeedValidator::getInformation($feed->id, $redirect), 3600 * 24); if ($redirect === TRUE) { set_transient('podlove_dashboard_feed_r_validation_' . $feed->id, \Podlove\Modules\FeedValidation\Model\FeedValidator::getValidationIcon($feed->id, $redirect), 3600 * 24); set_transient('podlove_dashboard_feed_r_information_' . $feed->id, \Podlove\Modules\FeedValidation\Model\FeedValidator::getInformation($feed->id, $redirect), 3600 * 24); } \Podlove\AJAX\Ajax::respond_with_json(array('validation_icon' => \Podlove\Modules\FeedValidation\Model\FeedValidator::getValidationIcon($feed->id, $redirect))); }
/** * Find and run migration for given version number. * * @todo move migrations into separate files * * @param int $version */ function run_migrations_for_version($version) { global $wpdb; switch ($version) { case 2: $sql = sprintf('ALTER TABLE `%s` ADD COLUMN `chapters` TEXT AFTER `cover_art`', \Podlove\Model\Release::table_name()); $wpdb->query($sql); break; case 3: $sql = sprintf('ALTER TABLE `%s` ADD COLUMN `format` VARCHAR(255) AFTER `slug`', \Podlove\Model\Feed::table_name()); $wpdb->query($sql); break; case 4: $sql = sprintf('ALTER TABLE `%s` ADD COLUMN `title` VARCHAR(255) AFTER `id`', \Podlove\Model\EpisodeAsset::table_name()); $wpdb->query($sql); break; case 5: \Podlove\Modules\Base::activate('podlove_web_player'); break; case 6: // title column is "int" for some people. this migration fixes that $sql = sprintf('SHOW COLUMNS FROM `wp_podlove_medialocation` WHERE Field = "title"', \Podlove\Model\EpisodeAsset::table_name()); $row = $wpdb->get_row($sql); if (strtolower(substr($row->Type, 0, 3)) === 'int') { $wpdb->query(sprintf('UPDATE `%s` SET title = NULL', \Podlove\Model\EpisodeAsset::table_name())); $wpdb->query(sprintf('ALTER TABLE `%s` MODIFY COLUMN `title` VARCHAR(255)', \Podlove\Model\EpisodeAsset::table_name())); } break; case 7: // move language from feed to show $sql = sprintf('ALTER TABLE `%s` ADD COLUMN `language` VARCHAR(255) AFTER `summary`', \Podlove\Model\Show::table_name()); $wpdb->query($sql); $sql = sprintf('ALTER TABLE `%s` DROP COLUMN `language`', \Podlove\Model\Feed::table_name()); $wpdb->query($sql); break; case 8: $sql = sprintf('ALTER TABLE `%s` ADD COLUMN `supports_cover_art` INT', \Podlove\Model\Show::table_name()); $wpdb->query($sql); break; case 9: // huge architecture migration // assume first show will be blueprint for the podcast $show = $wpdb->get_row(sprintf('SELECT * FROM %s LIMIT 1', $wpdb->prefix . 'podlove_show'), ARRAY_A); $show_id = $show['id']; // On my local machine the migration runs twice. // This is a quick fix. caveat: someone who has no show defined // will need to uninstall the plugin. That seems acceptable. if (!$show_id) { return; } // all releases of this show will be converted to episodes $releases = $wpdb->get_results(sprintf(' SELECT E.post_id, R.episode_id, R.active, R.enable, R.slug, R.duration, R.cover_art, R.chapters FROM %s R INNER JOIN %s E ON R.episode_id = E.id WHERE R.show_id = "%s" ', $wpdb->prefix . 'podlove_release', $wpdb->prefix . 'podlove_episode', $show_id), ARRAY_A); // write show settings to podcast $podcast = \Podlove\Model\Podcast::get_instance(); foreach ($show as $key => $value) { $podcast->{$key} = $value; } $podcast->save(); // rebuild show table \Podlove\Model\Show::destroy(); \Podlove\Model\Show::build(); // rebuild episodes table \Podlove\Model\Episode::destroy(); \Podlove\Model\Episode::build(); foreach ($releases as $release) { $episode = new \Podlove\Model\Episode(); foreach ($release as $key => $value) { if (!in_array($key, array('episode_id'))) { $episode->{$key} = $value; } } $episode->save(); } // clean feed table $sql = sprintf('DELETE FROM `%s` WHERE `show_id` != "%s"', \Podlove\Model\Feed::table_name(), $show_id); $wpdb->query($sql); $sql = sprintf('ALTER TABLE `%s` DROP COLUMN `show_id`', \Podlove\Model\Feed::table_name()); $wpdb->query($sql); // fix mediafile table $sql = sprintf('ALTER TABLE `%s` CHANGE `release_id` `episode_id` INT', \Podlove\Model\MediaFile::table_name()); $wpdb->query($sql); // remove suffix $sql = sprintf('ALTER TABLE `%s` DROP COLUMN `suffix`', \Podlove\Model\EpisodeAsset::table_name()); $wpdb->query($sql); // add more default formats $default_formats = array(array('name' => 'PDF Document', 'type' => 'ebook', 'mime_type' => 'application/pdf', 'extension' => 'pdf'), array('name' => 'ePub Document', 'type' => 'ebook', 'mime_type' => 'application/epub+zip', 'extension' => 'epub'), array('name' => 'PNG Image', 'type' => 'image', 'mime_type' => 'image/png', 'extension' => 'png'), array('name' => 'JPEG Image', 'type' => 'image', 'mime_type' => 'image/jpeg', 'extension' => 'jpg')); foreach ($default_formats as $format) { $f = new Model\FileType(); foreach ($format as $key => $value) { $f->{$key} = $value; } $f->save(); } // update assistant $assistant = \Podlove\Modules\EpisodeAssistant\Episode_Assistant::instance(); $template = $assistant->get_module_option('title_template'); $template = str_replace('%show_slug%', '%podcast_slug%', $template); $assistant->update_module_option('title_template', $template); // update media locations $media_locations = \Podlove\Model\EpisodeAsset::all(); foreach ($media_locations as $media_location) { $media_location->url_template = str_replace('%suffix%', '', $media_location->url_template); $media_location->save(); } break; case 10: $sql = sprintf('ALTER TABLE `%s` ADD COLUMN `summary` TEXT', \Podlove\Model\Episode::table_name()); $wpdb->query($sql); break; case 11: $sql = sprintf('ALTER TABLE `%s` ADD COLUMN `downloadable` INT', \Podlove\Model\EpisodeAsset::table_name()); $wpdb->query($sql); break; case 12: $sql = sprintf('UPDATE `%s` SET `downloadable` = 1', \Podlove\Model\EpisodeAsset::table_name()); $wpdb->query($sql); break; case 13: $opus = array('name' => 'Opus Audio', 'type' => 'audio', 'mime_type' => 'audio/opus', 'extension' => 'opus'); $f = new \Podlove\Model\FileType(); foreach ($opus as $key => $value) { $f->{$key} = $value; } $f->save(); break; case 14: $sql = sprintf('ALTER TABLE `%s` RENAME TO `%s`', $wpdb->prefix . 'podlove_medialocation', \Podlove\Model\EpisodeAsset::table_name()); $wpdb->query($sql); break; case 15: $sql = sprintf('ALTER TABLE `%s` CHANGE `media_location_id` `episode_asset_id` INT', \Podlove\Model\MediaFile::table_name()); $wpdb->query($sql); break; case 16: $sql = sprintf('ALTER TABLE `%s` CHANGE `media_location_id` `episode_asset_id` INT', \Podlove\Model\Feed::table_name()); $wpdb->query($sql); break; case 17: $sql = sprintf('ALTER TABLE `%s` RENAME TO `%s`', $wpdb->prefix . 'podlove_mediaformat', \Podlove\Model\FileType::table_name()); $wpdb->query($sql); break; case 18: $sql = sprintf('ALTER TABLE `%s` CHANGE `media_format_id` `file_type_id` INT', \Podlove\Model\EpisodeAsset::table_name()); $wpdb->query($sql); break; } }
/** * Adds feed discover links to WordPress head. * * @todo find a better place for this function */ function add_feed_discoverability() { if (is_admin()) { return; } $feeds = \Podlove\Model\Feed::find_all_by_discoverable(1); foreach ($feeds as $feed) { echo '<link rel="alternate" type="' . $feed->get_content_type() . '" title="' . esc_attr($feed->title_for_discovery()) . '" href="' . $feed->get_subscribe_url() . "\" />\n"; } }
public static function logValidation($feedid, $errors_and_warnings, $redirected = FALSE) { $feed = \Podlove\Model\Feed::find_by_id($feedid); $feed_subscribe_url = $redirected === FALSE ? $feed->get_subscribe_url() : $feed->redirect_url; if ($redirected === TRUE) { $redirected = ' (Redirected)'; } foreach ($errors_and_warnings['warnings'] as $warning_key => $warning) { \Podlove\Log::get()->addInfo('Warning: ' . $warning['text'] . ', line ' . $warning['line'] . ' in Feed <a href="' . $feed_subscribe_url . '">' . $feed->name . $redirected . '</a>.'); } foreach ($errors_and_warnings['errors'] as $error_key => $error) { \Podlove\Log::get()->addError('Error: ' . $error['text'] . ', line ' . $error['line'] . ' in Feed <a href="' . $feed_subscribe_url . '">' . $feed->name . $redirected . '</a>.'); } }
private function edit_template() { $feed = \Podlove\Model\Feed::find_by_id($_REQUEST['feed']); echo '<h3>' . sprintf(__('Edit Feed: %s', 'podlove'), $feed->name) . '</h3>'; $this->form_template($feed, 'save'); }
function feed_head_contributors() { global $wp_query; $feed = \Podlove\Model\Feed::find_one_by_slug($wp_query->query_vars['feed']); if (!$feed) { return; } $contributor_xml = $this->prepare_contributions_for_feed(\Podlove\Modules\Contributors\Model\ShowContribution::all(), $feed); echo apply_filters('podlove_feed_head_contributors', $contributor_xml); }
public function template() { // load already migrated posts $migrated_posts_cache = get_option('podlove_migrated_posts_cache', array()); // then begin to migrate $migration_settings = get_option('podlove_migration', array()); // Basic Podcast Settings $podcast = Model\Podcast::get(); $podcast->title = $migration_settings['podcast']['title']; $podcast->subtitle = $migration_settings['podcast']['subtitle']; $podcast->summary = $migration_settings['podcast']['summary']; $podcast->media_file_base_uri = \Podlove\Modules\Migration\get_media_file_base_url(); // harvest low hanging podPress fruits if ($podPress_config = get_option('podPress_config')) { if (isset($podPress_config['iTunes']['image']) && !$podcast->cover_image) { $podcast->cover_image = $podPress_config['iTunes']['image']; } } // harvest low hanging PowerPress fruits if ($powerPress_config = get_option('powerpress_feed')) { if (isset($powerPress_config['itunes_image']) && !$podcast->cover_image) { $podcast->cover_image = $powerPress_config['itunes_image']; } if (isset($powerPress_config['itunes_cat_1']) && !$podcast->category_1) { $podcast->category_1 = $powerPress_config['itunes_cat_1']; } if (isset($powerPress_config['itunes_cat_2']) && !$podcast->category_2) { $podcast->category_2 = $powerPress_config['itunes_cat_2']; } if (isset($powerPress_config['itunes_cat_3']) && !$podcast->category_3) { $podcast->category_3 = $powerPress_config['itunes_cat_3']; } } $podcast->save(); // Create Template $template = Model\Template::find_one_by_title('default'); if (!$template) { $template = new Model\Template(); $template->title = 'default'; $template->content = <<<EOT {{ episode.player }} [podlove-episode-downloads] EOT; $template->save(); } $template_assignment = Model\TemplateAssignment::get_instance(); if ($template_assignment->has_property($migration_settings['cleanup']['template'])) { $template_assignment->{$migration_settings}['cleanup']['template'] = $template->id; $template_assignment->save(); } // Create Assets $assets = array(); foreach ($migration_settings['file_types'] as $file_type_id => $_) { $file_type = Model\FileType::find_one_by_id($file_type_id); $is_image = in_array($file_type->extension, array('png', 'jpg', 'jpeg', 'gif')); $asset = Model\EpisodeAsset::find_one_by_file_type_id($file_type_id); if (!$asset) { $asset = new Model\EpisodeAsset(); $asset->title = $file_type->name; $asset->file_type_id = $file_type_id; $asset->downloadable = !$is_image; $asset->save(); } $assets[] = $asset; if ($is_image) { $asset_assignments = get_option('podlove_asset_assignment', array()); if (!$asset_assignments['image']) { $asset_assignments['image'] = $asset->id; update_option('podlove_asset_assignment', $asset_assignments); } } // create feeds if (stripos($file_type->mime_type, 'audio') !== false) { $feed = Model\Feed::find_one_by_episode_asset_id($asset->id); if (!$feed) { $feed = new Model\Feed(); $feed->episode_asset_id = $asset->id; $feed->name = $file_type->name; $feed->title = $file_type->name; $feed->slug = $file_type->extension; $feed->format = 'rss'; $feed->enable = true; $feed->discoverable = true; $feed->limit_items = -1; $feed->save(); } } // set web player settings $webplayer_formats = get_option('podlove_webplayer_formats', array()); if (!isset($webplayer_formats['audio'])) { $webplayer_formats['audio'] = array(); } if (stripos($file_type->mime_type, 'audio/mpeg') !== false) { $webplayer_formats['audio']['mp3'] = $asset->id; } elseif (stripos($file_type->mime_type, 'audio/mp4') !== false) { $webplayer_formats['audio']['mp4'] = $asset->id; } elseif (stripos($file_type->mime_type, 'audio/ogg') !== false) { $webplayer_formats['audio']['ogg'] = $asset->id; } elseif (stripos($file_type->mime_type, 'audio/opus') !== false) { $webplayer_formats['audio']['opus'] = $asset->id; } update_option('podlove_webplayer_formats', $webplayer_formats); } // flush rules after migration set_transient('podlove_needs_to_flush_rewrite_rules', true); ?> <form action="" method="POST"> <input type="submit" name="prev" class="btn" value="<?php echo __('Back', 'podlove'); ?> "> <input type="submit" name="next" id="continue_to_finish_button" class="btn btn-primary disabled pull-right" value="<?php echo __('Continue to last step', 'podlove'); ?> "> </form> <div class="row-fluid"> <div class="span12"> <h3 id="migration-header">Migrating <small></small></h3> </div> </div> <div class="progress progress-striped active" id="migration_progress"> <div class="bar" style="width:0%"></div> </div> <p> <input type="button" id="start_migration_button" class="btn btn-primary" value="<?php echo __('Start Migration', 'podlove'); ?> "> Starting the migration creates the actual episodes one by one. </p> <table class="table table-condensed" id="posts_to_migrate"> <thead> <tr> <th>Status</th> <th>Episode</th> </tr> </thead> <tbody> <?php $migrated_post_ids = array_keys($migrated_posts_cache); ?> <?php foreach ($migration_settings['episodes'] as $post_id => $_) { ?> <?php $done = in_array($post_id, $migrated_post_ids); ?> <tr data-post-id="<?php echo $post_id; ?> " <?php echo $done ? 'class="done"' : ''; ?> > <td class="status"> <span class="waiting" <?php echo !$done ? '' : 'style="display:none"'; ?> >not yet migrated</span> <span class="migrating" style="display:none"><i class="podlove-icon-spinner rotate"></i></span> <span class="done" <?php echo $done ? '' : 'style="display:none"'; ?> ><i class="podlove-icon-ok"></i></span> </td> <td class="episode"> <?php if ($done) { ?> <a href="<?php echo get_edit_post_link($migrated_posts_cache[$post_id]); ?> " target="_blank"> <?php echo get_the_title($post_id); ?> </a> <?php } else { ?> <?php echo get_the_title($post_id); ?> <?php } ?> </td> </tr> <?php } ?> </tbody> </table> <script type="text/javascript"> jQuery(function($) { var posts_to_migrate = $("#posts_to_migrate tbody tr").length; $("#continue_to_finish_button").hide(); function update_migration_progress_bar() { var posts_done = $("#posts_to_migrate tbody tr.done").length; progress = Math.round(posts_done / posts_to_migrate * 100) $("#migration_progress .bar") .css("width", progress + "%") .html(posts_done + " / " + posts_to_migrate); if ( progress == 100 ) { $("#migration_progress") .removeClass("active") .addClass("progress-success") .find(".bar").html("Done! Whoop whoop!"); $("#migration-header small").html(''); $("#start_migration_button").addClass("disabled"); $("#continue_to_finish_button").removeClass("disabled").show(); } }; function podlove_migrate_one_post() { $("#posts_to_migrate tbody tr:not(.done):first").each(function() { var post_id = $(this).data("post-id") that = $(this), episode_title = $(".episode", that).html(); $("#migration-header small").html(episode_title); var data = { action: 'podlove-migrate-post', post_id: post_id }; $.ajax({ url: ajaxurl, data: data, dataType: 'json', beforeSend: function(jqXHR, settings) { $(".waiting, .done", that).hide(); $(".migrating", that).show(); }, success: function(result) { var episode_url = result.url; $(".waiting, .migrating", that).hide(); $(".done", that).show(); that.addClass("done"); // add link $(".episode", that).html('<a href="' + episode_url + '" target="_blank">' + episode_title + '</a>') // update progress bar update_migration_progress_bar(); // continue podlove_migrate_one_post(); } }); }); } $("#start_migration_button").on("click", function(){ if (!$(this).hasClass("disabled")) { $(this).addClass("disabled"); podlove_migrate_one_post(); } }); update_migration_progress_bar(); }); </script> <?php }
/** * Feed list, ready for subscribe button. * * @return array list of prepared feed data-objects */ private function feeds() { return TemplateCache::get_instance()->cache_for('podlove_subscribe_button_feeds', function () { $feeds = array_map(function ($feed) { $file_type = $feed->episode_asset()->file_type(); return ['type' => $file_type->type, 'format' => self::feed_format($file_type->extension), 'url' => $feed->get_subscribe_url(), 'variant' => 'high']; }, $this->discoverable_feeds()); $itunes_feed = Feed::find_one_by_where('itunes_feed_id > 0'); if ($itunes_feed) { // @todo verify the url is valid $feeds[] = ['type' => 'itunes-url', 'url' => 'https://itunes.apple.com/podcast/id' . $itunes_feed->itunes_feed_id]; } return $feeds; }); }
function override_feed_entry($hook, $podcast, $feed, $format) { add_action($hook, function () use($podcast, $feed, $format) { global $post; $cache = \Podlove\Cache\TemplateCache::get_instance(); echo $cache->cache_for('feed_item_' . $feed->slug . '_' . $post->ID, function () use($podcast, $feed, $format, $post) { $xml = ""; $episode = Model\Episode::find_one_by_post_id($post->ID); $asset = $feed->episode_asset(); $file = Model\MediaFile::find_by_episode_id_and_episode_asset_id($episode->id, $asset->id); $asset_assignment = Model\AssetAssignment::get_instance(); if (!$file) { return; } $enclosure_file_size = $file->size; $cover_art_url = ""; if ($cover_art = $episode->cover_art()) { $cover_art_url = $cover_art->url(); } if (isset($_REQUEST['tracking']) && $_REQUEST['tracking'] == 'no') { $enclosure_url = $episode->enclosure_url($feed->episode_asset(), null, null); } else { $enclosure_url = $episode->enclosure_url($feed->episode_asset(), "feed", $feed->slug); } $deep_link = Model\Feed::get_link_tag(array('prefix' => 'atom', 'rel' => 'http://podlove.org/deep-link', 'type' => '', 'title' => '', 'href' => get_permalink() . "#")); $xml .= apply_filters('podlove_deep_link', $deep_link, $feed); $xml .= apply_filters('podlove_feed_enclosure', '', $enclosure_url, $enclosure_file_size, $format->mime_type, $file); $duration = sprintf('<itunes:duration>%s</itunes:duration>', $episode->get_duration('HH:MM:SS')); $xml .= apply_filters('podlove_feed_itunes_duration', $duration); $author = apply_filters('podlove_feed_content', $podcast->author_name); $author = sprintf('<itunes:author>%s</itunes:author>', $author); $xml .= apply_filters('podlove_feed_itunes_author', $author); $subtitle = apply_filters('podlove_feed_content', \Podlove\PHP\escape_shortcodes(strip_tags($episode->subtitle))); $subtitle = sprintf('<itunes:subtitle>%s</itunes:subtitle>', $subtitle); $xml .= apply_filters('podlove_feed_itunes_subtitle', $subtitle); $summary = apply_filters('podlove_feed_content', \Podlove\PHP\escape_shortcodes(strip_tags($episode->summary))); $summary = sprintf('<itunes:summary>%s</itunes:summary>', $summary); $xml .= apply_filters('podlove_feed_itunes_summary', $summary); if (\Podlove\get_setting('metadata', 'enable_episode_explicit')) { $itunes_explicit = apply_filters('podlove_feed_content', $episode->explicit_text()); $itunes_explicit = sprintf('<itunes:explicit>%s</itunes:explicit>', $itunes_explicit); $xml .= apply_filters('podlove_feed_itunes_explicit', $itunes_explicit); } if ($cover_art_url) { $cover_art = sprintf('<itunes:image href="%s" />', $cover_art_url); } else { $cover_art = ''; } $xml .= apply_filters('podlove_feed_itunes_image', $cover_art); if ($feed->embed_content_encoded) { add_filter('the_content_feed', function ($content, $feed_type) { return preg_replace('#<style(.*?)>(.*?)</style>#is', '', $content); }, 10, 2); $content_encoded = '<content:encoded><![CDATA[' . get_the_content_feed('rss2') . ']]></content:encoded>'; $xml .= apply_filters('podlove_feed_content_encoded', $content_encoded); } ob_start(); do_action('podlove_append_to_feed_entry', $podcast, $episode, $feed, $format); $xml .= ob_get_contents(); ob_end_clean(); return $xml; }, 15 * MINUTE_IN_SECONDS); }, 11); }
public function update_feed_position() { $feed_id = (int) $_REQUEST['feed_id']; $position = (double) $_REQUEST['position']; Model\Feed::find_by_id($feed_id)->update_attributes(array('position' => $position)); die; }
}); add_filter('query_vars', function ($qv) { $qv[] = 'show_slug'; $qv[] = 'feed_slug'; return $qv; }); } // Hooks: // parse_query => query vars available // wp => query_posts done add_action('wp', function () { global $wp_query; if (!($feed_slug = get_query_var('feed_slug'))) { return; } if (!($feed = \Podlove\Model\Feed::find_one_by_slug($feed_slug))) { return; } $is_feedburner_bot = preg_match("/feedburner|feedsqueezer/i", $_SERVER['HTTP_USER_AGENT']); $is_manual_redirect = !isset($_REQUEST['redirect']) || $_REQUEST['redirect'] != "no"; if (strlen($feed->redirect_url) > 0 && $is_manual_redirect && !$is_feedburner_bot) { header(sprintf("Location: %s", $feed->redirect_url), TRUE, 302); exit; } else { // make sure is_feed() returns true add_filter('the_content', function ($content) { global $wp_query; $wp_query->is_feed = true; return $content; }); if ($feed->format === "rss") {
public static function prepare_feed($feed_slug) { global $wp_query; add_action('rss2_ns', function () { echo 'xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd" '; echo 'xmlns:psc="http://podlove.org/simple-chapters" '; echo 'xmlns:content="http://purl.org/rss/1.0/modules/content/" '; echo 'xmlns:fh="http://purl.org/syndication/history/1.0" '; }); $podcast = Model\Podcast::get(); if (!($feed = Model\Feed::find_one_by_slug($feed_slug))) { self::wp_404(); } if (!($episode_asset = $feed->episode_asset())) { self::wp_404(); } $file_type = $episode_asset->file_type(); add_filter('podlove_feed_enclosure', function ($enclosure, $enclosure_url, $enclosure_file_size, $mime_type, $media_file) { if ($enclosure_file_size < 0) { $enclosure_file_size = 0; } $dom = new \Podlove\DomDocumentFragment(); $element = $dom->createElement('enclosure'); $attributes = ['url' => $enclosure_url, 'length' => $enclosure_file_size, 'type' => $mime_type]; $attributes = apply_filters('podlove_feed_enclosure_attributes', $attributes, $media_file); foreach ($attributes as $k => $v) { $element->setAttribute($k, $v); } $dom->appendChild($element); return (string) $dom; }, 10, 5); override_feed_title($feed); override_feed_description($feed); override_feed_language($feed); override_feed_head('rss2_head', $podcast, $feed, $file_type); override_feed_entry('rss2_item', $podcast, $feed, $file_type); add_action('rss2_item', function () { if (apply_filters('podlove_feed_show_summary', true)) { echo "<description><![CDATA["; \Podlove\Feeds\the_description(); echo "]]></description>"; } }, 9); add_action('rss2_head', function () use($podcast, $feed) { global $wp_query; $current_page = get_query_var('paged') ? get_query_var('paged') : 1; $feed_url_for_page = function ($page) use($feed) { $url = $feed->get_subscribe_url(); if ($page > 0) { $url .= '?paged=' . $page; } return $url; }; if ($current_page < $wp_query->max_num_pages) { echo "\n\t" . sprintf('<atom:link rel="next" href="%s" />', $feed_url_for_page($current_page + 1)); } if ($current_page > 2) { echo "\n\t" . sprintf('<atom:link rel="prev" href="%s" />', $feed_url_for_page($current_page - 1)); } elseif ($current_page == 2) { echo "\n\t" . sprintf('<atom:link rel="prev" href="%s" />', $feed_url_for_page(0)); } echo "\n\t" . sprintf('<atom:link rel="first" href="%s" />', $feed_url_for_page(0)); if ($wp_query->max_num_pages > 1) { echo "\n\t" . sprintf('<atom:link rel="last" href="%s" />', $feed_url_for_page($wp_query->max_num_pages)); } if ($podcast->language) { echo "\n\t" . '<language>' . $podcast->language . '</language>'; } do_action('podlove_rss2_head', $feed); }, 9); $posts_per_page = $feed->limit_items == 0 ? get_option('posts_per_rss') : $feed->limit_items; if ($posts_per_page == Model\Feed::ITEMS_GLOBAL_LIMIT) { $posts_per_page = $podcast->limit_items; } // now override the option so WP core functions accessing the option get the "correct" value add_filter('pre_option_posts_per_rss', function ($_) use($posts_per_page) { return $posts_per_page; }); $args = array('post_type' => 'podcast', 'post__in' => $feed->post_ids(), 'posts_per_page' => $posts_per_page); # The theme "getnoticed" globally overrides post_types in pre_get_posts. # Fix: hook in after the theme and override it again. # It's not bad practice because I *really* only want episodes in this feed. add_action('pre_get_posts', function ($query) { $query->set('post_type', 'podcast'); }, 20); /** * In feeds, WordPress ignores the 'posts_per_page' parameter * and overrides it with the 'posts_per_rss' option. So we need to * override that option. */ add_filter('post_limits', function ($limits) use($feed) { $page = get_query_var('paged') ? (int) get_query_var('paged') : 1; $max = $feed->get_post_limit_sql(); $start = $max * ($page - 1); if ($max > 0) { return 'LIMIT ' . $start . ', ' . $max; } else { return ''; } }); $args = array_merge($wp_query->query_vars, $args); query_posts($args); }
/** * Find and run migration for given version number. * * @todo move migrations into separate files * * @param int $version */ function run_migrations_for_version($version) { global $wpdb; switch ($version) { case 10: $sql = sprintf('ALTER TABLE `%s` ADD COLUMN `summary` TEXT', \Podlove\Model\Episode::table_name()); $wpdb->query($sql); break; case 11: $sql = sprintf('ALTER TABLE `%s` ADD COLUMN `downloadable` INT', \Podlove\Model\EpisodeAsset::table_name()); $wpdb->query($sql); break; case 12: $sql = sprintf('UPDATE `%s` SET `downloadable` = 1', \Podlove\Model\EpisodeAsset::table_name()); $wpdb->query($sql); break; case 13: $opus = array('name' => 'Opus Audio', 'type' => 'audio', 'mime_type' => 'audio/opus', 'extension' => 'opus'); $f = new \Podlove\Model\FileType(); foreach ($opus as $key => $value) { $f->{$key} = $value; } $f->save(); break; case 14: $sql = sprintf('ALTER TABLE `%s` RENAME TO `%s`', $wpdb->prefix . 'podlove_medialocation', \Podlove\Model\EpisodeAsset::table_name()); $wpdb->query($sql); break; case 15: $sql = sprintf('ALTER TABLE `%s` CHANGE `media_location_id` `episode_asset_id` INT', \Podlove\Model\MediaFile::table_name()); $wpdb->query($sql); break; case 16: $sql = sprintf('ALTER TABLE `%s` CHANGE `media_location_id` `episode_asset_id` INT', \Podlove\Model\Feed::table_name()); $wpdb->query($sql); break; case 17: $sql = sprintf('ALTER TABLE `%s` RENAME TO `%s`', $wpdb->prefix . 'podlove_mediaformat', \Podlove\Model\FileType::table_name()); $wpdb->query($sql); break; case 18: $sql = sprintf('ALTER TABLE `%s` CHANGE `media_format_id` `file_type_id` INT', \Podlove\Model\EpisodeAsset::table_name()); $wpdb->query($sql); break; case 19: \Podlove\Model\Template::build(); break; case 20: $sql = sprintf('ALTER TABLE `%s` ADD COLUMN `suffix` VARCHAR(255)', \Podlove\Model\EpisodeAsset::table_name()); $wpdb->query($sql); $sql = sprintf('ALTER TABLE `%s` DROP COLUMN `url_template`', \Podlove\Model\EpisodeAsset::table_name()); $wpdb->query($sql); break; case 21: $podcast = Model\Podcast::get(); $podcast->url_template = '%media_file_base_url%%episode_slug%%suffix%.%format_extension%'; $podcast->save(); break; case 22: $sql = sprintf('ALTER TABLE `%s` ADD COLUMN `redirect_http_status` INT AFTER `redirect_url`', Model\Feed::table_name()); $wpdb->query($sql); break; case 23: $sql = sprintf('ALTER TABLE `%s` DROP COLUMN `show_description`', Model\Feed::table_name()); $wpdb->query($sql); break; case 24: $podcast = Model\Podcast::get(); update_option('podlove_asset_assignment', array('image' => $podcast->supports_cover_art, 'chapters' => $podcast->chapter_file)); break; case 25: // rename meta podlove_guid to _podlove_guid $episodes = Model\Episode::all(); foreach ($episodes as $episode) { $post = get_post($episode->post_id); // skip revisions if ($post->post_status == 'inherit') { continue; } $guid = get_post_meta($episode->post_id, 'podlove_guid', true); if (!$guid) { $guid = $post->guid; } delete_post_meta($episode->post_id, 'podlove_guid'); update_post_meta($episode->post_id, '_podlove_guid', $guid); } break; case 26: $wpdb->query(sprintf('ALTER TABLE `%s` MODIFY COLUMN `subtitle` TEXT', Model\Episode::table_name())); break; case 27: $wpdb->query(sprintf('ALTER TABLE `%s` ADD COLUMN `record_date` DATETIME AFTER `chapters`', Model\Episode::table_name())); $wpdb->query(sprintf('ALTER TABLE `%s` ADD COLUMN `publication_date` DATETIME AFTER `record_date`', Model\Episode::table_name())); break; case 28: $wpdb->query(sprintf('ALTER TABLE `%s` ADD COLUMN `position` FLOAT AFTER `downloadable`', Model\EpisodeAsset::table_name())); $wpdb->query(sprintf('UPDATE `%s` SET position = id', Model\EpisodeAsset::table_name())); break; case 29: $wpdb->query(sprintf('ALTER TABLE `%s` ADD COLUMN `embed_content_encoded` INT AFTER `limit_items`', Model\Feed::table_name())); break; case 30: $wpdb->query(sprintf('ALTER TABLE `%s` MODIFY `autoinsert` VARCHAR(255)', Model\Template::table_name())); break; case 32: flush_rewrite_rules(); break; case 33: $apd = array('name' => 'Auphonic Production Description', 'type' => 'metadata', 'mime_type' => 'application/json', 'extension' => 'json'); $f = new \Podlove\Model\FileType(); foreach ($apd as $key => $value) { $f->{$key} = $value; } $f->save(); break; case 34: $options = get_option('podlove', array()); if (!array_key_exists('episode_archive', $options)) { $options['episode_archive'] = 'on'; } if (!array_key_exists('episode_archive_slug', $options)) { $options['episode_archive_slug'] = '/podcast/'; } if (!array_key_exists('use_post_permastruct', $options)) { $options['use_post_permastruct'] = 'off'; } if (!array_key_exists('custom_episode_slug', $options)) { $options['custom_episode_slug'] = '/podcast/%podcast%/'; } else { $options['custom_episode_slug'] = preg_replace('#/+#', '/', '/' . str_replace('#', '', $options['custom_episode_slug'])); } update_option('podlove', $options); break; case 35: Model\Feed::build_indices(); Model\FileType::build_indices(); Model\EpisodeAsset::build_indices(); Model\MediaFile::build_indices(); Model\Episode::build_indices(); Model\Template::build_indices(); break; case 36: $wpdb->query(sprintf('ALTER TABLE `%s` ADD COLUMN `etag` VARCHAR(255)', Model\MediaFile::table_name())); break; case 37: \Podlove\Modules\Base::activate('asset_validation'); break; case 38: \Podlove\Modules\Base::activate('logging'); break; case 39: // migrate previous template autoinsert settings $assignments = Model\TemplateAssignment::get_instance(); $results = $wpdb->get_results(sprintf('SELECT * FROM `%s`', Model\Template::table_name())); foreach ($results as $template) { if ($template->autoinsert == 'beginning') { $assignments->top = $template->id; } elseif ($template->autoinsert == 'end') { $assignments->bottom = $template->id; } } $assignments->save(); // remove template autoinsert column $sql = sprintf('ALTER TABLE `%s` DROP COLUMN `autoinsert`', \Podlove\Model\Template::table_name()); $wpdb->query($sql); break; case 40: $wpdb->query(sprintf('UPDATE `%s` SET position = id WHERE position IS NULL', Model\EpisodeAsset::table_name())); break; case 41: $wpdb->query(sprintf('ALTER TABLE `%s` ADD COLUMN `position` FLOAT AFTER `slug`', Model\Feed::table_name())); $wpdb->query(sprintf('UPDATE `%s` SET position = id', Model\Feed::table_name())); break; case 42: $wpdb->query('DELETE FROM `' . $wpdb->options . '` WHERE option_name LIKE "%podlove_chapters_string_%"'); break; case 43: $podlove_options = get_option('podlove', array()); $podlove_website = array('merge_episodes' => isset($podlove_options['merge_episodes']) ? $podlove_options['merge_episodes'] : false, 'hide_wp_feed_discovery' => isset($podlove_options['hide_wp_feed_discovery']) ? $podlove_options['hide_wp_feed_discovery'] : false, 'use_post_permastruct' => isset($podlove_options['use_post_permastruct']) ? $podlove_options['use_post_permastruct'] : false, 'custom_episode_slug' => isset($podlove_options['custom_episode_slug']) ? $podlove_options['custom_episode_slug'] : '/episode/%podcast%', 'episode_archive' => isset($podlove_options['episode_archive']) ? $podlove_options['episode_archive'] : false, 'episode_archive_slug' => isset($podlove_options['episode_archive_slug']) ? $podlove_options['episode_archive_slug'] : '/podcast/', 'url_template' => isset($podlove_options['url_template']) ? $podlove_options['url_template'] : '%media_file_base_url%%episode_slug%%suffix%.%format_extension%'); $podlove_metadata = array('enable_episode_record_date' => isset($podlove_options['enable_episode_record_date']) ? $podlove_options['enable_episode_record_date'] : false, 'enable_episode_publication_date' => isset($podlove_options['enable_episode_publication_date']) ? $podlove_options['enable_episode_publication_date'] : false); $podlove_redirects = array('podlove_setting_redirect' => isset($podlove_options['podlove_setting_redirect']) ? $podlove_options['podlove_setting_redirect'] : array()); add_option('podlove_website', $podlove_website); add_option('podlove_metadata', $podlove_metadata); add_option('podlove_redirects', $podlove_redirects); break; case 44: $wpdb->query('DELETE FROM `' . $wpdb->postmeta . '` WHERE meta_key = "last_validated_at"'); break; case 45: delete_transient('podlove_auphonic_user'); delete_transient('podlove_auphonic_presets'); break; case 46: if (\Podlove\Modules\Base::is_active('contributors')) { // manually trigger activation if the old module was active $module = \Podlove\Modules\Contributors\Contributors::instance(); $module->was_activated('contributors'); // then, migrate existing contributors // register old taxonomy so it can be queried $args = array('hierarchical' => false, 'labels' => array(), 'show_ui' => true, 'show_tagcloud' => true, 'query_var' => true, 'rewrite' => array('slug' => 'contributor')); register_taxonomy('podlove-contributors', 'podcast', $args); $contributor_settings = get_option('podlove_contributors', array()); $contributors = get_terms('podlove-contributors', array('hide_empty' => 0)); if ($contributors && !is_wp_error($contributors) && \Podlove\Modules\Contributors\Model\Contributor::count() == 0) { foreach ($contributors as $contributor) { // create new contributor $new = new \Podlove\Modules\Contributors\Model\Contributor(); $new->publicname = $contributor->name; $new->realname = $contributor->name; $new->slug = $contributor->slug; $new->showpublic = true; if (isset($contributor_settings[$contributor->term_id]['contributor_email'])) { $email = $contributor_settings[$contributor->term_id]['contributor_email']; if ($email) { $new->privateemail = $email; $new->avatar = $email; } } $new->save(); // create contributions $query = new \WP_Query(array('posts_per_page' => -1, 'post_type' => 'podcast', 'tax_query' => array(array('taxonomy' => 'podlove-contributors', 'field' => 'slug', 'terms' => $contributor->slug)))); while ($query->have_posts()) { $post = $query->next_post(); $contribution = new \Podlove\Modules\Contributors\Model\EpisodeContribution(); $contribution->contributor_id = $new->id; $contribution->episode_id = Model\Episode::find_one_by_post_id($post->ID)->id; $contribution->save(); } } } } break; case 47: $wpdb->query(sprintf('ALTER TABLE `%s` ADD COLUMN `protected` TINYINT(1) NULL', \Podlove\Model\Feed::table_name())); $wpdb->query(sprintf('ALTER TABLE `%s` ADD COLUMN `protection_type` TINYINT(1)', \Podlove\Model\Feed::table_name())); $wpdb->query(sprintf('ALTER TABLE `%s` ADD COLUMN `protection_user` VARCHAR(60)', \Podlove\Model\Feed::table_name())); $wpdb->query(sprintf('ALTER TABLE `%s` ADD COLUMN `protection_password` VARCHAR(64)', \Podlove\Model\Feed::table_name())); break; case 48: $podcast = Model\Podcast::get(); $podcast->limit_items = '-1'; $podcast->save(); break; case 49: $wpdb->query(sprintf('ALTER TABLE `%s` ADD COLUMN `explicit` TINYINT', Model\Episode::table_name())); break; case 50: $podcast = Model\Podcast::get(); $podcast->license_type = 'other'; $podcast->save(); $wpdb->query(sprintf('ALTER TABLE `%s` ADD COLUMN `license_type` VARCHAR(255) AFTER `publication_date`', Model\Episode::table_name())); $wpdb->query(sprintf('ALTER TABLE `%s` ADD COLUMN `license_name` TEXT AFTER `license_type`', Model\Episode::table_name())); $wpdb->query(sprintf('ALTER TABLE `%s` ADD COLUMN `license_url` TEXT AFTER `license_name`', Model\Episode::table_name())); $wpdb->query(sprintf('ALTER TABLE `%s` ADD COLUMN `license_cc_allow_modifications` TEXT AFTER `license_url`', Model\Episode::table_name())); $wpdb->query(sprintf('ALTER TABLE `%s` ADD COLUMN `license_cc_allow_commercial_use` TEXT AFTER `license_cc_allow_modifications`', Model\Episode::table_name())); $wpdb->query(sprintf('ALTER TABLE `%s` ADD COLUMN `license_cc_license_jurisdiction` TEXT AFTER `license_cc_allow_commercial_use`', Model\Episode::table_name())); break; case 51: if (\Podlove\Modules\Base::is_active('contributors')) { \Podlove\Modules\Contributors\Model\ContributorGroup::build(); $wpdb->query(sprintf('ALTER TABLE `%s` ADD COLUMN `group_id` VARCHAR(255) AFTER `role_id`', \Podlove\Modules\Contributors\Model\EpisodeContribution::table_name())); $wpdb->query(sprintf('ALTER TABLE `%s` ADD COLUMN `group_id` VARCHAR(255) AFTER `role_id`', \Podlove\Modules\Contributors\Model\ShowContribution::table_name())); $wpdb->query(sprintf('ALTER TABLE `%s` ADD COLUMN `paypal` VARCHAR(255) AFTER `flattr`', \Podlove\Modules\Contributors\Model\Contributor::table_name())); $wpdb->query(sprintf('ALTER TABLE `%s` ADD COLUMN `bitcoin` VARCHAR(255) AFTER `paypal`', \Podlove\Modules\Contributors\Model\Contributor::table_name())); $wpdb->query(sprintf('ALTER TABLE `%s` ADD COLUMN `litecoin` VARCHAR(255) AFTER `bitcoin`', \Podlove\Modules\Contributors\Model\Contributor::table_name())); $wpdb->query(sprintf('ALTER TABLE `%s` DROP COLUMN `permanentcontributor`', \Podlove\Modules\Contributors\Model\Contributor::table_name())); $wpdb->query(sprintf('ALTER TABLE `%s` DROP COLUMN `role`', \Podlove\Modules\Contributors\Model\Contributor::table_name())); } break; case 52: if (\Podlove\Modules\Base::is_active('contributors')) { $wpdb->query(sprintf('ALTER TABLE `%s` ADD COLUMN `jobtitle` VARCHAR(255) AFTER `department`', \Podlove\Modules\Contributors\Model\Contributor::table_name())); } break; case 53: // set all Episode as published (fix for ADN Module) $episodes = Model\Episode::all(); foreach ($episodes as $episode) { $post = get_post($episode->post_id); if ($post->post_status == 'publish') { update_post_meta($episode->post_id, '_podlove_episode_was_published', true); } } break; case 54: if (\Podlove\Modules\Base::is_active('contributors')) { $wpdb->query(sprintf('ALTER TABLE `%s` ADD COLUMN `googleplus` TEXT AFTER `ADN`', \Podlove\Modules\Contributors\Model\Contributor::table_name())); $wpdb->query(sprintf('ALTER TABLE `%s` CHANGE COLUMN `showpublic` `visibility` TINYINT(1)', \Podlove\Modules\Contributors\Model\Contributor::table_name())); } break; case 55: if (\Podlove\Modules\Base::is_active('contributors')) { \Podlove\Modules\Contributors\Model\DefaultContribution::build(); $wpdb->query(sprintf('ALTER TABLE `%s` ADD COLUMN `comment` TEXT AFTER `position`', \Podlove\Modules\Contributors\Model\EpisodeContribution::table_name())); $wpdb->query(sprintf('ALTER TABLE `%s` ADD COLUMN `comment` TEXT AFTER `position`', \Podlove\Modules\Contributors\Model\ShowContribution::table_name())); } break; case 56: // migrate Podcast Contributors to Default Contributors if (\Podlove\Modules\Base::is_active('contributors')) { $podcast_contributors = \Podlove\Modules\Contributors\Model\ShowContribution::all(); foreach ($podcast_contributors as $podcast_contributor_key => $podcast_contributor) { $new = new \Podlove\Modules\Contributors\Model\DefaultContribution(); $new->contributor_id = $podcast_contributor->contributor_id; $new->group_id = $podcast_contributor->group_id; $new->role_id = $podcast_contributor->role_id; $new->position = $podcast_contributor->positon; $new->save(); } } break; case 57: $wpdb->query(sprintf('ALTER TABLE `%s` ADD COLUMN `append_name_to_podcast_title` TINYINT(1) NULL AFTER `embed_content_encoded`', \Podlove\Model\Feed::table_name())); break; case 58: // if contributors module is active, activate social module if (\Podlove\Modules\Base::is_active('contributors')) { \Podlove\Modules\Base::activate('social'); } break; case 59: if (\Podlove\Modules\Base::is_active('bitlove')) { $wpdb->query(sprintf("ALTER TABLE `%s` ADD COLUMN `bitlove` TINYINT(1) DEFAULT '0'", \Podlove\Model\Feed::table_name())); } break; case 60: \Podlove\Modules\Base::activate('oembed'); \Podlove\Modules\Base::activate('feed_validation'); break; case 61: $wpdb->query(sprintf('ALTER TABLE `%s` DROP COLUMN `publication_date`', Model\Episode::table_name())); break; case 62: // rename column $wpdb->query(sprintf('ALTER TABLE `%s` CHANGE COLUMN `record_date` `recording_date` DATETIME', Model\Episode::table_name())); // update settings $meta = get_option('podlove_metadata'); if (isset($meta['enable_episode_publication_date'])) { unset($meta['enable_episode_publication_date']); } if (isset($meta['enable_episode_record_date'])) { $meta['enable_episode_recording_date'] = $meta['enable_episode_record_date']; unset($meta['enable_episode_record_date']); } update_option('podlove_metadata', $meta); break; case 63: if (\Podlove\Modules\Base::is_active('social')) { $tumblr_service = \Podlove\Modules\Social\Model\Service::find_one_by_property('title', 'Tumblr'); $tumblr_service->url_scheme = 'http://%account-placeholder%.tumblr.com/'; $tumblr_service->save(); } break; case 64: if (\Podlove\Modules\Base::is_active('social')) { $services = array(array('title' => '500px', 'type' => 'social', 'description' => '500px Account', 'logo' => '500px-128.png', 'url_scheme' => 'https://500px.com/%account-placeholder%'), array('title' => 'Last.fm', 'type' => 'social', 'description' => 'Last.fm Account', 'logo' => 'lastfm-128.png', 'url_scheme' => 'https://www.lastfm.de/user/%account-placeholder%'), array('title' => 'OpenStreetMap', 'type' => 'social', 'description' => 'OpenStreetMap Account', 'logo' => 'openstreetmap-128.png', 'url_scheme' => 'https://www.openstreetmap.org/user/%account-placeholder%'), array('title' => 'Soup', 'type' => 'social', 'description' => 'Soup Account', 'logo' => 'soup-128.png', 'url_scheme' => 'http://%account-placeholder%.soup.io')); foreach ($services as $service_key => $service) { $c = new \Podlove\Modules\Social\Model\Service(); $c->title = $service['title']; $c->type = $service['type']; $c->description = $service['description']; $c->logo = $service['logo']; $c->url_scheme = $service['url_scheme']; $c->save(); } } break; case 65: if (\Podlove\Modules\Base::is_active('social')) { $flattr_service = \Podlove\Modules\Social\Model\Service::find_one_by_where("`title` = 'Flattr' AND `type` = 'donation'"); if ($flattr_service) { $contributor_flattr_donations_accounts = \Podlove\Modules\Social\Model\ContributorService::find_all_by_property('service_id', $flattr_service->id); foreach ($contributor_flattr_donations_accounts as $contributor_flattr_donations_account) { $contributor = \Podlove\Modules\Contributors\Model\Contributor::find_by_id($contributor_flattr_donations_account->contributor_id); if ($contributor && is_null($contributor->flattr)) { $contributor->flattr = $contributor_flattr_donations_account->value; $contributor->save(); } $contributor_flattr_donations_account->delete(); } $flattr_service->delete(); } } break; case 66: // Temporary add license_type and CC license fields to episode model \Podlove\Model\Episode::property('license_type', 'VARCHAR(255)'); \Podlove\Model\Episode::property('license_cc_allow_modifications', 'VARCHAR(255)'); \Podlove\Model\Episode::property('license_cc_allow_commercial_use', 'VARCHAR(255)'); \Podlove\Model\Episode::property('license_cc_license_jurisdiction', 'VARCHAR(255)'); $podcast = \Podlove\Model\Podcast::get(); $episodes = \Podlove\Model\Episode::all(); // Migration for Podcast if ($podcast->license_type == 'cc' && $podcast->license_cc_allow_commercial_use !== '' && $podcast->license_cc_allow_modifications !== '' && $podcast->license_cc_license_jurisdiction !== '') { $license = array('version' => '3.0', 'commercial_use' => $podcast->license_cc_allow_commercial_use, 'modification' => $podcast->license_cc_allow_modifications, 'jurisdiction' => $podcast->license_cc_license_jurisdiction); $podcast->license_url = \Podlove\Model\License::get_url_from_license($license); $podcast->license_name = \Podlove\Model\License::get_name_from_license($license); $podcast->save(); } // Migration for Episodes foreach ($episodes as $episode) { if ($episode->license_type == 'other' || $episode->license_cc_allow_commercial_use == '' || $episode->license_cc_allow_modifications == '' || $episode->license_cc_license_jurisdiction == '') { continue; } $license = array('version' => '3.0', 'commercial_use' => $episode->license_cc_allow_commercial_use, 'modification' => $episode->license_cc_allow_modifications, 'jurisdiction' => $episode->license_cc_license_jurisdiction); $episode->license_url = \Podlove\Model\License::get_url_from_license($license); $episode->license_name = \Podlove\Model\License::get_name_from_license($license); $episode->save(); } break; case 67: if (\Podlove\Modules\Base::is_active('social')) { $instagram_service = \Podlove\Modules\Social\Model\Service::find_one_by_where("`title` = 'Instagram' AND `type` = 'social'"); if ($instagram_service) { $instagram_service->url_scheme = 'https://instagram.com/%account-placeholder%'; $instagram_service->save(); } } break; case 68: // Do that ADN module fix again, as we forgot to mark all episodes as published if the ADN module is activated $episodes = Model\Episode::all(); foreach ($episodes as $episode) { $post = get_post($episode->post_id); if ($post->post_status == 'publish' && !get_post_meta($episode->post_id, '_podlove_episode_was_published', true)) { update_post_meta($episode->post_id, '_podlove_episode_was_published', true); } } break; case 69: if (\Podlove\Modules\Base::is_active('app_dot_net')) { $adn = \Podlove\Modules\AppDotNet\App_Dot_Net::instance(); if ($adn->get_module_option('adn_auth_key')) { $adn->update_module_option('adn_automatic_announcement', 'on'); } } break; case 70: \Podlove\Model\DownloadIntent::build(); \Podlove\Model\UserAgent::build(); break; case 71: // update for everyone, so even those with inactive service tables get updated $wpdb->query(sprintf('ALTER TABLE `%s` CHANGE COLUMN `type` `category` VARCHAR(255)', \Podlove\Modules\Social\Model\Service::table_name())); $wpdb->query(sprintf("ALTER TABLE `%s` ADD COLUMN `type` VARCHAR(255) AFTER `category`", \Podlove\Modules\Social\Model\Service::table_name())); $services = \Podlove\Modules\Social\Model\Service::all(); foreach ($services as $service) { $service->type = strtolower($service->title); $service->save(); } break; case 72: if (\Podlove\Modules\Base::is_active('social')) { $services = array(array('title' => 'Vimeo', 'type' => 'vimeo', 'category' => 'social', 'description' => 'Vimeo Account', 'logo' => 'vimeo-128.png', 'url_scheme' => 'http://vimeo.com/%account-placeholder%'), array('title' => 'about.me', 'type' => 'about.me', 'category' => 'social', 'description' => 'about.me Account', 'logo' => 'aboutme-128.png', 'url_scheme' => 'http://about.me/%account-placeholder%'), array('title' => 'Gittip', 'type' => 'gittip', 'category' => 'donation', 'description' => 'Gittip Account', 'logo' => 'gittip-128.png', 'url_scheme' => 'https://www.gittip.com/%account-placeholder%')); foreach ($services as $service_key => $service) { $c = new \Podlove\Modules\Social\Model\Service(); $c->title = $service['title']; $c->type = $service['type']; $c->category = $service['category']; $c->description = $service['description']; $c->logo = $service['logo']; $c->url_scheme = $service['url_scheme']; $c->save(); } } break; case 73: if (\Podlove\Modules\Base::is_active('social')) { $jabber_service = \Podlove\Modules\Social\Model\Service::find_one_by_where("`type` = 'jabber' AND `category` = 'social'"); if ($jabber_service) { $jabber_service->url_scheme = 'jabber:%account-placeholder%'; $jabber_service->save(); } } break; case 74: Model\GeoArea::build(); Model\GeoAreaName::build(); \Podlove\Geo_Ip::register_updater_cron(); break; case 75: $tracking = get_option('podlove_tracking'); $tracking['mode'] = 0; update_option('podlove_tracking', $tracking); break; case 76: set_transient('podlove_needs_to_flush_rewrite_rules', true); break; case 77: // delete empty user agents $userAgentTable = Model\UserAgent::table_name(); $downloadIntentTable = Model\DownloadIntent::table_name(); $sql = "SELECT\n\t\t\t\tdi.id\n\t\t\tFROM\n\t\t\t\t{$downloadIntentTable} di\n\t\t\t\tJOIN {$userAgentTable} ua ON ua.id = di.user_agent_id\n\t\t\tWHERE\n\t\t\t\tua.user_agent IS NULL"; $ids = $wpdb->get_col($sql); if (is_array($ids) && count($ids)) { $sql = "UPDATE {$downloadIntentTable} SET user_agent_id = NULL WHERE id IN (" . implode(",", $ids) . ")"; $wpdb->query($sql); $sql = "DELETE FROM {$userAgentTable} WHERE user_agent IS NULL"; $wpdb->query($sql); } break; case 78: if (\Podlove\Modules\Base::is_active('social')) { $c = new \Podlove\Modules\Social\Model\Service(); $c->title = 'Auphonic Credits'; $c->category = 'donation'; $c->type = 'auphonic credits'; $c->description = 'Auphonic Account'; $c->logo = 'auphonic-128.png'; $c->url_scheme = 'https://auphonic.com/donate_credits?user=%account-placeholder%'; $c->save(); } break; case 79: set_transient('podlove_needs_to_flush_rewrite_rules', true); $cache = \Podlove\Cache\TemplateCache::get_instance(); $cache->setup_purge(); break; case 80: $sql = sprintf('ALTER TABLE `%s` ADD COLUMN `httprange` VARCHAR(255)', \Podlove\Model\DownloadIntent::table_name()); $wpdb->query($sql); break; case 81: // remove all caches with old namespace $wpdb->query("DELETE FROM {$wpdb->options} WHERE option_name LIKE \"_transient_podlove_cache%\""); break; case 82: // set all redirect entries to active $redirect_settings = \Podlove\get_setting('redirects', 'podlove_setting_redirect'); foreach ($redirect_settings as $index => $data) { $redirect_settings[$index]['active'] = 'active'; } update_option('podlove_redirects', array('podlove_setting_redirect' => $redirect_settings)); break; case 83: \Podlove\Model\DownloadIntentClean::build(); $alterations = array('ALTER TABLE `%s` ADD COLUMN `bot` TINYINT', 'ALTER TABLE `%s` ADD COLUMN `client_name` VARCHAR(255)', 'ALTER TABLE `%s` ADD COLUMN `client_version` VARCHAR(255)', 'ALTER TABLE `%s` ADD COLUMN `client_type` VARCHAR(255)', 'ALTER TABLE `%s` ADD COLUMN `os_name` VARCHAR(255)', 'ALTER TABLE `%s` ADD COLUMN `os_version` VARCHAR(255)', 'ALTER TABLE `%s` ADD COLUMN `device_brand` VARCHAR(255)', 'ALTER TABLE `%s` ADD COLUMN `device_model` VARCHAR(255)'); foreach ($alterations as $sql) { $wpdb->query(sprintf($sql, Model\UserAgent::table_name())); } Model\UserAgent::reparse_all(); break; case 84: delete_option('podlove_tpl_cache_keys'); break; case 85: add_option('podlove_tracking_delete_head_requests', 1); break; case 86: if (\Podlove\Modules\Base::is_active('social')) { $c = new \Podlove\Modules\Social\Model\Service(); $c->title = 'Foursquare'; $c->category = 'social'; $c->type = 'foursquare'; $c->description = 'Foursquare Account'; $c->logo = 'foursquare-128.png'; $c->url_scheme = 'https://foursquare.com/%account-placeholder%'; $c->save(); $services = array(array('title' => 'ResearchGate', 'name' => 'researchgate', 'category' => 'social', 'description' => 'ResearchGate URL', 'logo' => 'researchgate-128.png', 'url_scheme' => '%account-placeholder%'), array('title' => 'ORCiD', 'name' => 'orcid', 'category' => 'social', 'description' => 'ORCiD', 'logo' => 'orcid-128.png', 'url_scheme' => 'https://orcid.org/%account-placeholder%'), array('title' => 'Scopus', 'name' => 'scous', 'category' => 'social', 'description' => 'Scopus Author ID', 'logo' => 'scopus-128.png', 'url_scheme' => 'https://www.scopus.com/authid/detail.url?authorId=%account-placeholder%')); foreach ($services as $service_key => $service) { $c = new \Podlove\Modules\Social\Model\Service(); $c->title = $service['title']; $c->category = $service['category']; $c->type = $service['name']; $c->description = $service['description']; $c->logo = $service['logo']; $c->url_scheme = $service['url_scheme']; $c->save(); } } break; case 87: if (\Podlove\Modules\Base::is_active('app_dot_net')) { $adn = \Podlove\Modules\AppDotNet\App_Dot_Net::instance(); if ($adn->get_module_option('adn_auth_key')) { $adn->update_module_option('adn_poster_image_fallback', 'on'); } } break; case 88: $service = new \Podlove\Modules\Social\Model\Service(); $service->title = 'Email'; $service->category = 'social'; $service->type = 'email'; $service->description = 'Email'; $service->logo = 'email-128.png'; $service->url_scheme = 'mailto:%account-placeholder%'; $service->save(); break; case 89: $email_service = \Podlove\Modules\Social\Model\Service::find_one_by_type('email'); foreach (\Podlove\Modules\Contributors\Model\Contributor::all() as $contributor) { if (!$contributor->publicemail) { continue; } $contributor_service = new \Podlove\Modules\Social\Model\ContributorService(); $contributor_service->contributor_id = $contributor->id; $contributor_service->service_id = $email_service->id; $contributor_service->value = $contributor->publicemail; $contributor_service->save(); } break; case 90: \Podlove\Modules\Base::activate('subscribe_button'); break; case 91: $c = new \Podlove\Modules\Social\Model\Service(); $c->title = 'Miiverse'; $c->category = 'social'; $c->type = 'miiverse'; $c->description = 'Miiverse Account'; $c->logo = 'miiverse-128.png'; $c->url_scheme = 'https://miiverse.nintendo.net/users/%account-placeholder%'; $c->save(); break; case 92: $c = new \Podlove\Modules\Social\Model\Service(); $c->title = 'Prezi'; $c->category = 'social'; $c->type = 'prezi'; $c->description = 'Prezis'; $c->logo = 'prezi-128.png'; $c->url_scheme = 'http://prezi.com/user/%account-placeholder%'; $c->save(); break; case 93: // podlove_init_user_agent_refresh(); // do nothing instead, because see 94 below break; case 94: // this is a duplicate of migration 83 but it looks like that didn't work. Model\DownloadIntentClean::build(); $alterations = array('ALTER TABLE `%s` ADD COLUMN `bot` TINYINT', 'ALTER TABLE `%s` ADD COLUMN `client_name` VARCHAR(255)', 'ALTER TABLE `%s` ADD COLUMN `client_version` VARCHAR(255)', 'ALTER TABLE `%s` ADD COLUMN `client_type` VARCHAR(255)', 'ALTER TABLE `%s` ADD COLUMN `os_name` VARCHAR(255)', 'ALTER TABLE `%s` ADD COLUMN `os_version` VARCHAR(255)', 'ALTER TABLE `%s` ADD COLUMN `device_brand` VARCHAR(255)', 'ALTER TABLE `%s` ADD COLUMN `device_model` VARCHAR(255)'); foreach ($alterations as $sql) { $wpdb->query(sprintf($sql, Model\UserAgent::table_name())); } podlove_init_user_agent_refresh(); // manually trigger intent cron after user agents are parsed // parameter to make sure WP does not skip it due to 10 minute rule wp_schedule_single_event(time() + 120, 'podlove_cleanup_download_intents', ['really' => true]); // manually trigger average cron after intents are calculated wp_schedule_single_event(time() + 240, 'recalculate_episode_download_average', ['really' => true]); break; case 95: // add missing flattr column $wpdb->query(sprintf('ALTER TABLE `%s` ADD COLUMN `flattr` VARCHAR(255) AFTER `avatar`', \Podlove\Modules\Contributors\Model\Contributor::table_name())); break; case 96: \Podlove\DeleteHeadRequests::init(); break; case 97: // recalculate all downloads average data $wpdb->query(sprintf('DELETE FROM `%s` WHERE `meta_key` LIKE "_podlove_eda%%"', $wpdb->postmeta)); break; case 98: delete_transient('podlove_dashboard_stats_contributors'); break; case 99: // Activate network module for migrating users. // Core modules are automatically activated for _new_ setups and // whenever modules change. Since this can't be guaranteed for // existing setups, it must be triggered manually. \Podlove\Modules\Networks\Networks::instance()->was_activated(); break; case 101: // add patreon if (\Podlove\Modules\Social\Model\Service::table_exists()) { \Podlove\Modules\Social\RepairSocial::fix_missing_services(); } break; case 102: // update logos if (\Podlove\Modules\Social\Model\Service::table_exists()) { \Podlove\Modules\Social\Social::update_existing_services(); } break; case 103: $assignment = get_option('podlove_template_assignment', []); if ($assignment['top'] && is_numeric($assignment['top'])) { $assignment['top'] = Model\Template::find_by_id($assignment['top'])->title; } if ($assignment['bottom'] && is_numeric($assignment['bottom'])) { $assignment['bottom'] = Model\Template::find_by_id($assignment['bottom'])->title; } update_option('podlove_template_assignment', $assignment); break; case 104: \Podlove\unschedule_events(\Podlove\Cache\TemplateCache::CRON_PURGE_HOOK); break; case 105: // activate flattr plugin \Podlove\Modules\Base::activate('flattr'); // migrate flattr data $podcast = Model\Podcast::get(); $settings = get_option('podlove_flattr', []); $settings['account'] = $podcast->flattr; $settings['contributor_shortcode_default'] = 'yes'; update_option('podlove_flattr', $settings); break; case 106: podlove_init_user_agent_refresh(); break; case 107: // skipped break; case 108: podlove_init_user_agent_refresh(); break; case 109: \podlove_init_capabilities(); break; case 110: if (\Podlove\Modules\Social\Model\Service::table_exists()) { \Podlove\Modules\Social\Social::update_existing_services(); \Podlove\Modules\Social\Social::build_missing_services(); } break; case 111: if (\Podlove\Modules\Social\Model\Service::table_exists()) { \Podlove\Modules\Social\Social::update_existing_services(); \Podlove\Modules\Social\Social::build_missing_services(); } break; } }
public function render_link() { echo Model\Feed::get_link_tag(array('prefix' => 'atom', 'rel' => 'http://podlove.org/simple-chapters', 'type' => '', 'title' => '', 'href' => get_permalink() . "?chapters_format=psc")); }