From c815ecd6640931fee0895f80908a3ddfac482666 Mon Sep 17 00:00:00 2001
From: Yassine Doghri <yassine@doghri.fr>
Date: Fri, 26 Jun 2020 14:34:52 +0000
Subject: [PATCH] feat(rss): generate rss feed from podcast entity

- refactor episode, podcast and category entities to add dynamic properties
- refactor Routes when adding feed route
- update migration files to better fit itunes' and rss' specs
- update podcast and episode forms
- add SimpleRSSElement class to Libraries
- add rss_helper
- update home controller to redirect if system has only one podcast
---
 app/Config/App.php                            |    2 +-
 app/Config/Routes.php                         |   25 +-
 app/Config/Toolbar.php                        |    2 +-
 app/Controllers/BaseController.php            |    2 +-
 app/Controllers/{Episodes.php => Episode.php} |   46 +-
 app/Controllers/Feed.php                      |   22 +
 app/Controllers/Home.php                      |   12 +-
 app/Controllers/{Podcasts.php => Podcast.php} |   27 +-
 .../2020-05-29-152000_add_categories.php      |    4 +-
 .../2020-05-30-101500_add_podcasts.php        |   13 +-
 .../2020-06-05-170000_add_episodes.php        |   22 +-
 app/Entities/Category.php                     |   14 +
 app/Entities/Episode.php                      |   66 +-
 app/Entities/Podcast.php                      |   36 +-
 app/Helpers/database_helper.php               |   33 -
 app/Helpers/id3_helper.php                    |   10 +-
 app/Helpers/media_helper.php                  |    2 +-
 app/Helpers/rss_helper.php                    |  165 +
 app/Helpers/url_helper.php                    |   20 -
 app/Language/en/{Episodes.php => Episode.php} |    3 +
 app/Language/en/{Podcasts.php => Podcast.php} |    5 +-
 app/Libraries/SimpleRSSElement.php            |   27 +
 app/Models/CategoryModel.php                  |    7 +-
 app/Models/EpisodeModel.php                   |    7 +-
 app/Models/PodcastModel.php                   |    5 +-
 app/Views/episode/create.php                  |  105 +
 app/Views/episode/view.php                    |   16 +
 app/Views/episodes/create.php                 |   91 -
 app/Views/home.php                            |    8 +-
 app/Views/layouts/default.php                 |    2 +-
 app/Views/{podcasts => podcast}/create.php    |   66 +-
 app/Views/{podcasts => podcast}/view.php      |   35 +-
 composer.lock                                 | 4208 +++++++++--------
 docs/setup-development.md                     |    2 +-
 34 files changed, 2847 insertions(+), 2263 deletions(-)
 rename app/Controllers/{Episodes.php => Episode.php} (76%)
 create mode 100644 app/Controllers/Feed.php
 rename app/Controllers/{Podcasts.php => Podcast.php} (82%)
 delete mode 100644 app/Helpers/database_helper.php
 create mode 100644 app/Helpers/rss_helper.php
 rename app/Language/en/{Episodes.php => Episode.php} (82%)
 rename app/Language/en/{Podcasts.php => Podcast.php} (97%)
 create mode 100644 app/Libraries/SimpleRSSElement.php
 create mode 100644 app/Views/episode/create.php
 create mode 100644 app/Views/episode/view.php
 delete mode 100644 app/Views/episodes/create.php
 rename app/Views/{podcasts => podcast}/create.php (57%)
 rename app/Views/{podcasts => podcast}/view.php (58%)

diff --git a/app/Config/App.php b/app/Config/App.php
index 6bb6cb457e..a12599ff0e 100644
--- a/app/Config/App.php
+++ b/app/Config/App.php
@@ -100,7 +100,7 @@ class App extends BaseConfig
 	| dates with the date helper, and can be retrieved through app_timezone()
 	|
 	*/
-    public $appTimezone = 'America/Chicago';
+    public $appTimezone = 'UTC';
 
     /*
 	|--------------------------------------------------------------------------
diff --git a/app/Config/Routes.php b/app/Config/Routes.php
index f87b1d60bb..435af19d5a 100644
--- a/app/Config/Routes.php
+++ b/app/Config/Routes.php
@@ -22,7 +22,7 @@ $routes->setDefaultMethod('index');
 $routes->setTranslateURIDashes(false);
 $routes->set404Override();
 $routes->setAutoRoute(false);
-$routes->addPlaceholder('podcastSlug', '@[a-z0-9\_]{1,191}');
+$routes->addPlaceholder('podcastName', '[a-z0-9\_]{1,191}');
 $routes->addPlaceholder('episodeSlug', '[a-z0-9\-]{1,191}');
 
 /**
@@ -34,24 +34,27 @@ $routes->addPlaceholder('episodeSlug', '[a-z0-9\-]{1,191}');
 // We get a performance increase by specifying the default
 // route since we don't have to scan directories.
 $routes->get('/', 'Home::index', ['as' => 'home']);
-$routes->add('new-podcast', 'Podcasts::create', ['as' => 'podcasts_create']);
+$routes->add('new-podcast', 'Podcast::create', ['as' => 'podcast_create']);
 
-$routes->group('(:podcastSlug)', function ($routes) {
-    $routes->add('/', 'Podcasts::view/$1', ['as' => 'podcasts_view']);
-    $routes->add('new-episode', 'Episodes::create/$1', [
-        'as' => 'episodes_create',
+$routes->group('@(:podcastName)', function ($routes) {
+    $routes->add('/', 'Podcast::view/$1', ['as' => 'podcast_view']);
+    $routes->add('feed.xml', 'Feed/$1', ['as' => 'podcast_feed']);
+    $routes->add('new-episode', 'Episode::create/$1', [
+        'as' => 'episode_create',
     ]);
-    $routes->add('(:episodeSlug)', 'Episodes::view/$1/$2', [
-        'as' => 'episodes_view',
+    $routes->add('episodes/(:episodeSlug)', 'Episode::view/$1/$2', [
+        'as' => 'episode_view',
     ]);
 });
 
 // Route for podcast audio file analytics (/stats/podcast_id/episode_id/podcast_folder/filename.mp3)
-$routes->add('/stats/(:num)/(:num)/(:any)', 'Analytics::hit/$1/$2/$3');
+$routes->add('stats/(:num)/(:num)/(:any)', 'Analytics::hit/$1/$2/$3', [
+    'as' => 'analytics_hit',
+]);
 
 // Show the Unknown UserAgents
-$routes->add('/.well-known/unknown-useragents', 'UnknownUserAgents');
-$routes->add('/.well-known/unknown-useragents/(:num)', 'UnknownUserAgents/$1');
+$routes->add('.well-known/unknown-useragents', 'UnknownUserAgents');
+$routes->add('.well-known/unknown-useragents/(:num)', 'UnknownUserAgents/$1');
 
 /**
  * --------------------------------------------------------------------
diff --git a/app/Config/Toolbar.php b/app/Config/Toolbar.php
index ba4087a61d..639d431ab2 100644
--- a/app/Config/Toolbar.php
+++ b/app/Config/Toolbar.php
@@ -21,7 +21,7 @@ class Toolbar extends BaseConfig
         \CodeIgniter\Debug\Toolbar\Collectors\Database::class,
         \CodeIgniter\Debug\Toolbar\Collectors\Logs::class,
         \CodeIgniter\Debug\Toolbar\Collectors\Views::class,
-        // \CodeIgniter\Debug\Toolbar\Collectors\Cache::class,
+        \CodeIgniter\Debug\Toolbar\Collectors\Cache::class,
         \CodeIgniter\Debug\Toolbar\Collectors\Files::class,
         \CodeIgniter\Debug\Toolbar\Collectors\Routes::class,
         \CodeIgniter\Debug\Toolbar\Collectors\Events::class,
diff --git a/app/Controllers/BaseController.php b/app/Controllers/BaseController.php
index e2400f352a..5e3a8c0209 100644
--- a/app/Controllers/BaseController.php
+++ b/app/Controllers/BaseController.php
@@ -50,7 +50,7 @@ class BaseController extends Controller
         set_user_session_referer();
     }
 
-    protected function stats($postcast_id)
+    protected static function triggerWebpageHit($postcast_id)
     {
         webpage_hit($postcast_id);
     }
diff --git a/app/Controllers/Episodes.php b/app/Controllers/Episode.php
similarity index 76%
rename from app/Controllers/Episodes.php
rename to app/Controllers/Episode.php
index 90b1d5e766..a57fb84806 100644
--- a/app/Controllers/Episodes.php
+++ b/app/Controllers/Episode.php
@@ -10,15 +10,17 @@ namespace App\Controllers;
 use App\Models\EpisodeModel;
 use App\Models\PodcastModel;
 
-class Episodes extends BaseController
+helper('podcast');
+
+class Episode extends BaseController
 {
-    public function create($podcast_slug)
+    public function create($podcast_name)
     {
         helper(['form', 'database', 'media', 'id3']);
 
         $episode_model = new EpisodeModel();
         $podcast_model = new PodcastModel();
-        $podcast_name = substr($podcast_slug, 1);
+
         $podcast = $podcast_model->where('name', $podcast_name)->first();
 
         if (
@@ -33,13 +35,9 @@ class Episodes extends BaseController
         ) {
             $data = [
                 'podcast' => $podcast,
-                'episode_types' => field_enums(
-                    $episode_model->prefixTable('episodes'),
-                    'type'
-                ),
             ];
 
-            echo view('episodes/create', $data);
+            echo view('episode/create', $data);
         } else {
             $episode_slug = $this->request->getVar('slug');
 
@@ -49,7 +47,7 @@ class Episodes extends BaseController
             $image = $this->request->getFile('image');
 
             // By default, the episode's image path is set to the podcast's
-            $image_path = $podcast->image;
+            $image_path = $podcast->image_uri;
 
             // check whether the user has inputted an image and store it
             if ($image->isValid()) {
@@ -81,20 +79,21 @@ class Episodes extends BaseController
                 'podcast_id' => $podcast->id,
                 'title' => $this->request->getVar('title'),
                 'slug' => $episode_slug,
-                'enclosure_url' => $episode_path,
+                'enclosure_uri' => $episode_path,
                 'enclosure_length' => $episode_file->getSize(),
                 'enclosure_type' => $episode_file_metadata['mime_type'],
-                'guid' => $podcast_slug . '/' . $episode_slug,
                 'pub_date' => $this->request->getVar('pub_date'),
                 'description' => $this->request->getVar('description'),
                 'duration' => $episode_file_metadata['playtime_seconds'],
-                'image' => $image_path,
+                'image_uri' => $image_path,
                 'explicit' => $this->request->getVar('explicit') or false,
                 'number' => $this->request->getVar('episode_number'),
                 'season_number' => $this->request->getVar('season_number')
                     ? $this->request->getVar('season_number')
                     : null,
                 'type' => $this->request->getVar('type'),
+                'author_name' => $this->request->getVar('author_name'),
+                'author_email' => $this->request->getVar('author_email'),
                 'block' => $this->request->getVar('block') or false,
             ]);
 
@@ -103,30 +102,25 @@ class Episodes extends BaseController
             $episode_file = write_file_tags($podcast, $episode);
 
             return redirect()->to(
-                base_url(
-                    route_to(
-                        'episodes_view',
-                        '/@' . $podcast_name,
-                        $episode_slug
-                    )
-                )
+                base_url(route_to('episode_view', $podcast_name, $episode_slug))
             );
         }
     }
 
-    public function view($podcast_slug, $episode_slug)
+    public function view($podcast_name, $episode_slug)
     {
         $podcast_model = new PodcastModel();
         $episode_model = new EpisodeModel();
 
+        $podcast = $podcast_model->where('name', $podcast_name)->first();
+        $episode = $episode_model->where('slug', $episode_slug)->first();
+
         $data = [
-            'podcast' => $podcast_model
-                ->where('name', substr($podcast_slug, 1))
-                ->first(),
-            'episode' => $episode_model->where('slug', $episode_slug)->first(),
+            'podcast' => $podcast,
+            'episode' => $episode,
         ];
-        self::stats($data['podcast']->id);
+        self::triggerWebpageHit($data['podcast']->id);
 
-        return view('episodes/view.php', $data);
+        return view('episode/view.php', $data);
     }
 }
diff --git a/app/Controllers/Feed.php b/app/Controllers/Feed.php
new file mode 100644
index 0000000000..e76eb19924
--- /dev/null
+++ b/app/Controllers/Feed.php
@@ -0,0 +1,22 @@
+<?php
+
+namespace App\Controllers;
+
+use App\Models\PodcastModel;
+use CodeIgniter\Controller;
+
+class Feed extends Controller
+{
+    public function index($podcast_name)
+    {
+        helper('rss');
+
+        $podcast_model = new PodcastModel();
+        $podcast = $podcast_model->where('name', $podcast_name)->first();
+
+        // The page cache is set to a decade so it is deleted manually upon podcast update
+        $this->cachePage(DECADE);
+
+        return $this->response->setXML(get_rss_feed($podcast));
+    }
+}
diff --git a/app/Controllers/Home.php b/app/Controllers/Home.php
index e68ff7eb49..f87459b6fb 100644
--- a/app/Controllers/Home.php
+++ b/app/Controllers/Home.php
@@ -14,8 +14,18 @@ class Home extends BaseController
     public function index()
     {
         $model = new PodcastModel();
-        $data = ['podcasts' => $model->findAll()];
 
+        $all_podcasts = $model->findAll();
+
+        // check if there's only one podcast to redirect user to it
+        if (count($all_podcasts) == 1) {
+            return redirect()->to(
+                base_url(route_to('podcast_view', $all_podcasts[0]->name))
+            );
+        }
+
+        // default behavior: list all podcasts on home page
+        $data = ['podcasts' => $all_podcasts];
         return view('home', $data);
     }
 }
diff --git a/app/Controllers/Podcasts.php b/app/Controllers/Podcast.php
similarity index 82%
rename from app/Controllers/Podcasts.php
rename to app/Controllers/Podcast.php
index eb29154ec2..a3c4c6c359 100644
--- a/app/Controllers/Podcasts.php
+++ b/app/Controllers/Podcast.php
@@ -4,16 +4,14 @@
  * @license    https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3
  * @link       https://castopod.org/
  */
-
 namespace App\Controllers;
 
-use App\Entities\Podcast;
 use App\Models\CategoryModel;
 use App\Models\EpisodeModel;
 use App\Models\LanguageModel;
 use App\Models\PodcastModel;
 
-class Podcasts extends BaseController
+class Podcast extends BaseController
 {
     public function create()
     {
@@ -39,30 +37,27 @@ class Podcasts extends BaseController
                 'browser_lang' => get_browser_language(
                     $this->request->getServer('HTTP_ACCEPT_LANGUAGE')
                 ),
-                'podcast_types' => field_enums(
-                    $podcast_model->prefixTable('podcasts'),
-                    'type'
-                ),
             ];
 
-            echo view('podcasts/create', $data);
+            echo view('podcast/create', $data);
         } else {
             $image = $this->request->getFile('image');
             $podcast_name = $this->request->getVar('name');
             $image_path = save_podcast_media($image, $podcast_name, 'cover');
 
-            $podcast = new Podcast([
+            $podcast = new \App\Entities\Podcast([
                 'title' => $this->request->getVar('title'),
                 'name' => $podcast_name,
                 'description' => $this->request->getVar('description'),
                 'episode_description_footer' => $this->request->getVar(
                     'episode_description_footer'
                 ),
-                'image' => $image_path,
+                'image_uri' => $image_path,
                 'language' => $this->request->getVar('language'),
                 'category' => $this->request->getVar('category'),
                 'explicit' => $this->request->getVar('explicit') or false,
-                'author' => $this->request->getVar('author'),
+                'author_name' => $this->request->getVar('author_name'),
+                'author_email' => $this->request->getVar('author_email'),
                 'owner_name' => $this->request->getVar('owner_name'),
                 'owner_email' => $this->request->getVar('owner_email'),
                 'type' => $this->request->getVar('type'),
@@ -77,18 +72,16 @@ class Podcasts extends BaseController
             $podcast_model->save($podcast);
 
             return redirect()->to(
-                base_url(route_to('podcasts_view', '@' . $podcast_name))
+                base_url(route_to('podcast_view', $podcast->name))
             );
         }
     }
 
-    public function view($slug)
+    public function view($podcast_name)
     {
         $podcast_model = new PodcastModel();
         $episode_model = new EpisodeModel();
 
-        $podcast_name = substr($slug, 1);
-
         $podcast = $podcast_model->where('name', $podcast_name)->first();
         $data = [
             'podcast' => $podcast,
@@ -96,8 +89,8 @@ class Podcasts extends BaseController
                 ->where('podcast_id', $podcast->id)
                 ->findAll(),
         ];
-        self::stats($podcast->id);
+        self::triggerWebpageHit($podcast->id);
 
-        return view('podcasts/view', $data);
+        return view('podcast/view', $data);
     }
 }
diff --git a/app/Database/Migrations/2020-05-29-152000_add_categories.php b/app/Database/Migrations/2020-05-29-152000_add_categories.php
index c9e5604a93..717adc423e 100644
--- a/app/Database/Migrations/2020-05-29-152000_add_categories.php
+++ b/app/Database/Migrations/2020-05-29-152000_add_categories.php
@@ -29,8 +29,7 @@ class AddCategories extends Migration
             ],
             'code' => [
                 'type' => 'VARCHAR',
-                'constraint' => 1024,
-                'unique' => true,
+                'constraint' => 191,
             ],
             'apple_category' => [
                 'type' => 'VARCHAR',
@@ -42,6 +41,7 @@ class AddCategories extends Migration
             ],
         ]);
         $this->forge->addKey('id', true);
+        $this->forge->addUniqueKey('code');
         $this->forge->addForeignKey('parent_id', 'categories', 'id');
         $this->forge->createTable('categories');
     }
diff --git a/app/Database/Migrations/2020-05-30-101500_add_podcasts.php b/app/Database/Migrations/2020-05-30-101500_add_podcasts.php
index 6598d0697b..fa52ee51fd 100644
--- a/app/Database/Migrations/2020-05-30-101500_add_podcasts.php
+++ b/app/Database/Migrations/2020-05-30-101500_add_podcasts.php
@@ -41,7 +41,7 @@ class AddPodcasts extends Migration
                 'comment' =>
                     'The show description. Where description is text containing one or more sentences describing your podcast to potential listeners. The maximum amount of text allowed for this tag is 4000 characters. To include links in your description or rich HTML, adhere to the following technical guidelines: enclose all portions of your XML that contain embedded HTML in a CDATA section to prevent formatting issues, and to ensure proper link functionality.',
             ],
