Commit 6b34617d authored by Benjamin Bellamy's avatar Benjamin Bellamy 💬
Browse files

feat(rss): add soundbites according to the podcastindex specs

Closes #83
parent 0571a075
Loading
Loading
Loading
Loading
Loading
+23 −0
Original line number Diff line number Diff line
@@ -253,6 +253,29 @@ $routes->group(
                                'filter' => 'permission:podcast_episodes-edit',
                            ]
                        );
                        $routes->get(
                            'soundbites',
                            'Episode::soundbitesEdit/$1/$2',
                            [
                                'as' => 'soundbites-edit',
                                'filter' => 'permission:podcast_episodes-edit',
                            ]
                        );
                        $routes->post(
                            'soundbites',
                            'Episode::soundbitesAttemptEdit/$1/$2',
                            [
                                'filter' => 'permission:podcast_episodes-edit',
                            ]
                        );
                        $routes->add(
                            'soundbites/(:num)/delete',
                            'Episode::soundbiteDelete/$1/$2/$3',
                            [
                                'as' => 'soundbite-delete',
                                'filter' => 'permission:podcast_episodes-edit',
                            ]
                        );
                    });
                });

+95 −1
Original line number Diff line number Diff line
@@ -10,6 +10,7 @@ namespace App\Controllers\Admin;

use App\Models\EpisodeModel;
use App\Models\PodcastModel;
use App\Models\SoundbiteModel;
use CodeIgniter\I18n\Time;

class Episode extends BaseController
@@ -24,6 +25,11 @@ class Episode extends BaseController
     */
    protected $episode;

    /**
     * @var \App\Entities\Soundbite|null
     */
    protected $soundbites;

    public function _remap($method, ...$params)
    {
        $this->podcast = (new PodcastModel())->getPodcastById($params[0]);
@@ -39,9 +45,12 @@ class Episode extends BaseController
            ) {
                throw \CodeIgniter\Exceptions\PageNotFoundException::forPageNotFound();
            }

            unset($params[1]);
            unset($params[0]);
        }

        return $this->$method();
        return $this->$method(...$params);
    }

    public function list()
@@ -316,4 +325,89 @@ class Episode extends BaseController

        return redirect()->route('episode-list', [$this->podcast->id]);
    }

    public function soundbitesEdit()
    {
        helper(['form']);

        $data = [
            'podcast' => $this->podcast,
            'episode' => $this->episode,
        ];

        replace_breadcrumb_params([
            0 => $this->podcast->title,
            1 => $this->episode->title,
        ]);
        return view('admin/episode/soundbites', $data);
    }

    public function soundbitesAttemptEdit()
    {
        $soundbites_array = $this->request->getPost('soundbites_array');
        $rules = [
            'soundbites_array.0.start_time' =>
                'permit_empty|required_with[soundbites_array.0.duration]|decimal|greater_than_equal_to[0]',
            'soundbites_array.0.duration' =>
                'permit_empty|required_with[soundbites_array.0.start_time]|decimal|greater_than_equal_to[0]',
        ];
        foreach ($soundbites_array as $soundbite_id => $soundbite) {
            $rules += [
                "soundbites_array.{$soundbite_id}.start_time" => 'required|decimal|greater_than_equal_to[0]',
                "soundbites_array.{$soundbite_id}.duration" => 'required|decimal|greater_than_equal_to[0]',
            ];
        }
        if (!$this->validate($rules)) {
            return redirect()
                ->back()
                ->withInput()
                ->with('errors', $this->validator->getErrors());
        }

        foreach ($soundbites_array as $soundbite_id => $soundbite) {
            if (
                !empty($soundbite['start_time']) &&
                !empty($soundbite['duration'])
            ) {
                $data = [
                    'podcast_id' => $this->podcast->id,
                    'episode_id' => $this->episode->id,
                    'start_time' => $soundbite['start_time'],
                    'duration' => $soundbite['duration'],
                    'label' => $soundbite['label'],
                    'updated_by' => user()->id,
                ];
                if ($soundbite_id == 0) {
                    $data += ['created_by' => user()->id];
                } else {
                    $data += ['id' => $soundbite_id];
                }
                $soundbiteModel = new SoundbiteModel();
                if (!$soundbiteModel->save($data)) {
                    return redirect()
                        ->back()
                        ->withInput()
                        ->with('errors', $soundbiteModel->errors());
                }
            }
        }
        return redirect()->route('soundbites-edit', [
            $this->podcast->id,
            $this->episode->id,
        ]);
    }

    public function soundbiteDelete($soundbiteId)
    {
        (new SoundbiteModel())->deleteSoundbite(
            $this->podcast->id,
            $this->episode->id,
            $soundbiteId
        );

        return redirect()->route('soundbites-edit', [
            $this->podcast->id,
            $this->episode->id,
        ]);
    }
}
+77 −0
Original line number Diff line number Diff line
<?php

