├── cache └── .gitignore ├── .gitignore ├── templates ├── Bookmarks-bookmark.md ├── Stream-rss.md ├── Stream-bookmark.md ├── Stream-header.md ├── Stream-article.md ├── Bookmarks.md └── Stream.md ├── .env.example ├── composer.json ├── license.md ├── readme.md ├── app ├── Collector │ ├── CollectorInterface.php │ ├── RssFeedCollector.php │ ├── BookmarkCollector.php │ └── WallabagCollector.php └── Parser │ └── BookmarkParser.php ├── sync-twitter-bookmarks.php ├── init.php ├── sync-bookmarks.php ├── sync-wallabag.php ├── create-stream.php └── composer.lock /cache/.gitignore: -------------------------------------------------------------------------------- 1 | *.json -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .env 2 | vendor 3 | -------------------------------------------------------------------------------- /templates/Bookmarks-bookmark.md: -------------------------------------------------------------------------------- 1 | - [%s](%s) (%s) -------------------------------------------------------------------------------- /templates/Stream-rss.md: -------------------------------------------------------------------------------- 1 | - 📙 [%s](%s) (%s) -------------------------------------------------------------------------------- /templates/Stream-bookmark.md: -------------------------------------------------------------------------------- 1 | - ⭐ [%s](%s) (%s) -------------------------------------------------------------------------------- /templates/Stream-header.md: -------------------------------------------------------------------------------- 1 | - %s 2 | heading:: true -------------------------------------------------------------------------------- /templates/Stream-article.md: -------------------------------------------------------------------------------- 1 | - 📰 [%s](%s) 2 | Tags: %s, origineel artikel op [%s](%s) -------------------------------------------------------------------------------- /templates/Bookmarks.md: -------------------------------------------------------------------------------- 1 | --- 2 | public: true 3 | --- 4 | 5 | - Dit zijn al [mijn]([[Sander Dorigo]]) (publieke) ⭐ bookmarks ⭐. 6 | - Deze lijst is automagisch gemaakt met een [handig tooltje](https://github.com/SDx3/sync-to-logseq). 7 | -------------------------------------------------------------------------------- /.env.example: -------------------------------------------------------------------------------- 1 | LOG_LEVEL=200 2 | 3 | WALLABAG_HOST= 4 | WALLABAG_CLIENT_ID= 5 | WALLABAG_CLIENT_SECRET= 6 | WALLABAG_USERNAME= 7 | WALLABAG_PASSWORD= 8 | 9 | NEXTCLOUD_USERNAME= 10 | NEXTCLOUD_PASS= 11 | NEXTCLOUD_HOST= 12 | NEXTCLOUD_LOGSEQ_PATH= 13 | NEXTCLOUD_LOCAL_DIRECTORY= 14 | 15 | TWITTER_CONSUMER_KEY= 16 | TWITTER_CONSUMER_SECRET= 17 | TWITTER_ACCESS_TOKEN= 18 | TWITTER_ACCESS_TOKEN_SECRET= 19 | TWITTER_USER_ID= 20 | 21 | PUBLISHED_ARTICLES_FEED= -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "require": { 3 | "php": ">=8.0", 4 | "guzzlehttp/guzzle": "^7.3", 5 | "vlucas/phpdotenv": "^5.3", 6 | "nesbot/carbon": "^2.52", 7 | "monolog/monolog": "^2.3", 8 | "abraham/twitteroauth": "^3.1", 9 | "laminas/laminas-feed": "^2.14", 10 | "laminas/laminas-http": "^2.15", 11 | "league/climate": "^3.7" 12 | }, 13 | "autoload": { 14 | "psr-4": { 15 | "App\\": "app/" 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /templates/Stream.md: -------------------------------------------------------------------------------- 1 | public:: true 2 | 3 | - Deze **Stream** is een soort "stream of consciousness" 4 | - Het idee is dat je (met mate) deelt wat je online leest 5 | - Deze pagina is [mijn]([[Sander Dorigo]]) poging om zoiets te doen. 6 | - Alle links hieronder, aflopend in de tijd, zijn mijn [[Bookmarks]] en mijn [gelezen en bewaarde artikelen]([[Artikelen en leesvoer]]). 7 | - Ik zou zeggen, lees mee! 8 | - 🚧 Het syncen van [[Bookmarks]] werkt niet altijd lekker, excuses daarvoor. 9 | - Suggesties? [Twitter](https://twitter.com/SanderDorigo) 10 | -------------------------------------------------------------------------------- /license.md: -------------------------------------------------------------------------------- 1 | Copyright 2021 Sander Dorigo 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | 5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | 7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 8 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # Sync thing 2 | 3 | Three little scripts that sync bookmarks and articles to Logseq. It generates Markdown files. 4 | 5 | ## Basic instructions 6 | 7 | - First clone the repository, and copy `.env.example` to `.env` 8 | - You'll need [composer](https://getcomposer.org/) to install the dependencies using `composer install` 9 | - Filling in the details in the `.env` file is enough. You only need the Wallabag + Nextcloud details. 10 | - Both should be reachable from the web, be sure to use `https://` 11 | 12 | ## Nextcloud config 13 | 14 | `NEXTCLOUD_LOGSEQ_PATH` is the path where the files will be stored. Be sure to include the "pages" directory, ie. `misc/logseq/pages`. 15 | 16 | ## Running it 17 | 18 | Once configured and installed, run one of the following scripts 19 | 20 | - `php sync-bookmarks.php` generates `Bookmarks.md` based on your Nextcloud Bookmarks 21 | - `php sync-wallabag.php` generates `Artikelen en leesvoer.md` based on your Wallabag articles 22 | - `php create-stream.php` generates `Stream.md`, a date-based stream of articles and bookmarks 23 | 24 | The Wallabag script will make any archived Wallabag article public automatically. 25 | 26 | If you have questions, let me know. 27 | -------------------------------------------------------------------------------- /app/Collector/CollectorInterface.php: -------------------------------------------------------------------------------- 1 | get('account/verify_credentials'); 35 | $connection->setApiVersion('2'); 36 | 37 | // login info and setup 38 | $log->debug('Now syncing Twitter.'); 39 | $params= []; 40 | $res = $connection->get('timeline/bookmark', $params); 41 | 42 | var_dump($res); 43 | 44 | ///2/timeline/bookmarks -------------------------------------------------------------------------------- /init.php: -------------------------------------------------------------------------------- 1 | load(); 33 | 34 | // define cache path 35 | const CACHE = __DIR__ . '/cache'; 36 | 37 | // set up monolog 38 | $log = new Logger('sync'); 39 | $stringFormat = "[%datetime%] %level_name%: %message% %context% %extra%\n"; 40 | $dateFormat = 'H:i:s'; 41 | $formatter = new LineFormatter($stringFormat, $dateFormat, true, true); 42 | $handler = new StreamHandler('php://stdout', $_ENV['LOG_LEVEL']); 43 | $handler->setFormatter($formatter); 44 | $log->pushHandler($handler); 45 | setlocale(LC_ALL, ['nl', 'nl_NL.UTF-8', 'nl-NL']); 46 | -------------------------------------------------------------------------------- /app/Collector/RssFeedCollector.php: -------------------------------------------------------------------------------- 1 | collection = []; 41 | } 42 | 43 | /** 44 | * @inheritDoc 45 | */ 46 | public function setConfiguration(array $configuration): void 47 | { 48 | $this->configuration = $configuration; 49 | } 50 | 51 | /** 52 | * @inheritDoc 53 | */ 54 | public function collect(bool $skipCache = false): void 55 | { 56 | $feed = Reader::import($this->configuration['feed']); 57 | $data = []; 58 | foreach ($feed as $entry) { 59 | $edata = [ 60 | 'title' => $entry->getTitle(), 61 | 'description' => $entry->getDescription(), 62 | 'dateModified' => $entry->getDateModified(), 63 | 'authors' => $entry->getAuthors(), 64 | 'link' => $entry->getLink(), 65 | 'content' => $entry->getContent(), 66 | ]; 67 | $data[] = $edata; 68 | } 69 | $this->collection = $data; 70 | } 71 | 72 | /** 73 | * @inheritDoc 74 | */ 75 | public function getCollection(): array 76 | { 77 | return $this->collection; 78 | } 79 | 80 | /** 81 | * @inheritDoc 82 | */ 83 | public function setLogger(Logger $logger): void 84 | { 85 | $this->logger = $logger; 86 | } 87 | } -------------------------------------------------------------------------------- /app/Parser/BookmarkParser.php: -------------------------------------------------------------------------------- 1 | log->debug(sprintf('Now in processFolders, level %d and expected parent ID #%d.', $level, $expectedParent)); 27 | foreach ($this->bookmarks as $folderId => $folder) { 28 | $parentId = $this->getParentFolderId($folder); 29 | $this->log->debug(sprintf('Parent folder ID of folder "%s" is #%d.', $folder['title'], $parentId)); 30 | if ($parentId === $expectedParent) { 31 | $this->log->debug(sprintf('Parent and expected parent are a match, add folder "%s" (ID #%d) to markdown.', $folder['title'], $folderId)); 32 | 33 | // add title: 34 | $markdown .= str_repeat("\t", $level); 35 | $markdown .= sprintf("- **%s**\n", $folder['title']); 36 | 37 | // process subfolders 38 | $nextLevel = $level + 1; 39 | $markdown = $this->processFolders($markdown, $nextLevel, $folderId); 40 | 41 | // add bookmarks from THIS folder 42 | foreach ($folder['bookmarks'] as $bookmark) { 43 | $this->log->debug(sprintf('Will add bookmark from folder "%s" (#%d) to markdown', $folder['title'], $folderId)); 44 | $markdown .= str_repeat("\t", $nextLevel); 45 | 46 | $host = parse_url($bookmark['url'], PHP_URL_HOST); 47 | if (str_starts_with($host, 'www.')) { 48 | $host = substr($host, 4); 49 | } 50 | 51 | // parse template: 52 | $markdown .= sprintf($this->bookmarkTemplate, $bookmark['title'], $bookmark['url'], $host); 53 | $markdown .= "\n"; 54 | } 55 | } 56 | } 57 | 58 | return $markdown; 59 | } 60 | 61 | /** 62 | * @param Logger $log 63 | */ 64 | public function setLog(Logger $log): void 65 | { 66 | $this->log = $log; 67 | } 68 | 69 | 70 | /** 71 | * @param array $folder 72 | * 73 | * @return int 74 | */ 75 | protected function getParentFolderId(array $folder): int 76 | { 77 | // some folders dont "count" as parent: 78 | $ignoreFolders = [263]; 79 | if (in_array($folder['parent'], $ignoreFolders, true)) { 80 | return 0; 81 | } 82 | 83 | foreach ($this->bookmarks as $parentId => $parent) { 84 | if ($parentId === $folder['parent']) { 85 | return $parentId; 86 | } 87 | } 88 | 89 | return 0; 90 | } 91 | 92 | /** 93 | * @param string $bookmarkTemplate 94 | */ 95 | public function setBookmarkTemplate(string $bookmarkTemplate): void 96 | { 97 | $this->bookmarkTemplate = $bookmarkTemplate; 98 | } 99 | 100 | /** 101 | * @param array $bookmarks 102 | */ 103 | public function setBookmarks(array $bookmarks): void 104 | { 105 | $this->bookmarks = $bookmarks; 106 | } 107 | 108 | } -------------------------------------------------------------------------------- /sync-bookmarks.php: -------------------------------------------------------------------------------- 1 | debug('Now syncing bookmarks.'); 43 | $bookmarks = []; 44 | $client = new Client(); 45 | $opts = [ 46 | 'auth' => [$_ENV['NEXTCLOUD_USERNAME'], $_ENV['NEXTCLOUD_PASS']], 47 | 'headers' => [ 48 | 'Accept' => 'application/json', 49 | ], 50 | ]; 51 | 52 | $markdown = trim(file_get_contents(sprintf('%s/%s', __DIR__, 'templates/Bookmarks.md'))) . "\n"; 53 | 54 | // collect bookmarks 55 | $configuration = [ 56 | 'username' => $_ENV['NEXTCLOUD_USERNAME'], 57 | 'password' => $_ENV['NEXTCLOUD_PASS'], 58 | 'host' => $_ENV['NEXTCLOUD_HOST'], 59 | ]; 60 | $collector = new BookmarkCollector; 61 | $collector->setConfiguration($configuration); 62 | $collector->setLogger($log); 63 | $collector->collect(APP_DEBUG); 64 | $bookmarks = $collector->getCollection(); 65 | 66 | // sort folders 67 | uasort($bookmarks, function (array $a, array $b) { 68 | return strcmp($a['title'], $b['title']); 69 | }); 70 | 71 | // loop folders and generate markdown: 72 | $level = 0; 73 | $expectedParent = 0; 74 | 75 | // template 76 | $bookmarkTemplate = rtrim(file_get_contents(sprintf('%s/%s', __DIR__, 'templates/Bookmarks-bookmark.md'))); 77 | $bookmarkParser = new BookmarkParser; 78 | $bookmarkParser->setBookmarkTemplate($bookmarkTemplate); 79 | $bookmarkParser->setLog($log); 80 | $bookmarkParser->setBookmarks($bookmarks); 81 | $markdown = $bookmarkParser->processFolders($markdown, $level, $expectedParent); 82 | 83 | // now update (overwrite!) bookmarks file. 84 | if (false === APP_DEBUG) { 85 | $client = new Client; 86 | $url = sprintf('https://%s/remote.php/dav/files/%s/%s/Bookmarks.md', $_ENV['NEXTCLOUD_HOST'], $_ENV['NEXTCLOUD_USERNAME'], $_ENV['NEXTCLOUD_LOGSEQ_PATH']); 87 | $opts = [ 88 | 'auth' => [$_ENV['NEXTCLOUD_USERNAME'], $_ENV['NEXTCLOUD_PASS']], 89 | 'headers' => [ 90 | 'Accept' => 'application/json', 91 | ], 92 | 'body' => $markdown, 93 | ]; 94 | $log->debug(sprintf('Going to upload to %s', $url)); 95 | $res = $client->put($url, $opts); 96 | } 97 | if (true === APP_DEBUG) { 98 | $file = __DIR__ . '/Bookmarks.md'; 99 | file_put_contents($file, $markdown); 100 | $log->debug(sprintf('Written markdown to file %s', $file)); 101 | } 102 | $log->debug('Done!'); -------------------------------------------------------------------------------- /sync-wallabag.php: -------------------------------------------------------------------------------- 1 | load(); 34 | 35 | $markdown = "---\npublic: true\n---\n\n- Dit is een overzicht van alles dat [ik]([[Sander Dorigo]]) online heb 📰 gelezen 📰, en opgeslagen heb in [Wallabag](https://github.com/wallabag/wallabag).\n"; 36 | $markdown .= " - Deze lijst is gesorteerd op tijd (laatst gelezen eerst)\n"; 37 | $markdown .= " - Dit moet nog handiger ingedeeld worden maar voor nu is het even goed zo.\n"; 38 | 39 | $log->debug('Start of wallabag script.'); 40 | 41 | // collect bookmarks 42 | $collector = new WallabagCollector; 43 | $configuration = [ 44 | 'client_id' => $_ENV['WALLABAG_CLIENT_ID'], 45 | 'client_secret' => $_ENV['WALLABAG_CLIENT_SECRET'], 46 | 'username' => $_ENV['WALLABAG_USERNAME'], 47 | 'password' => $_ENV['WALLABAG_PASSWORD'], 48 | 'host' => $_ENV['WALLABAG_HOST'], 49 | ]; 50 | $collector->setConfiguration($configuration); 51 | $collector->setLogger($log); 52 | $collector->collect(); 53 | $articles = $collector->getCollection(); 54 | 55 | /** @var array $article */ 56 | foreach ($articles as $article) { 57 | $single = ''; 58 | 59 | // parse original host name 60 | $host = parse_url($article['original_url'], PHP_URL_HOST); 61 | if (str_starts_with($host, 'www.')) { 62 | $host = substr($host, 4); 63 | } 64 | 65 | // make Carbon objects: 66 | if (is_string($article['archived_at'])) { 67 | $article['archived_at'] = new Carbon($article['archived_at'], 'Europe/Amsterdam'); 68 | } 69 | if (is_string($article['created_at'])) { 70 | $article['created_at'] = new Carbon($article['created_at'], 'Europe/Amsterdam'); 71 | } 72 | 73 | // add link to article: 74 | $single .= sprintf("- **[%s](%s)**\n", $article['title'], $article['wallabag_url']); 75 | $single .= sprintf(' (origineel op [%s](%s))', $host, $article['original_url']) . "\n"; 76 | 77 | // add tags if present: 78 | if (count($article['tags']) > 0) { 79 | //$single .= ' tags:: ' . join(', ', $article['tags']) . "\n"; 80 | } 81 | 82 | // add "archived on" 83 | $single .= sprintf(' - Gelezen op %s', str_replace(' ', ' ', $article['archived_at']->formatLocalized('%A %e %B %Y'))) . "\n"; 84 | 85 | // add "saved on" (currently disabled): 86 | //$single .= sprintf(' - Oorspronkelijk opgeslagen op %s', str_replace(' ', ' ', $article['created_at']->formatLocalized('%A %e %B %Y'))) . "\n"; 87 | 88 | // add annotations (if present) 89 | if(count($article['annotations']) > 0) { 90 | $single .= " - Opmerkingen\n"; 91 | foreach($article['annotations'] as $annotation) { 92 | $single .= sprintf(" - > %s\n %s\n", $annotation['quote'], $annotation['text']); 93 | } 94 | } 95 | 96 | 97 | $markdown .= $single; 98 | } 99 | 100 | // now update (overwrite!) bookmarks file. 101 | $client = new Client; 102 | $url = sprintf('https://%s/remote.php/dav/files/%s/%s/Artikelen en leesvoer.md', $_ENV['NEXTCLOUD_HOST'], $_ENV['NEXTCLOUD_USERNAME'], $_ENV['NEXTCLOUD_LOGSEQ_PATH']); 103 | $opts = [ 104 | 'auth' => [$_ENV['NEXTCLOUD_USERNAME'], $_ENV['NEXTCLOUD_PASS']], 105 | 'headers' => [ 106 | 'Accept' => 'application/json', 107 | ], 108 | 'body' => $markdown, 109 | ]; 110 | $log->debug(sprintf('Going to upload to %s', $url)); 111 | $res = $client->put($url, $opts); 112 | $log->debug('Done!'); 113 | -------------------------------------------------------------------------------- /create-stream.php: -------------------------------------------------------------------------------- 1 | debug('Now creating a thought stream yay'); 45 | 46 | $markdown = trim(file_get_contents(sprintf('%s/%s', __DIR__, 'templates/Stream.md'))) . "\n"; 47 | $templates = [ 48 | 'header' => trim(file_get_contents(sprintf('%s/%s', __DIR__, 'templates/Stream-header.md'))), 49 | 'article' => rtrim(file_get_contents(sprintf('%s/%s', __DIR__, 'templates/Stream-article.md'))), 50 | 'bookmark' => rtrim(file_get_contents(sprintf('%s/%s', __DIR__, 'templates/Stream-bookmark.md'))), 51 | 'rss' => rtrim(file_get_contents(sprintf('%s/%s', __DIR__, 'templates/Stream-rss.md'))), 52 | ]; 53 | 54 | // collect RSS published things: 55 | $configuration = [ 56 | 'feed' => $_ENV['PUBLISHED_ARTICLES_FEED'], 57 | ]; 58 | 59 | $collector = new RssFeedCollector; 60 | $collector->setConfiguration($configuration); 61 | $collector->setLogger($log); 62 | $collector->collect(); 63 | $published = $collector->getCollection(); 64 | 65 | // collect bookmarks 66 | $configuration = [ 67 | 'username' => $_ENV['NEXTCLOUD_USERNAME'], 68 | 'password' => $_ENV['NEXTCLOUD_PASS'], 69 | 'host' => $_ENV['NEXTCLOUD_HOST'], 70 | ]; 71 | $collector = new BookmarkCollector; 72 | $collector->setConfiguration($configuration); 73 | $collector->setLogger($log); 74 | $collector->collect(); 75 | $bookmarks = $collector->getCollection(); 76 | 77 | // collect wallabag 78 | $collector = new WallabagCollector; 79 | $configuration = [ 80 | 'client_id' => $_ENV['WALLABAG_CLIENT_ID'], 81 | 'client_secret' => $_ENV['WALLABAG_CLIENT_SECRET'], 82 | 'username' => $_ENV['WALLABAG_USERNAME'], 83 | 'password' => $_ENV['WALLABAG_PASSWORD'], 84 | 'host' => $_ENV['WALLABAG_HOST'], 85 | ]; 86 | $collector->setConfiguration($configuration); 87 | $collector->setLogger($log); 88 | $collector->collect(); 89 | $articles = $collector->getCollection(); 90 | 91 | $dates = []; 92 | 93 | // loop and add to array 94 | $log->debug('Now looping bookmarks.'); 95 | 96 | /** @var array $folder */ 97 | foreach ($bookmarks as $folder) { 98 | /** @var array $bookmark */ 99 | foreach ($folder['bookmarks'] as $bookmark) { 100 | if (is_string($bookmark['added'])) { 101 | $bookmark['added'] = new Carbon($bookmark['added'], 'Europe/Amsterdam'); 102 | } 103 | $bookmark['folder'] = $folder['title']; 104 | $dateString = (string) $bookmark['added']->format('Ymd'); 105 | $timeString = $bookmark['added']->format('His'); 106 | $dates[$dateString] = array_key_exists($dateString, $dates) ? $dates[$dateString] : []; 107 | $dates[$dateString][$timeString] = array_key_exists($timeString, $dates[$dateString]) ? $dates[$dateString][$timeString] : []; 108 | // add bookmark to this array verbatim: 109 | $dates[$dateString][$timeString][] = [ 110 | 'type' => 'bookmark', 111 | 'data' => $bookmark, 112 | ]; 113 | 114 | } 115 | } 116 | $log->debug('Now looping articles.'); 117 | 118 | /** @var array $article */ 119 | foreach ($articles as $article) { 120 | if (is_string($article['archived_at'])) { 121 | $article['archived_at'] = new Carbon($article['archived_at'], 'Europe/Amsterdam'); 122 | } 123 | $dateString = (string) $article['archived_at']->format('Ymd'); 124 | $timeString = $article['archived_at']->format('His'); 125 | $dates[$dateString] = array_key_exists($dateString, $dates) ? $dates[$dateString] : []; 126 | $dates[$dateString][$timeString] = array_key_exists($timeString, $dates[$dateString]) ? $dates[$dateString][$timeString] : []; 127 | // add article to this array verbatim: 128 | $dates[$dateString][$timeString][] = [ 129 | 'type' => 'article', 130 | 'data' => $article, 131 | ]; 132 | } 133 | 134 | // now loop RSS feed 135 | $log->debug('Now looping RSS feed'); 136 | /** @var array $article */ 137 | foreach ($published as $feedArticle) { 138 | $dateString = $feedArticle['dateModified']->format('Ymd'); 139 | $timeString = $feedArticle['dateModified']->format('His'); 140 | $dates[$dateString] = array_key_exists($dateString, $dates) ? $dates[$dateString] : []; 141 | $dates[$dateString][$timeString] = array_key_exists($timeString, $dates[$dateString]) ? $dates[$dateString][$timeString] : []; 142 | 143 | // add published article to this array verbatim: 144 | $dates[$dateString][$timeString][] = [ 145 | 'type' => 'rss-article', 146 | 'data' => $feedArticle, 147 | ]; 148 | } 149 | 150 | 151 | // sort by date 152 | krsort($dates, SORT_STRING); 153 | $log->debug(sprintf('Collected all bookmarks and articles, grouped in %d specific date(s).', count(array_keys($dates)))); 154 | 155 | // loop to generate MD file. 156 | foreach ($dates as $date => $content) { 157 | krsort($content); 158 | $dateObject = Carbon::createFromFormat('Ymd', $date, 'Europe/Amsterdam'); 159 | $markdown .= sprintf($templates['header'], str_replace(' ', ' ', $dateObject->formatLocalized('%A %e %B %Y'))) . "\n"; 160 | // all entries for this date slot: 161 | foreach ($content as $timeSlot => $entries) { 162 | // each entry for this timeslot 163 | foreach ($entries as $entry) { 164 | switch ($entry['type']) { 165 | default: 166 | die(sprintf('Script cannot handle type "%s"', $entry['type'])); 167 | case 'bookmark': 168 | $host = parse_url($entry['data']['url'], PHP_URL_HOST); 169 | if (str_starts_with($host, 'www.')) { 170 | $host = substr($host, 4); 171 | } 172 | $markdown .= sprintf($templates['bookmark'], $entry['data']['title'], $entry['data']['url'], $host) . "\n"; 173 | break; 174 | case 'article': 175 | $host = parse_url($entry['data']['original_url'], PHP_URL_HOST); 176 | if (str_starts_with($host, 'www.')) { 177 | $host = substr($host, 4); 178 | } 179 | $tags = ''; 180 | $arr = []; 181 | foreach ($entry['data']['tags'] as $tag) { 182 | $arr[] = sprintf('#[[%s]]', $tag); 183 | } 184 | $tags = implode(', ', $arr); 185 | 186 | 187 | $sentence = sprintf($templates['article'], $entry['data']['title'], $entry['data']['wallabag_url'],$tags, $host, $entry['data']['original_url']) . "\n"; 188 | 189 | // add annotations (if present): 190 | // is not yet a template :( 191 | if (count($entry['data']['annotations']) > 0) { 192 | $sentence .= " - Opmerkingen\n"; 193 | foreach ($entry['data']['annotations'] as $annotation) { 194 | $sentence .= sprintf(" - > %s\n %s\n", $annotation['quote'], $annotation['text']); 195 | } 196 | } 197 | 198 | $markdown .= $sentence; 199 | break; 200 | case 'rss-article': 201 | $host = parse_url($entry['data']['link'], PHP_URL_HOST); 202 | if (str_starts_with($host, 'www.')) { 203 | $host = substr($host, 4); 204 | } 205 | $markdown .= sprintf($templates['rss'], $entry['data']['title'], $entry['data']['link'], $host) . "\n"; 206 | break; 207 | } 208 | } 209 | } 210 | } 211 | // temp 212 | // now update (overwrite!) bookmarks file. 213 | $client = new Client; 214 | $url = sprintf('https://%s/remote.php/dav/files/%s/%s/Stream.md', $_ENV['NEXTCLOUD_HOST'], $_ENV['NEXTCLOUD_USERNAME'], $_ENV['NEXTCLOUD_LOGSEQ_PATH']); 215 | $opts = [ 216 | 'auth' => [$_ENV['NEXTCLOUD_USERNAME'], $_ENV['NEXTCLOUD_PASS']], 217 | 'headers' => [ 218 | 'Accept' => 'application/json', 219 | ], 220 | 'body' => $markdown, 221 | ]; 222 | $log->debug(sprintf('Going to upload to %s', $url)); 223 | $res = $client->put($url, $opts); 224 | $log->debug('Done!'); 225 | -------------------------------------------------------------------------------- /app/Collector/BookmarkCollector.php: -------------------------------------------------------------------------------- 1 | skipCache = false; 49 | $this->collection = []; 50 | $this->folders = []; 51 | $this->cacheFile = sprintf('%s/bookmarks.json', CACHE); 52 | } 53 | 54 | /** 55 | * @inheritDoc 56 | */ 57 | public function setConfiguration(array $configuration): void 58 | { 59 | $this->configuration = $configuration; 60 | } 61 | 62 | /** 63 | * @inheritDoc 64 | */ 65 | public function collect(bool $skipCache = false): void 66 | { 67 | $this->logger->debug('BookmarkCollector will collect.'); 68 | $this->skipCache = $skipCache; 69 | $useCache = true; 70 | 71 | if (true === $this->skipCache) { 72 | $useCache = false; 73 | } 74 | if (false === $this->skipCache && $this->cacheOutOfDate()) { 75 | $useCache = false; 76 | } 77 | if (false === $useCache) { 78 | $this->logger->debug('BookmarkCollector will not use the cache.'); 79 | $this->collectBookmarks(); 80 | $this->collectFolders(); 81 | $this->mergeCollection(); 82 | $this->saveToCache(); 83 | } 84 | if (true === $useCache) { 85 | $this->logger->debug('BookmarkCollector will use the cache.'); 86 | $this->collectCache(); 87 | } 88 | $this->logger->debug('BookmarkCollector is done.'); 89 | } 90 | 91 | /** 92 | * @inheritDoc 93 | */ 94 | public function getCollection(): array 95 | { 96 | return $this->collection; 97 | } 98 | 99 | /** 100 | * @return bool 101 | */ 102 | private function cacheOutOfDate(): bool 103 | { 104 | if (!file_exists($this->cacheFile)) { 105 | $this->logger->debug('BookmarkCollector cache file does not exist.'); 106 | 107 | return true; 108 | } 109 | $content = file_get_contents($this->cacheFile); 110 | $json = json_decode($content, true, 128, JSON_THROW_ON_ERROR); 111 | // diff is over 12hrs 112 | if (time() - $json['moment'] > (12 * 60 * 60)) { 113 | $this->logger->debug('BookmarkCollector cache is out of date.'); 114 | 115 | return true; 116 | } 117 | $this->logger->debug('BookmarkCollector cache is fresh.'); 118 | 119 | return false; 120 | } 121 | 122 | /** 123 | * 124 | * @throws JsonException 125 | */ 126 | private function collectBookmarks(): void 127 | { 128 | $this->logger->debug('BookmarkCollector will collect fresh bookmarks.'); 129 | $client = new Client; 130 | $opts = [ 131 | 'auth' => [$this->configuration['username'], $this->configuration['password']], 132 | 'headers' => [ 133 | 'Accept' => 'application/json', 134 | ], 135 | ]; 136 | // collect all bookmarks with their folder ID: 137 | $hasMore = true; 138 | $page = 0; 139 | while (true === $hasMore) { 140 | $this->logger->debug(sprintf('BookmarkCollector is working on page #%d.', $page)); 141 | $res = $client->get( 142 | sprintf('https://%s/index.php/apps/bookmarks/public/rest/v2/bookmark?limit=100&page=%d', $this->configuration['host'], $page), $opts 143 | ); 144 | $data = (string) $res->getBody(); 145 | $body = json_decode($data, true, 128, JSON_THROW_ON_ERROR); 146 | if (isset($body['data'])) { 147 | if (0 === count($body['data'])) { 148 | $this->logger->debug('BookmarkCollector found no bookmarks on this page, and will stop.'); 149 | $hasMore = false; 150 | } 151 | $this->logger->debug(sprintf('BookmarkCollector found %d bookmarks.', count($body['data']))); 152 | foreach ($body['data'] as $entry) { 153 | $folderId = $entry['folders'][0] ?? -1; 154 | $this->collection[$folderId] = $this->collection[$folderId] ?? 155 | [ 156 | 'id' => $folderId, 157 | 'title' => '(empty)', 158 | 'parent' => 0, 159 | 'bookmarks' => [], 160 | ]; 161 | 162 | $this->collection[$folderId]['bookmarks'][] = [ 163 | 'title' => $entry['title'], 164 | 'url' => $entry['url'], 165 | 'added' => new Carbon($entry['added'])]; 166 | $this->logger->debug(sprintf('Found bookmark "%s" in folder #%d', $entry['title'], $folderId)); 167 | } 168 | } 169 | if (!isset($body['data'])) { 170 | $this->logger->debug('BookmarkCollector result has no body, so no more bookmarks.'); 171 | $hasMore = false; 172 | } 173 | $page++; 174 | } 175 | $this->logger->debug('BookmarkCollector is done collecting bookmarks.'); 176 | } 177 | 178 | /** 179 | * 180 | */ 181 | private function saveToCache(): void 182 | { 183 | $this->logger->debug('BookmarkCollector has saved the collection to cache.'); 184 | $content = [ 185 | 'moment' => time(), 186 | 'data' => $this->collection, 187 | ]; 188 | $json = json_encode($content, JSON_PRETTY_PRINT); 189 | file_put_contents($this->cacheFile, $json); 190 | } 191 | 192 | /** 193 | * 194 | */ 195 | private function collectFolders(): void 196 | { 197 | $this->logger->debug('BookmarkCollector is collecting folders.'); 198 | $client = new Client; 199 | $opts = [ 200 | 'auth' => [$this->configuration['username'], $this->configuration['password']], 201 | 'headers' => [ 202 | 'Accept' => 'application/json', 203 | ], 204 | ]; 205 | // get all folders, then get all bookmarks for that folder 206 | $res = $client->get(sprintf('https://%s/index.php/apps/bookmarks/public/rest/v2/folder', $this->configuration['host']), $opts); 207 | $data = (string) $res->getBody(); 208 | $body = json_decode($data, true); 209 | $this->parseFolderNames($body['data']); 210 | $this->logger->debug('BookmarkCollector is done collecting folders.'); 211 | } 212 | 213 | /** 214 | * @param array $array 215 | */ 216 | private function parseFolderNames(array $array): void 217 | { 218 | /** @var array $folder */ 219 | foreach ($array as $folder) { 220 | $folderId = (int) $folder['id']; 221 | $folderTitle = trim($folder['title']); 222 | $folderTitle = 0 === strlen($folderTitle) ? '(no title)' : $folderTitle; 223 | 224 | $this->logger->debug(sprintf('Found folder #%d with name "%s"', $folderId, $folderTitle)); 225 | 226 | $this->folders[$folderId] = [ 227 | 'id' => $folderId, 228 | 'title' => $folderTitle, 229 | 'parent' => (int) $folder['parent_folder'], 230 | ]; 231 | 232 | if (count($folder['children']) > 0) { 233 | $this->parseFolderNames($folder['children']); 234 | } 235 | } 236 | 237 | } 238 | 239 | private function mergeCollection(): void 240 | { 241 | /** 242 | * @var int $folderId 243 | * @var array $info 244 | */ 245 | foreach ($this->collection as $folderId => $info) { 246 | $this->collection[$folderId]['id'] = $folderId; 247 | $this->collection[$folderId]['title'] = $this->folders[$folderId]['title']; 248 | $this->collection[$folderId]['parent'] = $this->folders[$folderId]['parent']; 249 | $this->collection[$folderId]['bookmarks'] = $this->collection[$folderId]['bookmarks'] ?? []; 250 | } 251 | // add empty folders if necessary: 252 | foreach ($this->folders as $folderId => $info) { 253 | if (!array_key_exists($folderId, $this->collection)) { 254 | $this->collection[$folderId] = [ 255 | 'id' => $folderId, 256 | 'title' => $info['title'], 257 | 'parent' => $info['parent'], 258 | 'bookmarks' => [], 259 | ]; 260 | } 261 | } 262 | 263 | $this->logger->debug('BookmarkCollector has merged folders + bookmarks.'); 264 | } 265 | 266 | /** 267 | * @throws JsonException 268 | */ 269 | private function collectCache(): void 270 | { 271 | $content = file_get_contents($this->cacheFile); 272 | $json = json_decode($content, true, 128, JSON_THROW_ON_ERROR); 273 | $this->collection = $json['data']; 274 | $this->logger->debug('BookmarkCollector has collected bookmarks from the cache.'); 275 | } 276 | 277 | /** 278 | * @inheritDoc 279 | */ 280 | public function setLogger(Logger $logger): void 281 | { 282 | $this->logger = $logger; 283 | $this->logger->debug('BookmarkCollector has a logger!'); 284 | } 285 | 286 | /** 287 | * @return array 288 | */ 289 | public function getFolders(): array 290 | { 291 | return $this->folders; 292 | } 293 | } -------------------------------------------------------------------------------- /app/Collector/WallabagCollector.php: -------------------------------------------------------------------------------- 1 | skipCache = false; 49 | $this->collection = []; 50 | $this->token = []; 51 | $this->cacheFile = sprintf('%s/wallabag.json', CACHE); 52 | } 53 | 54 | /** 55 | * @inheritDoc 56 | */ 57 | public function setConfiguration(array $configuration): void 58 | { 59 | $this->configuration = $configuration; 60 | } 61 | 62 | /** 63 | * @inheritDoc 64 | */ 65 | public function collect(bool $skipCache = false): void 66 | { 67 | $this->logger->debug('WallabagCollector is going to collect.'); 68 | $this->skipCache = $skipCache; 69 | $useCache = true; 70 | 71 | if (true === $this->skipCache) { 72 | $useCache = false; 73 | } 74 | if (false === $this->skipCache && $this->cacheOutOfDate()) { 75 | $useCache = false; 76 | } 77 | if (false === $useCache) { 78 | $this->logger->debug('WallabagCollector will not use the cache.'); 79 | $this->getAccessToken(); 80 | $this->makePublicArticles(); 81 | $this->collectArchivedArticles(); 82 | $this->saveToCache(); 83 | } 84 | if (true === $useCache) { 85 | $this->logger->debug('WallabagCollector will use the cache.'); 86 | $this->collectCache(); 87 | } 88 | } 89 | 90 | /** 91 | * @return bool 92 | */ 93 | private function cacheOutOfDate(): bool 94 | { 95 | if (!file_exists($this->cacheFile)) { 96 | $this->logger->debug('WallabagCollector found no cache file, so its out of date.'); 97 | return true; 98 | } 99 | $content = file_get_contents($this->cacheFile); 100 | $json = json_decode($content, true, 128, JSON_THROW_ON_ERROR); 101 | // diff is over 12hrs 102 | if (time() - $json['moment'] > (12 * 60 * 60)) { 103 | $this->logger->debug('WallabagCollector cache is outdated.'); 104 | return true; 105 | } 106 | $this->logger->debug('WallabagCollector cache is fresh!'); 107 | 108 | return false; 109 | } 110 | 111 | 112 | /** 113 | * @inheritDoc 114 | */ 115 | public function getCollection(): array 116 | { 117 | return $this->collection; 118 | } 119 | 120 | /** 121 | * 122 | */ 123 | private function makePublicArticles(): void 124 | { 125 | $this->logger->debug('WallabagCollector will make all archived articles public.'); 126 | $client = new Client; 127 | $page = 1; 128 | $hasMore = true; 129 | $articlesUrl = '%s/api/entries.json?archive=1&sort=archived&perPage=5&page=%d&public=0'; 130 | $opts = [ 131 | 'headers' => [ 132 | 'Authorization' => sprintf('Bearer %s', $this->token['access_token']), 133 | ], 134 | ]; 135 | 136 | while (true === $hasMore) { 137 | $this->logger->debug(sprintf('WallabagCollector is now working on page #%d.', $page)); 138 | $url = sprintf($articlesUrl, $this->configuration['host'], $page); 139 | $response = $client->get($url, $opts); 140 | $body = (string) $response->getBody(); 141 | $results = json_decode($body, true, 512, JSON_THROW_ON_ERROR); 142 | 143 | $this->logger->addRecord($results['total'] > 0 ? 200 : 100, sprintf('WallabagCollector found %d new article(s) to make public.', $results['total'])); 144 | 145 | if ($results['pages'] <= $page) { 146 | $this->logger->debug('WallabagCollector has no more pages to process.'); 147 | $hasMore = false; 148 | } 149 | // loop articles 150 | foreach ($results['_embedded']['items'] as $item) { 151 | $patchClient = new Client; 152 | $patchUrl = sprintf('%s/api/entries/%d.json', $_ENV['WALLABAG_HOST'], $item['id']); 153 | $patchOpts = [ 154 | 'headers' => [ 155 | 'Authorization' => sprintf('Bearer %s', $this->token['access_token']), 156 | ], 157 | 'form_params' => [ 158 | 'public' => 1, 159 | ], 160 | ]; 161 | $patchClient->patch($patchUrl, $patchOpts); 162 | $this->logger->debug(sprintf('WallabagCollector made article #%d public.', $item['id'])); 163 | sleep(2); 164 | } 165 | $page++; 166 | } 167 | $this->logger->debug('WallabagCollector is done making articles public.'); 168 | } 169 | 170 | /** 171 | * 172 | */ 173 | private function getAccessToken(): void 174 | { 175 | $this->logger->debug('WallabagCollector will now get an access token.'); 176 | $client = new Client; 177 | $opts = [ 178 | 'form_params' => [ 179 | 'grant_type' => 'password', 180 | 'client_id' => $this->configuration['client_id'], 181 | 'client_secret' => $this->configuration['client_secret'], 182 | 'username' => $this->configuration['username'], 183 | 'password' => $this->configuration['password'], 184 | ], 185 | ]; 186 | $url = sprintf('%s/oauth/v2/token', $this->configuration['host']); 187 | $response = $client->post($url, $opts); 188 | $body = (string) $response->getBody(); 189 | $this->token = json_decode($body, true, 8, JSON_THROW_ON_ERROR); 190 | $this->logger->debug(sprintf('WallabagCollector has collected access token %s.', $this->token['access_token'])); 191 | } 192 | 193 | /** 194 | * 195 | */ 196 | private function collectArchivedArticles(): void 197 | { 198 | $this->logger->debug('WallabagCollector will now collect public + archived articles.'); 199 | $client = new Client; 200 | $page = 1; 201 | $hasMore = true; 202 | $articles = []; 203 | $articlesUrl = '%s/api/entries.json?archive=1&sort=archived&perPage=50&page=%d&public=1&detail=metadata'; 204 | $opts = [ 205 | 'headers' => [ 206 | 'Authorization' => sprintf('Bearer %s', $this->token['access_token']), 207 | ], 208 | ]; 209 | 210 | while (true === $hasMore) { 211 | $this->logger->debug(sprintf('WallabagCollector is now working on page #%d.', $page)); 212 | $url = sprintf($articlesUrl, $this->configuration['host'], $page); 213 | $response = $client->get($url, $opts); 214 | $body = (string) $response->getBody(); 215 | $results = json_decode($body, true, 512, JSON_THROW_ON_ERROR); 216 | 217 | if (1 === $page) { 218 | $this->logger->debug(sprintf('Found %d article(s) to share.', $results['total'])); 219 | } 220 | $this->logger->debug(sprintf('Working on page %d of %d...', $page, $results['pages'])); 221 | 222 | if ($results['pages'] <= $page) { 223 | // no more pages 224 | $hasMore = false; 225 | $this->logger->debug('WallabagCollector found the last page!'); 226 | } 227 | // loop articles and save them: 228 | foreach ($results['_embedded']['items'] as $item) { 229 | $articles[] = $this->processArticle($item); 230 | } 231 | sleep(2); 232 | $page++; 233 | } 234 | $this->logger->debug('WallabagCollector is done collecting articles.'); 235 | $this->collection = $articles; 236 | } 237 | 238 | /** 239 | * @param array $item 240 | * @return array 241 | */ 242 | private function processArticle(array $item): array 243 | { 244 | 245 | $article = [ 246 | 'title' => $item['title'], 247 | 'original_url' => $item['url'], 248 | 'archived_at' => new Carbon($item['archived_at']), 249 | 'created_at' => new Carbon($item['created_at']), 250 | 'wallabag_url' => sprintf('%s/share/%s', $this->configuration['host'], $item['uid']), 251 | 'tags' => [], 252 | 'annotations' => [], 253 | ]; 254 | 255 | /** @var array $tag */ 256 | foreach ($item['tags'] as $tag) { 257 | $article['tags'][] = $tag['label']; 258 | } 259 | /** @var array $annotation */ 260 | foreach ($item['annotations'] as $annotation) { 261 | $article['annotations'][] = [ 262 | 'quote' => $annotation['quote'], 263 | 'text' => $annotation['text'], 264 | ]; 265 | } 266 | 267 | return $article; 268 | } 269 | 270 | 271 | /** 272 | * @inheritDoc 273 | */ 274 | public function setLogger(Logger $logger): void 275 | { 276 | $this->logger = $logger; 277 | $this->logger->debug('WallabagCollector has a logger!'); 278 | 279 | } 280 | 281 | /** 282 | * 283 | */ 284 | private function saveToCache(): void 285 | { 286 | $content = [ 287 | 'moment' => time(), 288 | 'data' => $this->collection, 289 | ]; 290 | $json = json_encode($content, JSON_PRETTY_PRINT); 291 | file_put_contents($this->cacheFile, $json); 292 | $this->logger->debug('WallabagCollector has saved the results to the cache.'); 293 | } 294 | 295 | /** 296 | * @throws JsonException 297 | */ 298 | private function collectCache(): void 299 | { 300 | $content = file_get_contents($this->cacheFile); 301 | $json = json_decode($content, true, 128, JSON_THROW_ON_ERROR); 302 | $this->collection = $json['data']; 303 | $this->logger->debug('WallabagCollector has collected from the cache.'); 304 | } 305 | } -------------------------------------------------------------------------------- /composer.lock: -------------------------------------------------------------------------------- 1 | { 2 | "_readme": [ 3 | "This file locks the dependencies of your project to a known state", 4 | "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", 5 | "This file is @generated automatically" 6 | ], 7 | "content-hash": "890aa678857ea139ec111304f62ecd45", 8 | "packages": [ 9 | { 10 | "name": "abraham/twitteroauth", 11 | "version": "3.1.0", 12 | "source": { 13 | "type": "git", 14 | "url": "https://github.com/abraham/twitteroauth.git", 15 | "reference": "51a502cde3c4f414ea0f98827afbeca1f19dfe2d" 16 | }, 17 | "dist": { 18 | "type": "zip", 19 | "url": "https://api.github.com/repos/abraham/twitteroauth/zipball/51a502cde3c4f414ea0f98827afbeca1f19dfe2d", 20 | "reference": "51a502cde3c4f414ea0f98827afbeca1f19dfe2d", 21 | "shasum": "" 22 | }, 23 | "require": { 24 | "composer/ca-bundle": "^1.2", 25 | "ext-curl": "*", 26 | "php": "^7.3 || ^7.4 || ^8.0" 27 | }, 28 | "require-dev": { 29 | "php-vcr/php-vcr": "^1", 30 | "php-vcr/phpunit-testlistener-vcr": "dev-php-8", 31 | "phpmd/phpmd": "^2", 32 | "phpunit/phpunit": "^8 || ^9", 33 | "squizlabs/php_codesniffer": "^3" 34 | }, 35 | "type": "library", 36 | "autoload": { 37 | "psr-4": { 38 | "Abraham\\TwitterOAuth\\": "src" 39 | } 40 | }, 41 | "notification-url": "https://packagist.org/downloads/", 42 | "license": [ 43 | "MIT" 44 | ], 45 | "authors": [ 46 | { 47 | "name": "Abraham Williams", 48 | "email": "abraham@abrah.am", 49 | "homepage": "https://abrah.am", 50 | "role": "Developer" 51 | } 52 | ], 53 | "description": "The most popular PHP library for use with the Twitter OAuth REST API.", 54 | "homepage": "https://twitteroauth.com", 55 | "keywords": [ 56 | "Twitter API", 57 | "Twitter oAuth", 58 | "api", 59 | "oauth", 60 | "rest", 61 | "social", 62 | "twitter" 63 | ], 64 | "support": { 65 | "issues": "https://github.com/abraham/twitteroauth/issues", 66 | "source": "https://github.com/abraham/twitteroauth" 67 | }, 68 | "time": "2021-07-19T00:42:49+00:00" 69 | }, 70 | { 71 | "name": "composer/ca-bundle", 72 | "version": "1.2.11", 73 | "source": { 74 | "type": "git", 75 | "url": "https://github.com/composer/ca-bundle.git", 76 | "reference": "0b072d51c5a9c6f3412f7ea3ab043d6603cb2582" 77 | }, 78 | "dist": { 79 | "type": "zip", 80 | "url": "https://api.github.com/repos/composer/ca-bundle/zipball/0b072d51c5a9c6f3412f7ea3ab043d6603cb2582", 81 | "reference": "0b072d51c5a9c6f3412f7ea3ab043d6603cb2582", 82 | "shasum": "" 83 | }, 84 | "require": { 85 | "ext-openssl": "*", 86 | "ext-pcre": "*", 87 | "php": "^5.3.2 || ^7.0 || ^8.0" 88 | }, 89 | "require-dev": { 90 | "phpstan/phpstan": "^0.12.55", 91 | "psr/log": "^1.0", 92 | "symfony/phpunit-bridge": "^4.2 || ^5", 93 | "symfony/process": "^2.5 || ^3.0 || ^4.0 || ^5.0 || ^6.0" 94 | }, 95 | "type": "library", 96 | "extra": { 97 | "branch-alias": { 98 | "dev-main": "1.x-dev" 99 | } 100 | }, 101 | "autoload": { 102 | "psr-4": { 103 | "Composer\\CaBundle\\": "src" 104 | } 105 | }, 106 | "notification-url": "https://packagist.org/downloads/", 107 | "license": [ 108 | "MIT" 109 | ], 110 | "authors": [ 111 | { 112 | "name": "Jordi Boggiano", 113 | "email": "j.boggiano@seld.be", 114 | "homepage": "http://seld.be" 115 | } 116 | ], 117 | "description": "Lets you find a path to the system CA bundle, and includes a fallback to the Mozilla CA bundle.", 118 | "keywords": [ 119 | "cabundle", 120 | "cacert", 121 | "certificate", 122 | "ssl", 123 | "tls" 124 | ], 125 | "support": { 126 | "irc": "irc://irc.freenode.org/composer", 127 | "issues": "https://github.com/composer/ca-bundle/issues", 128 | "source": "https://github.com/composer/ca-bundle/tree/1.2.11" 129 | }, 130 | "funding": [ 131 | { 132 | "url": "https://packagist.com", 133 | "type": "custom" 134 | }, 135 | { 136 | "url": "https://github.com/composer", 137 | "type": "github" 138 | }, 139 | { 140 | "url": "https://tidelift.com/funding/github/packagist/composer/composer", 141 | "type": "tidelift" 142 | } 143 | ], 144 | "time": "2021-09-25T20:32:43+00:00" 145 | }, 146 | { 147 | "name": "container-interop/container-interop", 148 | "version": "1.2.0", 149 | "source": { 150 | "type": "git", 151 | "url": "https://github.com/container-interop/container-interop.git", 152 | "reference": "79cbf1341c22ec75643d841642dd5d6acd83bdb8" 153 | }, 154 | "dist": { 155 | "type": "zip", 156 | "url": "https://api.github.com/repos/container-interop/container-interop/zipball/79cbf1341c22ec75643d841642dd5d6acd83bdb8", 157 | "reference": "79cbf1341c22ec75643d841642dd5d6acd83bdb8", 158 | "shasum": "" 159 | }, 160 | "require": { 161 | "psr/container": "^1.0" 162 | }, 163 | "type": "library", 164 | "autoload": { 165 | "psr-4": { 166 | "Interop\\Container\\": "src/Interop/Container/" 167 | } 168 | }, 169 | "notification-url": "https://packagist.org/downloads/", 170 | "license": [ 171 | "MIT" 172 | ], 173 | "description": "Promoting the interoperability of container objects (DIC, SL, etc.)", 174 | "homepage": "https://github.com/container-interop/container-interop", 175 | "support": { 176 | "issues": "https://github.com/container-interop/container-interop/issues", 177 | "source": "https://github.com/container-interop/container-interop/tree/master" 178 | }, 179 | "abandoned": "psr/container", 180 | "time": "2017-02-14T19:40:03+00:00" 181 | }, 182 | { 183 | "name": "graham-campbell/result-type", 184 | "version": "v1.0.2", 185 | "source": { 186 | "type": "git", 187 | "url": "https://github.com/GrahamCampbell/Result-Type.git", 188 | "reference": "84afea85c6841deeea872f36249a206e878a5de0" 189 | }, 190 | "dist": { 191 | "type": "zip", 192 | "url": "https://api.github.com/repos/GrahamCampbell/Result-Type/zipball/84afea85c6841deeea872f36249a206e878a5de0", 193 | "reference": "84afea85c6841deeea872f36249a206e878a5de0", 194 | "shasum": "" 195 | }, 196 | "require": { 197 | "php": "^7.0 || ^8.0", 198 | "phpoption/phpoption": "^1.8" 199 | }, 200 | "require-dev": { 201 | "phpunit/phpunit": "^6.5.14 || ^7.5.20 || ^8.5.19 || ^9.5.8" 202 | }, 203 | "type": "library", 204 | "autoload": { 205 | "psr-4": { 206 | "GrahamCampbell\\ResultType\\": "src/" 207 | } 208 | }, 209 | "notification-url": "https://packagist.org/downloads/", 210 | "license": [ 211 | "MIT" 212 | ], 213 | "authors": [ 214 | { 215 | "name": "Graham Campbell", 216 | "email": "hello@gjcampbell.co.uk" 217 | } 218 | ], 219 | "description": "An Implementation Of The Result Type", 220 | "keywords": [ 221 | "Graham Campbell", 222 | "GrahamCampbell", 223 | "Result Type", 224 | "Result-Type", 225 | "result" 226 | ], 227 | "support": { 228 | "issues": "https://github.com/GrahamCampbell/Result-Type/issues", 229 | "source": "https://github.com/GrahamCampbell/Result-Type/tree/v1.0.2" 230 | }, 231 | "funding": [ 232 | { 233 | "url": "https://github.com/GrahamCampbell", 234 | "type": "github" 235 | }, 236 | { 237 | "url": "https://tidelift.com/funding/github/packagist/graham-campbell/result-type", 238 | "type": "tidelift" 239 | } 240 | ], 241 | "time": "2021-08-28T21:34:50+00:00" 242 | }, 243 | { 244 | "name": "guzzlehttp/guzzle", 245 | "version": "7.3.0", 246 | "source": { 247 | "type": "git", 248 | "url": "https://github.com/guzzle/guzzle.git", 249 | "reference": "7008573787b430c1c1f650e3722d9bba59967628" 250 | }, 251 | "dist": { 252 | "type": "zip", 253 | "url": "https://api.github.com/repos/guzzle/guzzle/zipball/7008573787b430c1c1f650e3722d9bba59967628", 254 | "reference": "7008573787b430c1c1f650e3722d9bba59967628", 255 | "shasum": "" 256 | }, 257 | "require": { 258 | "ext-json": "*", 259 | "guzzlehttp/promises": "^1.4", 260 | "guzzlehttp/psr7": "^1.7 || ^2.0", 261 | "php": "^7.2.5 || ^8.0", 262 | "psr/http-client": "^1.0" 263 | }, 264 | "provide": { 265 | "psr/http-client-implementation": "1.0" 266 | }, 267 | "require-dev": { 268 | "bamarni/composer-bin-plugin": "^1.4.1", 269 | "ext-curl": "*", 270 | "php-http/client-integration-tests": "^3.0", 271 | "phpunit/phpunit": "^8.5.5 || ^9.3.5", 272 | "psr/log": "^1.1" 273 | }, 274 | "suggest": { 275 | "ext-curl": "Required for CURL handler support", 276 | "ext-intl": "Required for Internationalized Domain Name (IDN) support", 277 | "psr/log": "Required for using the Log middleware" 278 | }, 279 | "type": "library", 280 | "extra": { 281 | "branch-alias": { 282 | "dev-master": "7.3-dev" 283 | } 284 | }, 285 | "autoload": { 286 | "psr-4": { 287 | "GuzzleHttp\\": "src/" 288 | }, 289 | "files": [ 290 | "src/functions_include.php" 291 | ] 292 | }, 293 | "notification-url": "https://packagist.org/downloads/", 294 | "license": [ 295 | "MIT" 296 | ], 297 | "authors": [ 298 | { 299 | "name": "Michael Dowling", 300 | "email": "mtdowling@gmail.com", 301 | "homepage": "https://github.com/mtdowling" 302 | }, 303 | { 304 | "name": "Márk Sági-Kazár", 305 | "email": "mark.sagikazar@gmail.com", 306 | "homepage": "https://sagikazarmark.hu" 307 | } 308 | ], 309 | "description": "Guzzle is a PHP HTTP client library", 310 | "homepage": "http://guzzlephp.org/", 311 | "keywords": [ 312 | "client", 313 | "curl", 314 | "framework", 315 | "http", 316 | "http client", 317 | "psr-18", 318 | "psr-7", 319 | "rest", 320 | "web service" 321 | ], 322 | "support": { 323 | "issues": "https://github.com/guzzle/guzzle/issues", 324 | "source": "https://github.com/guzzle/guzzle/tree/7.3.0" 325 | }, 326 | "funding": [ 327 | { 328 | "url": "https://github.com/GrahamCampbell", 329 | "type": "github" 330 | }, 331 | { 332 | "url": "https://github.com/Nyholm", 333 | "type": "github" 334 | }, 335 | { 336 | "url": "https://github.com/alexeyshockov", 337 | "type": "github" 338 | }, 339 | { 340 | "url": "https://github.com/gmponos", 341 | "type": "github" 342 | } 343 | ], 344 | "time": "2021-03-23T11:33:13+00:00" 345 | }, 346 | { 347 | "name": "guzzlehttp/promises", 348 | "version": "1.5.0", 349 | "source": { 350 | "type": "git", 351 | "url": "https://github.com/guzzle/promises.git", 352 | "reference": "136a635e2b4a49b9d79e9c8fee267ffb257fdba0" 353 | }, 354 | "dist": { 355 | "type": "zip", 356 | "url": "https://api.github.com/repos/guzzle/promises/zipball/136a635e2b4a49b9d79e9c8fee267ffb257fdba0", 357 | "reference": "136a635e2b4a49b9d79e9c8fee267ffb257fdba0", 358 | "shasum": "" 359 | }, 360 | "require": { 361 | "php": ">=5.5" 362 | }, 363 | "require-dev": { 364 | "symfony/phpunit-bridge": "^4.4 || ^5.1" 365 | }, 366 | "type": "library", 367 | "extra": { 368 | "branch-alias": { 369 | "dev-master": "1.5-dev" 370 | } 371 | }, 372 | "autoload": { 373 | "psr-4": { 374 | "GuzzleHttp\\Promise\\": "src/" 375 | }, 376 | "files": [ 377 | "src/functions_include.php" 378 | ] 379 | }, 380 | "notification-url": "https://packagist.org/downloads/", 381 | "license": [ 382 | "MIT" 383 | ], 384 | "authors": [ 385 | { 386 | "name": "Graham Campbell", 387 | "email": "hello@gjcampbell.co.uk", 388 | "homepage": "https://github.com/GrahamCampbell" 389 | }, 390 | { 391 | "name": "Michael Dowling", 392 | "email": "mtdowling@gmail.com", 393 | "homepage": "https://github.com/mtdowling" 394 | }, 395 | { 396 | "name": "Tobias Nyholm", 397 | "email": "tobias.nyholm@gmail.com", 398 | "homepage": "https://github.com/Nyholm" 399 | }, 400 | { 401 | "name": "Tobias Schultze", 402 | "email": "webmaster@tubo-world.de", 403 | "homepage": "https://github.com/Tobion" 404 | } 405 | ], 406 | "description": "Guzzle promises library", 407 | "keywords": [ 408 | "promise" 409 | ], 410 | "support": { 411 | "issues": "https://github.com/guzzle/promises/issues", 412 | "source": "https://github.com/guzzle/promises/tree/1.5.0" 413 | }, 414 | "funding": [ 415 | { 416 | "url": "https://github.com/GrahamCampbell", 417 | "type": "github" 418 | }, 419 | { 420 | "url": "https://github.com/Nyholm", 421 | "type": "github" 422 | }, 423 | { 424 | "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/promises", 425 | "type": "tidelift" 426 | } 427 | ], 428 | "time": "2021-10-07T13:05:22+00:00" 429 | }, 430 | { 431 | "name": "guzzlehttp/psr7", 432 | "version": "2.1.0", 433 | "source": { 434 | "type": "git", 435 | "url": "https://github.com/guzzle/psr7.git", 436 | "reference": "089edd38f5b8abba6cb01567c2a8aaa47cec4c72" 437 | }, 438 | "dist": { 439 | "type": "zip", 440 | "url": "https://api.github.com/repos/guzzle/psr7/zipball/089edd38f5b8abba6cb01567c2a8aaa47cec4c72", 441 | "reference": "089edd38f5b8abba6cb01567c2a8aaa47cec4c72", 442 | "shasum": "" 443 | }, 444 | "require": { 445 | "php": "^7.2.5 || ^8.0", 446 | "psr/http-factory": "^1.0", 447 | "psr/http-message": "^1.0", 448 | "ralouphie/getallheaders": "^3.0" 449 | }, 450 | "provide": { 451 | "psr/http-factory-implementation": "1.0", 452 | "psr/http-message-implementation": "1.0" 453 | }, 454 | "require-dev": { 455 | "bamarni/composer-bin-plugin": "^1.4.1", 456 | "http-interop/http-factory-tests": "^0.9", 457 | "phpunit/phpunit": "^8.5.8 || ^9.3.10" 458 | }, 459 | "suggest": { 460 | "laminas/laminas-httphandlerrunner": "Emit PSR-7 responses" 461 | }, 462 | "type": "library", 463 | "extra": { 464 | "branch-alias": { 465 | "dev-master": "2.1-dev" 466 | } 467 | }, 468 | "autoload": { 469 | "psr-4": { 470 | "GuzzleHttp\\Psr7\\": "src/" 471 | } 472 | }, 473 | "notification-url": "https://packagist.org/downloads/", 474 | "license": [ 475 | "MIT" 476 | ], 477 | "authors": [ 478 | { 479 | "name": "Graham Campbell", 480 | "email": "hello@gjcampbell.co.uk", 481 | "homepage": "https://github.com/GrahamCampbell" 482 | }, 483 | { 484 | "name": "Michael Dowling", 485 | "email": "mtdowling@gmail.com", 486 | "homepage": "https://github.com/mtdowling" 487 | }, 488 | { 489 | "name": "George Mponos", 490 | "email": "gmponos@gmail.com", 491 | "homepage": "https://github.com/gmponos" 492 | }, 493 | { 494 | "name": "Tobias Nyholm", 495 | "email": "tobias.nyholm@gmail.com", 496 | "homepage": "https://github.com/Nyholm" 497 | }, 498 | { 499 | "name": "Márk Sági-Kazár", 500 | "email": "mark.sagikazar@gmail.com", 501 | "homepage": "https://github.com/sagikazarmark" 502 | }, 503 | { 504 | "name": "Tobias Schultze", 505 | "email": "webmaster@tubo-world.de", 506 | "homepage": "https://github.com/Tobion" 507 | }, 508 | { 509 | "name": "Márk Sági-Kazár", 510 | "email": "mark.sagikazar@gmail.com", 511 | "homepage": "https://sagikazarmark.hu" 512 | } 513 | ], 514 | "description": "PSR-7 message implementation that also provides common utility methods", 515 | "keywords": [ 516 | "http", 517 | "message", 518 | "psr-7", 519 | "request", 520 | "response", 521 | "stream", 522 | "uri", 523 | "url" 524 | ], 525 | "support": { 526 | "issues": "https://github.com/guzzle/psr7/issues", 527 | "source": "https://github.com/guzzle/psr7/tree/2.1.0" 528 | }, 529 | "funding": [ 530 | { 531 | "url": "https://github.com/GrahamCampbell", 532 | "type": "github" 533 | }, 534 | { 535 | "url": "https://github.com/Nyholm", 536 | "type": "github" 537 | }, 538 | { 539 | "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/psr7", 540 | "type": "tidelift" 541 | } 542 | ], 543 | "time": "2021-10-06T17:43:30+00:00" 544 | }, 545 | { 546 | "name": "laminas/laminas-escaper", 547 | "version": "2.9.0", 548 | "source": { 549 | "type": "git", 550 | "url": "https://github.com/laminas/laminas-escaper.git", 551 | "reference": "891ad70986729e20ed2e86355fcf93c9dc238a5f" 552 | }, 553 | "dist": { 554 | "type": "zip", 555 | "url": "https://api.github.com/repos/laminas/laminas-escaper/zipball/891ad70986729e20ed2e86355fcf93c9dc238a5f", 556 | "reference": "891ad70986729e20ed2e86355fcf93c9dc238a5f", 557 | "shasum": "" 558 | }, 559 | "require": { 560 | "php": "^7.3 || ~8.0.0 || ~8.1.0" 561 | }, 562 | "conflict": { 563 | "zendframework/zend-escaper": "*" 564 | }, 565 | "require-dev": { 566 | "laminas/laminas-coding-standard": "~2.3.0", 567 | "phpunit/phpunit": "^9.3", 568 | "psalm/plugin-phpunit": "^0.12.2", 569 | "vimeo/psalm": "^3.16" 570 | }, 571 | "suggest": { 572 | "ext-iconv": "*", 573 | "ext-mbstring": "*" 574 | }, 575 | "type": "library", 576 | "autoload": { 577 | "psr-4": { 578 | "Laminas\\Escaper\\": "src/" 579 | } 580 | }, 581 | "notification-url": "https://packagist.org/downloads/", 582 | "license": [ 583 | "BSD-3-Clause" 584 | ], 585 | "description": "Securely and safely escape HTML, HTML attributes, JavaScript, CSS, and URLs", 586 | "homepage": "https://laminas.dev", 587 | "keywords": [ 588 | "escaper", 589 | "laminas" 590 | ], 591 | "support": { 592 | "chat": "https://laminas.dev/chat", 593 | "docs": "https://docs.laminas.dev/laminas-escaper/", 594 | "forum": "https://discourse.laminas.dev", 595 | "issues": "https://github.com/laminas/laminas-escaper/issues", 596 | "rss": "https://github.com/laminas/laminas-escaper/releases.atom", 597 | "source": "https://github.com/laminas/laminas-escaper" 598 | }, 599 | "funding": [ 600 | { 601 | "url": "https://funding.communitybridge.org/projects/laminas-project", 602 | "type": "community_bridge" 603 | } 604 | ], 605 | "time": "2021-09-02T17:10:53+00:00" 606 | }, 607 | { 608 | "name": "laminas/laminas-feed", 609 | "version": "2.15.0", 610 | "source": { 611 | "type": "git", 612 | "url": "https://github.com/laminas/laminas-feed.git", 613 | "reference": "3ef837a12833c74b438d2c3780023c4244e0abae" 614 | }, 615 | "dist": { 616 | "type": "zip", 617 | "url": "https://api.github.com/repos/laminas/laminas-feed/zipball/3ef837a12833c74b438d2c3780023c4244e0abae", 618 | "reference": "3ef837a12833c74b438d2c3780023c4244e0abae", 619 | "shasum": "" 620 | }, 621 | "require": { 622 | "ext-dom": "*", 623 | "ext-libxml": "*", 624 | "laminas/laminas-escaper": "^2.9", 625 | "laminas/laminas-stdlib": "^3.6", 626 | "php": "^7.3 || ~8.0.0 || ~8.1.0" 627 | }, 628 | "conflict": { 629 | "laminas/laminas-servicemanager": "<3.3", 630 | "zendframework/zend-feed": "*" 631 | }, 632 | "require-dev": { 633 | "laminas/laminas-cache": "^2.7.2", 634 | "laminas/laminas-coding-standard": "~2.2.1", 635 | "laminas/laminas-db": "^2.13.3", 636 | "laminas/laminas-http": "^2.15", 637 | "laminas/laminas-servicemanager": "^3.7", 638 | "laminas/laminas-validator": "^2.15", 639 | "phpunit/phpunit": "^9.5.5", 640 | "psalm/plugin-phpunit": "^0.13.0", 641 | "psr/http-message": "^1.0.1", 642 | "vimeo/psalm": "^4.1" 643 | }, 644 | "suggest": { 645 | "laminas/laminas-cache": "Laminas\\Cache component, for optionally caching feeds between requests", 646 | "laminas/laminas-db": "Laminas\\Db component, for use with PubSubHubbub", 647 | "laminas/laminas-http": "Laminas\\Http for PubSubHubbub, and optionally for use with Laminas\\Feed\\Reader", 648 | "laminas/laminas-servicemanager": "Laminas\\ServiceManager component, for easily extending ExtensionManager implementations", 649 | "laminas/laminas-validator": "Laminas\\Validator component, for validating email addresses used in Atom feeds and entries when using the Writer subcomponent", 650 | "psr/http-message": "PSR-7 ^1.0.1, if you wish to use Laminas\\Feed\\Reader\\Http\\Psr7ResponseDecorator" 651 | }, 652 | "type": "library", 653 | "autoload": { 654 | "psr-4": { 655 | "Laminas\\Feed\\": "src/" 656 | } 657 | }, 658 | "notification-url": "https://packagist.org/downloads/", 659 | "license": [ 660 | "BSD-3-Clause" 661 | ], 662 | "description": "provides functionality for consuming RSS and Atom feeds", 663 | "homepage": "https://laminas.dev", 664 | "keywords": [ 665 | "feed", 666 | "laminas" 667 | ], 668 | "support": { 669 | "chat": "https://laminas.dev/chat", 670 | "docs": "https://docs.laminas.dev/laminas-feed/", 671 | "forum": "https://discourse.laminas.dev", 672 | "issues": "https://github.com/laminas/laminas-feed/issues", 673 | "rss": "https://github.com/laminas/laminas-feed/releases.atom", 674 | "source": "https://github.com/laminas/laminas-feed" 675 | }, 676 | "funding": [ 677 | { 678 | "url": "https://funding.communitybridge.org/projects/laminas-project", 679 | "type": "community_bridge" 680 | } 681 | ], 682 | "time": "2021-09-20T18:11:11+00:00" 683 | }, 684 | { 685 | "name": "laminas/laminas-http", 686 | "version": "2.15.0", 687 | "source": { 688 | "type": "git", 689 | "url": "https://github.com/laminas/laminas-http.git", 690 | "reference": "e1f3420ab35e21ea135913d213b8d570e5e7b513" 691 | }, 692 | "dist": { 693 | "type": "zip", 694 | "url": "https://api.github.com/repos/laminas/laminas-http/zipball/e1f3420ab35e21ea135913d213b8d570e5e7b513", 695 | "reference": "e1f3420ab35e21ea135913d213b8d570e5e7b513", 696 | "shasum": "" 697 | }, 698 | "require": { 699 | "laminas/laminas-loader": "^2.8", 700 | "laminas/laminas-stdlib": "^3.6", 701 | "laminas/laminas-uri": "^2.9.1", 702 | "laminas/laminas-validator": "^2.15", 703 | "php": "^7.3 || ~8.0.0 || ~8.1.0" 704 | }, 705 | "conflict": { 706 | "zendframework/zend-http": "*" 707 | }, 708 | "require-dev": { 709 | "laminas/laminas-coding-standard": "~2.2.1", 710 | "phpunit/phpunit": "^9.5.5" 711 | }, 712 | "suggest": { 713 | "paragonie/certainty": "For automated management of cacert.pem" 714 | }, 715 | "type": "library", 716 | "autoload": { 717 | "psr-4": { 718 | "Laminas\\Http\\": "src/" 719 | } 720 | }, 721 | "notification-url": "https://packagist.org/downloads/", 722 | "license": [ 723 | "BSD-3-Clause" 724 | ], 725 | "description": "Provides an easy interface for performing Hyper-Text Transfer Protocol (HTTP) requests", 726 | "homepage": "https://laminas.dev", 727 | "keywords": [ 728 | "http", 729 | "http client", 730 | "laminas" 731 | ], 732 | "support": { 733 | "chat": "https://laminas.dev/chat", 734 | "docs": "https://docs.laminas.dev/laminas-http/", 735 | "forum": "https://discourse.laminas.dev", 736 | "issues": "https://github.com/laminas/laminas-http/issues", 737 | "rss": "https://github.com/laminas/laminas-http/releases.atom", 738 | "source": "https://github.com/laminas/laminas-http" 739 | }, 740 | "funding": [ 741 | { 742 | "url": "https://funding.communitybridge.org/projects/laminas-project", 743 | "type": "community_bridge" 744 | } 745 | ], 746 | "time": "2021-09-10T10:45:31+00:00" 747 | }, 748 | { 749 | "name": "laminas/laminas-loader", 750 | "version": "2.8.0", 751 | "source": { 752 | "type": "git", 753 | "url": "https://github.com/laminas/laminas-loader.git", 754 | "reference": "d0589ec9dd48365fd95ad10d1c906efd7711c16b" 755 | }, 756 | "dist": { 757 | "type": "zip", 758 | "url": "https://api.github.com/repos/laminas/laminas-loader/zipball/d0589ec9dd48365fd95ad10d1c906efd7711c16b", 759 | "reference": "d0589ec9dd48365fd95ad10d1c906efd7711c16b", 760 | "shasum": "" 761 | }, 762 | "require": { 763 | "php": "^7.3 || ~8.0.0 || ~8.1.0" 764 | }, 765 | "conflict": { 766 | "zendframework/zend-loader": "*" 767 | }, 768 | "require-dev": { 769 | "laminas/laminas-coding-standard": "~2.2.1", 770 | "phpunit/phpunit": "^9.3" 771 | }, 772 | "type": "library", 773 | "autoload": { 774 | "psr-4": { 775 | "Laminas\\Loader\\": "src/" 776 | } 777 | }, 778 | "notification-url": "https://packagist.org/downloads/", 779 | "license": [ 780 | "BSD-3-Clause" 781 | ], 782 | "description": "Autoloading and plugin loading strategies", 783 | "homepage": "https://laminas.dev", 784 | "keywords": [ 785 | "laminas", 786 | "loader" 787 | ], 788 | "support": { 789 | "chat": "https://laminas.dev/chat", 790 | "docs": "https://docs.laminas.dev/laminas-loader/", 791 | "forum": "https://discourse.laminas.dev", 792 | "issues": "https://github.com/laminas/laminas-loader/issues", 793 | "rss": "https://github.com/laminas/laminas-loader/releases.atom", 794 | "source": "https://github.com/laminas/laminas-loader" 795 | }, 796 | "funding": [ 797 | { 798 | "url": "https://funding.communitybridge.org/projects/laminas-project", 799 | "type": "community_bridge" 800 | } 801 | ], 802 | "time": "2021-09-02T18:30:53+00:00" 803 | }, 804 | { 805 | "name": "laminas/laminas-stdlib", 806 | "version": "3.6.0", 807 | "source": { 808 | "type": "git", 809 | "url": "https://github.com/laminas/laminas-stdlib.git", 810 | "reference": "c53d8537f108fac3fae652677a19735db730ba46" 811 | }, 812 | "dist": { 813 | "type": "zip", 814 | "url": "https://api.github.com/repos/laminas/laminas-stdlib/zipball/c53d8537f108fac3fae652677a19735db730ba46", 815 | "reference": "c53d8537f108fac3fae652677a19735db730ba46", 816 | "shasum": "" 817 | }, 818 | "require": { 819 | "php": "^7.3 || ~8.0.0 || ~8.1.0" 820 | }, 821 | "conflict": { 822 | "zendframework/zend-stdlib": "*" 823 | }, 824 | "require-dev": { 825 | "laminas/laminas-coding-standard": "~2.3.0", 826 | "phpbench/phpbench": "^0.17.1", 827 | "phpunit/phpunit": "~9.3.7", 828 | "psalm/plugin-phpunit": "^0.16.0", 829 | "vimeo/psalm": "^4.7" 830 | }, 831 | "type": "library", 832 | "autoload": { 833 | "psr-4": { 834 | "Laminas\\Stdlib\\": "src/" 835 | } 836 | }, 837 | "notification-url": "https://packagist.org/downloads/", 838 | "license": [ 839 | "BSD-3-Clause" 840 | ], 841 | "description": "SPL extensions, array utilities, error handlers, and more", 842 | "homepage": "https://laminas.dev", 843 | "keywords": [ 844 | "laminas", 845 | "stdlib" 846 | ], 847 | "support": { 848 | "chat": "https://laminas.dev/chat", 849 | "docs": "https://docs.laminas.dev/laminas-stdlib/", 850 | "forum": "https://discourse.laminas.dev", 851 | "issues": "https://github.com/laminas/laminas-stdlib/issues", 852 | "rss": "https://github.com/laminas/laminas-stdlib/releases.atom", 853 | "source": "https://github.com/laminas/laminas-stdlib" 854 | }, 855 | "funding": [ 856 | { 857 | "url": "https://funding.communitybridge.org/projects/laminas-project", 858 | "type": "community_bridge" 859 | } 860 | ], 861 | "time": "2021-09-02T16:11:32+00:00" 862 | }, 863 | { 864 | "name": "laminas/laminas-uri", 865 | "version": "2.9.1", 866 | "source": { 867 | "type": "git", 868 | "url": "https://github.com/laminas/laminas-uri.git", 869 | "reference": "7e837dc15c8fd3949df7d1213246fd7c8640032b" 870 | }, 871 | "dist": { 872 | "type": "zip", 873 | "url": "https://api.github.com/repos/laminas/laminas-uri/zipball/7e837dc15c8fd3949df7d1213246fd7c8640032b", 874 | "reference": "7e837dc15c8fd3949df7d1213246fd7c8640032b", 875 | "shasum": "" 876 | }, 877 | "require": { 878 | "laminas/laminas-escaper": "^2.9", 879 | "laminas/laminas-validator": "^2.15", 880 | "php": "^7.3 || ~8.0.0 || ~8.1.0" 881 | }, 882 | "conflict": { 883 | "zendframework/zend-uri": "*" 884 | }, 885 | "require-dev": { 886 | "laminas/laminas-coding-standard": "~2.2.1", 887 | "phpunit/phpunit": "^9.5.5" 888 | }, 889 | "type": "library", 890 | "autoload": { 891 | "psr-4": { 892 | "Laminas\\Uri\\": "src/" 893 | } 894 | }, 895 | "notification-url": "https://packagist.org/downloads/", 896 | "license": [ 897 | "BSD-3-Clause" 898 | ], 899 | "description": "A component that aids in manipulating and validating » Uniform Resource Identifiers (URIs)", 900 | "homepage": "https://laminas.dev", 901 | "keywords": [ 902 | "laminas", 903 | "uri" 904 | ], 905 | "support": { 906 | "chat": "https://laminas.dev/chat", 907 | "docs": "https://docs.laminas.dev/laminas-uri/", 908 | "forum": "https://discourse.laminas.dev", 909 | "issues": "https://github.com/laminas/laminas-uri/issues", 910 | "rss": "https://github.com/laminas/laminas-uri/releases.atom", 911 | "source": "https://github.com/laminas/laminas-uri" 912 | }, 913 | "funding": [ 914 | { 915 | "url": "https://funding.communitybridge.org/projects/laminas-project", 916 | "type": "community_bridge" 917 | } 918 | ], 919 | "time": "2021-09-09T18:37:15+00:00" 920 | }, 921 | { 922 | "name": "laminas/laminas-validator", 923 | "version": "2.15.0", 924 | "source": { 925 | "type": "git", 926 | "url": "https://github.com/laminas/laminas-validator.git", 927 | "reference": "270380e87904f5a1a1fba3059989d4ca157e16a9" 928 | }, 929 | "dist": { 930 | "type": "zip", 931 | "url": "https://api.github.com/repos/laminas/laminas-validator/zipball/270380e87904f5a1a1fba3059989d4ca157e16a9", 932 | "reference": "270380e87904f5a1a1fba3059989d4ca157e16a9", 933 | "shasum": "" 934 | }, 935 | "require": { 936 | "container-interop/container-interop": "^1.1", 937 | "laminas/laminas-stdlib": "^3.6", 938 | "php": "^7.3 || ~8.0.0 || ~8.1.0" 939 | }, 940 | "conflict": { 941 | "zendframework/zend-validator": "*" 942 | }, 943 | "require-dev": { 944 | "laminas/laminas-cache": "^2.6.1", 945 | "laminas/laminas-coding-standard": "~2.2.1", 946 | "laminas/laminas-db": "^2.7", 947 | "laminas/laminas-filter": "^2.6", 948 | "laminas/laminas-http": "^2.14.2", 949 | "laminas/laminas-i18n": "^2.6", 950 | "laminas/laminas-math": "^2.6", 951 | "laminas/laminas-servicemanager": "^2.7.11 || ^3.0.3", 952 | "laminas/laminas-session": "^2.8", 953 | "laminas/laminas-uri": "^2.7", 954 | "phpspec/prophecy-phpunit": "^2.0", 955 | "phpunit/phpunit": "^9.5.5", 956 | "psalm/plugin-phpunit": "^0.15.0", 957 | "psr/http-client": "^1.0", 958 | "psr/http-factory": "^1.0", 959 | "psr/http-message": "^1.0", 960 | "vimeo/psalm": "^4.3" 961 | }, 962 | "suggest": { 963 | "laminas/laminas-db": "Laminas\\Db component, required by the (No)RecordExists validator", 964 | "laminas/laminas-filter": "Laminas\\Filter component, required by the Digits validator", 965 | "laminas/laminas-i18n": "Laminas\\I18n component to allow translation of validation error messages", 966 | "laminas/laminas-i18n-resources": "Translations of validator messages", 967 | "laminas/laminas-math": "Laminas\\Math component, required by the Csrf validator", 968 | "laminas/laminas-servicemanager": "Laminas\\ServiceManager component to allow using the ValidatorPluginManager and validator chains", 969 | "laminas/laminas-session": "Laminas\\Session component, ^2.8; required by the Csrf validator", 970 | "laminas/laminas-uri": "Laminas\\Uri component, required by the Uri and Sitemap\\Loc validators", 971 | "psr/http-message": "psr/http-message, required when validating PSR-7 UploadedFileInterface instances via the Upload and UploadFile validators" 972 | }, 973 | "type": "library", 974 | "extra": { 975 | "laminas": { 976 | "component": "Laminas\\Validator", 977 | "config-provider": "Laminas\\Validator\\ConfigProvider" 978 | } 979 | }, 980 | "autoload": { 981 | "psr-4": { 982 | "Laminas\\Validator\\": "src/" 983 | } 984 | }, 985 | "notification-url": "https://packagist.org/downloads/", 986 | "license": [ 987 | "BSD-3-Clause" 988 | ], 989 | "description": "Validation classes for a wide range of domains, and the ability to chain validators to create complex validation criteria", 990 | "homepage": "https://laminas.dev", 991 | "keywords": [ 992 | "laminas", 993 | "validator" 994 | ], 995 | "support": { 996 | "chat": "https://laminas.dev/chat", 997 | "docs": "https://docs.laminas.dev/laminas-validator/", 998 | "forum": "https://discourse.laminas.dev", 999 | "issues": "https://github.com/laminas/laminas-validator/issues", 1000 | "rss": "https://github.com/laminas/laminas-validator/releases.atom", 1001 | "source": "https://github.com/laminas/laminas-validator" 1002 | }, 1003 | "funding": [ 1004 | { 1005 | "url": "https://funding.communitybridge.org/projects/laminas-project", 1006 | "type": "community_bridge" 1007 | } 1008 | ], 1009 | "time": "2021-09-08T23:16:56+00:00" 1010 | }, 1011 | { 1012 | "name": "league/climate", 1013 | "version": "3.7.0", 1014 | "source": { 1015 | "type": "git", 1016 | "url": "https://github.com/thephpleague/climate.git", 1017 | "reference": "5c717c3032c5118be7ad2395dbe0813d9894e8c7" 1018 | }, 1019 | "dist": { 1020 | "type": "zip", 1021 | "url": "https://api.github.com/repos/thephpleague/climate/zipball/5c717c3032c5118be7ad2395dbe0813d9894e8c7", 1022 | "reference": "5c717c3032c5118be7ad2395dbe0813d9894e8c7", 1023 | "shasum": "" 1024 | }, 1025 | "require": { 1026 | "php": "^7.3 || ^8.0", 1027 | "psr/log": "^1.0", 1028 | "seld/cli-prompt": "^1.0" 1029 | }, 1030 | "require-dev": { 1031 | "mikey179/vfsstream": "^1.4", 1032 | "mockery/mockery": "^1.4.2", 1033 | "phpunit/phpunit": "^9.5.0" 1034 | }, 1035 | "suggest": { 1036 | "ext-mbstring": "If ext-mbstring is not available you MUST install symfony/polyfill-mbstring" 1037 | }, 1038 | "type": "library", 1039 | "autoload": { 1040 | "psr-4": { 1041 | "League\\CLImate\\": "src/" 1042 | } 1043 | }, 1044 | "notification-url": "https://packagist.org/downloads/", 1045 | "license": [ 1046 | "MIT" 1047 | ], 1048 | "authors": [ 1049 | { 1050 | "name": "Joe Tannenbaum", 1051 | "email": "hey@joe.codes", 1052 | "homepage": "http://joe.codes/", 1053 | "role": "Developer" 1054 | }, 1055 | { 1056 | "name": "Craig Duncan", 1057 | "email": "git@duncanc.co.uk", 1058 | "homepage": "https://github.com/duncan3dc", 1059 | "role": "Developer" 1060 | } 1061 | ], 1062 | "description": "PHP's best friend for the terminal. CLImate allows you to easily output colored text, special formats, and more.", 1063 | "keywords": [ 1064 | "cli", 1065 | "colors", 1066 | "command", 1067 | "php", 1068 | "terminal" 1069 | ], 1070 | "support": { 1071 | "issues": "https://github.com/thephpleague/climate/issues", 1072 | "source": "https://github.com/thephpleague/climate/tree/3.7.0" 1073 | }, 1074 | "time": "2021-01-10T20:18:52+00:00" 1075 | }, 1076 | { 1077 | "name": "monolog/monolog", 1078 | "version": "2.3.5", 1079 | "source": { 1080 | "type": "git", 1081 | "url": "https://github.com/Seldaek/monolog.git", 1082 | "reference": "fd4380d6fc37626e2f799f29d91195040137eba9" 1083 | }, 1084 | "dist": { 1085 | "type": "zip", 1086 | "url": "https://api.github.com/repos/Seldaek/monolog/zipball/fd4380d6fc37626e2f799f29d91195040137eba9", 1087 | "reference": "fd4380d6fc37626e2f799f29d91195040137eba9", 1088 | "shasum": "" 1089 | }, 1090 | "require": { 1091 | "php": ">=7.2", 1092 | "psr/log": "^1.0.1 || ^2.0 || ^3.0" 1093 | }, 1094 | "provide": { 1095 | "psr/log-implementation": "1.0.0 || 2.0.0 || 3.0.0" 1096 | }, 1097 | "require-dev": { 1098 | "aws/aws-sdk-php": "^2.4.9 || ^3.0", 1099 | "doctrine/couchdb": "~1.0@dev", 1100 | "elasticsearch/elasticsearch": "^7", 1101 | "graylog2/gelf-php": "^1.4.2", 1102 | "mongodb/mongodb": "^1.8", 1103 | "php-amqplib/php-amqplib": "~2.4 || ^3", 1104 | "php-console/php-console": "^3.1.3", 1105 | "phpspec/prophecy": "^1.6.1", 1106 | "phpstan/phpstan": "^0.12.91", 1107 | "phpunit/phpunit": "^8.5", 1108 | "predis/predis": "^1.1", 1109 | "rollbar/rollbar": "^1.3", 1110 | "ruflin/elastica": ">=0.90@dev", 1111 | "swiftmailer/swiftmailer": "^5.3|^6.0" 1112 | }, 1113 | "suggest": { 1114 | "aws/aws-sdk-php": "Allow sending log messages to AWS services like DynamoDB", 1115 | "doctrine/couchdb": "Allow sending log messages to a CouchDB server", 1116 | "elasticsearch/elasticsearch": "Allow sending log messages to an Elasticsearch server via official client", 1117 | "ext-amqp": "Allow sending log messages to an AMQP server (1.0+ required)", 1118 | "ext-curl": "Required to send log messages using the IFTTTHandler, the LogglyHandler, the SendGridHandler, the SlackWebhookHandler or the TelegramBotHandler", 1119 | "ext-mbstring": "Allow to work properly with unicode symbols", 1120 | "ext-mongodb": "Allow sending log messages to a MongoDB server (via driver)", 1121 | "ext-openssl": "Required to send log messages using SSL", 1122 | "ext-sockets": "Allow sending log messages to a Syslog server (via UDP driver)", 1123 | "graylog2/gelf-php": "Allow sending log messages to a GrayLog2 server", 1124 | "mongodb/mongodb": "Allow sending log messages to a MongoDB server (via library)", 1125 | "php-amqplib/php-amqplib": "Allow sending log messages to an AMQP server using php-amqplib", 1126 | "php-console/php-console": "Allow sending log messages to Google Chrome", 1127 | "rollbar/rollbar": "Allow sending log messages to Rollbar", 1128 | "ruflin/elastica": "Allow sending log messages to an Elastic Search server" 1129 | }, 1130 | "type": "library", 1131 | "extra": { 1132 | "branch-alias": { 1133 | "dev-main": "2.x-dev" 1134 | } 1135 | }, 1136 | "autoload": { 1137 | "psr-4": { 1138 | "Monolog\\": "src/Monolog" 1139 | } 1140 | }, 1141 | "notification-url": "https://packagist.org/downloads/", 1142 | "license": [ 1143 | "MIT" 1144 | ], 1145 | "authors": [ 1146 | { 1147 | "name": "Jordi Boggiano", 1148 | "email": "j.boggiano@seld.be", 1149 | "homepage": "https://seld.be" 1150 | } 1151 | ], 1152 | "description": "Sends your logs to files, sockets, inboxes, databases and various web services", 1153 | "homepage": "https://github.com/Seldaek/monolog", 1154 | "keywords": [ 1155 | "log", 1156 | "logging", 1157 | "psr-3" 1158 | ], 1159 | "support": { 1160 | "issues": "https://github.com/Seldaek/monolog/issues", 1161 | "source": "https://github.com/Seldaek/monolog/tree/2.3.5" 1162 | }, 1163 | "funding": [ 1164 | { 1165 | "url": "https://github.com/Seldaek", 1166 | "type": "github" 1167 | }, 1168 | { 1169 | "url": "https://tidelift.com/funding/github/packagist/monolog/monolog", 1170 | "type": "tidelift" 1171 | } 1172 | ], 1173 | "time": "2021-10-01T21:08:31+00:00" 1174 | }, 1175 | { 1176 | "name": "nesbot/carbon", 1177 | "version": "2.53.1", 1178 | "source": { 1179 | "type": "git", 1180 | "url": "https://github.com/briannesbitt/Carbon.git", 1181 | "reference": "f4655858a784988f880c1b8c7feabbf02dfdf045" 1182 | }, 1183 | "dist": { 1184 | "type": "zip", 1185 | "url": "https://api.github.com/repos/briannesbitt/Carbon/zipball/f4655858a784988f880c1b8c7feabbf02dfdf045", 1186 | "reference": "f4655858a784988f880c1b8c7feabbf02dfdf045", 1187 | "shasum": "" 1188 | }, 1189 | "require": { 1190 | "ext-json": "*", 1191 | "php": "^7.1.8 || ^8.0", 1192 | "symfony/polyfill-mbstring": "^1.0", 1193 | "symfony/polyfill-php80": "^1.16", 1194 | "symfony/translation": "^3.4 || ^4.0 || ^5.0" 1195 | }, 1196 | "require-dev": { 1197 | "doctrine/orm": "^2.7", 1198 | "friendsofphp/php-cs-fixer": "^3.0", 1199 | "kylekatarnls/multi-tester": "^2.0", 1200 | "phpmd/phpmd": "^2.9", 1201 | "phpstan/extension-installer": "^1.0", 1202 | "phpstan/phpstan": "^0.12.54", 1203 | "phpunit/phpunit": "^7.5.20 || ^8.5.14", 1204 | "squizlabs/php_codesniffer": "^3.4" 1205 | }, 1206 | "bin": [ 1207 | "bin/carbon" 1208 | ], 1209 | "type": "library", 1210 | "extra": { 1211 | "branch-alias": { 1212 | "dev-3.x": "3.x-dev", 1213 | "dev-master": "2.x-dev" 1214 | }, 1215 | "laravel": { 1216 | "providers": [ 1217 | "Carbon\\Laravel\\ServiceProvider" 1218 | ] 1219 | }, 1220 | "phpstan": { 1221 | "includes": [ 1222 | "extension.neon" 1223 | ] 1224 | } 1225 | }, 1226 | "autoload": { 1227 | "psr-4": { 1228 | "Carbon\\": "src/Carbon/" 1229 | } 1230 | }, 1231 | "notification-url": "https://packagist.org/downloads/", 1232 | "license": [ 1233 | "MIT" 1234 | ], 1235 | "authors": [ 1236 | { 1237 | "name": "Brian Nesbitt", 1238 | "email": "brian@nesbot.com", 1239 | "homepage": "https://markido.com" 1240 | }, 1241 | { 1242 | "name": "kylekatarnls", 1243 | "homepage": "https://github.com/kylekatarnls" 1244 | } 1245 | ], 1246 | "description": "An API extension for DateTime that supports 281 different languages.", 1247 | "homepage": "https://carbon.nesbot.com", 1248 | "keywords": [ 1249 | "date", 1250 | "datetime", 1251 | "time" 1252 | ], 1253 | "support": { 1254 | "issues": "https://github.com/briannesbitt/Carbon/issues", 1255 | "source": "https://github.com/briannesbitt/Carbon" 1256 | }, 1257 | "funding": [ 1258 | { 1259 | "url": "https://opencollective.com/Carbon", 1260 | "type": "open_collective" 1261 | }, 1262 | { 1263 | "url": "https://tidelift.com/funding/github/packagist/nesbot/carbon", 1264 | "type": "tidelift" 1265 | } 1266 | ], 1267 | "time": "2021-09-06T09:29:23+00:00" 1268 | }, 1269 | { 1270 | "name": "phpoption/phpoption", 1271 | "version": "1.8.0", 1272 | "source": { 1273 | "type": "git", 1274 | "url": "https://github.com/schmittjoh/php-option.git", 1275 | "reference": "5455cb38aed4523f99977c4a12ef19da4bfe2a28" 1276 | }, 1277 | "dist": { 1278 | "type": "zip", 1279 | "url": "https://api.github.com/repos/schmittjoh/php-option/zipball/5455cb38aed4523f99977c4a12ef19da4bfe2a28", 1280 | "reference": "5455cb38aed4523f99977c4a12ef19da4bfe2a28", 1281 | "shasum": "" 1282 | }, 1283 | "require": { 1284 | "php": "^7.0 || ^8.0" 1285 | }, 1286 | "require-dev": { 1287 | "bamarni/composer-bin-plugin": "^1.4.1", 1288 | "phpunit/phpunit": "^6.5.14 || ^7.0.20 || ^8.5.19 || ^9.5.8" 1289 | }, 1290 | "type": "library", 1291 | "extra": { 1292 | "branch-alias": { 1293 | "dev-master": "1.8-dev" 1294 | } 1295 | }, 1296 | "autoload": { 1297 | "psr-4": { 1298 | "PhpOption\\": "src/PhpOption/" 1299 | } 1300 | }, 1301 | "notification-url": "https://packagist.org/downloads/", 1302 | "license": [ 1303 | "Apache-2.0" 1304 | ], 1305 | "authors": [ 1306 | { 1307 | "name": "Johannes M. Schmitt", 1308 | "email": "schmittjoh@gmail.com" 1309 | }, 1310 | { 1311 | "name": "Graham Campbell", 1312 | "email": "hello@gjcampbell.co.uk" 1313 | } 1314 | ], 1315 | "description": "Option Type for PHP", 1316 | "keywords": [ 1317 | "language", 1318 | "option", 1319 | "php", 1320 | "type" 1321 | ], 1322 | "support": { 1323 | "issues": "https://github.com/schmittjoh/php-option/issues", 1324 | "source": "https://github.com/schmittjoh/php-option/tree/1.8.0" 1325 | }, 1326 | "funding": [ 1327 | { 1328 | "url": "https://github.com/GrahamCampbell", 1329 | "type": "github" 1330 | }, 1331 | { 1332 | "url": "https://tidelift.com/funding/github/packagist/phpoption/phpoption", 1333 | "type": "tidelift" 1334 | } 1335 | ], 1336 | "time": "2021-08-28T21:27:29+00:00" 1337 | }, 1338 | { 1339 | "name": "psr/container", 1340 | "version": "1.1.1", 1341 | "source": { 1342 | "type": "git", 1343 | "url": "https://github.com/php-fig/container.git", 1344 | "reference": "8622567409010282b7aeebe4bb841fe98b58dcaf" 1345 | }, 1346 | "dist": { 1347 | "type": "zip", 1348 | "url": "https://api.github.com/repos/php-fig/container/zipball/8622567409010282b7aeebe4bb841fe98b58dcaf", 1349 | "reference": "8622567409010282b7aeebe4bb841fe98b58dcaf", 1350 | "shasum": "" 1351 | }, 1352 | "require": { 1353 | "php": ">=7.2.0" 1354 | }, 1355 | "type": "library", 1356 | "autoload": { 1357 | "psr-4": { 1358 | "Psr\\Container\\": "src/" 1359 | } 1360 | }, 1361 | "notification-url": "https://packagist.org/downloads/", 1362 | "license": [ 1363 | "MIT" 1364 | ], 1365 | "authors": [ 1366 | { 1367 | "name": "PHP-FIG", 1368 | "homepage": "https://www.php-fig.org/" 1369 | } 1370 | ], 1371 | "description": "Common Container Interface (PHP FIG PSR-11)", 1372 | "homepage": "https://github.com/php-fig/container", 1373 | "keywords": [ 1374 | "PSR-11", 1375 | "container", 1376 | "container-interface", 1377 | "container-interop", 1378 | "psr" 1379 | ], 1380 | "support": { 1381 | "issues": "https://github.com/php-fig/container/issues", 1382 | "source": "https://github.com/php-fig/container/tree/1.1.1" 1383 | }, 1384 | "time": "2021-03-05T17:36:06+00:00" 1385 | }, 1386 | { 1387 | "name": "psr/http-client", 1388 | "version": "1.0.1", 1389 | "source": { 1390 | "type": "git", 1391 | "url": "https://github.com/php-fig/http-client.git", 1392 | "reference": "2dfb5f6c5eff0e91e20e913f8c5452ed95b86621" 1393 | }, 1394 | "dist": { 1395 | "type": "zip", 1396 | "url": "https://api.github.com/repos/php-fig/http-client/zipball/2dfb5f6c5eff0e91e20e913f8c5452ed95b86621", 1397 | "reference": "2dfb5f6c5eff0e91e20e913f8c5452ed95b86621", 1398 | "shasum": "" 1399 | }, 1400 | "require": { 1401 | "php": "^7.0 || ^8.0", 1402 | "psr/http-message": "^1.0" 1403 | }, 1404 | "type": "library", 1405 | "extra": { 1406 | "branch-alias": { 1407 | "dev-master": "1.0.x-dev" 1408 | } 1409 | }, 1410 | "autoload": { 1411 | "psr-4": { 1412 | "Psr\\Http\\Client\\": "src/" 1413 | } 1414 | }, 1415 | "notification-url": "https://packagist.org/downloads/", 1416 | "license": [ 1417 | "MIT" 1418 | ], 1419 | "authors": [ 1420 | { 1421 | "name": "PHP-FIG", 1422 | "homepage": "http://www.php-fig.org/" 1423 | } 1424 | ], 1425 | "description": "Common interface for HTTP clients", 1426 | "homepage": "https://github.com/php-fig/http-client", 1427 | "keywords": [ 1428 | "http", 1429 | "http-client", 1430 | "psr", 1431 | "psr-18" 1432 | ], 1433 | "support": { 1434 | "source": "https://github.com/php-fig/http-client/tree/master" 1435 | }, 1436 | "time": "2020-06-29T06:28:15+00:00" 1437 | }, 1438 | { 1439 | "name": "psr/http-factory", 1440 | "version": "1.0.1", 1441 | "source": { 1442 | "type": "git", 1443 | "url": "https://github.com/php-fig/http-factory.git", 1444 | "reference": "12ac7fcd07e5b077433f5f2bee95b3a771bf61be" 1445 | }, 1446 | "dist": { 1447 | "type": "zip", 1448 | "url": "https://api.github.com/repos/php-fig/http-factory/zipball/12ac7fcd07e5b077433f5f2bee95b3a771bf61be", 1449 | "reference": "12ac7fcd07e5b077433f5f2bee95b3a771bf61be", 1450 | "shasum": "" 1451 | }, 1452 | "require": { 1453 | "php": ">=7.0.0", 1454 | "psr/http-message": "^1.0" 1455 | }, 1456 | "type": "library", 1457 | "extra": { 1458 | "branch-alias": { 1459 | "dev-master": "1.0.x-dev" 1460 | } 1461 | }, 1462 | "autoload": { 1463 | "psr-4": { 1464 | "Psr\\Http\\Message\\": "src/" 1465 | } 1466 | }, 1467 | "notification-url": "https://packagist.org/downloads/", 1468 | "license": [ 1469 | "MIT" 1470 | ], 1471 | "authors": [ 1472 | { 1473 | "name": "PHP-FIG", 1474 | "homepage": "http://www.php-fig.org/" 1475 | } 1476 | ], 1477 | "description": "Common interfaces for PSR-7 HTTP message factories", 1478 | "keywords": [ 1479 | "factory", 1480 | "http", 1481 | "message", 1482 | "psr", 1483 | "psr-17", 1484 | "psr-7", 1485 | "request", 1486 | "response" 1487 | ], 1488 | "support": { 1489 | "source": "https://github.com/php-fig/http-factory/tree/master" 1490 | }, 1491 | "time": "2019-04-30T12:38:16+00:00" 1492 | }, 1493 | { 1494 | "name": "psr/http-message", 1495 | "version": "1.0.1", 1496 | "source": { 1497 | "type": "git", 1498 | "url": "https://github.com/php-fig/http-message.git", 1499 | "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363" 1500 | }, 1501 | "dist": { 1502 | "type": "zip", 1503 | "url": "https://api.github.com/repos/php-fig/http-message/zipball/f6561bf28d520154e4b0ec72be95418abe6d9363", 1504 | "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363", 1505 | "shasum": "" 1506 | }, 1507 | "require": { 1508 | "php": ">=5.3.0" 1509 | }, 1510 | "type": "library", 1511 | "extra": { 1512 | "branch-alias": { 1513 | "dev-master": "1.0.x-dev" 1514 | } 1515 | }, 1516 | "autoload": { 1517 | "psr-4": { 1518 | "Psr\\Http\\Message\\": "src/" 1519 | } 1520 | }, 1521 | "notification-url": "https://packagist.org/downloads/", 1522 | "license": [ 1523 | "MIT" 1524 | ], 1525 | "authors": [ 1526 | { 1527 | "name": "PHP-FIG", 1528 | "homepage": "http://www.php-fig.org/" 1529 | } 1530 | ], 1531 | "description": "Common interface for HTTP messages", 1532 | "homepage": "https://github.com/php-fig/http-message", 1533 | "keywords": [ 1534 | "http", 1535 | "http-message", 1536 | "psr", 1537 | "psr-7", 1538 | "request", 1539 | "response" 1540 | ], 1541 | "support": { 1542 | "source": "https://github.com/php-fig/http-message/tree/master" 1543 | }, 1544 | "time": "2016-08-06T14:39:51+00:00" 1545 | }, 1546 | { 1547 | "name": "psr/log", 1548 | "version": "1.1.4", 1549 | "source": { 1550 | "type": "git", 1551 | "url": "https://github.com/php-fig/log.git", 1552 | "reference": "d49695b909c3b7628b6289db5479a1c204601f11" 1553 | }, 1554 | "dist": { 1555 | "type": "zip", 1556 | "url": "https://api.github.com/repos/php-fig/log/zipball/d49695b909c3b7628b6289db5479a1c204601f11", 1557 | "reference": "d49695b909c3b7628b6289db5479a1c204601f11", 1558 | "shasum": "" 1559 | }, 1560 | "require": { 1561 | "php": ">=5.3.0" 1562 | }, 1563 | "type": "library", 1564 | "extra": { 1565 | "branch-alias": { 1566 | "dev-master": "1.1.x-dev" 1567 | } 1568 | }, 1569 | "autoload": { 1570 | "psr-4": { 1571 | "Psr\\Log\\": "Psr/Log/" 1572 | } 1573 | }, 1574 | "notification-url": "https://packagist.org/downloads/", 1575 | "license": [ 1576 | "MIT" 1577 | ], 1578 | "authors": [ 1579 | { 1580 | "name": "PHP-FIG", 1581 | "homepage": "https://www.php-fig.org/" 1582 | } 1583 | ], 1584 | "description": "Common interface for logging libraries", 1585 | "homepage": "https://github.com/php-fig/log", 1586 | "keywords": [ 1587 | "log", 1588 | "psr", 1589 | "psr-3" 1590 | ], 1591 | "support": { 1592 | "source": "https://github.com/php-fig/log/tree/1.1.4" 1593 | }, 1594 | "time": "2021-05-03T11:20:27+00:00" 1595 | }, 1596 | { 1597 | "name": "ralouphie/getallheaders", 1598 | "version": "3.0.3", 1599 | "source": { 1600 | "type": "git", 1601 | "url": "https://github.com/ralouphie/getallheaders.git", 1602 | "reference": "120b605dfeb996808c31b6477290a714d356e822" 1603 | }, 1604 | "dist": { 1605 | "type": "zip", 1606 | "url": "https://api.github.com/repos/ralouphie/getallheaders/zipball/120b605dfeb996808c31b6477290a714d356e822", 1607 | "reference": "120b605dfeb996808c31b6477290a714d356e822", 1608 | "shasum": "" 1609 | }, 1610 | "require": { 1611 | "php": ">=5.6" 1612 | }, 1613 | "require-dev": { 1614 | "php-coveralls/php-coveralls": "^2.1", 1615 | "phpunit/phpunit": "^5 || ^6.5" 1616 | }, 1617 | "type": "library", 1618 | "autoload": { 1619 | "files": [ 1620 | "src/getallheaders.php" 1621 | ] 1622 | }, 1623 | "notification-url": "https://packagist.org/downloads/", 1624 | "license": [ 1625 | "MIT" 1626 | ], 1627 | "authors": [ 1628 | { 1629 | "name": "Ralph Khattar", 1630 | "email": "ralph.khattar@gmail.com" 1631 | } 1632 | ], 1633 | "description": "A polyfill for getallheaders.", 1634 | "support": { 1635 | "issues": "https://github.com/ralouphie/getallheaders/issues", 1636 | "source": "https://github.com/ralouphie/getallheaders/tree/develop" 1637 | }, 1638 | "time": "2019-03-08T08:55:37+00:00" 1639 | }, 1640 | { 1641 | "name": "seld/cli-prompt", 1642 | "version": "1.0.4", 1643 | "source": { 1644 | "type": "git", 1645 | "url": "https://github.com/Seldaek/cli-prompt.git", 1646 | "reference": "b8dfcf02094b8c03b40322c229493bb2884423c5" 1647 | }, 1648 | "dist": { 1649 | "type": "zip", 1650 | "url": "https://api.github.com/repos/Seldaek/cli-prompt/zipball/b8dfcf02094b8c03b40322c229493bb2884423c5", 1651 | "reference": "b8dfcf02094b8c03b40322c229493bb2884423c5", 1652 | "shasum": "" 1653 | }, 1654 | "require": { 1655 | "php": ">=5.3" 1656 | }, 1657 | "require-dev": { 1658 | "phpstan/phpstan": "^0.12.63" 1659 | }, 1660 | "type": "library", 1661 | "extra": { 1662 | "branch-alias": { 1663 | "dev-master": "1.x-dev" 1664 | } 1665 | }, 1666 | "autoload": { 1667 | "psr-4": { 1668 | "Seld\\CliPrompt\\": "src/" 1669 | } 1670 | }, 1671 | "notification-url": "https://packagist.org/downloads/", 1672 | "license": [ 1673 | "MIT" 1674 | ], 1675 | "authors": [ 1676 | { 1677 | "name": "Jordi Boggiano", 1678 | "email": "j.boggiano@seld.be" 1679 | } 1680 | ], 1681 | "description": "Allows you to prompt for user input on the command line, and optionally hide the characters they type", 1682 | "keywords": [ 1683 | "cli", 1684 | "console", 1685 | "hidden", 1686 | "input", 1687 | "prompt" 1688 | ], 1689 | "support": { 1690 | "issues": "https://github.com/Seldaek/cli-prompt/issues", 1691 | "source": "https://github.com/Seldaek/cli-prompt/tree/1.0.4" 1692 | }, 1693 | "time": "2020-12-15T21:32:01+00:00" 1694 | }, 1695 | { 1696 | "name": "symfony/deprecation-contracts", 1697 | "version": "v2.4.0", 1698 | "source": { 1699 | "type": "git", 1700 | "url": "https://github.com/symfony/deprecation-contracts.git", 1701 | "reference": "5f38c8804a9e97d23e0c8d63341088cd8a22d627" 1702 | }, 1703 | "dist": { 1704 | "type": "zip", 1705 | "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/5f38c8804a9e97d23e0c8d63341088cd8a22d627", 1706 | "reference": "5f38c8804a9e97d23e0c8d63341088cd8a22d627", 1707 | "shasum": "" 1708 | }, 1709 | "require": { 1710 | "php": ">=7.1" 1711 | }, 1712 | "type": "library", 1713 | "extra": { 1714 | "branch-alias": { 1715 | "dev-main": "2.4-dev" 1716 | }, 1717 | "thanks": { 1718 | "name": "symfony/contracts", 1719 | "url": "https://github.com/symfony/contracts" 1720 | } 1721 | }, 1722 | "autoload": { 1723 | "files": [ 1724 | "function.php" 1725 | ] 1726 | }, 1727 | "notification-url": "https://packagist.org/downloads/", 1728 | "license": [ 1729 | "MIT" 1730 | ], 1731 | "authors": [ 1732 | { 1733 | "name": "Nicolas Grekas", 1734 | "email": "p@tchwork.com" 1735 | }, 1736 | { 1737 | "name": "Symfony Community", 1738 | "homepage": "https://symfony.com/contributors" 1739 | } 1740 | ], 1741 | "description": "A generic function and convention to trigger deprecation notices", 1742 | "homepage": "https://symfony.com", 1743 | "support": { 1744 | "source": "https://github.com/symfony/deprecation-contracts/tree/v2.4.0" 1745 | }, 1746 | "funding": [ 1747 | { 1748 | "url": "https://symfony.com/sponsor", 1749 | "type": "custom" 1750 | }, 1751 | { 1752 | "url": "https://github.com/fabpot", 1753 | "type": "github" 1754 | }, 1755 | { 1756 | "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", 1757 | "type": "tidelift" 1758 | } 1759 | ], 1760 | "time": "2021-03-23T23:28:01+00:00" 1761 | }, 1762 | { 1763 | "name": "symfony/polyfill-ctype", 1764 | "version": "v1.23.0", 1765 | "source": { 1766 | "type": "git", 1767 | "url": "https://github.com/symfony/polyfill-ctype.git", 1768 | "reference": "46cd95797e9df938fdd2b03693b5fca5e64b01ce" 1769 | }, 1770 | "dist": { 1771 | "type": "zip", 1772 | "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/46cd95797e9df938fdd2b03693b5fca5e64b01ce", 1773 | "reference": "46cd95797e9df938fdd2b03693b5fca5e64b01ce", 1774 | "shasum": "" 1775 | }, 1776 | "require": { 1777 | "php": ">=7.1" 1778 | }, 1779 | "suggest": { 1780 | "ext-ctype": "For best performance" 1781 | }, 1782 | "type": "library", 1783 | "extra": { 1784 | "branch-alias": { 1785 | "dev-main": "1.23-dev" 1786 | }, 1787 | "thanks": { 1788 | "name": "symfony/polyfill", 1789 | "url": "https://github.com/symfony/polyfill" 1790 | } 1791 | }, 1792 | "autoload": { 1793 | "psr-4": { 1794 | "Symfony\\Polyfill\\Ctype\\": "" 1795 | }, 1796 | "files": [ 1797 | "bootstrap.php" 1798 | ] 1799 | }, 1800 | "notification-url": "https://packagist.org/downloads/", 1801 | "license": [ 1802 | "MIT" 1803 | ], 1804 | "authors": [ 1805 | { 1806 | "name": "Gert de Pagter", 1807 | "email": "BackEndTea@gmail.com" 1808 | }, 1809 | { 1810 | "name": "Symfony Community", 1811 | "homepage": "https://symfony.com/contributors" 1812 | } 1813 | ], 1814 | "description": "Symfony polyfill for ctype functions", 1815 | "homepage": "https://symfony.com", 1816 | "keywords": [ 1817 | "compatibility", 1818 | "ctype", 1819 | "polyfill", 1820 | "portable" 1821 | ], 1822 | "support": { 1823 | "source": "https://github.com/symfony/polyfill-ctype/tree/v1.23.0" 1824 | }, 1825 | "funding": [ 1826 | { 1827 | "url": "https://symfony.com/sponsor", 1828 | "type": "custom" 1829 | }, 1830 | { 1831 | "url": "https://github.com/fabpot", 1832 | "type": "github" 1833 | }, 1834 | { 1835 | "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", 1836 | "type": "tidelift" 1837 | } 1838 | ], 1839 | "time": "2021-02-19T12:13:01+00:00" 1840 | }, 1841 | { 1842 | "name": "symfony/polyfill-mbstring", 1843 | "version": "v1.23.1", 1844 | "source": { 1845 | "type": "git", 1846 | "url": "https://github.com/symfony/polyfill-mbstring.git", 1847 | "reference": "9174a3d80210dca8daa7f31fec659150bbeabfc6" 1848 | }, 1849 | "dist": { 1850 | "type": "zip", 1851 | "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/9174a3d80210dca8daa7f31fec659150bbeabfc6", 1852 | "reference": "9174a3d80210dca8daa7f31fec659150bbeabfc6", 1853 | "shasum": "" 1854 | }, 1855 | "require": { 1856 | "php": ">=7.1" 1857 | }, 1858 | "suggest": { 1859 | "ext-mbstring": "For best performance" 1860 | }, 1861 | "type": "library", 1862 | "extra": { 1863 | "branch-alias": { 1864 | "dev-main": "1.23-dev" 1865 | }, 1866 | "thanks": { 1867 | "name": "symfony/polyfill", 1868 | "url": "https://github.com/symfony/polyfill" 1869 | } 1870 | }, 1871 | "autoload": { 1872 | "psr-4": { 1873 | "Symfony\\Polyfill\\Mbstring\\": "" 1874 | }, 1875 | "files": [ 1876 | "bootstrap.php" 1877 | ] 1878 | }, 1879 | "notification-url": "https://packagist.org/downloads/", 1880 | "license": [ 1881 | "MIT" 1882 | ], 1883 | "authors": [ 1884 | { 1885 | "name": "Nicolas Grekas", 1886 | "email": "p@tchwork.com" 1887 | }, 1888 | { 1889 | "name": "Symfony Community", 1890 | "homepage": "https://symfony.com/contributors" 1891 | } 1892 | ], 1893 | "description": "Symfony polyfill for the Mbstring extension", 1894 | "homepage": "https://symfony.com", 1895 | "keywords": [ 1896 | "compatibility", 1897 | "mbstring", 1898 | "polyfill", 1899 | "portable", 1900 | "shim" 1901 | ], 1902 | "support": { 1903 | "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.23.1" 1904 | }, 1905 | "funding": [ 1906 | { 1907 | "url": "https://symfony.com/sponsor", 1908 | "type": "custom" 1909 | }, 1910 | { 1911 | "url": "https://github.com/fabpot", 1912 | "type": "github" 1913 | }, 1914 | { 1915 | "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", 1916 | "type": "tidelift" 1917 | } 1918 | ], 1919 | "time": "2021-05-27T12:26:48+00:00" 1920 | }, 1921 | { 1922 | "name": "symfony/polyfill-php80", 1923 | "version": "v1.23.1", 1924 | "source": { 1925 | "type": "git", 1926 | "url": "https://github.com/symfony/polyfill-php80.git", 1927 | "reference": "1100343ed1a92e3a38f9ae122fc0eb21602547be" 1928 | }, 1929 | "dist": { 1930 | "type": "zip", 1931 | "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/1100343ed1a92e3a38f9ae122fc0eb21602547be", 1932 | "reference": "1100343ed1a92e3a38f9ae122fc0eb21602547be", 1933 | "shasum": "" 1934 | }, 1935 | "require": { 1936 | "php": ">=7.1" 1937 | }, 1938 | "type": "library", 1939 | "extra": { 1940 | "branch-alias": { 1941 | "dev-main": "1.23-dev" 1942 | }, 1943 | "thanks": { 1944 | "name": "symfony/polyfill", 1945 | "url": "https://github.com/symfony/polyfill" 1946 | } 1947 | }, 1948 | "autoload": { 1949 | "psr-4": { 1950 | "Symfony\\Polyfill\\Php80\\": "" 1951 | }, 1952 | "files": [ 1953 | "bootstrap.php" 1954 | ], 1955 | "classmap": [ 1956 | "Resources/stubs" 1957 | ] 1958 | }, 1959 | "notification-url": "https://packagist.org/downloads/", 1960 | "license": [ 1961 | "MIT" 1962 | ], 1963 | "authors": [ 1964 | { 1965 | "name": "Ion Bazan", 1966 | "email": "ion.bazan@gmail.com" 1967 | }, 1968 | { 1969 | "name": "Nicolas Grekas", 1970 | "email": "p@tchwork.com" 1971 | }, 1972 | { 1973 | "name": "Symfony Community", 1974 | "homepage": "https://symfony.com/contributors" 1975 | } 1976 | ], 1977 | "description": "Symfony polyfill backporting some PHP 8.0+ features to lower PHP versions", 1978 | "homepage": "https://symfony.com", 1979 | "keywords": [ 1980 | "compatibility", 1981 | "polyfill", 1982 | "portable", 1983 | "shim" 1984 | ], 1985 | "support": { 1986 | "source": "https://github.com/symfony/polyfill-php80/tree/v1.23.1" 1987 | }, 1988 | "funding": [ 1989 | { 1990 | "url": "https://symfony.com/sponsor", 1991 | "type": "custom" 1992 | }, 1993 | { 1994 | "url": "https://github.com/fabpot", 1995 | "type": "github" 1996 | }, 1997 | { 1998 | "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", 1999 | "type": "tidelift" 2000 | } 2001 | ], 2002 | "time": "2021-07-28T13:41:28+00:00" 2003 | }, 2004 | { 2005 | "name": "symfony/translation", 2006 | "version": "v5.3.9", 2007 | "source": { 2008 | "type": "git", 2009 | "url": "https://github.com/symfony/translation.git", 2010 | "reference": "6e69f3551c1a3356cf6ea8d019bf039a0f8b6886" 2011 | }, 2012 | "dist": { 2013 | "type": "zip", 2014 | "url": "https://api.github.com/repos/symfony/translation/zipball/6e69f3551c1a3356cf6ea8d019bf039a0f8b6886", 2015 | "reference": "6e69f3551c1a3356cf6ea8d019bf039a0f8b6886", 2016 | "shasum": "" 2017 | }, 2018 | "require": { 2019 | "php": ">=7.2.5", 2020 | "symfony/deprecation-contracts": "^2.1", 2021 | "symfony/polyfill-mbstring": "~1.0", 2022 | "symfony/polyfill-php80": "^1.16", 2023 | "symfony/translation-contracts": "^2.3" 2024 | }, 2025 | "conflict": { 2026 | "symfony/config": "<4.4", 2027 | "symfony/dependency-injection": "<5.0", 2028 | "symfony/http-kernel": "<5.0", 2029 | "symfony/twig-bundle": "<5.0", 2030 | "symfony/yaml": "<4.4" 2031 | }, 2032 | "provide": { 2033 | "symfony/translation-implementation": "2.3" 2034 | }, 2035 | "require-dev": { 2036 | "psr/log": "^1|^2|^3", 2037 | "symfony/config": "^4.4|^5.0", 2038 | "symfony/console": "^4.4|^5.0", 2039 | "symfony/dependency-injection": "^5.0", 2040 | "symfony/finder": "^4.4|^5.0", 2041 | "symfony/http-kernel": "^5.0", 2042 | "symfony/intl": "^4.4|^5.0", 2043 | "symfony/polyfill-intl-icu": "^1.21", 2044 | "symfony/service-contracts": "^1.1.2|^2", 2045 | "symfony/yaml": "^4.4|^5.0" 2046 | }, 2047 | "suggest": { 2048 | "psr/log-implementation": "To use logging capability in translator", 2049 | "symfony/config": "", 2050 | "symfony/yaml": "" 2051 | }, 2052 | "type": "library", 2053 | "autoload": { 2054 | "files": [ 2055 | "Resources/functions.php" 2056 | ], 2057 | "psr-4": { 2058 | "Symfony\\Component\\Translation\\": "" 2059 | }, 2060 | "exclude-from-classmap": [ 2061 | "/Tests/" 2062 | ] 2063 | }, 2064 | "notification-url": "https://packagist.org/downloads/", 2065 | "license": [ 2066 | "MIT" 2067 | ], 2068 | "authors": [ 2069 | { 2070 | "name": "Fabien Potencier", 2071 | "email": "fabien@symfony.com" 2072 | }, 2073 | { 2074 | "name": "Symfony Community", 2075 | "homepage": "https://symfony.com/contributors" 2076 | } 2077 | ], 2078 | "description": "Provides tools to internationalize your application", 2079 | "homepage": "https://symfony.com", 2080 | "support": { 2081 | "source": "https://github.com/symfony/translation/tree/v5.3.9" 2082 | }, 2083 | "funding": [ 2084 | { 2085 | "url": "https://symfony.com/sponsor", 2086 | "type": "custom" 2087 | }, 2088 | { 2089 | "url": "https://github.com/fabpot", 2090 | "type": "github" 2091 | }, 2092 | { 2093 | "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", 2094 | "type": "tidelift" 2095 | } 2096 | ], 2097 | "time": "2021-08-26T08:22:53+00:00" 2098 | }, 2099 | { 2100 | "name": "symfony/translation-contracts", 2101 | "version": "v2.4.0", 2102 | "source": { 2103 | "type": "git", 2104 | "url": "https://github.com/symfony/translation-contracts.git", 2105 | "reference": "95c812666f3e91db75385749fe219c5e494c7f95" 2106 | }, 2107 | "dist": { 2108 | "type": "zip", 2109 | "url": "https://api.github.com/repos/symfony/translation-contracts/zipball/95c812666f3e91db75385749fe219c5e494c7f95", 2110 | "reference": "95c812666f3e91db75385749fe219c5e494c7f95", 2111 | "shasum": "" 2112 | }, 2113 | "require": { 2114 | "php": ">=7.2.5" 2115 | }, 2116 | "suggest": { 2117 | "symfony/translation-implementation": "" 2118 | }, 2119 | "type": "library", 2120 | "extra": { 2121 | "branch-alias": { 2122 | "dev-main": "2.4-dev" 2123 | }, 2124 | "thanks": { 2125 | "name": "symfony/contracts", 2126 | "url": "https://github.com/symfony/contracts" 2127 | } 2128 | }, 2129 | "autoload": { 2130 | "psr-4": { 2131 | "Symfony\\Contracts\\Translation\\": "" 2132 | } 2133 | }, 2134 | "notification-url": "https://packagist.org/downloads/", 2135 | "license": [ 2136 | "MIT" 2137 | ], 2138 | "authors": [ 2139 | { 2140 | "name": "Nicolas Grekas", 2141 | "email": "p@tchwork.com" 2142 | }, 2143 | { 2144 | "name": "Symfony Community", 2145 | "homepage": "https://symfony.com/contributors" 2146 | } 2147 | ], 2148 | "description": "Generic abstractions related to translation", 2149 | "homepage": "https://symfony.com", 2150 | "keywords": [ 2151 | "abstractions", 2152 | "contracts", 2153 | "decoupling", 2154 | "interfaces", 2155 | "interoperability", 2156 | "standards" 2157 | ], 2158 | "support": { 2159 | "source": "https://github.com/symfony/translation-contracts/tree/v2.4.0" 2160 | }, 2161 | "funding": [ 2162 | { 2163 | "url": "https://symfony.com/sponsor", 2164 | "type": "custom" 2165 | }, 2166 | { 2167 | "url": "https://github.com/fabpot", 2168 | "type": "github" 2169 | }, 2170 | { 2171 | "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", 2172 | "type": "tidelift" 2173 | } 2174 | ], 2175 | "time": "2021-03-23T23:28:01+00:00" 2176 | }, 2177 | { 2178 | "name": "vlucas/phpdotenv", 2179 | "version": "v5.3.1", 2180 | "source": { 2181 | "type": "git", 2182 | "url": "https://github.com/vlucas/phpdotenv.git", 2183 | "reference": "accaddf133651d4b5cf81a119f25296736ffc850" 2184 | }, 2185 | "dist": { 2186 | "type": "zip", 2187 | "url": "https://api.github.com/repos/vlucas/phpdotenv/zipball/accaddf133651d4b5cf81a119f25296736ffc850", 2188 | "reference": "accaddf133651d4b5cf81a119f25296736ffc850", 2189 | "shasum": "" 2190 | }, 2191 | "require": { 2192 | "ext-pcre": "*", 2193 | "graham-campbell/result-type": "^1.0.2", 2194 | "php": "^7.1.3 || ^8.0", 2195 | "phpoption/phpoption": "^1.8", 2196 | "symfony/polyfill-ctype": "^1.23", 2197 | "symfony/polyfill-mbstring": "^1.23.1", 2198 | "symfony/polyfill-php80": "^1.23.1" 2199 | }, 2200 | "require-dev": { 2201 | "bamarni/composer-bin-plugin": "^1.4.1", 2202 | "ext-filter": "*", 2203 | "phpunit/phpunit": "^7.5.20 || ^8.5.21 || ^9.5.10" 2204 | }, 2205 | "suggest": { 2206 | "ext-filter": "Required to use the boolean validator." 2207 | }, 2208 | "type": "library", 2209 | "extra": { 2210 | "branch-alias": { 2211 | "dev-master": "5.3-dev" 2212 | } 2213 | }, 2214 | "autoload": { 2215 | "psr-4": { 2216 | "Dotenv\\": "src/" 2217 | } 2218 | }, 2219 | "notification-url": "https://packagist.org/downloads/", 2220 | "license": [ 2221 | "BSD-3-Clause" 2222 | ], 2223 | "authors": [ 2224 | { 2225 | "name": "Graham Campbell", 2226 | "email": "hello@gjcampbell.co.uk" 2227 | }, 2228 | { 2229 | "name": "Vance Lucas", 2230 | "email": "vance@vancelucas.com" 2231 | } 2232 | ], 2233 | "description": "Loads environment variables from `.env` to `getenv()`, `$_ENV` and `$_SERVER` automagically.", 2234 | "keywords": [ 2235 | "dotenv", 2236 | "env", 2237 | "environment" 2238 | ], 2239 | "support": { 2240 | "issues": "https://github.com/vlucas/phpdotenv/issues", 2241 | "source": "https://github.com/vlucas/phpdotenv/tree/v5.3.1" 2242 | }, 2243 | "funding": [ 2244 | { 2245 | "url": "https://github.com/GrahamCampbell", 2246 | "type": "github" 2247 | }, 2248 | { 2249 | "url": "https://tidelift.com/funding/github/packagist/vlucas/phpdotenv", 2250 | "type": "tidelift" 2251 | } 2252 | ], 2253 | "time": "2021-10-02T19:24:42+00:00" 2254 | } 2255 | ], 2256 | "packages-dev": [], 2257 | "aliases": [], 2258 | "minimum-stability": "stable", 2259 | "stability-flags": [], 2260 | "prefer-stable": false, 2261 | "prefer-lowest": false, 2262 | "platform": { 2263 | "php": ">=8.0" 2264 | }, 2265 | "platform-dev": [], 2266 | "plugin-api-version": "2.1.0" 2267 | } 2268 | --------------------------------------------------------------------------------