-            'image' => [
+            'image_uri' => [
                 'type' => 'VARCHAR',
                 'constraint' => 1024,
                 'comment' =>
@@ -67,11 +67,18 @@ class AddPodcasts extends Migration
                 'comment' =>
                     'The podcast parental advisory information.  The explicit value can be one of the following:      True: If you specify true, indicating the presence of explicit content, Apple Podcasts displays an Explicit parental advisory graphic for your podcast.      Podcasts containing explicit material aren’t available in some Apple Podcasts territories.      False: If you specify false, indicating that your podcast doesn’t contain explicit language or adult content, Apple Podcasts displays a Clean parental advisory graphic for your podcast.',
             ],
-            'author' => [
+            'author_name' => [
                 'type' => 'VARCHAR',
                 'constraint' => 1024,
                 'comment' =>
-                    'The group responsible for creating the show.  Show author most often refers to the parent company or network of a podcast, but it can also be used to identify the host(s) if none exists.  Author information is especially useful if a company or organization publishes multiple podcasts. Providing this information will allow listeners to see all shows created by the same entity.',
+                    'Name of the group responsible for creating the show.  Show author most often refers to the parent company or network of a podcast, but it can also be used to identify the host(s) if none exists.  Author information is especially useful if a company or organization publishes multiple podcasts. Providing this information will allow listeners to see all shows created by the same entity.',
+                'null' => true,
+            ],
+            'author_email' => [
+                'type' => 'VARCHAR',
+                'constraint' => 1024,
+                'owner_email' =>
+                    'Email of the group responsible for creating the show.  Show author most often refers to the parent company or network of a podcast, but it can also be used to identify the host(s) if none exists.  Author information is especially useful if a company or organization publishes multiple podcasts. Providing this information will allow listeners to see all shows created by the same entity.',
                 'null' => true,
             ],
             'owner_name' => [
diff --git a/app/Database/Migrations/2020-06-05-170000_add_episodes.php b/app/Database/Migrations/2020-06-05-170000_add_episodes.php
index e6363dc529..f842a81b34 100644
--- a/app/Database/Migrations/2020-06-05-170000_add_episodes.php
+++ b/app/Database/Migrations/2020-06-05-170000_add_episodes.php
@@ -41,11 +41,11 @@ class AddEpisodes extends Migration
                 'constraint' => 191,
                 'comment' => 'Episode slug for URLs',
             ],
-            'enclosure_url' => [
+            'enclosure_uri' => [
                 'type' => 'VARCHAR',
                 'constraint' => 1024,
                 'comment' =>
-                    'The URL attribute points to your podcast media file. The file extension specified within the URL attribute determines whether or not content appears in the podcast directory. Supported file formats include M4A, MP3, MOV, MP4, M4V, and PDF.',
+                    'The URI attribute points to your podcast media file. The file extension specified within the URI attribute determines whether or not content appears in the podcast directory. Supported file formats include M4A, MP3, MOV, MP4, M4V, and PDF.',
             ],
             'enclosure_length' => [
                 'type' => 'INT',
@@ -69,7 +69,7 @@ class AddEpisodes extends Migration
             'pub_date' => [
                 'type' => 'DATETIME',
                 'comment' =>
-                    'The date and time when an episode was released. Format the date using the RFC 2822 specifications. For example: Wed, 15 Jun 2019 19:00:00 GMT.',
+                    'The date and time when an episode was released. Format the date using the RFC 2822 specifications. For example: Wed, 15 Jun 2019 19:00:00 UTC.',
             ],
             'description' => [
                 'type' => 'TEXT',
@@ -84,7 +84,7 @@ class AddEpisodes extends Migration
                 'comment' =>
                     'The duration of an episode. Different duration formats are accepted however it is recommended to convert the length of the episode into seconds.',
             ],
-            'image' => [
+            'image_uri' => [
                 'type' => 'VARCHAR',
                 'constraint' => 1024,
                 'comment' =>
@@ -112,6 +112,20 @@ class AddEpisodes extends Migration
                 'comment' =>
                     'The episode season number. If an episode is within a season use this tag. Where season is a non-zero integer (1, 2, 3, etc.) representing your season number. To allow the season feature for shows containing a single season, if only one season exists in the RSS feed, Apple Podcasts doesn’t display a season number. When you add a second season to the RSS feed, Apple Podcasts displays the season numbers.',
             ],
+            'author_name' => [
+                'type' => 'VARCHAR',
+                'constraint' => 1024,
+                'comment' =>
+                    'Name of the group responsible for creating the episode.  Episode author most often refers to the parent company or network of a podcast, but it can also be used to identify the host(s) if none exists.  Author information is especially useful if a company or organization publishes multiple podcasts. Providing this information will allow listeners to see all episodes created by the same entity.',
+                'null' => true,
+            ],
+            'author_email' => [
+                'type' => 'VARCHAR',
+                'constraint' => 1024,
+                'owner_email' =>
+                    'Email of the group responsible for creating the episode.  Episode author most often refers to the parent company or network of a podcast, but it can also be used to identify the host(s) if none exists.  Author information is especially useful if a company or organization publishes multiple podcasts. Providing this information will allow listeners to see all episodes created by the same entity.',
+                'null' => true,
+            ],
             'type' => [
                 'type' => 'ENUM',
                 'constraint' => ['full', 'trailer', 'bonus'],
diff --git a/app/Entities/Category.php b/app/Entities/Category.php
index d15e52d839..2de786198f 100644
--- a/app/Entities/Category.php
+++ b/app/Entities/Category.php
@@ -7,13 +7,27 @@
 
 namespace App\Entities;
 
+use App\Models\CategoryModel;
 use CodeIgniter\Entity;
 
 class Category extends Entity
 {
+    protected $parent;
+
     protected $casts = [
         'parent_id' => 'integer',
+        'code' => 'string',
         'apple_category' => 'string',
         'google_category' => 'string',
     ];
+
+    public function getParent()
+    {
+        $category_model = new CategoryModel();
+        $parent_id = $this->attributes['parent_id'];
+
+        return $parent_id != 0
+            ? $category_model->find($this->attributes['parent_id'])
+            : null;
+    }
 }
diff --git a/app/Entities/Episode.php b/app/Entities/Episode.php
index 48ac268d6f..21f9cfa0fd 100644
--- a/app/Entities/Episode.php
+++ b/app/Entities/Episode.php
@@ -7,25 +7,85 @@
 
 namespace App\Entities;
 
+use App\Models\PodcastModel;
 use CodeIgniter\Entity;
 
 class Episode extends Entity
 {
+    protected $link;
+    protected $image_media_path;
+    protected $image_url;
+    protected $enclosure_media_path;
+    protected $enclosure_url;
+    protected $guid;
+    protected $podcast;
+
     protected $casts = [
         'slug' => 'string',
         'title' => 'string',
-        'enclosure_url' => 'string',
+        'enclosure_uri' => 'string',
         'enclosure_length' => 'integer',
         'enclosure_type' => 'string',
-        'guid' => 'string',
         'pub_date' => 'datetime',
         'description' => 'string',
         'duration' => 'integer',
-        'image' => 'string',
+        'image_uri' => 'string',
+        'author_name' => '?string',
+        'author_email' => '?string',
         'explicit' => 'boolean',
         'number' => 'integer',
         'season_number' => '?integer',
         'type' => 'string',
         'block' => 'boolean',
     ];
+
+    public function getImageMediaPath()
+    {
+        return media_path($this->attributes['image_uri']);
+    }
+
+    public function getImageUrl()
+    {
+        return media_url($this->attributes['image_uri']);
+    }
+
+    public function getEnclosureMediaPath()
+    {
+        return media_path($this->attributes['enclosure_uri']);
+    }
+
+    public function getEnclosureUrl()
+    {
+        return base_url(
+            route_to(
+                'analytics_hit',
+                $this->attributes['podcast_id'],
+                $this->attributes['id'],
+                $this->attributes['enclosure_uri']
+            )
+        );
+    }
+
+    public function getLink()
+    {
+        return base_url(
+            route_to(
+                'episode_view',
+                $this->getPodcast()->name,
+                $this->attributes['slug']
+            )
+        );
+    }
+
+    public function getGuid()
+    {
+        return $this->getLink();
+    }
+
+    public function getPodcast()
+    {
+        $podcast_model = new PodcastModel();
+
+        return $podcast_model->find($this->attributes['podcast_id']);
+    }
 }
diff --git a/app/Entities/Podcast.php b/app/Entities/Podcast.php
index 4bbd6de60e..5b623094cb 100644
--- a/app/Entities/Podcast.php
+++ b/app/Entities/Podcast.php
@@ -7,27 +7,57 @@
 
 namespace App\Entities;
 
+use App\Models\EpisodeModel;
 use CodeIgniter\Entity;
 
 class Podcast extends Entity
 {
+    protected $link;
+    protected $image_url;
+    protected $episodes;
+
     protected $casts = [
         'id' => 'integer',
         'title' => 'string',
         'name' => 'string',
         'description' => 'string',
-        'image' => 'string',
+        'image_uri' => 'string',
         'language' => 'string',
         'category' => 'string',
         'explicit' => 'boolean',
-        'author' => '?string',
+        'author_name' => '?string',
+        'author_email' => '?string',
         'owner_name' => '?string',
         'owner_email' => '?string',
-        'type' => '?string',
+        'type' => 'string',
         'copyright' => '?string',
         'block' => 'boolean',
         'complete' => 'boolean',
         'episode_description_footer' => '?string',
         'custom_html_head' => '?string',
     ];
+
+    public function getImageUrl()
+    {
+        return media_url($this->attributes['image_uri']);
+    }
+
+    public function getLink()
+    {
+        return base_url(route_to('podcast_view', $this->attributes['name']));
+    }
+
+    public function getFeedUrl()
+    {
+        return base_url(route_to('podcast_feed', $this->attributes['name']));
+    }
+
+    public function getEpisodes()
+    {
+        $episode_model = new EpisodeModel();
+
+        return $episode_model
+            ->where('podcast_id', $this->attributes['id'])
+            ->findAll();
+    }
 }
diff --git a/app/Helpers/database_helper.php b/app/Helpers/database_helper.php
deleted file mode 100644
index bd0e07bfb8..0000000000
--- a/app/Helpers/database_helper.php
+++ /dev/null
@@ -1,33 +0,0 @@
-<?php
-/**
- * @copyright  2020 Podlibre
- * @license    https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3
- * @link       https://castopod.org/
- */
-
-/**
- * Get all possible enum values for a table field
- *
- * @param string $table
- * @param string $field
- *
- * @return array $enums
- */
-function field_enums($table = '', $field = '')
-{
-    $enums = [];
-    if ($table == '' || $field == '') {
-        return $enums;
-    }
-    $db = \Config\Database::connect();
-    preg_match_all(
-        "/'(.*?)'/",
-        $db->query("SHOW COLUMNS FROM {$table} LIKE '{$field}'")->getRow()
-            ->Type,
-        $matches
-    );
-    foreach ($matches[1] as $value) {
-        $enums[$value] = $value;
-    }
-    return $enums;
-}
diff --git a/app/Helpers/id3_helper.php b/app/Helpers/id3_helper.php
index 0c5ade85f3..d8e96fcd43 100644
--- a/app/Helpers/id3_helper.php
+++ b/app/Helpers/id3_helper.php
@@ -44,20 +44,20 @@ function write_file_tags($podcast, $episode)
 
     // Initialize getID3 tag-writing module
     $tagwriter = new WriteTags();
-    $tagwriter->filename = media_path($episode->enclosure_url);
+    $tagwriter->filename = $episode->enclosure_media_path;
 
     // set various options (optional)
     $tagwriter->tagformats = ['id3v2.4'];
     $tagwriter->tag_encoding = $TextEncoding;
 
-    $cover = new \CodeIgniter\Files\File(media_path($episode->image));
+    $cover = new \CodeIgniter\Files\File($episode->image_media_path);
 
     $APICdata = file_get_contents($cover->getRealPath());
 
     // TODO: variables used for podcast specific tags
-    // $podcast_url = base_url('@' . $podcast->name);
-    // $podcast_feed_url = base_url('@' . $podcast->name . '/feed.xml');
-    // $episode_media_url = media_url($podcast->name . '/' . $episode->slug);
+    // $podcast_url = $podcast->link;
+    // $podcast_feed_url = $podcast->feed_url;
+    // $episode_media_url = $episode->link;
 
     // populate data array
     $TagData = [
diff --git a/app/Helpers/media_helper.php b/app/Helpers/media_helper.php
index 32845057ee..09edaf196f 100644
--- a/app/Helpers/media_helper.php
+++ b/app/Helpers/media_helper.php
@@ -12,7 +12,7 @@
  * @param string $podcast_name
  * @param string $file_name
  *
- * @return string The absolute path of the file in media root
+ * @return string The episode's file path in media root
  */
 function save_podcast_media($file, $podcast_name, $media_name)
 {
diff --git a/app/Helpers/rss_helper.php b/app/Helpers/rss_helper.php
new file mode 100644
index 0000000000..8b61f3b131
--- /dev/null
+++ b/app/Helpers/rss_helper.php
@@ -0,0 +1,165 @@
+<?php
+/**
+ * @copyright  2020 Podlibre
+ * @license    https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3
+ * @link       https://castopod.org/
+ */
+
+use App\Models\CategoryModel;
+use CodeIgniter\I18n\Time;
+
+/**
+ * Generates the rss feed for a given podcast entity
+ *
+ * @param App\Entities\Podcast $podcast
+ * @return string rss feed as xml
+ */
+function get_rss_feed($podcast)
+{
+    $category_model = new CategoryModel();
+
+    $episodes = $podcast->episodes;
+
+    $podcast_category = $category_model
+        ->where('code', $podcast->category)
+        ->first();
+
+    $itunes_namespace = 'http://www.itunes.com/dtds/podcast-1.0.dtd';
+
+    $rss = new SimpleRSSElement(
+        "<?xml version='1.0' encoding='utf-8'?><rss version='2.0' xmlns:itunes='$itunes_namespace' xmlns:content='http://purl.org/rss/1.0/modules/content/'></rss>"
+    );
+
+    $channel = $rss->addChild('channel');
+
+    $atom_link = $channel->addChild(
+        'atom:link',
+        null,
+        'http://www.w3.org/2005/Atom'
+    );
+    $atom_link->addAttribute('href', $podcast->feed_url);
+    $atom_link->addAttribute('rel', 'self');
+    $atom_link->addAttribute('type', 'application/rss+xml');
+
+    // the last build date corresponds to the creation of the feed.xml cache
+    $channel->addChild(
+        'lastBuildDate',
+        (new Time('now'))->format(DATE_RFC1123)
+    );
+    $channel->addChild(
+        'generator',
+        'Castopod 0.0.0-development - https://castopod.org'
+    );
+    $channel->addChild('docs', 'https://cyber.harvard.edu/rss/rss.html');
+
+    $channel->addChild('title', $podcast->title);
+    $channel->addChildWithCDATA('description', $podcast->description);
+    $itunes_image = $channel->addChild('image', null, $itunes_namespace);
+    $itunes_image->addAttribute('href', $podcast->image_url);
+    $channel->addChild('language', $podcast->language);
+
+    $itunes_category = $channel->addChild('category', null, $itunes_namespace);
+    $itunes_category->addAttribute(
+        'text',
+        $podcast_category->parent
+            ? $podcast_category->parent->apple_category
+            : $podcast_category->apple_category
+    );
+
+    if ($podcast_category->parent) {
+        $itunes_category_child = $itunes_category->addChild(
+            'category',
+            null,
+            $itunes_namespace
+        );
+        $itunes_category_child->addAttribute(
+            'text',
+            $podcast_category->apple_category
+        );
+        $channel->addChild(
+            'category',
+            $podcast_category->parent->apple_category
+        );
+    }
+    $channel->addChild('category', $podcast_category->apple_category);
+
+    $channel->addChild(
+        'explicit',
+        $podcast->explicit ? 'true' : 'false',
+        $itunes_namespace
+    );
+
+    $podcast->author_name &&
+        $channel->addChild('author', $podcast->author_name, $itunes_namespace);
+    $channel->addChild('link', $podcast->link);
+
+    if ($podcast->owner_name || $podcast->owner_email) {
+        $owner = $channel->addChild('owner', null, $itunes_namespace);
+        $podcast->owner_name &&
+            $owner->addChild('name', $podcast->owner_name, $itunes_namespace);
+        $podcast->owner_email &&
+            $owner->addChild('email', $podcast->owner_email, $itunes_namespace);
+    }
+
+    $channel->addChild('type', $podcast->type, $itunes_namespace);
+    $podcast->copyright && $channel->addChild('copyright', $podcast->copyright);
+    $podcast->block && $channel->addChild('block', 'Yes', $itunes_namespace);
+    $podcast->complete &&
+        $channel->addChild('complete', 'Yes', $itunes_namespace);
+
+    $image = $channel->addChild('image');
+    $image->addChild('url', $podcast->image_url);
+    $image->addChild('title', $podcast->title);
+    $image->addChild('link', $podcast->link);
+
+    foreach ($episodes as $episode) {
+        $item = $channel->addChild('item');
+        $item->addChild('title', $episode->title);
+        $enclosure = $item->addChild('enclosure');
+        $enclosure->addAttribute('url', $episode->enclosure_url);
+        $enclosure->addAttribute('length', $episode->enclosure_length);
+        $enclosure->addAttribute('type', $episode->enclosure_type);
+
+        $item->addChild('guid', $episode->guid);
+        $item->addChild('pubDate', $episode->pub_date->format(DATE_RFC1123));
+        $item->addChildWithCDATA('description', $episode->description);
+        $item->addChild('duration', $episode->duration, $itunes_namespace);
+        $item->addChild('link', $episode->link);
+        $episode_itunes_image = $item->addChild(
+            'image',
+            null,
+            $itunes_namespace
+        );
+        $episode_itunes_image->addAttribute('href', $episode->image_url);
+        $item->addChild(
+            'explicit',
+            $episode->explicit ? 'true' : 'false',
+            $itunes_namespace
+        );
+
+        if ($episode->author_email || $episode->author_name) {
+            $item->addChild(
+                'author',
+                $episode->author_name
+                    ? $episode->author_email .
+                        ' (' .
+                        $episode->author_name .
+                        ')'
+                    : $episode->author_email
+            );
+        }
+
+        $item->addChild('episode', $episode->number, $itunes_namespace);
+        $episode->season_number &&
+            $item->addChild(
+                'season',
+                $episode->season_number,
+                $itunes_namespace
+            );
+        $item->addChild('episodeType', $episode->type, $itunes_namespace);
+
+        $episode->block && $item->addChild('block', 'Yes', $itunes_namespace);
+    }
+
+    return $rss->asXML();
+}
diff --git a/app/Helpers/url_helper.php b/app/Helpers/url_helper.php
index 858f3de72e..5b3ca930e4 100644
--- a/app/Helpers/url_helper.php
+++ b/app/Helpers/url_helper.php
@@ -16,23 +16,3 @@ function media_url($uri = '', string $protocol = null): string
 {
     return base_url(config('App')->mediaRoot . '/' . $uri, $protocol);
 }
-
-/**
- * Return the podcast URL to use in views
- *
- * @param  mixed  $uri      URI string or array of URI segments
- * @param  string $protocol
- * @return string
- */
-function podcast_url(
-    $podcast_id = 1,
-    $episode_id = 1,
-    $podcast_name = '',
-    $uri = '',
-    string $protocol = null
-): string {
-    return base_url(
-        "/stats/$podcast_id/$episode_id/$podcast_name/$uri",
-        $protocol
-    );
-}
diff --git a/app/Language/en/Episodes.php b/app/Language/en/Episode.php
similarity index 82%
rename from app/Language/en/Episodes.php
rename to app/Language/en/Episode.php
index 319b1f8d0f..318044441d 100644
--- a/app/Language/en/Episodes.php
+++ b/app/Language/en/Episode.php
@@ -1,6 +1,7 @@
 <?
 
 return [
+    'back_to_podcast' => 'Go back to podcast',
     'create' => 'Add an episode',
     'form' => [
         'file' => 'Audio file',
@@ -10,6 +11,8 @@ return [
         'pub_date' => 'Publication date',
         'image' => 'Image',
         'explicit' => 'Explicit',
+        'author_name' => 'Author name',
+        'author_email' => 'Author email',
         'type' => [
             'label' => 'Type',
             'full' => 'Full',
diff --git a/app/Language/en/Podcasts.php b/app/Language/en/Podcast.php
similarity index 97%
rename from app/Language/en/Podcasts.php
rename to app/Language/en/Podcast.php
index af04529337..3da3747f1a 100644
--- a/app/Language/en/Podcasts.php
+++ b/app/Language/en/Podcast.php
@@ -11,7 +11,8 @@ return [
         'language' => 'Language',
         'category' => 'Category',
         'explicit' => 'Explicit',
-        'author' => 'Author',
+        'author_name' => 'Author name',
+        'author_email' => 'Author email',
         'owner_name' => 'Owner name',
         'owner_email' => 'Owner email',
         'type' => [
@@ -64,7 +65,7 @@ return [
         'courses' => 'Courses',
         'how_to' => 'How To',
         'language_learning' => 'Language Learning',
-        'self-improvement' => 'Self-Improvement',
+        'self_improvement' => 'Self-Improvement',
         'comedy_fiction' => 'Comedy Fiction',
         'drama' => 'Drama',
         'science_fiction' => 'Science Fiction',
diff --git a/app/Libraries/SimpleRSSElement.php b/app/Libraries/SimpleRSSElement.php
new file mode 100644
index 0000000000..c5211e9b6e
--- /dev/null
+++ b/app/Libraries/SimpleRSSElement.php
@@ -0,0 +1,27 @@
+<?php
+/**
+ * @copyright  2020 Podlibre
+ * @license    https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3
+ * @link       https://castopod.org/
+ */
+
+class SimpleRSSElement extends SimpleXMLElement
+{
+    /**
+     * Adds a child with $value inside CDATA
+     * @param unknown $name
+     * @param unknown $value
+     */
+    public function addChildWithCDATA($name, $value = null, $namespace = null)
+    {
+        $new_child = $this->addChild($name, null, $namespace);
+
+        if ($new_child !== null) {
+            $node = dom_import_simplexml($new_child);
+            $no = $node->ownerDocument;
+            $node->appendChild($no->createCDATASection($value));
+        }
+
+        return $new_child;
+    }
+}
diff --git a/app/Models/CategoryModel.php b/app/Models/CategoryModel.php
index 1013920c8e..69c3f9543e 100644
--- a/app/Models/CategoryModel.php
+++ b/app/Models/CategoryModel.php
@@ -14,7 +14,12 @@ class CategoryModel extends Model
     protected $table = 'categories';
     protected $primaryKey = 'id';
 
-    protected $allowedFields = ['apple_category', 'google_category'];
+    protected $allowedFields = [
+        'parent_id',
+        'code',
+        'apple_category',
+        'google_category',
+    ];
 
     protected $returnType = 'App\Entities\Category';
     protected $useSoftDeletes = false;
diff --git a/app/Models/EpisodeModel.php b/app/Models/EpisodeModel.php
index 268d7c4bb4..3c27ff79c8 100644
--- a/app/Models/EpisodeModel.php
+++ b/app/Models/EpisodeModel.php
@@ -18,17 +18,18 @@ class EpisodeModel extends Model
         'podcast_id',
         'title',
         'slug',
-        'enclosure_url',
+        'enclosure_uri',
         'enclosure_length',
         'enclosure_type',
-        'guid',
         'pub_date',
         'description',
         'duration',
-        'image',
+        'image_uri',
         'explicit',
         'number',
         'season_number',
+        'author_name',
+        'author_email',
         'type',
         'block',
     ];
diff --git a/app/Models/PodcastModel.php b/app/Models/PodcastModel.php
index 3fe1c70c2b..4dfb2cf890 100644
--- a/app/Models/PodcastModel.php
+++ b/app/Models/PodcastModel.php
@@ -20,11 +20,12 @@ class PodcastModel extends Model
         'name',
         'description',
         'episode_description_footer',
-        'image',
+        'image_uri',
         'language',
         'category',
         'explicit',
-        'author',
+        'author_name',
+        'author_email',
         'owner_name',
         'owner_email',
         'type',
diff --git a/app/Views/episode/create.php b/app/Views/episode/create.php
new file mode 100644
index 0000000000..ac267cd942
--- /dev/null
+++ b/app/Views/episode/create.php
@@ -0,0 +1,105 @@
+<?= $this->extend('layouts/default') ?>
+
+<?= $this->section('content') ?>
+
+<h1 class="mb-6 text-xl"><?= lang('Episode.create') ?></h1>
+
+<div class="mb-8">
+    <?= \Config\Services::validation()->listErrors() ?>
+</div>
+
+<?= form_open_multipart(route_to('episode_create', $podcast->name), [
+    'method' => 'post',
+    'class' => 'flex flex-col max-w-md',
+]) ?>
+<?= csrf_field() ?>
+
+<div class="flex flex-col mb-4">
+    <label for="episode_file"><?= lang('Episode.form.file') ?></label>
+    <input type="file" class="form-input" id="episode_file" name="episode_file" required accept=".mp3,.m4a" />
+</div>
+
+<div class="flex flex-col mb-4">
+    <label for="title"><?= lang('Episode.form.title') ?></label>
+    <input type="text" class="form-input" id="title" name="title" required />
+</div>
+
+<div class="flex flex-col mb-4">
+    <label for="slug"><?= lang('Episode.form.slug') ?></label>
+    <input type="text" class="form-input" id="slug" name="slug" required />
+</div>
+
+<div class="flex flex-col mb-4">
+    <label for="description"><?= lang('Episode.form.description') ?></label>
+    <textarea class="form-textarea" id="description" name="description" required></textarea>
+</div>
+
+<div class="flex flex-col mb-4">
+    <label for="pub_date"><?= lang('Episode.form.pub_date') ?></label>
+    <input type="date" class="form-input" id="pub_date" name="pub_date" value="<?= date(
+        'Y-m-d'
+    ) ?>" />
+</div>
+
+<div class="flex flex-col mb-4">
+    <label for="image"><?= lang('Episode.form.image') ?></label>
+    <input type="file" class="form-input" id="image" name="image" accept=".jpg,.jpeg,.png" />
+</div>
+
+<div class="flex flex-col mb-4">
+    <label for="episode_number"><?= lang(
+        'Episode.form.episode_number'
+    ) ?></label>
+    <input type="number" class="form-input" id="episode_number" name="episode_number" required />
+</div>
+
+<div class="flex flex-col mb-4">
+    <label for="season_number"><?= lang('Episode.form.season_number') ?></label>
+    <input type="number" class="form-input" id="season_number" name="season_number" />
+</div>
+
+<div class="inline-flex items-center mb-4">
+    <input type="checkbox" id="explicit" name="explicit" class="form-checkbox" />
+    <label for="explicit" class="pl-2"><?= lang(
+        'Episode.form.explicit'
+    ) ?></label>
+</div>
+
+<div class="flex flex-col mb-4">
+    <label for="author_name"><?= lang('Podcast.form.author_name') ?></label>
+    <input type="text" class="form-input" id="author_name" name="author_name" />
+</div>
+
+<div class="flex flex-col mb-4">
+    <label for="author_email"><?= lang('Podcast.form.author_email') ?></label>
+    <input type="email" class="form-input" id="author_email" name="author_email" />
+</div>
+
+<fieldset class="flex flex-col mb-4">
+    <legend><?= lang('Episode.form.type.label') ?></legend>
+    <label for="full" class="inline-flex items-center">
+        <input type="radio" class="form-radio" value="full" id="full" name="type" required checked />
+        <span class="ml-2"><?= lang('Episode.form.type.full') ?></span>  
+    </label>
+    <label for="trailer" class="inline-flex items-center">
+        <input type="radio" class="form-radio" value="trailer" id="trailer" name="type" required />
+        <span class="ml-2"><?= lang('Episode.form.type.trailer') ?></span>  
+    </label>
+    <label for="bonus" class="inline-flex items-center">
+        <input type="radio" class="form-radio" value="bonus" id="bonus" name="type" required />
+        <span class="ml-2"><?= lang('Episode.form.type.bonus') ?></span>  
+    </label>
+</fieldset>
+
+<div class="inline-flex items-center mb-4">
+    <input type="checkbox" id="block" name="block" class="form-checkbox" />
+    <label for="block" class="pl-2"><?= lang('Episode.form.block') ?></label>
+</div>
+
+<button type="submit" name="submit" class="self-end px-4 py-2 bg-gray-200"><?= lang(
+    'Episode.form.submit'
+) ?></button>
+<?= form_close() ?>
+
+
+<?= $this->endSection() ?>
diff --git a/app/Views/episode/view.php b/app/Views/episode/view.php
new file mode 100644
index 0000000000..855312b5f9
--- /dev/null
+++ b/app/Views/episode/view.php
@@ -0,0 +1,16 @@
+<?= $this->extend('layouts/default') ?>
+
+<?= $this->section('content') ?>
+
+<a class="underline hover:no-underline" href="<?= route_to(
+    'podcast_view',
+    $podcast->name
+) ?>">< <?= lang('Episode.back_to_podcast') ?></a>
+<h1 class="text-2xl font-semibold"><?= $episode->title ?></h1>
+<img src="<?= $episode->image_url ?>" alt="Episode cover"  class="object-cover w-40 h-40 mb-6" />
+<audio controls preload="none">
+  <source src="<?= $episode->enclosure_url ?>" type="<?= $episode->enclosure_type ?>">
+  Your browser does not support the audio tag.
+</audio>
+
+<?= $this->endSection() ?>
diff --git a/app/Views/episodes/create.php b/app/Views/episodes/create.php
deleted file mode 100644
index 1f23d23490..0000000000
--- a/app/Views/episodes/create.php
+++ /dev/null
@@ -1,91 +0,0 @@
-<?= $this->extend('layouts/default') ?>
-
-<?= $this->section('content') ?>
-
-<h1 class="mb-6 text-xl"><?= lang('Episodes.create') ?></h1>
-
-<div class="mb-8">
-    <?= \Config\Services::validation()->listErrors() ?>
-</div>
-
-<?= form_open_multipart(route_to('episodes_create', '@' . $podcast->name), [
-    'method' => 'post',
-    'class' => 'flex flex-col max-w-md',
-]) ?>
-<?= csrf_field() ?>
-
-<div class="flex flex-col mb-4">
-    <label for="episode_file"><?= lang('Episodes.form.file') ?></label>
-    <input type="file" class="form-input" id="episode_file" name="episode_file" required accept=".mp3,.m4a" />
-</div>
-
-<div class="flex flex-col mb-4">
-    <label for="title"><?= lang('Episodes.form.title') ?></label>
-    <input type="text" class="form-input" id="title" name="title" required />
-</div>
-
-<div class="flex flex-col mb-4">
-    <label for="slug"><?= lang('Episodes.form.slug') ?></label>
-    <input type="text" class="form-input" id="slug" name="slug" required />
-</div>
-
-<div class="flex flex-col mb-4">
-    <label for="description"><?= lang('Episodes.form.description') ?></label>
-    <textarea class="form-textarea" id="description" name="description" required></textarea>
-</div>
-
-<div class="flex flex-col mb-4">
-    <label for="pub_date"><?= lang('Episodes.form.pub_date') ?></label>
-    <input type="date" class="form-input" id="pub_date" name="pub_date" value="<?= date(
-        'Y-m-d'
-    ) ?>" />
-</div>
-
-<div class="flex flex-col mb-4">
-    <label for="image"><?= lang('Episodes.form.image') ?></label>
-    <input type="file" class="form-input" id="image" name="image" accept=".jpg,.jpeg,.png" />
-</div>
-
-<div class="flex flex-col mb-4">
-    <label for="episode_number"><?= lang(
-        'Episodes.form.episode_number'
-    ) ?></label>
-    <input type="number" class="form-input" id="episode_number" name="episode_number" required />
-</div>
-
-<div class="flex flex-col mb-4">
-    <label for="season_number"><?= lang(
-        'Episodes.form.season_number'
-    ) ?></label>
-    <input type="number" class="form-input" id="season_number" name="season_number" />
-</div>
-
-<div class="inline-flex items-center mb-4">
-    <input type="checkbox" id="explicit" name="explicit" class="form-checkbox" />
-    <label for="explicit" class="pl-2"><?= lang(
-        'Episodes.form.explicit'
-    ) ?></label>
-</div>
-
-<fieldset class="flex flex-col mb-4">
-    <legend><?= lang('Episodes.form.type.label') ?></legend>
-    <?php foreach ($episode_types as $type): ?>
-        <label for="<?= $type ?>" class="inline-flex items-center">
-        <input type="radio" class="form-radio" value="<?= $type ?>" id="<?= $type ?>" name="type" required />
-        <span class="ml-2"><?= lang('Episodes.form.type.' . $type) ?></span>  
-    </label>
-    <?php endforeach; ?>
-</fieldset>
-
-<div class="inline-flex items-center mb-4">
-    <input type="checkbox" id="block" name="block" class="form-checkbox" />
-    <label for="block" class="pl-2"><?= lang('Episodes.form.block') ?></label>
-</div>
-
-<button type="submit" name="submit" class="self-end px-4 py-2 bg-gray-200"><?= lang(
-    'Episodes.form.submit'
-) ?></button>
-<?= form_close() ?>
-
-
-<?= $this->endSection() ?>
diff --git a/app/Views/home.php b/app/Views/home.php
index c9e242a762..43a397c41e 100644
--- a/app/Views/home.php
+++ b/app/Views/home.php
@@ -8,13 +8,9 @@
 <section class="flex flex-wrap">
     <?php if ($podcasts): ?>
         <?php foreach ($podcasts as $podcast): ?>
-            <a href="<?= route_to('podcasts_view', '@' . $podcast->name) ?>">
+            <a href="<?= route_to('podcast_view', $podcast->name) ?>">
                 <article class="w-48 p-2 mb-4 mr-4 border shadow-sm hover:bg-gray-100 hover:shadow">
-                    <img alt="<?= $podcast->title ?>"
-                        src="<?= media_url(
-                            $podcast->image
-                        ) ?>" class="object-cover w-full h-40 mb-2"
-                    />
+                    <img alt="<?= $podcast->title ?>" src="<?= $podcast->image_url ?>" class="object-cover w-full h-40 mb-2" />
                     <h2 class="font-semibold leading-tight"><?= $podcast->title ?></h2>
                     <p class="text-gray-600">@<?= $podcast->name ?></p>
                 </article>
diff --git a/app/Views/layouts/default.php b/app/Views/layouts/default.php
index f0c27589b4..6f23967094 100644
--- a/app/Views/layouts/default.php
+++ b/app/Views/layouts/default.php
@@ -16,7 +16,7 @@
 			<a href="<?= route_to('home') ?>" class="text-2xl">Castopod</a>
 			<nav>
 				<a class="px-4 py-2 border hover:bg-gray-100" href="<?= route_to(
-        'podcasts_create'
+        'podcast_create'
     ) ?>">New podcast</a>
 			</nav>
 		</div>
diff --git a/app/Views/podcasts/create.php b/app/Views/podcast/create.php
similarity index 57%
rename from app/Views/podcasts/create.php
rename to app/Views/podcast/create.php
index 69fd68974f..2c2536e31d 100644
--- a/app/Views/podcasts/create.php
+++ b/app/Views/podcast/create.php
@@ -2,63 +2,66 @@
 
 <?= $this->section('content') ?>
 
-<h1 class="mb-6 text-xl"><?= lang('Podcasts.create') ?></h1>
+<h1 class="mb-6 text-xl"><?= lang('Podcast.create') ?></h1>
 
 <div class="mb-8">
      <?= \Config\Services::validation()->listErrors() ?>
 </div>
 
-<?= form_open_multipart(base_url(route_to('podcasts_create')), [
+<?= form_open_multipart(base_url(route_to('podcast_create')), [
     'method' => 'post',
     'class' => 'flex flex-col max-w-md',
 ]) ?>
 <?= csrf_field() ?>
 
 <div class="flex flex-col mb-4">
-    <label for="title"><?= lang('Podcasts.form.title') ?></label>
+    <label for="title"><?= lang('Podcast.form.title') ?></label>
     <input type="text" class="form-input" id="title" name="title" required />
 </div>
 
 <div class="flex flex-col mb-4">
-    <label for="name"><?= lang('Podcasts.form.name') ?></label>
+    <label for="name"><?= lang('Podcast.form.name') ?></label>
     <input type="text" class="form-input" id="name" name="name" required />
 </div>
 
 <div class="flex flex-col mb-4">
-    <label for="description"><?= lang('Podcasts.form.description') ?></label>
+    <label for="description"><?= lang('Podcast.form.description') ?></label>
     <textarea class="form-textarea" id="description" name="description" required></textarea>
 </div>
 
 <div class="flex flex-col mb-4">
     <label for="episode_description_footer"><?= lang(
-        'Podcasts.form.episode_description_footer'
+        'Podcast.form.episode_description_footer'
     ) ?></label>
     <textarea class="form-textarea" id="episode_description_footer" name="episode_description_footer"></textarea>
 </div>
 
 <div class="flex flex-col mb-4">
-    <label for="image"><?= lang('Podcasts.form.image') ?></label>
+    <label for="image"><?= lang('Podcast.form.image') ?></label>
     <input type="file" class="form-input" id="image" name="image" required />
 </div>
 
 <div class="flex flex-col mb-4">
-    <label for="language"><?= lang('Podcasts.form.language') ?></label>
+    <label for="language"><?= lang('Podcast.form.language') ?></label>
     <select id="language" name="language" autocomplete="off" class="form-select" required>
         <?php foreach ($languages as $language): ?>
             <option <?= $language->code == $browser_lang
                 ? "selected='selected'"
-                : '' ?> value="<?= $language->code ?>"><?= $language->native_name ?></option>
+                : '' ?> value="<?= $language->code ?>">
+                <?= $language->native_name ?>
+            </option>
         <?php endforeach; ?>
     </select>
 </div>
 
 <div class="flex flex-col mb-4">
-    <label for="category"><?= lang('Podcasts.form.category') ?></label>
+    <label for="category"><?= lang('Podcast.form.category') ?></label>
     <select id="category" name="category" class="form-select" required>
         <?php foreach ($categories as $category): ?>
             <option value="<?= $category->code ?>"><?= lang(
-    'Podcasts.category_options.' . $category->code
-) ?></option>
+    'Podcast.category_options.' . $category->code
+) ?>
+            </option>
         <?php endforeach; ?>
     </select>
 </div>
@@ -66,61 +69,68 @@
 <div class="inline-flex items-center mb-4">
     <input type="checkbox" id="explicit" name="explicit" class="form-checkbox" />
     <label for="explicit" class="pl-2"><?= lang(
-        'Podcasts.form.explicit'
+        'Podcast.form.explicit'
     ) ?></label>
 </div>
 
 <div class="flex flex-col mb-4">
-    <label for="author"><?= lang('Podcasts.form.author') ?></label>
-    <input type="text" class="form-input" id="author" name="author" />
+    <label for="author_name"><?= lang('Podcast.form.author_name') ?></label>
+    <input type="text" class="form-input" id="author_name" name="author_name" />
 </div>
 
 <div class="flex flex-col mb-4">
-    <label for="owner_name"><?= lang('Podcasts.form.owner_name') ?></label>
+    <label for="author_email"><?= lang('Podcast.form.author_email') ?></label>
+    <input type="email" class="form-input" id="author_email" name="author_email" />
+</div>
+
+<div class="flex flex-col mb-4">
+    <label for="owner_name"><?= lang('Podcast.form.owner_name') ?></label>
     <input type="text" class="form-input" id="owner_name" name="owner_name" />
 </div>
 
 <div class="flex flex-col mb-4">
-    <label for="owner_email"><?= lang('Podcasts.form.owner_email') ?></label>
+    <label for="owner_email"><?= lang('Podcast.form.owner_email') ?></label>
     <input type="email" class="form-input" id="owner_email" name="owner_email" required />
 </div>
 
 <fieldset class="flex flex-col mb-4">
-    <legend><?= lang('Podcasts.form.type.label') ?></legend>
-    <?php foreach ($podcast_types as $type): ?>
-        <label for="<?= $type ?>" class="inline-flex items-center">
-        <input type="radio" class="form-radio" value="<?= $type ?>" id="<?= $type ?>" name="type" required />
-        <span class="ml-2"><?= lang('Podcasts.form.type.' . $type) ?></span>  
+    <legend><?= lang('Podcast.form.type.label') ?></legend>
+    <label for="episodic" class="inline-flex items-center">
+        <input type="radio" class="form-radio" value="episodic" id="episodic" name="type" required checked />
+        <span class="ml-2"><?= lang('Podcast.form.type.episodic') ?></span>  
+    </label>
+    <label for="serial" class="inline-flex items-center">
+        <input type="radio" class="form-radio" value="serial" id="serial" name="type" required />
+        <span class="ml-2"><?= lang('Podcast.form.type.serial') ?></span>  
     </label>
-    <?php endforeach; ?>
 </fieldset>
 
 <div class="flex flex-col mb-4">
-    <label for="copyright"><?= lang('Podcasts.form.copyright') ?></label>
+    <label for="copyright"><?= lang('Podcast.form.copyright') ?></label>
     <input type="text" class="form-input" id="copyright" name="copyright" />
 </div>
 
 <div class="inline-flex items-center mb-4">
     <input type="checkbox" id="block" name="block" class="form-checkbox" />
-    <label for="block" class="pl-2"><?= lang('Podcasts.form.block') ?></label>
+    <label for="block" class="pl-2"><?= lang('Podcast.form.block') ?></label>
 </div>
 
 <div class="inline-flex items-center mb-4">
     <input type="checkbox" id="complete" name="complete" class="form-checkbox" />
     <label for="complete" class="pl-2"><?= lang(
-        'Podcasts.form.complete'
+        'Podcast.form.complete'
     ) ?></label>
 </div>
 
 <div class="flex flex-col mb-4">
     <label for="custom_html_head"><?= esc(
-        lang('Podcasts.form.custom_html_head')
+        lang('Podcast.form.custom_html_head')
     ) ?></label>
     <textarea class="form-textarea" id="custom_html_head" name="custom_html_head"></textarea>
 </div>
 
 <button type="submit" name="submit" class="self-end px-4 py-2 bg-gray-200"><?= lang(
-    'Podcasts.form.submit'
+    'Podcast.form.submit'
 ) ?></button>
 <?= form_close() ?>
 
diff --git a/app/Views/podcasts/view.php b/app/Views/podcast/view.php
similarity index 58%
rename from app/Views/podcasts/view.php
rename to app/Views/podcast/view.php
index 34641d4a18..449090c67a 100644
--- a/app/Views/podcasts/view.php
+++ b/app/Views/podcast/view.php
@@ -3,29 +3,29 @@
 <?= $this->section('content') ?>
 <header class="py-4 border-b">
     <h1 class="text-2xl"><?= $podcast->title ?></h1>
-    <img src="<?= media_url(
-        $podcast->image
-    ) ?>" alt="Podcast cover" class="w-40 h-40 mb-6" />
+    <img src="<?= $podcast->image_url ?>" alt="Podcast cover" class="w-40 h-40 mb-6" />
 <a class="inline-flex px-4 py-2 border hover:bg-gray-100" href="<?= route_to(
-    'episodes_create',
-    '@' . $podcast->name
+    'episode_create',
+    $podcast->name
 ) ?>">New Episode</a>
+<a class="inline-flex px-4 py-2 bg-orange-500 hover:bg-orange-600" href="<?= route_to(
+    'podcast_feed',
+    $podcast->name
+) ?>">RSS feed</a>
 </header>
 
 <section class="flex flex-col py-4">
-    <h2 class="mb-4 text-xl"><?= lang(
-        'Podcasts.list_of_episodes'
-    ) ?> (<?= count($episodes) ?>)</h2>
+    <h2 class="mb-4 text-xl"><?= lang('Podcast.list_of_episodes') ?> (<?= count(
+     $episodes
+ ) ?>)</h2>
     <?php if ($episodes): ?>
         <?php foreach ($episodes as $episode): ?>
             <article class="flex w-full max-w-lg p-4 mb-4 border shadow">
-                <img src="<?= media_url(
-                    $episode->image ? $episode->image : $podcast->image
-                ) ?>" alt="<?= $episode->title ?>" class="object-cover w-32 h-32 mr-4" />
+                <img src="<?= $episode->image_url ?>" alt="<?= $episode->title ?>" class="object-cover w-32 h-32 mr-4" />
                 <div class="flex flex-col flex-1">
                     <a href="<?= route_to(
-                        'episodes_view',
-                        '@' . $podcast->name,
+                        'episode_view',
+                        $podcast->name,
                         $episode->slug
                     ) ?>">
                         <h3 class="text-xl font-semibold">
@@ -35,19 +35,14 @@
                         <p><?= $episode->description ?></p>
                     </a>
                     <audio controls class="mt-auto" preload="none">
-                        <source src="<?= podcast_url(
-                            $episode->podcast_id,
-                            $episode->id,
-                            $podcast->name,
-                            $episode->enclosure_url
-                        ) ?>" type="<?= $episode->enclosure_type ?>">
+                        <source src="<?= $episode->enclosure_url ?>" type="<?= $episode->enclosure_type ?>">
                         Your browser does not support the audio tag.
                     </audio>
                 </div>
             </article>
         <?php endforeach; ?>
     <?php else: ?>
-        <p class="italic"><?= lang('Podcasts.no_episode') ?></p>
+        <p class="italic"><?= lang('Podcast.no_episode') ?></p>
     <?php endif; ?>
 </section>
 
diff --git a/composer.lock b/composer.lock
index 7f2dba26a4..19b6d1e112 100644
--- a/composer.lock
+++ b/composer.lock
@@ -1,2049 +1,2305 @@
 {
-  "_readme": [
-    "This file locks the dependencies of your project to a known state",
-    "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
-    "This file is @generated automatically"
-  ],
-  "content-hash": "8db0ba517a2c2b9718293a386c05c746",
-  "packages": [
-    {
-      "name": "codeigniter4/framework",
-      "version": "v4.0.3",
-      "source": {
-        "type": "git",
-        "url": "https://github.com/codeigniter4/framework.git",
-        "reference": "edd88b18483e309bab1411651d846aace255ab36"
-      },
-      "dist": {
-        "type": "zip",
-        "url": "https://api.github.com/repos/codeigniter4/framework/zipball/edd88b18483e309bab1411651d846aace255ab36",
-        "reference": "edd88b18483e309bab1411651d846aace255ab36",
-        "shasum": ""
-      },
-      "require": {
-        "ext-curl": "*",
-        "ext-intl": "*",
-        "ext-json": "*",
-        "ext-mbstring": "*",
-        "kint-php/kint": "^3.3",
-        "laminas/laminas-escaper": "^2.6",
-        "php": ">=7.2",
-        "psr/log": "^1.1"
-      },
-      "require-dev": {
-        "codeigniter4/codeigniter4-standard": "^1.0",
-        "mikey179/vfsstream": "1.6.*",
-        "phpunit/phpunit": "^8.5",
-        "squizlabs/php_codesniffer": "^3.3"
-      },
-      "type": "project",
-      "autoload": {
-        "psr-4": {
-          "CodeIgniter\\": "system/"
-        }
-      },
-      "notification-url": "https://packagist.org/downloads/",
-      "license": ["MIT"],
-      "description": "The CodeIgniter framework v4",
-      "homepage": "https://codeigniter.com",
-      "time": "2020-05-01T05:01:20+00:00"
-    },
-    {
-      "name": "composer/ca-bundle",
-      "version": "1.2.7",
-      "source": {
-        "type": "git",
-        "url": "https://github.com/composer/ca-bundle.git",
-        "reference": "95c63ab2117a72f48f5a55da9740a3273d45b7fd"
-      },
-      "dist": {
-        "type": "zip",
-        "url": "https://api.github.com/repos/composer/ca-bundle/zipball/95c63ab2117a72f48f5a55da9740a3273d45b7fd",
-        "reference": "95c63ab2117a72f48f5a55da9740a3273d45b7fd",
-        "shasum": ""
-      },
-      "require": {
-        "ext-openssl": "*",
-        "ext-pcre": "*",
-        "php": "^5.3.2 || ^7.0 || ^8.0"
-      },
-      "require-dev": {
-        "phpunit/phpunit": "^4.8.35 || ^5.7 || 6.5 - 8",
-        "psr/log": "^1.0",
-        "symfony/process": "^2.5 || ^3.0 || ^4.0 || ^5.0"
-      },
-      "type": "library",
-      "extra": {
-        "branch-alias": {
-          "dev-master": "1.x-dev"
-        }
-      },
-      "autoload": {
-        "psr-4": {
-          "Composer\\CaBundle\\": "src"
-        }
-      },
-      "notification-url": "https://packagist.org/downloads/",
-      "license": ["MIT"],
-      "authors": [
-        {
-          "name": "Jordi Boggiano",
-          "email": "j.boggiano@seld.be",
-          "homepage": "http://seld.be"
-        }
-      ],
-      "description": "Lets you find a path to the system CA bundle, and includes a fallback to the Mozilla CA bundle.",
-      "keywords": ["cabundle", "cacert", "certificate", "ssl", "tls"],
-      "funding": [
-        {
-          "url": "https://packagist.com",
-          "type": "custom"
+    "_readme": [
+        "This file locks the dependencies of your project to a known state",
+        "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
+        "This file is @generated automatically"
+    ],
+    "content-hash": "8db0ba517a2c2b9718293a386c05c746",
+    "packages": [
+        {
+            "name": "codeigniter4/framework",
+            "version": "v4.0.3",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/codeigniter4/framework.git",
+                "reference": "edd88b18483e309bab1411651d846aace255ab36"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/codeigniter4/framework/zipball/edd88b18483e309bab1411651d846aace255ab36",
+                "reference": "edd88b18483e309bab1411651d846aace255ab36",
+                "shasum": ""
+            },
+            "require": {
+                "ext-curl": "*",
+                "ext-intl": "*",
+                "ext-json": "*",
+                "ext-mbstring": "*",
+                "kint-php/kint": "^3.3",
+                "laminas/laminas-escaper": "^2.6",
+                "php": ">=7.2",
+                "psr/log": "^1.1"
+            },
+            "require-dev": {
+                "codeigniter4/codeigniter4-standard": "^1.0",
+                "mikey179/vfsstream": "1.6.*",
+                "phpunit/phpunit": "^8.5",
+                "squizlabs/php_codesniffer": "^3.3"
+            },
+            "type": "project",
+            "autoload": {
+                "psr-4": {
+                    "CodeIgniter\\": "system/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "description": "The CodeIgniter framework v4",
+            "homepage": "https://codeigniter.com",
+            "time": "2020-05-01T05:01:20+00:00"
         },
         {
-          "url": "https://tidelift.com/funding/github/packagist/composer/composer",
-          "type": "tidelift"
-        }
-      ],
-      "time": "2020-04-08T08:27:21+00:00"
-    },
-    {
-      "name": "geoip2/geoip2",
-      "version": "v2.10.0",
-      "source": {
-        "type": "git",
-        "url": "https://github.com/maxmind/GeoIP2-php.git",
-        "reference": "419557cd21d9fe039721a83490701a58c8ce784a"
-      },
-      "dist": {
-        "type": "zip",
-        "url": "https://api.github.com/repos/maxmind/GeoIP2-php/zipball/419557cd21d9fe039721a83490701a58c8ce784a",
-        "reference": "419557cd21d9fe039721a83490701a58c8ce784a",
-        "shasum": ""
-      },
-      "require": {
-        "ext-json": "*",
-        "maxmind-db/reader": "~1.5",
-        "maxmind/web-service-common": "~0.6",
-        "php": ">=5.6"
-      },
-      "require-dev": {
-        "friendsofphp/php-cs-fixer": "2.*",
-        "phpunit/phpunit": "5.*",
-        "squizlabs/php_codesniffer": "3.*"
-      },
-      "type": "library",
-      "autoload": {
-        "psr-4": {
-          "GeoIp2\\": "src"
-        }
-      },
-      "notification-url": "https://packagist.org/downloads/",
-      "license": ["Apache-2.0"],
-      "authors": [
-        {
-          "name": "Gregory J. Oschwald",
-          "email": "goschwald@maxmind.com",
-          "homepage": "https://www.maxmind.com/"
-        }
-      ],
-      "description": "MaxMind GeoIP2 PHP API",
-      "homepage": "https://github.com/maxmind/GeoIP2-php",
-      "keywords": ["IP", "geoip", "geoip2", "geolocation", "maxmind"],
-      "time": "2019-12-12T18:48:39+00:00"
-    },
-    {
-      "name": "james-heinrich/getid3",
-      "version": "2.0.x-dev",
-      "source": {
-        "type": "git",
-        "url": "https://github.com/JamesHeinrich/getID3.git",
-        "reference": "8cf765ec4c42ed732993a9aa60b638ee398df154"
-      },
-      "dist": {
-        "type": "zip",
-        "url": "https://api.github.com/repos/JamesHeinrich/getID3/zipball/8cf765ec4c42ed732993a9aa60b638ee398df154",
-        "reference": "8cf765ec4c42ed732993a9aa60b638ee398df154",
-        "shasum": ""
-      },
-      "require": {
-        "php": ">=5.4.0"
-      },
-      "require-dev": {
-        "jakub-onderka/php-parallel-lint": "^0.9 || ^1.0",
-        "phpunit/phpunit": "^4.8|^5.0"
-      },
-      "suggest": {
-        "ext-SimpleXML": "SimpleXML extension is required to analyze RIFF/WAV/BWF audio files (also requires `ext-libxml`).",
-        "ext-com_dotnet": "COM extension is required when loading files larger than 2GB on Windows.",
-        "ext-ctype": "ctype extension is required when loading files larger than 2GB on 32-bit PHP (also on 64-bit PHP on Windows) or executing `getid3_lib::CopyTagsToComments`.",
-        "ext-dba": "DBA extension is required to use the DBA database as a cache storage.",
-        "ext-exif": "EXIF extension is required for graphic modules.",
-        "ext-iconv": "iconv extension is required to work with different character sets (when `ext-mbstring` is not available).",
-        "ext-json": "JSON extension is required to analyze Apple Quicktime videos.",
-        "ext-libxml": "libxml extension is required to analyze RIFF/WAV/BWF audio files.",
-        "ext-mbstring": "mbstring extension is required to work with different character sets.",
-        "ext-mysql": "MySQL extension is required to use the MySQL database as a cache storage (deprecated in PHP 5.5, removed in PHP >= 7.0, use `ext-mysqli` instead).",
-        "ext-mysqli": "MySQLi extension is required to use the MySQL database as a cache storage.",
-        "ext-rar": "RAR extension is required for RAR archive module.",
-        "ext-sqlite3": "SQLite3 extension is required to use the SQLite3 database as a cache storage.",
-        "ext-xml": "XML extension is required for graphic modules to analyze the XML metadata.",
-        "ext-zlib": "Zlib extension is required for archive modules and compressed metadata."
-      },
-      "type": "library",
-      "extra": {
-        "branch-alias": {
-          "dev-master": "2.0.x-dev"
-        }
-      },
-      "autoload": {
-        "psr-4": {
-          "JamesHeinrich\\GetID3\\": "src/"
-        }
-      },
-      "notification-url": "https://packagist.org/downloads/",
-      "license": ["GPL-1.0-or-later", "LGPL-3.0-only", "MPL-2.0"],
-      "authors": [
-        {
-          "name": "James Heinrich",
-          "email": "info@getid3.org",
-          "homepage": "https://github.com/JamesHeinrich",
-          "role": "Developer"
+            "name": "composer/ca-bundle",
+            "version": "1.2.7",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/composer/ca-bundle.git",
+                "reference": "95c63ab2117a72f48f5a55da9740a3273d45b7fd"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/composer/ca-bundle/zipball/95c63ab2117a72f48f5a55da9740a3273d45b7fd",
+                "reference": "95c63ab2117a72f48f5a55da9740a3273d45b7fd",
+                "shasum": ""
+            },
+            "require": {
+                "ext-openssl": "*",
+                "ext-pcre": "*",
+                "php": "^5.3.2 || ^7.0 || ^8.0"
+            },
+            "require-dev": {
+                "phpunit/phpunit": "^4.8.35 || ^5.7 || 6.5 - 8",
+                "psr/log": "^1.0",
+                "symfony/process": "^2.5 || ^3.0 || ^4.0 || ^5.0"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "1.x-dev"
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "Composer\\CaBundle\\": "src"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Jordi Boggiano",
+                    "email": "j.boggiano@seld.be",
+                    "homepage": "http://seld.be"
+                }
+            ],
+            "description": "Lets you find a path to the system CA bundle, and includes a fallback to the Mozilla CA bundle.",
+            "keywords": [
+                "cabundle",
+                "cacert",
+                "certificate",
+                "ssl",
+                "tls"
+            ],
+            "funding": [
+                {
+                    "url": "https://packagist.com",
+                    "type": "custom"
+                },
+                {
+                    "url": "https://tidelift.com/funding/github/packagist/composer/composer",
+                    "type": "tidelift"
+                }
+            ],
+            "time": "2020-04-08T08:27:21+00:00"
         },
         {
-          "name": "Craig Duncan",
-          "email": "git@duncanc.co.uk",
-          "homepage": "https://github.com/duncan3dc",
-          "role": "Developer"
-        }
-      ],
-      "description": "Extract and write useful information to/from popular multimedia file formats",
-      "homepage": "https://www.getid3.org/",
-      "keywords": ["audio", "codecs", "id3", "metadata", "tags", "video"],
-      "time": "2019-07-22T12:33:16+00:00"
-    },
-    {
-      "name": "kint-php/kint",
-      "version": "3.3",
-      "source": {
-        "type": "git",
-        "url": "https://github.com/kint-php/kint.git",
-        "reference": "335ac1bcaf04d87df70d8aa51e8887ba2c6d203b"
-      },
-      "dist": {
-        "type": "zip",
-        "url": "https://api.github.com/repos/kint-php/kint/zipball/335ac1bcaf04d87df70d8aa51e8887ba2c6d203b",
-        "reference": "335ac1bcaf04d87df70d8aa51e8887ba2c6d203b",
-        "shasum": ""
-      },
-      "require": {
-        "php": ">=5.3.6"
-      },
-      "require-dev": {
-        "friendsofphp/php-cs-fixer": "^2.0",
-        "phpunit/phpunit": "^4.0",
-        "seld/phar-utils": "^1.0",
-        "symfony/finder": "^2.0 || ^3.0 || ^4.0",
-        "vimeo/psalm": "^3.0"
-      },
-      "suggest": {
-        "ext-ctype": "Simple data type tests",
-        "ext-iconv": "Provides fallback detection for ambiguous legacy string encodings such as the Windows and ISO 8859 code pages",
-        "ext-mbstring": "Provides string encoding detection",
-        "kint-php/kint-js": "Provides a simplified dump to console.log()",
-        "kint-php/kint-twig": "Provides d() and s() functions in twig templates",
-        "symfony/polyfill-ctype": "Replacement for ext-ctype if missing",
-        "symfony/polyfill-iconv": "Replacement for ext-iconv if missing",
-        "symfony/polyfill-mbstring": "Replacement for ext-mbstring if missing"
-      },
-      "type": "library",
-      "autoload": {
-        "files": ["init.php"],
-        "psr-4": {
-          "Kint\\": "src/"
-        }
-      },
-      "notification-url": "https://packagist.org/downloads/",
-      "license": ["MIT"],
-      "authors": [
-        {
-          "name": "Jonathan Vollebregt",
-          "homepage": "https://github.com/jnvsor"
+            "name": "geoip2/geoip2",
+            "version": "v2.10.0",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/maxmind/GeoIP2-php.git",
+                "reference": "419557cd21d9fe039721a83490701a58c8ce784a"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/maxmind/GeoIP2-php/zipball/419557cd21d9fe039721a83490701a58c8ce784a",
+                "reference": "419557cd21d9fe039721a83490701a58c8ce784a",
+                "shasum": ""
+            },
+            "require": {
+                "ext-json": "*",
+                "maxmind-db/reader": "~1.5",
+                "maxmind/web-service-common": "~0.6",
+                "php": ">=5.6"
+            },
+            "require-dev": {
+                "friendsofphp/php-cs-fixer": "2.*",
+                "phpunit/phpunit": "5.*",
+                "squizlabs/php_codesniffer": "3.*"
+            },
+            "type": "library",
+            "autoload": {
+                "psr-4": {
+                    "GeoIp2\\": "src"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "Apache-2.0"
+            ],
+            "authors": [
+                {
+                    "name": "Gregory J. Oschwald",
+                    "email": "goschwald@maxmind.com",
+                    "homepage": "https://www.maxmind.com/"
+                }
+            ],
+            "description": "MaxMind GeoIP2 PHP API",
+            "homepage": "https://github.com/maxmind/GeoIP2-php",
+            "keywords": [
+                "IP",
+                "geoip",
+                "geoip2",
+                "geolocation",
+                "maxmind"
+            ],
+            "time": "2019-12-12T18:48:39+00:00"
         },
         {
-          "name": "Rokas Šleinius",
-          "homepage": "https://github.com/raveren"
+            "name": "james-heinrich/getid3",
+            "version": "2.0.x-dev",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/JamesHeinrich/getID3.git",
+                "reference": "8cf765ec4c42ed732993a9aa60b638ee398df154"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/JamesHeinrich/getID3/zipball/8cf765ec4c42ed732993a9aa60b638ee398df154",
+                "reference": "8cf765ec4c42ed732993a9aa60b638ee398df154",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=5.4.0"
+            },
+            "require-dev": {
+                "jakub-onderka/php-parallel-lint": "^0.9 || ^1.0",
+                "phpunit/phpunit": "^4.8|^5.0"
+            },
+            "suggest": {
+                "ext-SimpleXML": "SimpleXML extension is required to analyze RIFF/WAV/BWF audio files (also requires `ext-libxml`).",
+                "ext-com_dotnet": "COM extension is required when loading files larger than 2GB on Windows.",
+                "ext-ctype": "ctype extension is required when loading files larger than 2GB on 32-bit PHP (also on 64-bit PHP on Windows) or executing `getid3_lib::CopyTagsToComments`.",
+                "ext-dba": "DBA extension is required to use the DBA database as a cache storage.",
+                "ext-exif": "EXIF extension is required for graphic modules.",
+                "ext-iconv": "iconv extension is required to work with different character sets (when `ext-mbstring` is not available).",
+                "ext-json": "JSON extension is required to analyze Apple Quicktime videos.",
+                "ext-libxml": "libxml extension is required to analyze RIFF/WAV/BWF audio files.",
+                "ext-mbstring": "mbstring extension is required to work with different character sets.",
+                "ext-mysql": "MySQL extension is required to use the MySQL database as a cache storage (deprecated in PHP 5.5, removed in PHP >= 7.0, use `ext-mysqli` instead).",
+                "ext-mysqli": "MySQLi extension is required to use the MySQL database as a cache storage.",
+                "ext-rar": "RAR extension is required for RAR archive module.",
+                "ext-sqlite3": "SQLite3 extension is required to use the SQLite3 database as a cache storage.",
+                "ext-xml": "XML extension is required for graphic modules to analyze the XML metadata.",
+                "ext-zlib": "Zlib extension is required for archive modules and compressed metadata."
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "2.0.x-dev"
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "JamesHeinrich\\GetID3\\": "src/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "GPL-1.0-or-later",
+                "LGPL-3.0-only",
+                "MPL-2.0"
+            ],
+            "authors": [
+                {
+                    "name": "James Heinrich",
+                    "email": "info@getid3.org",
+                    "homepage": "https://github.com/JamesHeinrich",
+                    "role": "Developer"
+                },
+                {
+                    "name": "Craig Duncan",
+                    "email": "git@duncanc.co.uk",
+                    "homepage": "https://github.com/duncan3dc",
+                    "role": "Developer"
+                }
+            ],
+            "description": "Extract and write useful information to/from popular multimedia file formats",
+            "homepage": "https://www.getid3.org/",
+            "keywords": [
+                "audio",
+                "codecs",
+                "id3",
+                "metadata",
+                "tags",
+                "video"
+            ],
+            "time": "2019-07-22T12:33:16+00:00"
         },
         {
-          "name": "Contributors",
-          "homepage": "https://github.com/kint-php/kint/graphs/contributors"
-        }
-      ],
-      "description": "Kint - debugging tool for PHP developers",
-      "homepage": "https://kint-php.github.io/kint/",
-      "keywords": ["debug", "kint", "php"],
-      "time": "2019-10-17T18:05:24+00:00"
-    },
-    {
-      "name": "laminas/laminas-escaper",
-      "version": "2.6.1",
-      "source": {
-        "type": "git",
-        "url": "https://github.com/laminas/laminas-escaper.git",
-        "reference": "25f2a053eadfa92ddacb609dcbbc39362610da70"
-      },
-      "dist": {
-        "type": "zip",
-        "url": "https://api.github.com/repos/laminas/laminas-escaper/zipball/25f2a053eadfa92ddacb609dcbbc39362610da70",
-        "reference": "25f2a053eadfa92ddacb609dcbbc39362610da70",
-        "shasum": ""
-      },
-      "require": {
-        "laminas/laminas-zendframework-bridge": "^1.0",
-        "php": "^5.6 || ^7.0"
-      },
-      "replace": {
-        "zendframework/zend-escaper": "self.version"
-      },
-      "require-dev": {
-        "laminas/laminas-coding-standard": "~1.0.0",
-        "phpunit/phpunit": "^5.7.27 || ^6.5.8 || ^7.1.2"
-      },
-      "type": "library",
-      "extra": {
-        "branch-alias": {
-          "dev-master": "2.6.x-dev",
-          "dev-develop": "2.7.x-dev"
-        }
-      },
-      "autoload": {
-        "psr-4": {
-          "Laminas\\Escaper\\": "src/"
-        }
-      },
-      "notification-url": "https://packagist.org/downloads/",
-      "license": ["BSD-3-Clause"],
-      "description": "Securely and safely escape HTML, HTML attributes, JavaScript, CSS, and URLs",
-      "homepage": "https://laminas.dev",
-      "keywords": ["escaper", "laminas"],
-      "time": "2019-12-31T16:43:30+00:00"
-    },
-    {
-      "name": "laminas/laminas-zendframework-bridge",
-      "version": "1.0.4",
-      "source": {
-        "type": "git",
-        "url": "https://github.com/laminas/laminas-zendframework-bridge.git",
-        "reference": "fcd87520e4943d968557803919523772475e8ea3"
-      },
-      "dist": {
-        "type": "zip",
-        "url": "https://api.github.com/repos/laminas/laminas-zendframework-bridge/zipball/fcd87520e4943d968557803919523772475e8ea3",
-        "reference": "fcd87520e4943d968557803919523772475e8ea3",
-        "shasum": ""
-      },
-      "require": {
-        "php": "^5.6 || ^7.0"
-      },
-      "require-dev": {
-        "phpunit/phpunit": "^5.7 || ^6.5 || ^7.5 || ^8.1",
-        "squizlabs/php_codesniffer": "^3.5"
-      },
-      "type": "library",
-      "extra": {
-        "branch-alias": {
-          "dev-master": "1.0.x-dev",
-          "dev-develop": "1.1.x-dev"
+            "name": "kint-php/kint",
+            "version": "3.3",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/kint-php/kint.git",
+                "reference": "335ac1bcaf04d87df70d8aa51e8887ba2c6d203b"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/kint-php/kint/zipball/335ac1bcaf04d87df70d8aa51e8887ba2c6d203b",
+                "reference": "335ac1bcaf04d87df70d8aa51e8887ba2c6d203b",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=5.3.6"
+            },
+            "require-dev": {
+                "friendsofphp/php-cs-fixer": "^2.0",
+                "phpunit/phpunit": "^4.0",
+                "seld/phar-utils": "^1.0",
+                "symfony/finder": "^2.0 || ^3.0 || ^4.0",
+                "vimeo/psalm": "^3.0"
+            },
+            "suggest": {
+                "ext-ctype": "Simple data type tests",
+                "ext-iconv": "Provides fallback detection for ambiguous legacy string encodings such as the Windows and ISO 8859 code pages",
+                "ext-mbstring": "Provides string encoding detection",
+                "kint-php/kint-js": "Provides a simplified dump to console.log()",
+                "kint-php/kint-twig": "Provides d() and s() functions in twig templates",
+                "symfony/polyfill-ctype": "Replacement for ext-ctype if missing",
+                "symfony/polyfill-iconv": "Replacement for ext-iconv if missing",
+                "symfony/polyfill-mbstring": "Replacement for ext-mbstring if missing"
+            },
+            "type": "library",
+            "autoload": {
+                "files": [
+                    "init.php"
+                ],
+                "psr-4": {
+                    "Kint\\": "src/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Jonathan Vollebregt",
+                    "homepage": "https://github.com/jnvsor"
+                },
+                {
+                    "name": "Rokas Šleinius",
+                    "homepage": "https://github.com/raveren"
+                },
+                {
+                    "name": "Contributors",
+                    "homepage": "https://github.com/kint-php/kint/graphs/contributors"
+                }
+            ],
+            "description": "Kint - debugging tool for PHP developers",
+            "homepage": "https://kint-php.github.io/kint/",
+            "keywords": [
+                "debug",
+                "kint",
+                "php"
+            ],
+            "time": "2019-10-17T18:05:24+00:00"
         },
-        "laminas": {
-          "module": "Laminas\\ZendFrameworkBridge"
-        }
-      },
-      "autoload": {
-        "files": ["src/autoload.php"],
-        "psr-4": {
-          "Laminas\\ZendFrameworkBridge\\": "src//"
-        }
-      },
-      "notification-url": "https://packagist.org/downloads/",
-      "license": ["BSD-3-Clause"],
-      "description": "Alias legacy ZF class names to Laminas Project equivalents.",
-      "keywords": ["ZendFramework", "autoloading", "laminas", "zf"],
-      "funding": [
-        {
-          "url": "https://funding.communitybridge.org/projects/laminas-project",
-          "type": "community_bridge"
-        }
-      ],
-      "time": "2020-05-20T16:45:56+00:00"
-    },
-    {
-      "name": "maxmind-db/reader",
-      "version": "v1.6.0",
-      "source": {
-        "type": "git",
-        "url": "https://github.com/maxmind/MaxMind-DB-Reader-php.git",
-        "reference": "febd4920bf17c1da84cef58e56a8227dfb37fbe4"
-      },
-      "dist": {
-        "type": "zip",
-        "url": "https://api.github.com/repos/maxmind/MaxMind-DB-Reader-php/zipball/febd4920bf17c1da84cef58e56a8227dfb37fbe4",
-        "reference": "febd4920bf17c1da84cef58e56a8227dfb37fbe4",
-        "shasum": ""
-      },
-      "require": {
-        "php": ">=5.6"
-      },
-      "conflict": {
-        "ext-maxminddb": "<1.6.0,>=2.0.0"
-      },
-      "require-dev": {
-        "friendsofphp/php-cs-fixer": "2.*",
-        "php-coveralls/php-coveralls": "^2.1",
-        "phpunit/phpcov": "^3.0",
-        "phpunit/phpunit": "5.*",
-        "squizlabs/php_codesniffer": "3.*"
-      },
-      "suggest": {
-        "ext-bcmath": "bcmath or gmp is required for decoding larger integers with the pure PHP decoder",
-        "ext-gmp": "bcmath or gmp is required for decoding larger integers with the pure PHP decoder",
-        "ext-maxminddb": "A C-based database decoder that provides significantly faster lookups"
-      },
-      "type": "library",
-      "autoload": {
-        "psr-4": {
-          "MaxMind\\Db\\": "src/MaxMind/Db"
-        }
-      },
-      "notification-url": "https://packagist.org/downloads/",
-      "license": ["Apache-2.0"],
-      "authors": [
-        {
-          "name": "Gregory J. Oschwald",
-          "email": "goschwald@maxmind.com",
-          "homepage": "https://www.maxmind.com/"
-        }
-      ],
-      "description": "MaxMind DB Reader API",
-      "homepage": "https://github.com/maxmind/MaxMind-DB-Reader-php",
-      "keywords": ["database", "geoip", "geoip2", "geolocation", "maxmind"],
-      "time": "2019-12-19T22:59:03+00:00"
-    },
-    {
-      "name": "maxmind/web-service-common",
-      "version": "v0.7.0",
-      "source": {
-        "type": "git",
-        "url": "https://github.com/maxmind/web-service-common-php.git",
-        "reference": "74c996c218ada5c639c8c2f076756e059f5552fc"
-      },
-      "dist": {
-        "type": "zip",
-        "url": "https://api.github.com/repos/maxmind/web-service-common-php/zipball/74c996c218ada5c639c8c2f076756e059f5552fc",
-        "reference": "74c996c218ada5c639c8c2f076756e059f5552fc",
-        "shasum": ""
-      },
-      "require": {
-        "composer/ca-bundle": "^1.0.3",
-        "ext-curl": "*",
-        "ext-json": "*",
-        "php": ">=5.6"
-      },
-      "require-dev": {
-        "friendsofphp/php-cs-fixer": "2.*",
-        "phpunit/phpunit": "^4.8.36 || ^5.7 || ^6.5 || ^7.0",
-        "squizlabs/php_codesniffer": "3.*"
-      },
-      "type": "library",
-      "autoload": {
-        "psr-4": {
-          "MaxMind\\Exception\\": "src/Exception",
-          "MaxMind\\WebService\\": "src/WebService"
-        }
-      },
-      "notification-url": "https://packagist.org/downloads/",
-      "license": ["Apache-2.0"],
-      "authors": [
-        {
-          "name": "Gregory Oschwald",
-          "email": "goschwald@maxmind.com"
-        }
-      ],
-      "description": "Internal MaxMind Web Service API",
-      "homepage": "https://github.com/maxmind/web-service-common-php",
-      "time": "2020-05-06T14:07:26+00:00"
-    },
-    {
-      "name": "psr/cache",
-      "version": "1.0.1",
-      "source": {
-        "type": "git",
-        "url": "https://github.com/php-fig/cache.git",
-        "reference": "d11b50ad223250cf17b86e38383413f5a6764bf8"
-      },
-      "dist": {
-        "type": "zip",
-        "url": "https://api.github.com/repos/php-fig/cache/zipball/d11b50ad223250cf17b86e38383413f5a6764bf8",
-        "reference": "d11b50ad223250cf17b86e38383413f5a6764bf8",
-        "shasum": ""
-      },
-      "require": {
-        "php": ">=5.3.0"
-      },
-      "type": "library",
-      "extra": {
-        "branch-alias": {
-          "dev-master": "1.0.x-dev"
-        }
-      },
-      "autoload": {
-        "psr-4": {
-          "Psr\\Cache\\": "src/"
-        }
-      },
-      "notification-url": "https://packagist.org/downloads/",
-      "license": ["MIT"],
-      "authors": [
-        {
-          "name": "PHP-FIG",
-          "homepage": "http://www.php-fig.org/"
-        }
-      ],
-      "description": "Common interface for caching libraries",
-      "keywords": ["cache", "psr", "psr-6"],
-      "time": "2016-08-06T20:24:11+00:00"
-    },
-    {
-      "name": "psr/log",
-      "version": "1.1.3",
-      "source": {
-        "type": "git",
-        "url": "https://github.com/php-fig/log.git",
-        "reference": "0f73288fd15629204f9d42b7055f72dacbe811fc"
-      },
-      "dist": {
-        "type": "zip",
-        "url": "https://api.github.com/repos/php-fig/log/zipball/0f73288fd15629204f9d42b7055f72dacbe811fc",
-        "reference": "0f73288fd15629204f9d42b7055f72dacbe811fc",
-        "shasum": ""
-      },
-      "require": {
-        "php": ">=5.3.0"
-      },
-      "type": "library",
-      "extra": {
-        "branch-alias": {
-          "dev-master": "1.1.x-dev"
-        }
-      },
-      "autoload": {
-        "psr-4": {
-          "Psr\\Log\\": "Psr/Log/"
-        }
-      },
-      "notification-url": "https://packagist.org/downloads/",
-      "license": ["MIT"],
-      "authors": [
-        {
-          "name": "PHP-FIG",
-          "homepage": "http://www.php-fig.org/"
-        }
-      ],
-      "description": "Common interface for logging libraries",
-      "homepage": "https://github.com/php-fig/log",
-      "keywords": ["log", "psr", "psr-3"],
-      "time": "2020-03-23T09:12:05+00:00"
-    },
-    {
-      "name": "whichbrowser/parser",
-      "version": "v2.0.42",
-      "source": {
-        "type": "git",
-        "url": "https://github.com/WhichBrowser/Parser-PHP.git",
-        "reference": "4899110cd2f87b01e04ced62dbb9dec541031dee"
-      },
-      "dist": {
-        "type": "zip",
-        "url": "https://api.github.com/repos/WhichBrowser/Parser-PHP/zipball/4899110cd2f87b01e04ced62dbb9dec541031dee",
-        "reference": "4899110cd2f87b01e04ced62dbb9dec541031dee",
-        "shasum": ""
-      },
-      "require": {
-        "php": ">=5.4.0",
-        "psr/cache": "^1.0"
-      },
-      "require-dev": {
-        "icomefromthenet/reverse-regex": "0.0.6.3",
-        "phpunit/php-code-coverage": "^2.2 || ^3.0",
-        "phpunit/phpunit": "^4.0 || ^5.0 || ^6.0 || ^7.0 || ^8.0",
-        "satooshi/php-coveralls": "^1.0",
-        "squizlabs/php_codesniffer": "2.5.*",
-        "symfony/yaml": "~2.8 || ~3.4 || ~4.2 || ~5.0"
-      },
-      "suggest": {
-        "cache/array-adapter": "Allows testing of the caching functionality"
-      },
-      "type": "library",
-      "autoload": {
-        "psr-4": {
-          "WhichBrowser\\": ["src/", "tests/src/"]
-        }
-      },
-      "notification-url": "https://packagist.org/downloads/",
-      "license": ["MIT"],
-      "authors": [
-        {
-          "name": "Niels Leenheer",
-          "email": "niels@leenheer.nl",
-          "role": "Developer"
-        }
-      ],
-      "description": "Useragent sniffing library for PHP",
-      "homepage": "http://whichbrowser.net",
-      "keywords": ["browser", "sniffing", "ua", "useragent"],
-      "time": "2020-02-12T10:54:23+00:00"
-    }
-  ],
-  "packages-dev": [
-    {
-      "name": "doctrine/instantiator",
-      "version": "1.3.1",
-      "source": {
-        "type": "git",
-        "url": "https://github.com/doctrine/instantiator.git",
-        "reference": "f350df0268e904597e3bd9c4685c53e0e333feea"
-      },
-      "dist": {
-        "type": "zip",
-        "url": "https://api.github.com/repos/doctrine/instantiator/zipball/f350df0268e904597e3bd9c4685c53e0e333feea",
-        "reference": "f350df0268e904597e3bd9c4685c53e0e333feea",
-        "shasum": ""
-      },
-      "require": {
-        "php": "^7.1 || ^8.0"
-      },
-      "require-dev": {
-        "doctrine/coding-standard": "^6.0",
-        "ext-pdo": "*",
-        "ext-phar": "*",
-        "phpbench/phpbench": "^0.13",
-        "phpstan/phpstan-phpunit": "^0.11",
-        "phpstan/phpstan-shim": "^0.11",
-        "phpunit/phpunit": "^7.0"
-      },
-      "type": "library",
-      "extra": {
-        "branch-alias": {
-          "dev-master": "1.2.x-dev"
-        }
-      },
-      "autoload": {
-        "psr-4": {
-          "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/"
-        }
-      },
-      "notification-url": "https://packagist.org/downloads/",
-      "license": ["MIT"],
-      "authors": [
-        {
-          "name": "Marco Pivetta",
-          "email": "ocramius@gmail.com",
-          "homepage": "http://ocramius.github.com/"
-        }
-      ],
-      "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors",
-      "homepage": "https://www.doctrine-project.org/projects/instantiator.html",
-      "keywords": ["constructor", "instantiate"],
-      "funding": [
         {
-          "url": "https://www.doctrine-project.org/sponsorship.html",
-          "type": "custom"
+            "name": "laminas/laminas-escaper",
+            "version": "2.6.1",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/laminas/laminas-escaper.git",
+                "reference": "25f2a053eadfa92ddacb609dcbbc39362610da70"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/laminas/laminas-escaper/zipball/25f2a053eadfa92ddacb609dcbbc39362610da70",
+                "reference": "25f2a053eadfa92ddacb609dcbbc39362610da70",
+                "shasum": ""
+            },
+            "require": {
+                "laminas/laminas-zendframework-bridge": "^1.0",
+                "php": "^5.6 || ^7.0"
+            },
+            "replace": {
+                "zendframework/zend-escaper": "self.version"
+            },
+            "require-dev": {
+                "laminas/laminas-coding-standard": "~1.0.0",
+                "phpunit/phpunit": "^5.7.27 || ^6.5.8 || ^7.1.2"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "2.6.x-dev",
+                    "dev-develop": "2.7.x-dev"
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "Laminas\\Escaper\\": "src/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "BSD-3-Clause"
+            ],
+            "description": "Securely and safely escape HTML, HTML attributes, JavaScript, CSS, and URLs",
+            "homepage": "https://laminas.dev",
+            "keywords": [
+                "escaper",
+                "laminas"
+            ],
+            "time": "2019-12-31T16:43:30+00:00"
         },
         {
-          "url": "https://www.patreon.com/phpdoctrine",
-          "type": "patreon"
+            "name": "laminas/laminas-zendframework-bridge",
+            "version": "1.0.4",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/laminas/laminas-zendframework-bridge.git",
+                "reference": "fcd87520e4943d968557803919523772475e8ea3"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/laminas/laminas-zendframework-bridge/zipball/fcd87520e4943d968557803919523772475e8ea3",
+                "reference": "fcd87520e4943d968557803919523772475e8ea3",
+                "shasum": ""
+            },
+            "require": {
+                "php": "^5.6 || ^7.0"
+            },
+            "require-dev": {
+                "phpunit/phpunit": "^5.7 || ^6.5 || ^7.5 || ^8.1",
+                "squizlabs/php_codesniffer": "^3.5"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "1.0.x-dev",
+                    "dev-develop": "1.1.x-dev"
+                },
+                "laminas": {
+                    "module": "Laminas\\ZendFrameworkBridge"
+                }
+            },
+            "autoload": {
+                "files": [
+                    "src/autoload.php"
+                ],
+                "psr-4": {
+                    "Laminas\\ZendFrameworkBridge\\": "src//"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "BSD-3-Clause"
+            ],
+            "description": "Alias legacy ZF class names to Laminas Project equivalents.",
+            "keywords": [
+                "ZendFramework",
+                "autoloading",
+                "laminas",
+                "zf"
+            ],
+            "funding": [
+                {
+                    "url": "https://funding.communitybridge.org/projects/laminas-project",
+                    "type": "community_bridge"
+                }
+            ],
+            "time": "2020-05-20T16:45:56+00:00"
         },
         {
-          "url": "https://tidelift.com/funding/github/packagist/doctrine%2Finstantiator",
-          "type": "tidelift"
-        }
-      ],
-      "time": "2020-05-29T17:27:14+00:00"
-    },
-    {
-      "name": "mikey179/vfsstream",
-      "version": "v1.6.8",
-      "source": {
-        "type": "git",
-        "url": "https://github.com/bovigo/vfsStream.git",
-        "reference": "231c73783ebb7dd9ec77916c10037eff5a2b6efe"
-      },
-      "dist": {
-        "type": "zip",
-        "url": "https://api.github.com/repos/bovigo/vfsStream/zipball/231c73783ebb7dd9ec77916c10037eff5a2b6efe",
-        "reference": "231c73783ebb7dd9ec77916c10037eff5a2b6efe",
-        "shasum": ""
-      },
-      "require": {
-        "php": ">=5.3.0"
-      },
-      "require-dev": {
-        "phpunit/phpunit": "^4.5|^5.0"
-      },
-      "type": "library",
-      "extra": {
-        "branch-alias": {
-          "dev-master": "1.6.x-dev"
-        }
-      },
-      "autoload": {
-        "psr-0": {
-          "org\\bovigo\\vfs\\": "src/main/php"
-        }
-      },
-      "notification-url": "https://packagist.org/downloads/",
-      "license": ["BSD-3-Clause"],
-      "authors": [
-        {
-          "name": "Frank Kleine",
-          "homepage": "http://frankkleine.de/",
-          "role": "Developer"
-        }
-      ],
-      "description": "Virtual file system to mock the real file system in unit tests.",
-      "homepage": "http://vfs.bovigo.org/",
-      "time": "2019-10-30T15:31:00+00:00"
-    },
-    {
-      "name": "myclabs/deep-copy",
-      "version": "1.9.5",
-      "source": {
-        "type": "git",
-        "url": "https://github.com/myclabs/DeepCopy.git",
-        "reference": "b2c28789e80a97badd14145fda39b545d83ca3ef"
-      },
-      "dist": {
-        "type": "zip",
-        "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/b2c28789e80a97badd14145fda39b545d83ca3ef",
-        "reference": "b2c28789e80a97badd14145fda39b545d83ca3ef",
-        "shasum": ""
-      },
-      "require": {
-        "php": "^7.1"
-      },
-      "replace": {
-        "myclabs/deep-copy": "self.version"
-      },
-      "require-dev": {
-        "doctrine/collections": "^1.0",
-        "doctrine/common": "^2.6",
-        "phpunit/phpunit": "^7.1"
-      },
-      "type": "library",
-      "autoload": {
-        "psr-4": {
-          "DeepCopy\\": "src/DeepCopy/"
+            "name": "maxmind-db/reader",
+            "version": "v1.6.0",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/maxmind/MaxMind-DB-Reader-php.git",
+                "reference": "febd4920bf17c1da84cef58e56a8227dfb37fbe4"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/maxmind/MaxMind-DB-Reader-php/zipball/febd4920bf17c1da84cef58e56a8227dfb37fbe4",
+                "reference": "febd4920bf17c1da84cef58e56a8227dfb37fbe4",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=5.6"
+            },
+            "conflict": {
+                "ext-maxminddb": "<1.6.0,>=2.0.0"
+            },
+            "require-dev": {
+                "friendsofphp/php-cs-fixer": "2.*",
+                "php-coveralls/php-coveralls": "^2.1",
+                "phpunit/phpcov": "^3.0",
+                "phpunit/phpunit": "5.*",
+                "squizlabs/php_codesniffer": "3.*"
+            },
+            "suggest": {
+                "ext-bcmath": "bcmath or gmp is required for decoding larger integers with the pure PHP decoder",
+                "ext-gmp": "bcmath or gmp is required for decoding larger integers with the pure PHP decoder",
+                "ext-maxminddb": "A C-based database decoder that provides significantly faster lookups"
+            },
+            "type": "library",
+            "autoload": {
+                "psr-4": {
+                    "MaxMind\\Db\\": "src/MaxMind/Db"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "Apache-2.0"
+            ],
+            "authors": [
+                {
+                    "name": "Gregory J. Oschwald",
+                    "email": "goschwald@maxmind.com",
+                    "homepage": "https://www.maxmind.com/"
+                }
+            ],
+            "description": "MaxMind DB Reader API",
+            "homepage": "https://github.com/maxmind/MaxMind-DB-Reader-php",
+            "keywords": [
+                "database",
+                "geoip",
+                "geoip2",
+                "geolocation",
+                "maxmind"
+            ],
+            "time": "2019-12-19T22:59:03+00:00"
         },
-        "files": ["src/DeepCopy/deep_copy.php"]
-      },
-      "notification-url": "https://packagist.org/downloads/",
-      "license": ["MIT"],
-      "description": "Create deep copies (clones) of your objects",
-      "keywords": ["clone", "copy", "duplicate", "object", "object graph"],
-      "time": "2020-01-17T21:11:47+00:00"
-    },
-    {
-      "name": "phar-io/manifest",
-      "version": "1.0.3",
-      "source": {
-        "type": "git",
-        "url": "https://github.com/phar-io/manifest.git",
-        "reference": "7761fcacf03b4d4f16e7ccb606d4879ca431fcf4"
-      },
-      "dist": {
-        "type": "zip",
-        "url": "https://api.github.com/repos/phar-io/manifest/zipball/7761fcacf03b4d4f16e7ccb606d4879ca431fcf4",
-        "reference": "7761fcacf03b4d4f16e7ccb606d4879ca431fcf4",
-        "shasum": ""
-      },
-      "require": {
-        "ext-dom": "*",
-        "ext-phar": "*",
-        "phar-io/version": "^2.0",
-        "php": "^5.6 || ^7.0"
-      },
-      "type": "library",
-      "extra": {
-        "branch-alias": {
-          "dev-master": "1.0.x-dev"
-        }
-      },
-      "autoload": {
-        "classmap": ["src/"]
-      },
-      "notification-url": "https://packagist.org/downloads/",
-      "license": ["BSD-3-Clause"],
-      "authors": [
         {
-          "name": "Arne Blankerts",
-          "email": "arne@blankerts.de",
-          "role": "Developer"
+            "name": "maxmind/web-service-common",
+            "version": "v0.7.0",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/maxmind/web-service-common-php.git",
+                "reference": "74c996c218ada5c639c8c2f076756e059f5552fc"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/maxmind/web-service-common-php/zipball/74c996c218ada5c639c8c2f076756e059f5552fc",
+                "reference": "74c996c218ada5c639c8c2f076756e059f5552fc",
+                "shasum": ""
+            },
+            "require": {
+                "composer/ca-bundle": "^1.0.3",
+                "ext-curl": "*",
+                "ext-json": "*",
+                "php": ">=5.6"
+            },
+            "require-dev": {
+                "friendsofphp/php-cs-fixer": "2.*",
+                "phpunit/phpunit": "^4.8.36 || ^5.7 || ^6.5 || ^7.0",
+                "squizlabs/php_codesniffer": "3.*"
+            },
+            "type": "library",
+            "autoload": {
+                "psr-4": {
+                    "MaxMind\\Exception\\": "src/Exception",
+                    "MaxMind\\WebService\\": "src/WebService"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "Apache-2.0"
+            ],
+            "authors": [
+                {
+                    "name": "Gregory Oschwald",
+                    "email": "goschwald@maxmind.com"
+                }
+            ],
+            "description": "Internal MaxMind Web Service API",
+            "homepage": "https://github.com/maxmind/web-service-common-php",
+            "time": "2020-05-06T14:07:26+00:00"
         },
         {
-          "name": "Sebastian Heuer",
-          "email": "sebastian@phpeople.de",
-          "role": "Developer"
+            "name": "psr/cache",
+            "version": "1.0.1",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/php-fig/cache.git",
+                "reference": "d11b50ad223250cf17b86e38383413f5a6764bf8"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/php-fig/cache/zipball/d11b50ad223250cf17b86e38383413f5a6764bf8",
+                "reference": "d11b50ad223250cf17b86e38383413f5a6764bf8",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=5.3.0"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "1.0.x-dev"
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "Psr\\Cache\\": "src/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "PHP-FIG",
+                    "homepage": "http://www.php-fig.org/"
+                }
+            ],
+            "description": "Common interface for caching libraries",
+            "keywords": [
+                "cache",
+                "psr",
+                "psr-6"
+            ],
+            "time": "2016-08-06T20:24:11+00:00"
         },
         {
-          "name": "Sebastian Bergmann",
-          "email": "sebastian@phpunit.de",
-          "role": "Developer"
-        }
-      ],
-      "description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)",
-      "time": "2018-07-08T19:23:20+00:00"
-    },
-    {
-      "name": "phar-io/version",
-      "version": "2.0.1",
-      "source": {
-        "type": "git",
-        "url": "https://github.com/phar-io/version.git",
-        "reference": "45a2ec53a73c70ce41d55cedef9063630abaf1b6"
-      },
-      "dist": {
-        "type": "zip",
-        "url": "https://api.github.com/repos/phar-io/version/zipball/45a2ec53a73c70ce41d55cedef9063630abaf1b6",
-        "reference": "45a2ec53a73c70ce41d55cedef9063630abaf1b6",
-        "shasum": ""
-      },
-      "require": {
-        "php": "^5.6 || ^7.0"
-      },
-      "type": "library",
-      "autoload": {
-        "classmap": ["src/"]
-      },
-      "notification-url": "https://packagist.org/downloads/",
-      "license": ["BSD-3-Clause"],
-      "authors": [
-        {
-          "name": "Arne Blankerts",
-          "email": "arne@blankerts.de",
-          "role": "Developer"
+            "name": "psr/log",
+            "version": "1.1.3",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/php-fig/log.git",
+                "reference": "0f73288fd15629204f9d42b7055f72dacbe811fc"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/php-fig/log/zipball/0f73288fd15629204f9d42b7055f72dacbe811fc",
+                "reference": "0f73288fd15629204f9d42b7055f72dacbe811fc",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=5.3.0"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "1.1.x-dev"
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "Psr\\Log\\": "Psr/Log/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "PHP-FIG",
+                    "homepage": "http://www.php-fig.org/"
+                }
+            ],
+            "description": "Common interface for logging libraries",
+            "homepage": "https://github.com/php-fig/log",
+            "keywords": [
+                "log",
+                "psr",
+                "psr-3"
+            ],
+            "time": "2020-03-23T09:12:05+00:00"
         },
         {
-          "name": "Sebastian Heuer",
-          "email": "sebastian@phpeople.de",
-          "role": "Developer"
+            "name": "whichbrowser/parser",
+            "version": "v2.0.42",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/WhichBrowser/Parser-PHP.git",
+                "reference": "4899110cd2f87b01e04ced62dbb9dec541031dee"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/WhichBrowser/Parser-PHP/zipball/4899110cd2f87b01e04ced62dbb9dec541031dee",
+                "reference": "4899110cd2f87b01e04ced62dbb9dec541031dee",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=5.4.0",
+                "psr/cache": "^1.0"
+            },
+            "require-dev": {
+                "icomefromthenet/reverse-regex": "0.0.6.3",
+                "phpunit/php-code-coverage": "^2.2 || ^3.0",
+                "phpunit/phpunit": "^4.0 || ^5.0 || ^6.0 || ^7.0 || ^8.0",
+                "satooshi/php-coveralls": "^1.0",
+                "squizlabs/php_codesniffer": "2.5.*",
+                "symfony/yaml": "~2.8 || ~3.4 || ~4.2 || ~5.0"
+            },
+            "suggest": {
+                "cache/array-adapter": "Allows testing of the caching functionality"
+            },
+            "type": "library",
+            "autoload": {
+                "psr-4": {
+                    "WhichBrowser\\": [
+                        "src/",
+                        "tests/src/"
+                    ]
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Niels Leenheer",
+                    "email": "niels@leenheer.nl",
+                    "role": "Developer"
+                }
+            ],
+            "description": "Useragent sniffing library for PHP",
+            "homepage": "http://whichbrowser.net",
+            "keywords": [
+                "browser",
+                "sniffing",
+                "ua",
+                "useragent"
+            ],
+            "time": "2020-02-12T10:54:23+00:00"
+        }
+    ],
+    "packages-dev": [
+        {
+            "name": "doctrine/instantiator",
+            "version": "1.3.1",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/doctrine/instantiator.git",
+                "reference": "f350df0268e904597e3bd9c4685c53e0e333feea"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/doctrine/instantiator/zipball/f350df0268e904597e3bd9c4685c53e0e333feea",
+                "reference": "f350df0268e904597e3bd9c4685c53e0e333feea",
+                "shasum": ""
+            },
+            "require": {
+                "php": "^7.1 || ^8.0"
+            },
+            "require-dev": {
+                "doctrine/coding-standard": "^6.0",
+                "ext-pdo": "*",
+                "ext-phar": "*",
+                "phpbench/phpbench": "^0.13",
+                "phpstan/phpstan-phpunit": "^0.11",
+                "phpstan/phpstan-shim": "^0.11",
+                "phpunit/phpunit": "^7.0"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "1.2.x-dev"
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Marco Pivetta",
+                    "email": "ocramius@gmail.com",
+                    "homepage": "http://ocramius.github.com/"
+                }
+            ],
+            "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors",
+            "homepage": "https://www.doctrine-project.org/projects/instantiator.html",
+            "keywords": [
+                "constructor",
+                "instantiate"
+            ],
+            "funding": [
+                {
+                    "url": "https://www.doctrine-project.org/sponsorship.html",
+                    "type": "custom"
+                },
+                {
+                    "url": "https://www.patreon.com/phpdoctrine",
+                    "type": "patreon"
+                },
+                {
+                    "url": "https://tidelift.com/funding/github/packagist/doctrine%2Finstantiator",
+                    "type": "tidelift"
+                }
+            ],
+            "time": "2020-05-29T17:27:14+00:00"
         },
         {
-          "name": "Sebastian Bergmann",
-          "email": "sebastian@phpunit.de",
-          "role": "Developer"
-        }
-      ],
-      "description": "Library for handling version information and constraints",
-      "time": "2018-07-08T19:19:57+00:00"
-    },
-    {
-      "name": "phpdocumentor/reflection-common",
-      "version": "2.1.0",
-      "source": {
-        "type": "git",
-        "url": "https://github.com/phpDocumentor/ReflectionCommon.git",
-        "reference": "6568f4687e5b41b054365f9ae03fcb1ed5f2069b"
-      },
-      "dist": {
-        "type": "zip",
-        "url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/6568f4687e5b41b054365f9ae03fcb1ed5f2069b",
-        "reference": "6568f4687e5b41b054365f9ae03fcb1ed5f2069b",
-        "shasum": ""
-      },
-      "require": {
-        "php": ">=7.1"
-      },
-      "type": "library",
-      "extra": {
-        "branch-alias": {
-          "dev-master": "2.x-dev"
-        }
-      },
-      "autoload": {
-        "psr-4": {
-          "phpDocumentor\\Reflection\\": "src/"
-        }
-      },
-      "notification-url": "https://packagist.org/downloads/",
-      "license": ["MIT"],
-      "authors": [
-        {
-          "name": "Jaap van Otterdijk",
-          "email": "opensource@ijaap.nl"
-        }
-      ],
-      "description": "Common reflection classes used by phpdocumentor to reflect the code structure",
-      "homepage": "http://www.phpdoc.org",
-      "keywords": [
-        "FQSEN",
-        "phpDocumentor",
-        "phpdoc",
-        "reflection",
-        "static analysis"
-      ],
-      "time": "2020-04-27T09:25:28+00:00"
-    },
-    {
-      "name": "phpdocumentor/reflection-docblock",
-      "version": "5.1.0",
-      "source": {
-        "type": "git",
-        "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git",
-        "reference": "cd72d394ca794d3466a3b2fc09d5a6c1dc86b47e"
-      },
-      "dist": {
-        "type": "zip",
-        "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/cd72d394ca794d3466a3b2fc09d5a6c1dc86b47e",
-        "reference": "cd72d394ca794d3466a3b2fc09d5a6c1dc86b47e",
-        "shasum": ""
-      },
-      "require": {
-        "ext-filter": "^7.1",
-        "php": "^7.2",
-        "phpdocumentor/reflection-common": "^2.0",
-        "phpdocumentor/type-resolver": "^1.0",
-        "webmozart/assert": "^1"
-      },
-      "require-dev": {
-        "doctrine/instantiator": "^1",
-        "mockery/mockery": "^1"
-      },
-      "type": "library",
-      "extra": {
-        "branch-alias": {
-          "dev-master": "5.x-dev"
-        }
-      },
-      "autoload": {
-        "psr-4": {
-          "phpDocumentor\\Reflection\\": "src"
-        }
-      },
-      "notification-url": "https://packagist.org/downloads/",
-      "license": ["MIT"],
-      "authors": [
-        {
-          "name": "Mike van Riel",
-          "email": "me@mikevanriel.com"
+            "name": "mikey179/vfsstream",
+            "version": "v1.6.8",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/bovigo/vfsStream.git",
+                "reference": "231c73783ebb7dd9ec77916c10037eff5a2b6efe"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/bovigo/vfsStream/zipball/231c73783ebb7dd9ec77916c10037eff5a2b6efe",
+                "reference": "231c73783ebb7dd9ec77916c10037eff5a2b6efe",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=5.3.0"
+            },
+            "require-dev": {
+                "phpunit/phpunit": "^4.5|^5.0"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "1.6.x-dev"
+                }
+            },
+            "autoload": {
+                "psr-0": {
+                    "org\\bovigo\\vfs\\": "src/main/php"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "BSD-3-Clause"
+            ],
+            "authors": [
+                {
+                    "name": "Frank Kleine",
+                    "homepage": "http://frankkleine.de/",
+                    "role": "Developer"
+                }
+            ],
+            "description": "Virtual file system to mock the real file system in unit tests.",
+            "homepage": "http://vfs.bovigo.org/",
+            "time": "2019-10-30T15:31:00+00:00"
         },
         {
-          "name": "Jaap van Otterdijk",
-          "email": "account@ijaap.nl"
-        }
-      ],
-      "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.",
-      "time": "2020-02-22T12:28:44+00:00"
-    },
-    {
-      "name": "phpdocumentor/type-resolver",
-      "version": "1.1.0",
-      "source": {
-        "type": "git",
-        "url": "https://github.com/phpDocumentor/TypeResolver.git",
-        "reference": "7462d5f123dfc080dfdf26897032a6513644fc95"
-      },
-      "dist": {
-        "type": "zip",
-        "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/7462d5f123dfc080dfdf26897032a6513644fc95",
-        "reference": "7462d5f123dfc080dfdf26897032a6513644fc95",
-        "shasum": ""
-      },
-      "require": {
-        "php": "^7.2",
-        "phpdocumentor/reflection-common": "^2.0"
-      },
-      "require-dev": {
-        "ext-tokenizer": "^7.2",
-        "mockery/mockery": "~1"
-      },
-      "type": "library",
-      "extra": {
-        "branch-alias": {
-          "dev-master": "1.x-dev"
-        }
-      },
-      "autoload": {
-        "psr-4": {
-          "phpDocumentor\\Reflection\\": "src"
-        }
-      },
-      "notification-url": "https://packagist.org/downloads/",
-      "license": ["MIT"],
-      "authors": [
-        {
-          "name": "Mike van Riel",
-          "email": "me@mikevanriel.com"
-        }
-      ],
-      "description": "A PSR-5 based resolver of Class names, Types and Structural Element Names",
-      "time": "2020-02-18T18:59:58+00:00"
-    },
-    {
-      "name": "phpspec/prophecy",
-      "version": "v1.10.3",
-      "source": {
-        "type": "git",
-        "url": "https://github.com/phpspec/prophecy.git",
-        "reference": "451c3cd1418cf640de218914901e51b064abb093"
-      },
-      "dist": {
-        "type": "zip",
-        "url": "https://api.github.com/repos/phpspec/prophecy/zipball/451c3cd1418cf640de218914901e51b064abb093",
-        "reference": "451c3cd1418cf640de218914901e51b064abb093",
-        "shasum": ""
-      },
-      "require": {
-        "doctrine/instantiator": "^1.0.2",
-        "php": "^5.3|^7.0",
-        "phpdocumentor/reflection-docblock": "^2.0|^3.0.2|^4.0|^5.0",
-        "sebastian/comparator": "^1.2.3|^2.0|^3.0|^4.0",
-        "sebastian/recursion-context": "^1.0|^2.0|^3.0|^4.0"
-      },
-      "require-dev": {
-        "phpspec/phpspec": "^2.5 || ^3.2",
-        "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.5 || ^7.1"
-      },
-      "type": "library",
-      "extra": {
-        "branch-alias": {
-          "dev-master": "1.10.x-dev"
-        }
-      },
-      "autoload": {
-        "psr-4": {
-          "Prophecy\\": "src/Prophecy"
-        }
-      },
-      "notification-url": "https://packagist.org/downloads/",
-      "license": ["MIT"],
-      "authors": [
-        {
-          "name": "Konstantin Kudryashov",
-          "email": "ever.zet@gmail.com",
-          "homepage": "http://everzet.com"
+            "name": "myclabs/deep-copy",
+            "version": "1.9.5",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/myclabs/DeepCopy.git",
+                "reference": "b2c28789e80a97badd14145fda39b545d83ca3ef"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/b2c28789e80a97badd14145fda39b545d83ca3ef",
+                "reference": "b2c28789e80a97badd14145fda39b545d83ca3ef",
+                "shasum": ""
+            },
+            "require": {
+                "php": "^7.1"
+            },
+            "replace": {
+                "myclabs/deep-copy": "self.version"
+            },
+            "require-dev": {
+                "doctrine/collections": "^1.0",
+                "doctrine/common": "^2.6",
+                "phpunit/phpunit": "^7.1"
+            },
+            "type": "library",
+            "autoload": {
+                "psr-4": {
+                    "DeepCopy\\": "src/DeepCopy/"
+                },
+                "files": [
+                    "src/DeepCopy/deep_copy.php"
+                ]
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "description": "Create deep copies (clones) of your objects",
+            "keywords": [
+                "clone",
+                "copy",
+                "duplicate",
+                "object",
+                "object graph"
+            ],
+            "time": "2020-01-17T21:11:47+00:00"
         },
         {
-          "name": "Marcello Duarte",
-          "email": "marcello.duarte@gmail.com"
-        }
-      ],
-      "description": "Highly opinionated mocking framework for PHP 5.3+",
-      "homepage": "https://github.com/phpspec/prophecy",
-      "keywords": ["Double", "Dummy", "fake", "mock", "spy", "stub"],
-      "time": "2020-03-05T15:02:03+00:00"
-    },
-    {
-      "name": "phpunit/php-code-coverage",
-      "version": "7.0.10",
-      "source": {
-        "type": "git",
-        "url": "https://github.com/sebastianbergmann/php-code-coverage.git",
-        "reference": "f1884187926fbb755a9aaf0b3836ad3165b478bf"
-      },
-      "dist": {
-        "type": "zip",
-        "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/f1884187926fbb755a9aaf0b3836ad3165b478bf",
-        "reference": "f1884187926fbb755a9aaf0b3836ad3165b478bf",
-        "shasum": ""
-      },
-      "require": {
-        "ext-dom": "*",
-        "ext-xmlwriter": "*",
-        "php": "^7.2",
-        "phpunit/php-file-iterator": "^2.0.2",
-        "phpunit/php-text-template": "^1.2.1",
-        "phpunit/php-token-stream": "^3.1.1",
-        "sebastian/code-unit-reverse-lookup": "^1.0.1",
-        "sebastian/environment": "^4.2.2",
-        "sebastian/version": "^2.0.1",
-        "theseer/tokenizer": "^1.1.3"
-      },
-      "require-dev": {
-        "phpunit/phpunit": "^8.2.2"
-      },
-      "suggest": {
-        "ext-xdebug": "^2.7.2"
-      },
-      "type": "library",
-      "extra": {
-        "branch-alias": {
-          "dev-master": "7.0-dev"
-        }
-      },
-      "autoload": {
-        "classmap": ["src/"]
-      },
-      "notification-url": "https://packagist.org/downloads/",
-      "license": ["BSD-3-Clause"],
-      "authors": [
-        {
-          "name": "Sebastian Bergmann",
-          "email": "sebastian@phpunit.de",
-          "role": "lead"
-        }
-      ],
-      "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.",
-      "homepage": "https://github.com/sebastianbergmann/php-code-coverage",
-      "keywords": ["coverage", "testing", "xunit"],
-      "time": "2019-11-20T13:55:58+00:00"
-    },
-    {
-      "name": "phpunit/php-file-iterator",
-      "version": "2.0.2",
-      "source": {
-        "type": "git",
-        "url": "https://github.com/sebastianbergmann/php-file-iterator.git",
-        "reference": "050bedf145a257b1ff02746c31894800e5122946"
-      },
-      "dist": {
-        "type": "zip",
-        "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/050bedf145a257b1ff02746c31894800e5122946",
-        "reference": "050bedf145a257b1ff02746c31894800e5122946",
-        "shasum": ""
-      },
-      "require": {
-        "php": "^7.1"
-      },
-      "require-dev": {
-        "phpunit/phpunit": "^7.1"
-      },
-      "type": "library",
-      "extra": {
-        "branch-alias": {
-          "dev-master": "2.0.x-dev"
-        }
-      },
-      "autoload": {
-        "classmap": ["src/"]
-      },
-      "notification-url": "https://packagist.org/downloads/",
-      "license": ["BSD-3-Clause"],
-      "authors": [
-        {
-          "name": "Sebastian Bergmann",
-          "email": "sebastian@phpunit.de",
-          "role": "lead"
-        }
-      ],
-      "description": "FilterIterator implementation that filters files based on a list of suffixes.",
-      "homepage": "https://github.com/sebastianbergmann/php-file-iterator/",
-      "keywords": ["filesystem", "iterator"],
-      "time": "2018-09-13T20:33:42+00:00"
-    },
-    {
-      "name": "phpunit/php-text-template",
-      "version": "1.2.1",
-      "source": {
-        "type": "git",
-        "url": "https://github.com/sebastianbergmann/php-text-template.git",
-        "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686"
-      },
-      "dist": {
-        "type": "zip",
-        "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/31f8b717e51d9a2afca6c9f046f5d69fc27c8686",
-        "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686",
-        "shasum": ""
-      },
-      "require": {
-        "php": ">=5.3.3"
-      },
-      "type": "library",
-      "autoload": {
-        "classmap": ["src/"]
-      },
-      "notification-url": "https://packagist.org/downloads/",
-      "license": ["BSD-3-Clause"],
-      "authors": [
-        {
-          "name": "Sebastian Bergmann",
-          "email": "sebastian@phpunit.de",
-          "role": "lead"
-        }
-      ],
-      "description": "Simple template engine.",
-      "homepage": "https://github.com/sebastianbergmann/php-text-template/",
-      "keywords": ["template"],
-      "time": "2015-06-21T13:50:34+00:00"
-    },
-    {
-      "name": "phpunit/php-timer",
-      "version": "2.1.2",
-      "source": {
-        "type": "git",
-        "url": "https://github.com/sebastianbergmann/php-timer.git",
-        "reference": "1038454804406b0b5f5f520358e78c1c2f71501e"
-      },
-      "dist": {
-        "type": "zip",
-        "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/1038454804406b0b5f5f520358e78c1c2f71501e",
-        "reference": "1038454804406b0b5f5f520358e78c1c2f71501e",
-        "shasum": ""
-      },
-      "require": {
-        "php": "^7.1"
-      },
-      "require-dev": {
-        "phpunit/phpunit": "^7.0"
-      },
-      "type": "library",
-      "extra": {
-        "branch-alias": {
-          "dev-master": "2.1-dev"
-        }
-      },
-      "autoload": {
-        "classmap": ["src/"]
-      },
-      "notification-url": "https://packagist.org/downloads/",
-      "license": ["BSD-3-Clause"],
-      "authors": [
-        {
-          "name": "Sebastian Bergmann",
-          "email": "sebastian@phpunit.de",
-          "role": "lead"
-        }
-      ],
-      "description": "Utility class for timing",
-      "homepage": "https://github.com/sebastianbergmann/php-timer/",
-      "keywords": ["timer"],
-      "time": "2019-06-07T04:22:29+00:00"
-    },
-    {
-      "name": "phpunit/php-token-stream",
-      "version": "3.1.1",
-      "source": {
-        "type": "git",
-        "url": "https://github.com/sebastianbergmann/php-token-stream.git",
-        "reference": "995192df77f63a59e47f025390d2d1fdf8f425ff"
-      },
-      "dist": {
-        "type": "zip",
-        "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/995192df77f63a59e47f025390d2d1fdf8f425ff",
-        "reference": "995192df77f63a59e47f025390d2d1fdf8f425ff",
-        "shasum": ""
-      },
-      "require": {
-        "ext-tokenizer": "*",
-        "php": "^7.1"
-      },
-      "require-dev": {
-        "phpunit/phpunit": "^7.0"
-      },
-      "type": "library",
-      "extra": {
-        "branch-alias": {
-          "dev-master": "3.1-dev"
-        }
-      },
-      "autoload": {
-        "classmap": ["src/"]
-      },
-      "notification-url": "https://packagist.org/downloads/",
-      "license": ["BSD-3-Clause"],
-      "authors": [
-        {
-          "name": "Sebastian Bergmann",
-          "email": "sebastian@phpunit.de"
-        }
-      ],
-      "description": "Wrapper around PHP's tokenizer extension.",
-      "homepage": "https://github.com/sebastianbergmann/php-token-stream/",
-      "keywords": ["tokenizer"],
-      "time": "2019-09-17T06:23:10+00:00"
-    },
-    {
-      "name": "phpunit/phpunit",
-      "version": "8.5.5",
-      "source": {
-        "type": "git",
-        "url": "https://github.com/sebastianbergmann/phpunit.git",
-        "reference": "63dda3b212a0025d380a745f91bdb4d8c985adb7"
-      },
-      "dist": {
-        "type": "zip",
-        "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/63dda3b212a0025d380a745f91bdb4d8c985adb7",
-        "reference": "63dda3b212a0025d380a745f91bdb4d8c985adb7",
-        "shasum": ""
-      },
-      "require": {
-        "doctrine/instantiator": "^1.2.0",
-        "ext-dom": "*",
-        "ext-json": "*",
-        "ext-libxml": "*",
-        "ext-mbstring": "*",
-        "ext-xml": "*",
-        "ext-xmlwriter": "*",
-        "myclabs/deep-copy": "^1.9.1",
-        "phar-io/manifest": "^1.0.3",
-        "phar-io/version": "^2.0.1",
-        "php": "^7.2",
-        "phpspec/prophecy": "^1.8.1",
-        "phpunit/php-code-coverage": "^7.0.7",
-        "phpunit/php-file-iterator": "^2.0.2",
-        "phpunit/php-text-template": "^1.2.1",
-        "phpunit/php-timer": "^2.1.2",
-        "sebastian/comparator": "^3.0.2",
-        "sebastian/diff": "^3.0.2",
-        "sebastian/environment": "^4.2.2",
-        "sebastian/exporter": "^3.1.1",
-        "sebastian/global-state": "^3.0.0",
-        "sebastian/object-enumerator": "^3.0.3",
-        "sebastian/resource-operations": "^2.0.1",
-        "sebastian/type": "^1.1.3",
-        "sebastian/version": "^2.0.1"
-      },
-      "require-dev": {
-        "ext-pdo": "*"
-      },
-      "suggest": {
-        "ext-soap": "*",
-        "ext-xdebug": "*",
-        "phpunit/php-invoker": "^2.0.0"
-      },
-      "bin": ["phpunit"],
-      "type": "library",
-      "extra": {
-        "branch-alias": {
-          "dev-master": "8.5-dev"
-        }
-      },
-      "autoload": {
-        "classmap": ["src/"]
-      },
-      "notification-url": "https://packagist.org/downloads/",
-      "license": ["BSD-3-Clause"],
-      "authors": [
-        {
-          "name": "Sebastian Bergmann",
-          "email": "sebastian@phpunit.de",
-          "role": "lead"
-        }
-      ],
-      "description": "The PHP Unit Testing framework.",
-      "homepage": "https://phpunit.de/",
-      "keywords": ["phpunit", "testing", "xunit"],
-      "funding": [
-        {
-          "url": "https://phpunit.de/donate.html",
-          "type": "custom"
+            "name": "phar-io/manifest",
+            "version": "1.0.3",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/phar-io/manifest.git",
+                "reference": "7761fcacf03b4d4f16e7ccb606d4879ca431fcf4"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/phar-io/manifest/zipball/7761fcacf03b4d4f16e7ccb606d4879ca431fcf4",
+                "reference": "7761fcacf03b4d4f16e7ccb606d4879ca431fcf4",
+                "shasum": ""
+            },
+            "require": {
+                "ext-dom": "*",
+                "ext-phar": "*",
+                "phar-io/version": "^2.0",
+                "php": "^5.6 || ^7.0"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "1.0.x-dev"
+                }
+            },
+            "autoload": {
+                "classmap": [
+                    "src/"
+                ]
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "BSD-3-Clause"
+            ],
+            "authors": [
+                {
+                    "name": "Arne Blankerts",
+                    "email": "arne@blankerts.de",
+                    "role": "Developer"
+                },
+                {
+                    "name": "Sebastian Heuer",
+                    "email": "sebastian@phpeople.de",
+                    "role": "Developer"
+                },
+                {
+                    "name": "Sebastian Bergmann",
+                    "email": "sebastian@phpunit.de",
+                    "role": "Developer"
+                }
+            ],
+            "description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)",
+            "time": "2018-07-08T19:23:20+00:00"
         },
         {
-          "url": "https://github.com/sebastianbergmann",
-          "type": "github"
-        }
-      ],
-      "time": "2020-05-22T13:51:52+00:00"
-    },
-    {
-      "name": "sebastian/code-unit-reverse-lookup",
-      "version": "1.0.1",
-      "source": {
-        "type": "git",
-        "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git",
-        "reference": "4419fcdb5eabb9caa61a27c7a1db532a6b55dd18"
-      },
-      "dist": {
-        "type": "zip",
-        "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/4419fcdb5eabb9caa61a27c7a1db532a6b55dd18",
-        "reference": "4419fcdb5eabb9caa61a27c7a1db532a6b55dd18",
-        "shasum": ""
-      },
-      "require": {
-        "php": "^5.6 || ^7.0"
-      },
-      "require-dev": {
-        "phpunit/phpunit": "^5.7 || ^6.0"
-      },
-      "type": "library",
-      "extra": {
-        "branch-alias": {
-          "dev-master": "1.0.x-dev"
-        }
-      },
-      "autoload": {
-        "classmap": ["src/"]
-      },
-      "notification-url": "https://packagist.org/downloads/",
-      "license": ["BSD-3-Clause"],
-      "authors": [
-        {
-          "name": "Sebastian Bergmann",
-          "email": "sebastian@phpunit.de"
-        }
-      ],
-      "description": "Looks up which function or method a line of code belongs to",
-      "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/",
-      "time": "2017-03-04T06:30:41+00:00"
-    },
-    {
-      "name": "sebastian/comparator",
-      "version": "3.0.2",
-      "source": {
-        "type": "git",
-        "url": "https://github.com/sebastianbergmann/comparator.git",
-        "reference": "5de4fc177adf9bce8df98d8d141a7559d7ccf6da"
-      },
-      "dist": {
-        "type": "zip",
-        "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/5de4fc177adf9bce8df98d8d141a7559d7ccf6da",
-        "reference": "5de4fc177adf9bce8df98d8d141a7559d7ccf6da",
-        "shasum": ""
-      },
-      "require": {
-        "php": "^7.1",
-        "sebastian/diff": "^3.0",
-        "sebastian/exporter": "^3.1"
-      },
-      "require-dev": {
-        "phpunit/phpunit": "^7.1"
-      },
-      "type": "library",
-      "extra": {
-        "branch-alias": {
-          "dev-master": "3.0-dev"
-        }
-      },
-      "autoload": {
-        "classmap": ["src/"]
-      },
-      "notification-url": "https://packagist.org/downloads/",
-      "license": ["BSD-3-Clause"],
-      "authors": [
-        {
-          "name": "Jeff Welch",
-          "email": "whatthejeff@gmail.com"
+            "name": "phar-io/version",
+            "version": "2.0.1",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/phar-io/version.git",
+                "reference": "45a2ec53a73c70ce41d55cedef9063630abaf1b6"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/phar-io/version/zipball/45a2ec53a73c70ce41d55cedef9063630abaf1b6",
+                "reference": "45a2ec53a73c70ce41d55cedef9063630abaf1b6",
+                "shasum": ""
+            },
+            "require": {
+                "php": "^5.6 || ^7.0"
+            },
+            "type": "library",
+            "autoload": {
+                "classmap": [
+                    "src/"
+                ]
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "BSD-3-Clause"
+            ],
+            "authors": [
+                {
+                    "name": "Arne Blankerts",
+                    "email": "arne@blankerts.de",
+                    "role": "Developer"
+                },
+                {
+                    "name": "Sebastian Heuer",
+                    "email": "sebastian@phpeople.de",
+                    "role": "Developer"
+                },
+                {
+                    "name": "Sebastian Bergmann",
+                    "email": "sebastian@phpunit.de",
+                    "role": "Developer"
+                }
+            ],
+            "description": "Library for handling version information and constraints",
+            "time": "2018-07-08T19:19:57+00:00"
         },
         {
-          "name": "Volker Dusch",
-          "email": "github@wallbash.com"
+            "name": "phpdocumentor/reflection-common",
+            "version": "2.1.0",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/phpDocumentor/ReflectionCommon.git",
+                "reference": "6568f4687e5b41b054365f9ae03fcb1ed5f2069b"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/6568f4687e5b41b054365f9ae03fcb1ed5f2069b",
+                "reference": "6568f4687e5b41b054365f9ae03fcb1ed5f2069b",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=7.1"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "2.x-dev"
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "phpDocumentor\\Reflection\\": "src/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Jaap van Otterdijk",
+                    "email": "opensource@ijaap.nl"
+                }
+            ],
+            "description": "Common reflection classes used by phpdocumentor to reflect the code structure",
+            "homepage": "http://www.phpdoc.org",
+            "keywords": [
+                "FQSEN",
+                "phpDocumentor",
+                "phpdoc",
+                "reflection",
+                "static analysis"
+            ],
+            "time": "2020-04-27T09:25:28+00:00"
         },
         {
-          "name": "Bernhard Schussek",
-          "email": "bschussek@2bepublished.at"
+            "name": "phpdocumentor/reflection-docblock",
+            "version": "5.1.0",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git",
+                "reference": "cd72d394ca794d3466a3b2fc09d5a6c1dc86b47e"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/cd72d394ca794d3466a3b2fc09d5a6c1dc86b47e",
+                "reference": "cd72d394ca794d3466a3b2fc09d5a6c1dc86b47e",
+                "shasum": ""
+            },
+            "require": {
+                "ext-filter": "^7.1",
+                "php": "^7.2",
+                "phpdocumentor/reflection-common": "^2.0",
+                "phpdocumentor/type-resolver": "^1.0",
+                "webmozart/assert": "^1"
+            },
+            "require-dev": {
+                "doctrine/instantiator": "^1",
+                "mockery/mockery": "^1"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "5.x-dev"
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "phpDocumentor\\Reflection\\": "src"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Mike van Riel",
+                    "email": "me@mikevanriel.com"
+                },
+                {
+                    "name": "Jaap van Otterdijk",
+                    "email": "account@ijaap.nl"
+                }
+            ],
+            "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.",
+            "time": "2020-02-22T12:28:44+00:00"
         },
         {
-          "name": "Sebastian Bergmann",
-          "email": "sebastian@phpunit.de"
-        }
-      ],
-      "description": "Provides the functionality to compare PHP values for equality",
-      "homepage": "https://github.com/sebastianbergmann/comparator",
-      "keywords": ["comparator", "compare", "equality"],
-      "time": "2018-07-12T15:12:46+00:00"
-    },
-    {
-      "name": "sebastian/diff",
-      "version": "3.0.2",
-      "source": {
-        "type": "git",
-        "url": "https://github.com/sebastianbergmann/diff.git",
-        "reference": "720fcc7e9b5cf384ea68d9d930d480907a0c1a29"
-      },
-      "dist": {
-        "type": "zip",
-        "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/720fcc7e9b5cf384ea68d9d930d480907a0c1a29",
-        "reference": "720fcc7e9b5cf384ea68d9d930d480907a0c1a29",
-        "shasum": ""
-      },
-      "require": {
-        "php": "^7.1"
-      },
-      "require-dev": {
-        "phpunit/phpunit": "^7.5 || ^8.0",
-        "symfony/process": "^2 || ^3.3 || ^4"
-      },
-      "type": "library",
-      "extra": {
-        "branch-alias": {
-          "dev-master": "3.0-dev"
-        }
-      },
-      "autoload": {
-        "classmap": ["src/"]
-      },
-      "notification-url": "https://packagist.org/downloads/",
-      "license": ["BSD-3-Clause"],
-      "authors": [
+            "name": "phpdocumentor/type-resolver",
+            "version": "1.2.0",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/phpDocumentor/TypeResolver.git",
+                "reference": "30441f2752e493c639526b215ed81d54f369d693"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/30441f2752e493c639526b215ed81d54f369d693",
+                "reference": "30441f2752e493c639526b215ed81d54f369d693",
+                "shasum": ""
+            },
+            "require": {
+                "php": "^7.2",
+                "phpdocumentor/reflection-common": "^2.0"
+            },
+            "require-dev": {
+                "ext-tokenizer": "^7.2",
+                "mockery/mockery": "~1"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-1.x": "1.x-dev"
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "phpDocumentor\\Reflection\\": "src"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Mike van Riel",
+                    "email": "me@mikevanriel.com"
+                }
+            ],
+            "description": "A PSR-5 based resolver of Class names, Types and Structural Element Names",
+            "time": "2020-06-19T20:22:09+00:00"
+        },
         {
-          "name": "Kore Nordmann",
-          "email": "mail@kore-nordmann.de"
+            "name": "phpspec/prophecy",
+            "version": "v1.10.3",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/phpspec/prophecy.git",
+                "reference": "451c3cd1418cf640de218914901e51b064abb093"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/phpspec/prophecy/zipball/451c3cd1418cf640de218914901e51b064abb093",
+                "reference": "451c3cd1418cf640de218914901e51b064abb093",
+                "shasum": ""
+            },
+            "require": {
+                "doctrine/instantiator": "^1.0.2",
+                "php": "^5.3|^7.0",
+                "phpdocumentor/reflection-docblock": "^2.0|^3.0.2|^4.0|^5.0",
+                "sebastian/comparator": "^1.2.3|^2.0|^3.0|^4.0",
+                "sebastian/recursion-context": "^1.0|^2.0|^3.0|^4.0"
+            },
+            "require-dev": {
+                "phpspec/phpspec": "^2.5 || ^3.2",
+                "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.5 || ^7.1"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "1.10.x-dev"
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "Prophecy\\": "src/Prophecy"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Konstantin Kudryashov",
+                    "email": "ever.zet@gmail.com",
+                    "homepage": "http://everzet.com"
+                },
+                {
+                    "name": "Marcello Duarte",
+                    "email": "marcello.duarte@gmail.com"
+                }
+            ],
+            "description": "Highly opinionated mocking framework for PHP 5.3+",
+            "homepage": "https://github.com/phpspec/prophecy",
+            "keywords": [
+                "Double",
+                "Dummy",
+                "fake",
+                "mock",
+                "spy",
+                "stub"
+            ],
+            "time": "2020-03-05T15:02:03+00:00"
         },
         {
-          "name": "Sebastian Bergmann",
-          "email": "sebastian@phpunit.de"
-        }
-      ],
-      "description": "Diff implementation",
-      "homepage": "https://github.com/sebastianbergmann/diff",
-      "keywords": ["diff", "udiff", "unidiff", "unified diff"],
-      "time": "2019-02-04T06:01:07+00:00"
-    },
-    {
-      "name": "sebastian/environment",
-      "version": "4.2.3",
-      "source": {
-        "type": "git",
-        "url": "https://github.com/sebastianbergmann/environment.git",
-        "reference": "464c90d7bdf5ad4e8a6aea15c091fec0603d4368"
-      },
-      "dist": {
-        "type": "zip",
-        "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/464c90d7bdf5ad4e8a6aea15c091fec0603d4368",
-        "reference": "464c90d7bdf5ad4e8a6aea15c091fec0603d4368",
-        "shasum": ""
-      },
-      "require": {
-        "php": "^7.1"
-      },
-      "require-dev": {
-        "phpunit/phpunit": "^7.5"
-      },
-      "suggest": {
-        "ext-posix": "*"
-      },
-      "type": "library",
-      "extra": {
-        "branch-alias": {
-          "dev-master": "4.2-dev"
-        }
-      },
-      "autoload": {
-        "classmap": ["src/"]
-      },
-      "notification-url": "https://packagist.org/downloads/",
-      "license": ["BSD-3-Clause"],
-      "authors": [
+            "name": "phpunit/php-code-coverage",
+            "version": "7.0.10",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/sebastianbergmann/php-code-coverage.git",
+                "reference": "f1884187926fbb755a9aaf0b3836ad3165b478bf"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/f1884187926fbb755a9aaf0b3836ad3165b478bf",
+                "reference": "f1884187926fbb755a9aaf0b3836ad3165b478bf",
+                "shasum": ""
+            },
+            "require": {
+                "ext-dom": "*",
+                "ext-xmlwriter": "*",
+                "php": "^7.2",
+                "phpunit/php-file-iterator": "^2.0.2",
+                "phpunit/php-text-template": "^1.2.1",
+                "phpunit/php-token-stream": "^3.1.1",
+                "sebastian/code-unit-reverse-lookup": "^1.0.1",
+                "sebastian/environment": "^4.2.2",
+                "sebastian/version": "^2.0.1",
+                "theseer/tokenizer": "^1.1.3"
+            },
+            "require-dev": {
+                "phpunit/phpunit": "^8.2.2"
+            },
+            "suggest": {
+                "ext-xdebug": "^2.7.2"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "7.0-dev"
+                }
+            },
+            "autoload": {
+                "classmap": [
+                    "src/"
+                ]
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "BSD-3-Clause"
+            ],
+            "authors": [
+                {
+                    "name": "Sebastian Bergmann",
+                    "email": "sebastian@phpunit.de",
+                    "role": "lead"
+                }
+            ],
+            "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.",
+            "homepage": "https://github.com/sebastianbergmann/php-code-coverage",
+            "keywords": [
+                "coverage",
+                "testing",
+                "xunit"
+            ],
+            "time": "2019-11-20T13:55:58+00:00"
+        },
         {
-          "name": "Sebastian Bergmann",
-          "email": "sebastian@phpunit.de"
-        }
-      ],
-      "description": "Provides functionality to handle HHVM/PHP environments",
-      "homepage": "http://www.github.com/sebastianbergmann/environment",
-      "keywords": ["Xdebug", "environment", "hhvm"],
-      "time": "2019-11-20T08:46:58+00:00"
-    },
-    {
-      "name": "sebastian/exporter",
-      "version": "3.1.2",
-      "source": {
-        "type": "git",
-        "url": "https://github.com/sebastianbergmann/exporter.git",
-        "reference": "68609e1261d215ea5b21b7987539cbfbe156ec3e"
-      },
-      "dist": {
-        "type": "zip",
-        "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/68609e1261d215ea5b21b7987539cbfbe156ec3e",
-        "reference": "68609e1261d215ea5b21b7987539cbfbe156ec3e",
-        "shasum": ""
-      },
-      "require": {
-        "php": "^7.0",
-        "sebastian/recursion-context": "^3.0"
-      },
-      "require-dev": {
-        "ext-mbstring": "*",
-        "phpunit/phpunit": "^6.0"
-      },
-      "type": "library",
-      "extra": {
-        "branch-alias": {
-          "dev-master": "3.1.x-dev"
-        }
-      },
-      "autoload": {
-        "classmap": ["src/"]
-      },
-      "notification-url": "https://packagist.org/downloads/",
-      "license": ["BSD-3-Clause"],
-      "authors": [
+            "name": "phpunit/php-file-iterator",
+            "version": "2.0.2",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/sebastianbergmann/php-file-iterator.git",
+                "reference": "050bedf145a257b1ff02746c31894800e5122946"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/050bedf145a257b1ff02746c31894800e5122946",
+                "reference": "050bedf145a257b1ff02746c31894800e5122946",
+                "shasum": ""
+            },
+            "require": {
+                "php": "^7.1"
+            },
+            "require-dev": {
+                "phpunit/phpunit": "^7.1"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "2.0.x-dev"
+                }
+            },
+            "autoload": {
+                "classmap": [
+                    "src/"
+                ]
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "BSD-3-Clause"
+            ],
+            "authors": [
+                {
+                    "name": "Sebastian Bergmann",
+                    "email": "sebastian@phpunit.de",
+                    "role": "lead"
+                }
+            ],
+            "description": "FilterIterator implementation that filters files based on a list of suffixes.",
+            "homepage": "https://github.com/sebastianbergmann/php-file-iterator/",
+            "keywords": [
+                "filesystem",
+                "iterator"
+            ],
+            "time": "2018-09-13T20:33:42+00:00"
+        },
         {
-          "name": "Sebastian Bergmann",
-          "email": "sebastian@phpunit.de"
+            "name": "phpunit/php-text-template",
+            "version": "1.2.1",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/sebastianbergmann/php-text-template.git",
+                "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/31f8b717e51d9a2afca6c9f046f5d69fc27c8686",
+                "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=5.3.3"
+            },
+            "type": "library",
+            "autoload": {
+                "classmap": [
+                    "src/"
+                ]
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "BSD-3-Clause"
+            ],
+            "authors": [
+                {
+                    "name": "Sebastian Bergmann",
+                    "email": "sebastian@phpunit.de",
+                    "role": "lead"
+                }
+            ],
+            "description": "Simple template engine.",
+            "homepage": "https://github.com/sebastianbergmann/php-text-template/",
+            "keywords": [
+                "template"
+            ],
+            "time": "2015-06-21T13:50:34+00:00"
         },
         {
-          "name": "Jeff Welch",
-          "email": "whatthejeff@gmail.com"
+            "name": "phpunit/php-timer",
+            "version": "2.1.2",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/sebastianbergmann/php-timer.git",
+                "reference": "1038454804406b0b5f5f520358e78c1c2f71501e"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/1038454804406b0b5f5f520358e78c1c2f71501e",
+                "reference": "1038454804406b0b5f5f520358e78c1c2f71501e",
+                "shasum": ""
+            },
+            "require": {
+                "php": "^7.1"
+            },
+            "require-dev": {
+                "phpunit/phpunit": "^7.0"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "2.1-dev"
+                }
+            },
+            "autoload": {
+                "classmap": [
+                    "src/"
+                ]
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "BSD-3-Clause"
+            ],
+            "authors": [
+                {
+                    "name": "Sebastian Bergmann",
+                    "email": "sebastian@phpunit.de",
+                    "role": "lead"
+                }
+            ],
+            "description": "Utility class for timing",
+            "homepage": "https://github.com/sebastianbergmann/php-timer/",
+            "keywords": [
+                "timer"
+            ],
+            "time": "2019-06-07T04:22:29+00:00"
         },
         {
-          "name": "Volker Dusch",
-          "email": "github@wallbash.com"
+            "name": "phpunit/php-token-stream",
+            "version": "3.1.1",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/sebastianbergmann/php-token-stream.git",
+                "reference": "995192df77f63a59e47f025390d2d1fdf8f425ff"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/995192df77f63a59e47f025390d2d1fdf8f425ff",
+                "reference": "995192df77f63a59e47f025390d2d1fdf8f425ff",
+                "shasum": ""
+            },
+            "require": {
+                "ext-tokenizer": "*",
+                "php": "^7.1"
+            },
+            "require-dev": {
+                "phpunit/phpunit": "^7.0"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "3.1-dev"
+                }
+            },
+            "autoload": {
+                "classmap": [
+                    "src/"
+                ]
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "BSD-3-Clause"
+            ],
+            "authors": [
+                {
+                    "name": "Sebastian Bergmann",
+                    "email": "sebastian@phpunit.de"
+                }
+            ],
+            "description": "Wrapper around PHP's tokenizer extension.",
+            "homepage": "https://github.com/sebastianbergmann/php-token-stream/",
+            "keywords": [
+                "tokenizer"
+            ],
+            "time": "2019-09-17T06:23:10+00:00"
         },
         {
-          "name": "Adam Harvey",
-          "email": "aharvey@php.net"
+            "name": "phpunit/phpunit",
+            "version": "8.5.8",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/sebastianbergmann/phpunit.git",
+                "reference": "34c18baa6a44f1d1fbf0338907139e9dce95b997"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/34c18baa6a44f1d1fbf0338907139e9dce95b997",
+                "reference": "34c18baa6a44f1d1fbf0338907139e9dce95b997",
+                "shasum": ""
+            },
+            "require": {
+                "doctrine/instantiator": "^1.2.0",
+                "ext-dom": "*",
+                "ext-json": "*",
+                "ext-libxml": "*",
+                "ext-mbstring": "*",
+                "ext-xml": "*",
+                "ext-xmlwriter": "*",
+                "myclabs/deep-copy": "^1.9.1",
+                "phar-io/manifest": "^1.0.3",
+                "phar-io/version": "^2.0.1",
+                "php": "^7.2",
+                "phpspec/prophecy": "^1.8.1",
+                "phpunit/php-code-coverage": "^7.0.7",
+                "phpunit/php-file-iterator": "^2.0.2",
+                "phpunit/php-text-template": "^1.2.1",
+                "phpunit/php-timer": "^2.1.2",
+                "sebastian/comparator": "^3.0.2",
+                "sebastian/diff": "^3.0.2",
+                "sebastian/environment": "^4.2.2",
+                "sebastian/exporter": "^3.1.1",
+                "sebastian/global-state": "^3.0.0",
+                "sebastian/object-enumerator": "^3.0.3",
+                "sebastian/resource-operations": "^2.0.1",
+                "sebastian/type": "^1.1.3",
+                "sebastian/version": "^2.0.1"
+            },
+            "require-dev": {
+                "ext-pdo": "*"
+            },
+            "suggest": {
+                "ext-soap": "*",
+                "ext-xdebug": "*",
+                "phpunit/php-invoker": "^2.0.0"
+            },
+            "bin": [
+                "phpunit"
+            ],
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "8.5-dev"
+                }
+            },
+            "autoload": {
+                "classmap": [
+                    "src/"
+                ]
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "BSD-3-Clause"
+            ],
+            "authors": [
+                {
+                    "name": "Sebastian Bergmann",
+                    "email": "sebastian@phpunit.de",
+                    "role": "lead"
+                }
+            ],
+            "description": "The PHP Unit Testing framework.",
+            "homepage": "https://phpunit.de/",
+            "keywords": [
+                "phpunit",
+                "testing",
+                "xunit"
+            ],
+            "funding": [
+                {
+                    "url": "https://phpunit.de/donate.html",
+                    "type": "custom"
+                },
+                {
+                    "url": "https://github.com/sebastianbergmann",
+                    "type": "github"
+                }
+            ],
+            "time": "2020-06-22T07:06:58+00:00"
         },
         {
-          "name": "Bernhard Schussek",
-          "email": "bschussek@gmail.com"
-        }
-      ],
-      "description": "Provides the functionality to export PHP variables for visualization",
-      "homepage": "http://www.github.com/sebastianbergmann/exporter",
-      "keywords": ["export", "exporter"],
-      "time": "2019-09-14T09:02:43+00:00"
-    },
-    {
-      "name": "sebastian/global-state",
-      "version": "3.0.0",
-      "source": {
-        "type": "git",
-        "url": "https://github.com/sebastianbergmann/global-state.git",
-        "reference": "edf8a461cf1d4005f19fb0b6b8b95a9f7fa0adc4"
-      },
-      "dist": {
-        "type": "zip",
-        "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/edf8a461cf1d4005f19fb0b6b8b95a9f7fa0adc4",
-        "reference": "edf8a461cf1d4005f19fb0b6b8b95a9f7fa0adc4",
-        "shasum": ""
-      },
-      "require": {
-        "php": "^7.2",
-        "sebastian/object-reflector": "^1.1.1",
-        "sebastian/recursion-context": "^3.0"
-      },
-      "require-dev": {
-        "ext-dom": "*",
-        "phpunit/phpunit": "^8.0"
-      },
-      "suggest": {
-        "ext-uopz": "*"
-      },
-      "type": "library",
-      "extra": {
-        "branch-alias": {
-          "dev-master": "3.0-dev"
-        }
-      },
-      "autoload": {
-        "classmap": ["src/"]
-      },
-      "notification-url": "https://packagist.org/downloads/",
-      "license": ["BSD-3-Clause"],
-      "authors": [
+            "name": "sebastian/code-unit-reverse-lookup",
+            "version": "1.0.1",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git",
+                "reference": "4419fcdb5eabb9caa61a27c7a1db532a6b55dd18"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/4419fcdb5eabb9caa61a27c7a1db532a6b55dd18",
+                "reference": "4419fcdb5eabb9caa61a27c7a1db532a6b55dd18",
+                "shasum": ""
+            },
+            "require": {
+                "php": "^5.6 || ^7.0"
+            },
+            "require-dev": {
+                "phpunit/phpunit": "^5.7 || ^6.0"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "1.0.x-dev"
+                }
+            },
+            "autoload": {
+                "classmap": [
+                    "src/"
+                ]
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "BSD-3-Clause"
+            ],
+            "authors": [
+                {
+                    "name": "Sebastian Bergmann",
+                    "email": "sebastian@phpunit.de"
+                }
+            ],
+            "description": "Looks up which function or method a line of code belongs to",
+            "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/",
+            "time": "2017-03-04T06:30:41+00:00"
+        },
         {
-          "name": "Sebastian Bergmann",
-          "email": "sebastian@phpunit.de"
-        }
-      ],
-      "description": "Snapshotting of global state",
-      "homepage": "http://www.github.com/sebastianbergmann/global-state",
-      "keywords": ["global state"],
-      "time": "2019-02-01T05:30:01+00:00"
-    },
-    {
-      "name": "sebastian/object-enumerator",
-      "version": "3.0.3",
-      "source": {
-        "type": "git",
-        "url": "https://github.com/sebastianbergmann/object-enumerator.git",
-        "reference": "7cfd9e65d11ffb5af41198476395774d4c8a84c5"
-      },
-      "dist": {
-        "type": "zip",
-        "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/7cfd9e65d11ffb5af41198476395774d4c8a84c5",
-        "reference": "7cfd9e65d11ffb5af41198476395774d4c8a84c5",
-        "shasum": ""
-      },
-      "require": {
-        "php": "^7.0",
-        "sebastian/object-reflector": "^1.1.1",
-        "sebastian/recursion-context": "^3.0"
-      },
-      "require-dev": {
-        "phpunit/phpunit": "^6.0"
-      },
-      "type": "library",
-      "extra": {
-        "branch-alias": {
-          "dev-master": "3.0.x-dev"
-        }
-      },
-      "autoload": {
-        "classmap": ["src/"]
-      },
-      "notification-url": "https://packagist.org/downloads/",
-      "license": ["BSD-3-Clause"],
-      "authors": [
+            "name": "sebastian/comparator",
+            "version": "3.0.2",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/sebastianbergmann/comparator.git",
+                "reference": "5de4fc177adf9bce8df98d8d141a7559d7ccf6da"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/5de4fc177adf9bce8df98d8d141a7559d7ccf6da",
+                "reference": "5de4fc177adf9bce8df98d8d141a7559d7ccf6da",
+                "shasum": ""
+            },
+            "require": {
+                "php": "^7.1",
+                "sebastian/diff": "^3.0",
+                "sebastian/exporter": "^3.1"
+            },
+            "require-dev": {
+                "phpunit/phpunit": "^7.1"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "3.0-dev"
+                }
+            },
+            "autoload": {
+                "classmap": [
+                    "src/"
+                ]
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "BSD-3-Clause"
+            ],
+            "authors": [
+                {
+                    "name": "Jeff Welch",
+                    "email": "whatthejeff@gmail.com"
+                },
+                {
+                    "name": "Volker Dusch",
+                    "email": "github@wallbash.com"
+                },
+                {
+                    "name": "Bernhard Schussek",
+                    "email": "bschussek@2bepublished.at"
+                },
+                {
+                    "name": "Sebastian Bergmann",
+                    "email": "sebastian@phpunit.de"
+                }
+            ],
+            "description": "Provides the functionality to compare PHP values for equality",
+            "homepage": "https://github.com/sebastianbergmann/comparator",
+            "keywords": [
+                "comparator",
+                "compare",
+                "equality"
+            ],
+            "time": "2018-07-12T15:12:46+00:00"
+        },
         {
-          "name": "Sebastian Bergmann",
-          "email": "sebastian@phpunit.de"
-        }
-      ],
-      "description": "Traverses array structures and object graphs to enumerate all referenced objects",
-      "homepage": "https://github.com/sebastianbergmann/object-enumerator/",
-      "time": "2017-08-03T12:35:26+00:00"
-    },
-    {
-      "name": "sebastian/object-reflector",
-      "version": "1.1.1",
-      "source": {
-        "type": "git",
-        "url": "https://github.com/sebastianbergmann/object-reflector.git",
-        "reference": "773f97c67f28de00d397be301821b06708fca0be"
-      },
-      "dist": {
-        "type": "zip",
-        "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/773f97c67f28de00d397be301821b06708fca0be",
-        "reference": "773f97c67f28de00d397be301821b06708fca0be",
-        "shasum": ""
-      },
-      "require": {
-        "php": "^7.0"
-      },
-      "require-dev": {
-        "phpunit/phpunit": "^6.0"
-      },
-      "type": "library",
-      "extra": {
-        "branch-alias": {
-          "dev-master": "1.1-dev"
-        }
-      },
-      "autoload": {
-        "classmap": ["src/"]
-      },
-      "notification-url": "https://packagist.org/downloads/",
-      "license": ["BSD-3-Clause"],
-      "authors": [
+            "name": "sebastian/diff",
+            "version": "3.0.2",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/sebastianbergmann/diff.git",
+                "reference": "720fcc7e9b5cf384ea68d9d930d480907a0c1a29"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/720fcc7e9b5cf384ea68d9d930d480907a0c1a29",
+                "reference": "720fcc7e9b5cf384ea68d9d930d480907a0c1a29",
+                "shasum": ""
+            },
+            "require": {
+                "php": "^7.1"
+            },
+            "require-dev": {
+                "phpunit/phpunit": "^7.5 || ^8.0",
+                "symfony/process": "^2 || ^3.3 || ^4"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "3.0-dev"
+                }
+            },
+            "autoload": {
+                "classmap": [
+                    "src/"
+                ]
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "BSD-3-Clause"
+            ],
+            "authors": [
+                {
+                    "name": "Kore Nordmann",
+                    "email": "mail@kore-nordmann.de"
+                },
+                {
+                    "name": "Sebastian Bergmann",
+                    "email": "sebastian@phpunit.de"
+                }
+            ],
+            "description": "Diff implementation",
+            "homepage": "https://github.com/sebastianbergmann/diff",
+            "keywords": [
+                "diff",
+                "udiff",
+                "unidiff",
+                "unified diff"
+            ],
+            "time": "2019-02-04T06:01:07+00:00"
+        },
         {
-          "name": "Sebastian Bergmann",
-          "email": "sebastian@phpunit.de"
-        }
-      ],
-      "description": "Allows reflection of object attributes, including inherited and non-public ones",
-      "homepage": "https://github.com/sebastianbergmann/object-reflector/",
-      "time": "2017-03-29T09:07:27+00:00"
-    },
-    {
-      "name": "sebastian/recursion-context",
-      "version": "3.0.0",
-      "source": {
-        "type": "git",
-        "url": "https://github.com/sebastianbergmann/recursion-context.git",
-        "reference": "5b0cd723502bac3b006cbf3dbf7a1e3fcefe4fa8"
-      },
-      "dist": {
-        "type": "zip",
-        "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/5b0cd723502bac3b006cbf3dbf7a1e3fcefe4fa8",
-        "reference": "5b0cd723502bac3b006cbf3dbf7a1e3fcefe4fa8",
-        "shasum": ""
-      },
-      "require": {
-        "php": "^7.0"
-      },
-      "require-dev": {
-        "phpunit/phpunit": "^6.0"
-      },
-      "type": "library",
-      "extra": {
-        "branch-alias": {
-          "dev-master": "3.0.x-dev"
-        }
-      },
-      "autoload": {
-        "classmap": ["src/"]
-      },
-      "notification-url": "https://packagist.org/downloads/",
-      "license": ["BSD-3-Clause"],
-      "authors": [
+            "name": "sebastian/environment",
+            "version": "4.2.3",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/sebastianbergmann/environment.git",
+                "reference": "464c90d7bdf5ad4e8a6aea15c091fec0603d4368"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/464c90d7bdf5ad4e8a6aea15c091fec0603d4368",
+                "reference": "464c90d7bdf5ad4e8a6aea15c091fec0603d4368",
+                "shasum": ""
+            },
+            "require": {
+                "php": "^7.1"
+            },
+            "require-dev": {
+                "phpunit/phpunit": "^7.5"
+            },
+            "suggest": {
+                "ext-posix": "*"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "4.2-dev"
+                }
+            },
+            "autoload": {
+                "classmap": [
+                    "src/"
+                ]
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "BSD-3-Clause"
+            ],
+            "authors": [
+                {
+                    "name": "Sebastian Bergmann",
+                    "email": "sebastian@phpunit.de"
+                }
+            ],
+            "description": "Provides functionality to handle HHVM/PHP environments",
+            "homepage": "http://www.github.com/sebastianbergmann/environment",
+            "keywords": [
+                "Xdebug",
+                "environment",
+                "hhvm"
+            ],
+            "time": "2019-11-20T08:46:58+00:00"
+        },
         {
-          "name": "Jeff Welch",
-          "email": "whatthejeff@gmail.com"
+            "name": "sebastian/exporter",
+            "version": "3.1.2",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/sebastianbergmann/exporter.git",
+                "reference": "68609e1261d215ea5b21b7987539cbfbe156ec3e"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/68609e1261d215ea5b21b7987539cbfbe156ec3e",
+                "reference": "68609e1261d215ea5b21b7987539cbfbe156ec3e",
+                "shasum": ""
+            },
+            "require": {
+                "php": "^7.0",
+                "sebastian/recursion-context": "^3.0"
+            },
+            "require-dev": {
+                "ext-mbstring": "*",
+                "phpunit/phpunit": "^6.0"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "3.1.x-dev"
+                }
+            },
+            "autoload": {
+                "classmap": [
+                    "src/"
+                ]
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "BSD-3-Clause"
+            ],
+            "authors": [
+                {
+                    "name": "Sebastian Bergmann",
+                    "email": "sebastian@phpunit.de"
+                },
+                {
+                    "name": "Jeff Welch",
+                    "email": "whatthejeff@gmail.com"
+                },
+                {
+                    "name": "Volker Dusch",
+                    "email": "github@wallbash.com"
+                },
+                {
+                    "name": "Adam Harvey",
+                    "email": "aharvey@php.net"
+                },
+                {
+                    "name": "Bernhard Schussek",
+                    "email": "bschussek@gmail.com"
+                }
+            ],
+            "description": "Provides the functionality to export PHP variables for visualization",
+            "homepage": "http://www.github.com/sebastianbergmann/exporter",
+            "keywords": [
+                "export",
+                "exporter"
+            ],
+            "time": "2019-09-14T09:02:43+00:00"
         },
         {
-          "name": "Sebastian Bergmann",
-          "email": "sebastian@phpunit.de"
+            "name": "sebastian/global-state",
+            "version": "3.0.0",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/sebastianbergmann/global-state.git",
+                "reference": "edf8a461cf1d4005f19fb0b6b8b95a9f7fa0adc4"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/edf8a461cf1d4005f19fb0b6b8b95a9f7fa0adc4",
+                "reference": "edf8a461cf1d4005f19fb0b6b8b95a9f7fa0adc4",
+                "shasum": ""
+            },
+            "require": {
+                "php": "^7.2",
+                "sebastian/object-reflector": "^1.1.1",
+                "sebastian/recursion-context": "^3.0"
+            },
+            "require-dev": {
+                "ext-dom": "*",
+                "phpunit/phpunit": "^8.0"
+            },
+            "suggest": {
+                "ext-uopz": "*"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "3.0-dev"
+                }
+            },
+            "autoload": {
+                "classmap": [
+                    "src/"
+                ]
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "BSD-3-Clause"
+            ],
+            "authors": [
+                {
+                    "name": "Sebastian Bergmann",
+                    "email": "sebastian@phpunit.de"
+                }
+            ],
+            "description": "Snapshotting of global state",
+            "homepage": "http://www.github.com/sebastianbergmann/global-state",
+            "keywords": [
+                "global state"
+            ],
+            "time": "2019-02-01T05:30:01+00:00"
         },
         {
-          "name": "Adam Harvey",
-          "email": "aharvey@php.net"
-        }
-      ],
-      "description": "Provides functionality to recursively process PHP variables",
-      "homepage": "http://www.github.com/sebastianbergmann/recursion-context",
-      "time": "2017-03-03T06:23:57+00:00"
-    },
-    {
-      "name": "sebastian/resource-operations",
-      "version": "2.0.1",
-      "source": {
-        "type": "git",
-        "url": "https://github.com/sebastianbergmann/resource-operations.git",
-        "reference": "4d7a795d35b889bf80a0cc04e08d77cedfa917a9"
-      },
-      "dist": {
-        "type": "zip",
-        "url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/4d7a795d35b889bf80a0cc04e08d77cedfa917a9",
-        "reference": "4d7a795d35b889bf80a0cc04e08d77cedfa917a9",
-        "shasum": ""
-      },
-      "require": {
-        "php": "^7.1"
-      },
-      "type": "library",
-      "extra": {
-        "branch-alias": {
-          "dev-master": "2.0-dev"
-        }
-      },
-      "autoload": {
-        "classmap": ["src/"]
-      },
-      "notification-url": "https://packagist.org/downloads/",
-      "license": ["BSD-3-Clause"],
-      "authors": [
+            "name": "sebastian/object-enumerator",
+            "version": "3.0.3",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/sebastianbergmann/object-enumerator.git",
+                "reference": "7cfd9e65d11ffb5af41198476395774d4c8a84c5"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/7cfd9e65d11ffb5af41198476395774d4c8a84c5",
+                "reference": "7cfd9e65d11ffb5af41198476395774d4c8a84c5",
+                "shasum": ""
+            },
+            "require": {
+                "php": "^7.0",
+                "sebastian/object-reflector": "^1.1.1",
+                "sebastian/recursion-context": "^3.0"
+            },
+            "require-dev": {
+                "phpunit/phpunit": "^6.0"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "3.0.x-dev"
+                }
+            },
+            "autoload": {
+                "classmap": [
+                    "src/"
+                ]
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "BSD-3-Clause"
+            ],
+            "authors": [
+                {
+                    "name": "Sebastian Bergmann",
+                    "email": "sebastian@phpunit.de"
+                }
+            ],
+            "description": "Traverses array structures and object graphs to enumerate all referenced objects",
+            "homepage": "https://github.com/sebastianbergmann/object-enumerator/",
+            "time": "2017-08-03T12:35:26+00:00"
+        },
         {
-          "name": "Sebastian Bergmann",
-          "email": "sebastian@phpunit.de"
-        }
-      ],
-      "description": "Provides a list of PHP built-in functions that operate on resources",
-      "homepage": "https://www.github.com/sebastianbergmann/resource-operations",
-      "time": "2018-10-04T04:07:39+00:00"
-    },
-    {
-      "name": "sebastian/type",
-      "version": "1.1.3",
-      "source": {
-        "type": "git",
-        "url": "https://github.com/sebastianbergmann/type.git",
-        "reference": "3aaaa15fa71d27650d62a948be022fe3b48541a3"
-      },
-      "dist": {
-        "type": "zip",
-        "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/3aaaa15fa71d27650d62a948be022fe3b48541a3",
-        "reference": "3aaaa15fa71d27650d62a948be022fe3b48541a3",
-        "shasum": ""
-      },
-      "require": {
-        "php": "^7.2"
-      },
-      "require-dev": {
-        "phpunit/phpunit": "^8.2"
-      },
-      "type": "library",
-      "extra": {
-        "branch-alias": {
-          "dev-master": "1.1-dev"
-        }
-      },
-      "autoload": {
-        "classmap": ["src/"]
-      },
-      "notification-url": "https://packagist.org/downloads/",
-      "license": ["BSD-3-Clause"],
-      "authors": [
+            "name": "sebastian/object-reflector",
+            "version": "1.1.1",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/sebastianbergmann/object-reflector.git",
+                "reference": "773f97c67f28de00d397be301821b06708fca0be"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/773f97c67f28de00d397be301821b06708fca0be",
+                "reference": "773f97c67f28de00d397be301821b06708fca0be",
+                "shasum": ""
+            },
+            "require": {
+                "php": "^7.0"
+            },
+            "require-dev": {
+                "phpunit/phpunit": "^6.0"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "1.1-dev"
+                }
+            },
+            "autoload": {
+                "classmap": [
+                    "src/"
+                ]
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "BSD-3-Clause"
+            ],
+            "authors": [
+                {
+                    "name": "Sebastian Bergmann",
+                    "email": "sebastian@phpunit.de"
+                }
+            ],
+            "description": "Allows reflection of object attributes, including inherited and non-public ones",
+            "homepage": "https://github.com/sebastianbergmann/object-reflector/",
+            "time": "2017-03-29T09:07:27+00:00"
+        },
         {
-          "name": "Sebastian Bergmann",
-          "email": "sebastian@phpunit.de",
-          "role": "lead"
-        }
-      ],
-      "description": "Collection of value objects that represent the types of the PHP type system",
-      "homepage": "https://github.com/sebastianbergmann/type",
-      "time": "2019-07-02T08:10:15+00:00"
-    },
-    {
-      "name": "sebastian/version",
-      "version": "2.0.1",
-      "source": {
-        "type": "git",
-        "url": "https://github.com/sebastianbergmann/version.git",
-        "reference": "99732be0ddb3361e16ad77b68ba41efc8e979019"
-      },
-      "dist": {
-        "type": "zip",
-        "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/99732be0ddb3361e16ad77b68ba41efc8e979019",
-        "reference": "99732be0ddb3361e16ad77b68ba41efc8e979019",
-        "shasum": ""
-      },
-      "require": {
-        "php": ">=5.6"
-      },
-      "type": "library",
-      "extra": {
-        "branch-alias": {
-          "dev-master": "2.0.x-dev"
-        }
-      },
-      "autoload": {
-        "classmap": ["src/"]
-      },
-      "notification-url": "https://packagist.org/downloads/",
-      "license": ["BSD-3-Clause"],
-      "authors": [
+            "name": "sebastian/recursion-context",
+            "version": "3.0.0",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/sebastianbergmann/recursion-context.git",
+                "reference": "5b0cd723502bac3b006cbf3dbf7a1e3fcefe4fa8"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/5b0cd723502bac3b006cbf3dbf7a1e3fcefe4fa8",
+                "reference": "5b0cd723502bac3b006cbf3dbf7a1e3fcefe4fa8",
+                "shasum": ""
+            },
+            "require": {
+                "php": "^7.0"
+            },
+            "require-dev": {
+                "phpunit/phpunit": "^6.0"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "3.0.x-dev"
+                }
+            },
+            "autoload": {
+                "classmap": [
+                    "src/"
+                ]
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "BSD-3-Clause"
+            ],
+            "authors": [
+                {
+                    "name": "Jeff Welch",
+                    "email": "whatthejeff@gmail.com"
+                },
+                {
+                    "name": "Sebastian Bergmann",
+                    "email": "sebastian@phpunit.de"
+                },
+                {
+                    "name": "Adam Harvey",
+                    "email": "aharvey@php.net"
+                }
+            ],
+            "description": "Provides functionality to recursively process PHP variables",
+            "homepage": "http://www.github.com/sebastianbergmann/recursion-context",
+            "time": "2017-03-03T06:23:57+00:00"
+        },
         {
-          "name": "Sebastian Bergmann",
-          "email": "sebastian@phpunit.de",
-          "role": "lead"
-        }
-      ],
-      "description": "Library that helps with managing the version number of Git-hosted PHP projects",
-      "homepage": "https://github.com/sebastianbergmann/version",
-      "time": "2016-10-03T07:35:21+00:00"
-    },
-    {
-      "name": "symfony/polyfill-ctype",
-      "version": "v1.17.0",
-      "source": {
-        "type": "git",
-        "url": "https://github.com/symfony/polyfill-ctype.git",
-        "reference": "e94c8b1bbe2bc77507a1056cdb06451c75b427f9"
-      },
-      "dist": {
-        "type": "zip",
-        "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/e94c8b1bbe2bc77507a1056cdb06451c75b427f9",
-        "reference": "e94c8b1bbe2bc77507a1056cdb06451c75b427f9",
-        "shasum": ""
-      },
-      "require": {
-        "php": ">=5.3.3"
-      },
-      "suggest": {
-        "ext-ctype": "For best performance"
-      },
-      "type": "library",
-      "extra": {
-        "branch-alias": {
-          "dev-master": "1.17-dev"
-        }
-      },
-      "autoload": {
-        "psr-4": {
-          "Symfony\\Polyfill\\Ctype\\": ""
+            "name": "sebastian/resource-operations",
+            "version": "2.0.1",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/sebastianbergmann/resource-operations.git",
+                "reference": "4d7a795d35b889bf80a0cc04e08d77cedfa917a9"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/4d7a795d35b889bf80a0cc04e08d77cedfa917a9",
+                "reference": "4d7a795d35b889bf80a0cc04e08d77cedfa917a9",
+                "shasum": ""
+            },
+            "require": {
+                "php": "^7.1"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "2.0-dev"
+                }
+            },
+            "autoload": {
+                "classmap": [
+                    "src/"
+                ]
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "BSD-3-Clause"
+            ],
+            "authors": [
+                {
+                    "name": "Sebastian Bergmann",
+                    "email": "sebastian@phpunit.de"
+                }
+            ],
+            "description": "Provides a list of PHP built-in functions that operate on resources",
+            "homepage": "https://www.github.com/sebastianbergmann/resource-operations",
+            "time": "2018-10-04T04:07:39+00:00"
         },
