From 9399656ecb8754fd8897571364b091756e16547d Mon Sep 17 00:00:00 2001 From: Alexander Heimbuch Date: Fri, 22 May 2020 08:57:22 +0200 Subject: [PATCH 1/2] chore: extract default settings --- env/.htaccess | 21 +- .../class-podlove-web-player-options.php | 382 +++++++++--------- src/plugin/podlove-web-player.php | 2 +- 3 files changed, 204 insertions(+), 201 deletions(-) diff --git a/env/.htaccess b/env/.htaccess index cd8f3fd..b5f42ee 100644 --- a/env/.htaccess +++ b/env/.htaccess @@ -1,22 +1,11 @@ -# BEGIN WordPress -# The directives (lines) between `BEGIN WordPress` and `END WordPress` are -# dynamically generated, and should only be modified via WordPress filters. -# Any changes to the directives between these markers will be overwritten. -# https://wordpress.org/support/article/htaccess/ +# BEGIN WordPress + RewriteEngine On RewriteBase / RewriteRule ^index\.php$ - [L] - -# add a trailing slash to /wp-admin -RewriteRule ^wp-admin$ wp-admin/ [R=301,L] - -RewriteCond %{REQUEST_FILENAME} -f [OR] -RewriteCond %{REQUEST_FILENAME} -d -RewriteRule ^ - [L] -RewriteRule ^(wp-(content|admin|includes).*) $1 [L] -RewriteRule ^(.*\.php)$ $1 [L] -RewriteRule . index.php [L] - +RewriteCond %{REQUEST_FILENAME} !-f +RewriteCond %{REQUEST_FILENAME} !-d +RewriteRule . /index.php [L] # END WordPress diff --git a/src/plugin/includes/class-podlove-web-player-options.php b/src/plugin/includes/class-podlove-web-player-options.php index cb3df24..31581fc 100644 --- a/src/plugin/includes/class-podlove-web-player-options.php +++ b/src/plugin/includes/class-podlove-web-player-options.php @@ -12,206 +12,220 @@ class Podlove_Web_Player_Options { - /** - * The unique identifier of this plugin. - * - * @since 5.0.2 - * @access protected - * @var string $plugin_name The string used to uniquely identify this plugin. - */ - protected $plugin_name; - - /** - * The plugin directory - * - * @since 5.0.2 - * @access protected - * @var string $plugin_directory The plugin directory. - */ - protected $plugin_directory; - - /** - * The default web player configuration - * - * @since 5.0.2 - * @access protected - * @var array $defaults Default configuration values. - */ - protected $defaults; - - - /** - * Interoperability Object - * - * @since 5.0.13 - * @access private - * @var object $interoperability The player interoperability. - */ - private $interoperability; - - public function __construct($plugin_name) - { - global $content_width; - - $this->plugin_name = $plugin_name; - $this->plugin_directory = plugin_dir_path(__DIR__); - $this->interoperability = new Podlove_Web_Player_Interoperability($this->plugin_name); - - $this->defaults = array( - 'configs' => array( - 'default' => $this->readFile($this->plugin_directory . 'defaults/configs/default.json', 'json'), - ), - 'themes' => array( - 'default' => $this->readFile($this->plugin_directory . 'defaults/themes/default.json', 'json'), - ), - 'templates' => array( - 'default' => $this->readFile($this->plugin_directory . 'defaults/templates/default.html', 'html'), - ), - 'settings' => array( - 'source' => array( - 'selected' => 'local', - 'items' => array( - 'local' => PODLOVE_WEB_PLAYER_PATH . 'web-player/', - 'cdn' => 'https://cdn.podlove.org/web-player/5.x/' - ) - ), - 'contentWidth' => $content_width, - 'enclosure' => 'bottom', - 'legacy' => false, - 'defaults' => array( - 'theme' => 'default', - 'config' => 'default', - 'template' => 'default' - ) - ) - ); - } - - /** - * Serializes values with defaults - * - * @since 5.0.2 - */ - private function serializer($value = []) - { - $merged = (object) array_merge((array) $this->defaults, (array) $value); - - return json_encode($merged); - } - - /** - * Reads file from plugin - */ - private function readFile($path = null, $type = 'json') - { - if (!$path) { - return null; + /** + * The unique identifier of this plugin. + * + * @since 5.0.2 + * @access protected + * @var string $plugin_name The string used to uniquely identify this plugin. + */ + protected $plugin_name; + + /** + * The plugin directory + * + * @since 5.0.2 + * @access protected + * @var string $plugin_directory The plugin directory. + */ + protected $plugin_directory; + + /** + * The default web player configuration + * + * @since 5.0.2 + * @access protected + * @var array $defaults Default configuration values. + */ + protected $defaults; + + /*** + * static configuration values + * @since 5.1.3 + * @access private + * @var object $interoperability The player interoperability. + */ + protected $config; + + /** + * Interoperability Object + * + * @since 5.0.13 + * @access private + * @var object $interoperability The player interoperability. + */ + private $interoperability; + + public function __construct($plugin_name) + { + global $content_width; + + $this->plugin_name = $plugin_name; + $this->plugin_directory = plugin_dir_path(__DIR__); + $this->interoperability = new Podlove_Web_Player_Interoperability($this->plugin_name); + + $this->defaults = array( + 'configs' => array( + 'default' => $this->readFile($this->plugin_directory . 'defaults/configs/default.json', 'json'), + ), + 'themes' => array( + 'default' => $this->readFile($this->plugin_directory . 'defaults/themes/default.json', 'json'), + ), + 'templates' => array( + 'default' => $this->readFile($this->plugin_directory . 'defaults/templates/default.html', 'html'), + ), + 'settings' => array( + 'source' => array( + 'selected' => 'local', + ), + + 'enclosure' => 'bottom', + 'legacy' => false, + 'defaults' => array( + 'theme' => 'default', + 'config' => 'default', + 'template' => 'default', + ), + ), + ); + + $this->config = array( + 'settings' => array( + 'source' => array( + 'items' => array( + 'local' => PODLOVE_WEB_PLAYER_PATH . '/web-player/', + 'cdn' => 'https://cdn.podlove.org/web-player/5.x/', + ), + ), + 'contentWidth' => $content_width, + ), + ); } - $content = file_get_contents($path); - - if ($type === 'json') { - $content = json_decode($content, true); + /** + * Serializes values with defaults + * + * @since 5.0.2 + */ + private function serializer($value = []) + { + return json_encode($value); } - return $content; - } + /** + * Reads file from plugin + */ + private function readFile($path = null, $type = 'json') + { + if (!$path) { + return null; + } + + $content = file_get_contents($path); - /** - * Reads files from the plugin - */ - private function readFolder($path = null, $type = 'json') - { - if (!$path || !is_dir($path)) { - return null; + if ($type === 'json') { + $content = json_decode($content, true); + } + + return $content; } - $files = scandir($path); - $contents = array(); + /** + * Reads files from the plugin + */ + private function readFolder($path = null, $type = 'json') + { + if (!$path || !is_dir($path)) { + return null; + } + + $files = scandir($path); + $contents = array(); - foreach ($files as &$file) { - $info = pathinfo($file); + foreach ($files as &$file) { + $info = pathinfo($file); - if ($info['extension'] !== $type) { - continue; - } + if ($info['extension'] !== $type) { + continue; + } - $contents[$info['filename']] = $this->readFile(trailingslashit($path) . $file, $info['extension']); + $contents[$info['filename']] = $this->readFile(trailingslashit($path) . $file, $info['extension']); + } + + return $contents; } - return $contents; - } - - /** - * Creates the plugin options - * - * @since 5.0.2 - */ - public function create($networkActivated) - { - if ($networkActivated) { - add_site_option($this->plugin_name, $this->serializer()); - } else { - add_option($this->plugin_name, $this->serializer()); + /** + * Creates the plugin options + * + * @since 5.0.2 + */ + public function create($networkActivated) + { + if ($networkActivated) { + add_site_option($this->plugin_name, $this->serializer()); + } else { + add_option($this->plugin_name, $this->serializer()); + } } - } - - /** - * Gets the defaults - * - * @since 5.0.14 - */ - public function presets() - { - return array( - 'configs' => $this->readFolder($this->plugin_directory . 'defaults/configs/', 'json'), - 'themes' => $this->readFolder($this->plugin_directory . 'defaults/themes/', 'json'), - 'templates' => $this->readFolder($this->plugin_directory . 'defaults/templates/', 'html') - ); - } - - /** - * Reads the plugin options - * - * @since 5.0.2 - */ - public function read() - { - if ($this->interoperability->isNetworkActivated()) { - $options = json_decode(get_site_option($this->plugin_name), true); - } else { - $options = json_decode(get_option($this->plugin_name), true); + + /** + * Gets the defaults + * + * @since 5.0.14 + */ + public function presets() + { + return array( + 'configs' => $this->readFolder($this->plugin_directory . 'defaults/configs/', 'json'), + 'themes' => $this->readFolder($this->plugin_directory . 'defaults/themes/', 'json'), + 'templates' => $this->readFolder($this->plugin_directory . 'defaults/templates/', 'html'), + ); } + /** + * Reads the plugin options + * + * @since 5.0.2 + */ + public function read() + { + if ($this->interoperability->isNetworkActivated()) { + $options = json_decode(get_site_option($this->plugin_name), true); + } else { + $options = json_decode(get_option($this->plugin_name), true); + } + + $settings = array_replace_recursive($options ?? array(), $this->config); + + return array_replace_recursive($this->defaults, $settings); + } - return array_replace_recursive($this->defaults, $options ?? array()); - } - - /** - * Updates the plugin options - * - * @since 5.0.2 - */ - public function update($value = array()) - { - if ($this->interoperability->isNetworkActivated()) { - update_site_option($this->plugin_name, $this->serializer($value)); - } else { - update_option($this->plugin_name, $this->serializer($value)); + /** + * Updates the plugin options + * + * @since 5.0.2 + */ + public function update($value = array()) + { + if ($this->interoperability->isNetworkActivated()) { + update_site_option($this->plugin_name, $this->serializer($value)); + } else { + update_option($this->plugin_name, $this->serializer($value)); + } } - } - - /** - * Updates the plugin options - * - * @since 5.0.2 - */ - public function delete() - { - if ($this->interoperability->isNetworkActivated()) { - delete_site_option($this->plugin_name); - } else { - delete_option($this->plugin_name); + + /** + * Updates the plugin options + * + * @since 5.0.2 + */ + public function delete() + { + if ($this->interoperability->isNetworkActivated()) { + delete_site_option($this->plugin_name); + } else { + delete_option($this->plugin_name); + } } - } } diff --git a/src/plugin/podlove-web-player.php b/src/plugin/podlove-web-player.php index d21ca82..d5bf652 100755 --- a/src/plugin/podlove-web-player.php +++ b/src/plugin/podlove-web-player.php @@ -31,7 +31,7 @@ } define( 'PODLOVE_WEB_PLAYER_VERSION', '5.1.2' ); -define( 'PODLOVE_WEB_PLAYER_PATH', plugin_dir_url( __FILE__ ) ); +define( 'PODLOVE_WEB_PLAYER_PATH', plugins_url( basename( __DIR__ ) ) ); /** * The code that runs during plugin activation. From 91f002b78199f8314453c9d579500662e17a3305 Mon Sep 17 00:00:00 2001 From: Alexander Heimbuch Date: Fri, 22 May 2020 16:57:46 +0200 Subject: [PATCH 2/2] feat: use publisher shows for playlists --- package-lock.json | 2 +- package.json | 2 +- src/block/block.js | 4 + src/block/components/inspector/index.js | 2 + src/block/components/inspector/settings.js | 2 +- src/block/components/inspector/shows.js | 60 ++ src/block/components/player.js | 2 +- src/block/components/source.js | 2 +- src/configurator/assets/episode.js | 74 ++ src/configurator/assets/index.js | 5 + src/configurator/components/Player.vue | 100 +-- src/plugin/README.txt | 5 + .../class-podlove-web-player-admin-api.php | 834 +++++++++--------- .../class-podlove-web-player-embed-api.php | 179 ++-- .../class-podlove-web-player-shortcode.php | 63 +- src/plugin/podlove-web-player.php | 4 +- 16 files changed, 767 insertions(+), 573 deletions(-) create mode 100644 src/block/components/inspector/shows.js create mode 100644 src/configurator/assets/episode.js create mode 100644 src/configurator/assets/index.js diff --git a/package-lock.json b/package-lock.json index 9d9baca..5214656 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "@podlove/web-player-configurator", - "version": "5.1.2", + "version": "5.2.0", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 0b30054..bff2746 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@podlove/web-player-configurator", - "version": "5.1.2", + "version": "5.2.0", "description": "Podlove Web Player Configurator", "author": "Alexander Heimbuch ", "scripts": { diff --git a/src/block/block.js b/src/block/block.js index 6636f11..1f73dcc 100644 --- a/src/block/block.js +++ b/src/block/block.js @@ -41,6 +41,10 @@ registerBlockType('podlove-web-player/shortcode', { type: 'string', default: 'default', }, + + show: { + type: 'string' + }, }, edit: props => ( diff --git a/src/block/components/inspector/index.js b/src/block/components/inspector/index.js index b30a42a..b9f118f 100644 --- a/src/block/components/inspector/index.js +++ b/src/block/components/inspector/index.js @@ -2,6 +2,7 @@ import Custom from './custom' import Post from './post' import Publisher from './publisher' import Settings from './settings' +import Shows from './shows' import { type } from '../utils' const { compose } = wp.compose @@ -26,6 +27,7 @@ class Inspector extends Component { + ) diff --git a/src/block/components/inspector/settings.js b/src/block/components/inspector/settings.js index 34562a3..5ceddb8 100644 --- a/src/block/components/inspector/settings.js +++ b/src/block/components/inspector/settings.js @@ -24,7 +24,7 @@ class Settings extends Component { this.setState({ configs: keys(data.configs).map(data => ({ value: data, label: data })), themes: keys(data.themes).map(data => ({ value: data, label: data })), - templates: keys(data.templates).map(data => ({ value: data, label: data })) + templates: keys(data.templates).map(data => ({ value: data, label: data })), }) } diff --git a/src/block/components/inspector/shows.js b/src/block/components/inspector/shows.js new file mode 100644 index 0000000..cbd3b02 --- /dev/null +++ b/src/block/components/inspector/shows.js @@ -0,0 +1,60 @@ +import './inspector.scss' +import { keys } from 'lodash' + +const { Component } = wp.element +const { compose } = wp.compose +const { withSpokenMessages, SelectControl, PanelBody, PanelRow } = wp.components +const { InspectorControls } = wp.blockEditor +const { __ } = wp.i18n + +class Shows extends Component { + constructor(props) { + super(...arguments); + this.props = props; + this.state = { + shows: [] + } + } + + async componentDidMount() { + const shows = await fetch(window.PODLOVE_WEB_PLAYER.api.shows).then(result => result.json()) + console.log(shows) + this.setState({ + shows: shows || [] + }) + } + + render() { + const { + setAttributes, + attributes + } = this.props + + const { shows } = this.state + + if (shows.concat.length === 0) { + return null + } + + const select = show => console.log(show) || setAttributes({ show }) + const options = [{ id: null, name: __('Select', 'podlove-web-player') }] + .concat(shows || []) + .map(({ slug, name }) => ({ value: slug, label: name })) + + return + + + + + + + } +} + +export default compose([ + withSpokenMessages +])(Shows) diff --git a/src/block/components/player.js b/src/block/components/player.js index b0cc31b..dca87c3 100644 --- a/src/block/components/player.js +++ b/src/block/components/player.js @@ -27,7 +27,7 @@ class Player extends Component { const routes = window.PODLOVE_WEB_PLAYER.embed let episode - const config = [routes.config, attributes.config, 'theme', attributes.theme].join('/') + const config = [routes.config, attributes.config, 'theme', attributes.theme, ...(attributes.show ? ['show', attributes.show] : [])].join('/') const template = get(this.plugin, ['templates', attributes.template], '') switch (this.type) { diff --git a/src/block/components/source.js b/src/block/components/source.js index 5336d3e..95cf43f 100644 --- a/src/block/components/source.js +++ b/src/block/components/source.js @@ -50,7 +50,7 @@ export default compose([ }), posts: getEntityRecords('postType', 'post', { per_page: 1, - }), + }) } }), withSpokenMessages, diff --git a/src/configurator/assets/episode.js b/src/configurator/assets/episode.js new file mode 100644 index 0000000..bcb7a40 --- /dev/null +++ b/src/configurator/assets/episode.js @@ -0,0 +1,74 @@ +import poster from './cover.png' +import fry from './fry.png' +import bender from './bender.png' +import professor from './professor.png' + +export default ({ title, duration }) => ({ + title, + version: 5, + show: { + title: 'Futurama', + subtitle: `Intergalactic conspiracies and other strange stuff`, + summary: `Hatched from Matt Groening's brain, Futurama follows pizza guy Philip J. Fry, who reawakens in 31st century New New York after a cryonics lab accident.`, + poster, + url: 'http://fillerama.io/', + }, + + subtitle: `Why am I sticky and naked? Did I miss something fun? In your time, yes, but nowadays shut up! Besides, these are adult stemcells, harvested from perfectly healthy adults whom I killed for their stemcells.`, + summary: `Ah, computer dating. It's like pimping, but you rarely have to use the phrase "upside your head." Who am I making this out to? Okay, I like a challenge. As an interesting side note, as a head without a body, I envy the dead.`, + publicationDate: '2016-02-11T03:13:55+00:00', + duration, + + contributors: [ + { + id: 'fry', + avatar: fry, + name: 'Philip J. Fry', + group: { id: '1', slug: 'planet-express', title: 'Planet Express' }, + }, + { + id: 'farnsworth', + avatar: professor, + name: 'Professor Farnsworth', + group: { id: '1', slug: 'planet-express', title: 'Planet Express' }, + }, + { + id: 'bender', + avatar: bender, + name: 'Bender Bending Rodríguez', + group: { id: '1', slug: 'planet-express', title: 'Planet Express' }, + }, + ], + + chapters: [ + { start: '00:00:00', title: 'With gusto.' }, + { start: '00:01:39', title: 'Good news' }, + { start: '00:04:58', title: 'You stole the atom' }, + { start: '00:18:37', title: `Oh, I don't have time for this` }, + { start: '00:33:40', title: 'Her company is big and evil!' }, + { start: '00:35:37', title: 'Have you ever tried just turning off the TV' }, + { start: '01:17:26', title: 'Hello, little man' }, + { start: '01:24:55', title: 'Take me to your leader!' }, + ], + + audio: [ + { + url: 'http://techslides.com/demos/samples/sample.m4a', + mimeType: 'audio/mp4', + size: 93260000, + title: 'Audio MP4', + }, + { + url: 'http://techslides.com/demos/samples/sample.mp3', + mimeType: 'audio/mp3', + size: 14665000, + title: 'Audio MP3', + }, + { + url: 'http://techslides.com/demos/samples/sample.ogg', + mimeType: 'audio/ogg', + size: 94400000, + title: 'Audio Ogg', + }, + ], +}) diff --git a/src/configurator/assets/index.js b/src/configurator/assets/index.js new file mode 100644 index 0000000..86bc185 --- /dev/null +++ b/src/configurator/assets/index.js @@ -0,0 +1,5 @@ +import episode from './episode' + +export { + episode +} diff --git a/src/configurator/components/Player.vue b/src/configurator/components/Player.vue index 710c971..78a1290 100644 --- a/src/configurator/components/Player.vue +++ b/src/configurator/components/Player.vue @@ -6,11 +6,7 @@