/**
 * Class AddSoundbites
 * Creates soundbites table in database
 *
 * @copyright  2020 Podlibre
 * @license    https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3
 * @link       https://castopod.org/
 */

namespace App\Database\Migrations;

use CodeIgniter\Database\Migration;

class AddSoundbites extends Migration
{
    public function up()
    {
        $this->forge->addField([
            'id' => [
                'type' => 'INT',
                'unsigned' => true,
                'auto_increment' => true,
            ],
            'podcast_id' => [
                'type' => 'INT',
                'unsigned' => true,
            ],
            'episode_id' => [
                'type' => 'INT',
                'unsigned' => true,
            ],
            'start_time' => [
                'type' => 'FLOAT',
            ],
            'duration' => [
                'type' => 'FLOAT',
            ],
            'label' => [
                'type' => 'VARCHAR',
                'constraint' => 128,
                'null' => true,
            ],
            'created_by' => [
                'type' => 'INT',
                'unsigned' => true,
            ],
            'updated_by' => [
                'type' => 'INT',
                'unsigned' => true,
            ],
            'created_at' => [
                'type' => 'DATETIME',
            ],
            'updated_at' => [
                'type' => 'DATETIME',
            ],
            'deleted_at' => [
                'type' => 'DATETIME',
                'null' => true,
            ],
        ]);
        $this->forge->addKey('id', true);
        $this->forge->addUniqueKey(['episode_id', 'start_time', 'duration']);
        $this->forge->addForeignKey('podcast_id', 'podcasts', 'id');
        $this->forge->addForeignKey('episode_id', 'episodes', 'id');
        $this->forge->addForeignKey('created_by', 'users', 'id');
        $this->forge->addForeignKey('updated_by', 'users', 'id');
        $this->forge->createTable('soundbites');
    }

    public function down()
    {
        $this->forge->dropTable('soundbites');
    }
}
+1 −0
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@ class Category extends Entity
    protected $parent;

    protected $casts = [
        'id' => 'integer',
        'parent_id' => 'integer',
        'code' => 'string',
        'apple_category' => 'string',
+30 −0
Original line number Diff line number Diff line
@@ -9,6 +9,7 @@
namespace App\Entities;

use App\Models\PodcastModel;
use App\Models\SoundbiteModel;
use CodeIgniter\Entity;
use CodeIgniter\I18n\Time;
use League\CommonMark\CommonMarkConverter;
@@ -75,6 +76,11 @@ class Episode extends Entity
     */
    protected $chapters_url;

    /**
     * @var \App\Entities\Soundbite[]
     */
    protected $soundbites;

    /**
     * Holds text only description, striped of any markdown or html special characters
     *
@@ -95,6 +101,7 @@ class Episode extends Entity
    ];

    protected $casts = [
        'id' => 'integer',
        'guid' => 'string',
        'slug' => 'string',
        'title' => 'string',
@@ -348,6 +355,29 @@ class Episode extends Entity
            : null;
    }

    /**
     * Returns the episode’s soundbites
     *
     * @return \App\Entities\Episode[]
     */
    public function getSoundbites()
    {
        if (empty($this->id)) {
            throw new \RuntimeException(
                'Episode must be created before getting soundbites.'
            );
        }

        if (empty($this->soundbites)) {
            $this->soundbites = (new SoundbiteModel())->getEpisodeSoundbites(
                $this->getPodcast()->id,
                $this->id
            );
        }

        return $this->soundbites;
    }

    public function getLink()
    {
        return base_url(
Loading