-        "files": ["bootstrap.php"]
-      },
-      "notification-url": "https://packagist.org/downloads/",
-      "license": ["MIT"],
-      "authors": [
         {
-          "name": "Gert de Pagter",
-          "email": "BackEndTea@gmail.com"
+            "name": "sebastian/type",
+            "version": "1.1.3",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/sebastianbergmann/type.git",
+                "reference": "3aaaa15fa71d27650d62a948be022fe3b48541a3"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/3aaaa15fa71d27650d62a948be022fe3b48541a3",
+                "reference": "3aaaa15fa71d27650d62a948be022fe3b48541a3",
+                "shasum": ""
+            },
+            "require": {
+                "php": "^7.2"
+            },
+            "require-dev": {
+                "phpunit/phpunit": "^8.2"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "1.1-dev"
+                }
+            },
+            "autoload": {
+                "classmap": [
+                    "src/"
+                ]
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "BSD-3-Clause"
+            ],
+            "authors": [
+                {
+                    "name": "Sebastian Bergmann",
+                    "email": "sebastian@phpunit.de",
+                    "role": "lead"
+                }
+            ],
+            "description": "Collection of value objects that represent the types of the PHP type system",
+            "homepage": "https://github.com/sebastianbergmann/type",
+            "time": "2019-07-02T08:10:15+00:00"
         },
         {
-          "name": "Symfony Community",
-          "homepage": "https://symfony.com/contributors"
-        }
-      ],
-      "description": "Symfony polyfill for ctype functions",
-      "homepage": "https://symfony.com",
-      "keywords": ["compatibility", "ctype", "polyfill", "portable"],
-      "funding": [
+            "name": "sebastian/version",
+            "version": "2.0.1",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/sebastianbergmann/version.git",
+                "reference": "99732be0ddb3361e16ad77b68ba41efc8e979019"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/99732be0ddb3361e16ad77b68ba41efc8e979019",
+                "reference": "99732be0ddb3361e16ad77b68ba41efc8e979019",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=5.6"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "2.0.x-dev"
+                }
+            },
+            "autoload": {
+                "classmap": [
+                    "src/"
+                ]
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "BSD-3-Clause"
+            ],
+            "authors": [
+                {
+                    "name": "Sebastian Bergmann",
+                    "email": "sebastian@phpunit.de",
+                    "role": "lead"
+                }
+            ],
+            "description": "Library that helps with managing the version number of Git-hosted PHP projects",
+            "homepage": "https://github.com/sebastianbergmann/version",
+            "time": "2016-10-03T07:35:21+00:00"
+        },
         {
-          "url": "https://symfony.com/sponsor",
-          "type": "custom"
+            "name": "symfony/polyfill-ctype",
+            "version": "v1.17.1",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/symfony/polyfill-ctype.git",
+                "reference": "2edd75b8b35d62fd3eeabba73b26b8f1f60ce13d"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/2edd75b8b35d62fd3eeabba73b26b8f1f60ce13d",
+                "reference": "2edd75b8b35d62fd3eeabba73b26b8f1f60ce13d",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=5.3.3"
+            },
+            "suggest": {
+                "ext-ctype": "For best performance"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "1.17-dev"
+                },
+                "thanks": {
+                    "name": "symfony/polyfill",
+                    "url": "https://github.com/symfony/polyfill"
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "Symfony\\Polyfill\\Ctype\\": ""
+                },
+                "files": [
+                    "bootstrap.php"
+                ]
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Gert de Pagter",
+                    "email": "BackEndTea@gmail.com"
+                },
+                {
+                    "name": "Symfony Community",
+                    "homepage": "https://symfony.com/contributors"
+                }
+            ],
+            "description": "Symfony polyfill for ctype functions",
+            "homepage": "https://symfony.com",
+            "keywords": [
+                "compatibility",
+                "ctype",
+                "polyfill",
+                "portable"
+            ],
+            "funding": [
+                {
+                    "url": "https://symfony.com/sponsor",
+                    "type": "custom"
+                },
+                {
+                    "url": "https://github.com/fabpot",
+                    "type": "github"
+                },
+                {
+                    "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+                    "type": "tidelift"
+                }
+            ],
+            "time": "2020-06-06T08:46:27+00:00"
         },
         {
-          "url": "https://github.com/fabpot",
-          "type": "github"
+            "name": "theseer/tokenizer",
+            "version": "1.1.3",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/theseer/tokenizer.git",
+                "reference": "11336f6f84e16a720dae9d8e6ed5019efa85a0f9"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/theseer/tokenizer/zipball/11336f6f84e16a720dae9d8e6ed5019efa85a0f9",
+                "reference": "11336f6f84e16a720dae9d8e6ed5019efa85a0f9",
+                "shasum": ""
+            },
+            "require": {
+                "ext-dom": "*",
+                "ext-tokenizer": "*",
+                "ext-xmlwriter": "*",
+                "php": "^7.0"
+            },
+            "type": "library",
+            "autoload": {
+                "classmap": [
+                    "src/"
+                ]
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "BSD-3-Clause"
+            ],
+            "authors": [
+                {
+                    "name": "Arne Blankerts",
+                    "email": "arne@blankerts.de",
+                    "role": "Developer"
+                }
+            ],
+            "description": "A small library for converting tokenized PHP source code into XML and potentially other formats",
+            "time": "2019-06-13T22:48:21+00:00"
         },
         {
-          "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
-          "type": "tidelift"
-        }
-      ],
-      "time": "2020-05-12T16:14:59+00:00"
+            "name": "webmozart/assert",
+            "version": "1.9.0",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/webmozart/assert.git",
+                "reference": "9dc4f203e36f2b486149058bade43c851dd97451"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/webmozart/assert/zipball/9dc4f203e36f2b486149058bade43c851dd97451",
+                "reference": "9dc4f203e36f2b486149058bade43c851dd97451",
+                "shasum": ""
+            },
+            "require": {
+                "php": "^5.3.3 || ^7.0",
+                "symfony/polyfill-ctype": "^1.8"
+            },
+            "conflict": {
+                "phpstan/phpstan": "<0.12.20",
+                "vimeo/psalm": "<3.9.1"
+            },
+            "require-dev": {
+                "phpunit/phpunit": "^4.8.36 || ^7.5.13"
+            },
+            "type": "library",
+            "autoload": {
+                "psr-4": {
+                    "Webmozart\\Assert\\": "src/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Bernhard Schussek",
+                    "email": "bschussek@gmail.com"
+                }
+            ],
+            "description": "Assertions to validate method input/output with nice error messages.",
+            "keywords": [
+                "assert",
+                "check",
+                "validate"
+            ],
+            "time": "2020-06-16T10:16:42+00:00"
+        }
+    ],
+    "aliases": [],
+    "minimum-stability": "stable",
+    "stability-flags": {
+        "james-heinrich/getid3": 20
     },
-    {
-      "name": "theseer/tokenizer",
-      "version": "1.1.3",
-      "source": {
-        "type": "git",
-        "url": "https://github.com/theseer/tokenizer.git",
-        "reference": "11336f6f84e16a720dae9d8e6ed5019efa85a0f9"
-      },
-      "dist": {
-        "type": "zip",
-        "url": "https://api.github.com/repos/theseer/tokenizer/zipball/11336f6f84e16a720dae9d8e6ed5019efa85a0f9",
-        "reference": "11336f6f84e16a720dae9d8e6ed5019efa85a0f9",
-        "shasum": ""
-      },
-      "require": {
-        "ext-dom": "*",
-        "ext-tokenizer": "*",
-        "ext-xmlwriter": "*",
-        "php": "^7.0"
-      },
-      "type": "library",
-      "autoload": {
-        "classmap": ["src/"]
-      },
-      "notification-url": "https://packagist.org/downloads/",
-      "license": ["BSD-3-Clause"],
-      "authors": [
-        {
-          "name": "Arne Blankerts",
-          "email": "arne@blankerts.de",
-          "role": "Developer"
-        }
-      ],
-      "description": "A small library for converting tokenized PHP source code into XML and potentially other formats",
-      "time": "2019-06-13T22:48:21+00:00"
+    "prefer-stable": false,
+    "prefer-lowest": false,
+    "platform": {
+        "php": ">=7.2"
     },
-    {
-      "name": "webmozart/assert",
-      "version": "1.8.0",
-      "source": {
-        "type": "git",
-        "url": "https://github.com/webmozart/assert.git",
-        "reference": "ab2cb0b3b559010b75981b1bdce728da3ee90ad6"
-      },
-      "dist": {
-        "type": "zip",
-        "url": "https://api.github.com/repos/webmozart/assert/zipball/ab2cb0b3b559010b75981b1bdce728da3ee90ad6",
-        "reference": "ab2cb0b3b559010b75981b1bdce728da3ee90ad6",
-        "shasum": ""
-      },
-      "require": {
-        "php": "^5.3.3 || ^7.0",
-        "symfony/polyfill-ctype": "^1.8"
-      },
-      "conflict": {
-        "vimeo/psalm": "<3.9.1"
-      },
-      "require-dev": {
-        "phpunit/phpunit": "^4.8.36 || ^7.5.13"
-      },
-      "type": "library",
-      "autoload": {
-        "psr-4": {
-          "Webmozart\\Assert\\": "src/"
-        }
-      },
-      "notification-url": "https://packagist.org/downloads/",
-      "license": ["MIT"],
-      "authors": [
-        {
-          "name": "Bernhard Schussek",
-          "email": "bschussek@gmail.com"
-        }
-      ],
-      "description": "Assertions to validate method input/output with nice error messages.",
-      "keywords": ["assert", "check", "validate"],
-      "time": "2020-04-18T12:12:48+00:00"
-    }
-  ],
-  "aliases": [],
-  "minimum-stability": "stable",
-  "stability-flags": {
-    "james-heinrich/getid3": 20
-  },
-  "prefer-stable": false,
-  "prefer-lowest": false,
-  "platform": {
-    "php": ">=7.2"
-  },
-  "platform-dev": [],
-  "plugin-api-version": "1.1.0"
+    "platform-dev": [],
+    "plugin-api-version": "1.1.0"
 }
diff --git a/docs/setup-development.md b/docs/setup-development.md
index e77fb66ec9..a2673ae716 100644
--- a/docs/setup-development.md
+++ b/docs/setup-development.md
@@ -117,7 +117,7 @@ You can install / update the project's dependencies using both `composer` and `n
 
 ```bash
 # install php dependencies
-docker-compose run --rm composer update --ignore-platform-reqs
+docker-compose run --rm composer install --ignore-platform-reqs
 
 # update php dependencies
 docker-compose run --rm composer update --ignore-platform-reqs
-- 
GitLab