diff --git a/.env b/.env deleted file mode 100644 index a59ee2e..0000000 --- a/.env +++ /dev/null @@ -1,126 +0,0 @@ -# In all environments, the following files are loaded if they exist, -# the latter taking precedence over the former: -# -# * .env contains default values for the environment variables needed by the app -# * .env.local uncommitted file with local overrides -# * .env.$APP_ENV committed environment-specific defaults -# * .env.$APP_ENV.local uncommitted environment-specific overrides -# -# Real environment variables win over .env files. -# -# DO NOT DEFINE PRODUCTION SECRETS IN THIS FILE NOR IN ANY OTHER COMMITTED FILES. -# https://symfony.com/doc/current/configuration/secrets.html -# -# Run "composer dump-env prod" to compile .env files for production use (requires symfony/flex >=1.2). -# https://symfony.com/doc/current/best_practices.html#use-environment-variables-for-infrastructure-configuration - -###> symfony/framework-bundle ### -APP_ENV=dev -APP_SECRET=EDITME -APP_KEY=EDITME -###< symfony/framework-bundle ### - -###> doctrine/doctrine-bundle ### -# Format described at https://www.doctrine-project.org/projects/doctrine-dbal/en/latest/reference/configuration.html#connecting-using-a-url -# IMPORTANT: You MUST configure your server version, either here or in config/packages/doctrine.yaml -# -DATABASE_URL="sqlite:///%kernel.project_dir%/var/data.db" -# DATABASE_URL="mysql://app:!ChangeMe!@127.0.0.1:3306/app?serverVersion=8.0.32&charset=utf8mb4" -# DATABASE_URL="mysql://app:!ChangeMe!@127.0.0.1:3306/app?serverVersion=10.11.2-MariaDB&charset=utf8mb4" -# DATABASE_URL="postgresql://app:!ChangeMe!@127.0.0.1:5432/app?serverVersion=15&charset=utf8" -###< doctrine/doctrine-bundle ### - -###> symfony/messenger ### -# Choose one of the transports below -# MESSENGER_TRANSPORT_DSN=amqp://guest:guest@localhost:5672/%2f/messages -# MESSENGER_TRANSPORT_DSN=redis://localhost:6379/messages -MESSENGER_TRANSPORT_DSN=doctrine://default?auto_setup=0 -###< symfony/messenger ### - -###> symfony/mailer ### -# MAILER_DSN=null://null -###< symfony/mailer ### - -###> symfony/crowdin-translation-provider ### -# CROWDIN_DSN=crowdin://PROJECT_ID:API_TOKEN@ORGANIZATION_DOMAIN.default -###< symfony/crowdin-translation-provider ### - -# YGGtracker - -# Application version, used for API and media cache -APP_VERSION=2.6.2 - -# Application name -APP_NAME=YGGtracker - -# Default locale -APP_LOCALE=en - -# Supported locales for interface and content filters -APP_LOCALES=en|cs|nl|eo|fr|ja|ka|de|he|it|lv|pl|pt|ru|es|uk - -# Content categories, lowercase, enabled by default for new users -# src/Twig/AppExtension.php:transCategory -APP_CATEGORIES=movie|series|tv|animation|music|game|audiobook|podcast|book|archive|picture|software|other - -# Items per page on pagination -APP_PAGINATION=10 - -# Default application theme -APP_THEME=default - -# Additional themes, stored in /src/templates, /public/asset -APP_THEMES=default - -# Default sensitive status for new users -APP_SENSITIVE=1 - -# Default approved status for new users -APP_APPROVED=1 - -# Default Yggdrasil filters status for new users -APP_YGGDRASIL=1 - -# Default posters status for new users -APP_POSTERS=1 - -# Build-in trackers append to downloads -APP_TRACKERS=http://[201:23b4:991a:634d:8359:4521:5576:15b7]:2023/announce|http://[200:1e2f:e608:eb3a:2bf:1e62:87ba:e2f7]/announce|http://[316:c51a:62a3:8b9::5]/announce - -# List of crawlers where ignored in actions and activity features -APP_CRAWLERS=201:23b4:991a:634d:8359:4521:5576:15b7|30a:5fad::e|202:f2bc:f800:7cc4:c109:7857:5cae:6630|200:1554:e730:4030:605b:47be:6fb6:7b11 - -# Max torrent filesize for uploads (check upload_max_filesize in the php.ini) -APP_TORRENT_FILE_SIZE_MAX=1024000 - -# Max torrent poster filesize for uploads (check upload_max_filesize in the php.ini) -APP_TORRENT_POSTER_FILE_SIZE_MAX=10240000 - -# Store wanted torrent files in /app/var/ftp by /app/crontab/torrent/scrape/{key} -APP_TORRENT_WANTED_FTP_ENABLED=1 -APP_TORRENT_WANTED_FTP_FOLDER=/yggtracker -APP_TORRENT_WANTED_FTP_APPROVED_ONLY=1 - -# Enable search index for torrent name -APP_INDEX_TORRENT_NAME_ENABLED=1 - -# Enable search index for torrent info hash v1 -APP_INDEX_TORRENT_HASH_V1_ENABLED=1 - -# Enable search index for torrent info hash v2 -APP_INDEX_TORRENT_HASH_V2_ENABLED=1 - -# Enable search index for torrent filenames -APP_INDEX_TORRENT_FILENAMES_ENABLED=1 - -# Enable search index for torrent source -APP_INDEX_TORRENT_SOURCE_ENABLED=1 - -# Enable search index for torrent comment -APP_INDEX_TORRENT_COMMENT_ENABLED=1 - -# Enable search index for words length greater than N chars -APP_INDEX_WORD_LENGTH_MIN=3 - -# Enable search index for words length not greater than N chars -APP_INDEX_WORD_LENGTH_MAX=255 \ No newline at end of file diff --git a/.env.test b/.env.test deleted file mode 100644 index 9e7162f..0000000 --- a/.env.test +++ /dev/null @@ -1,6 +0,0 @@ -# define your env variables for the test env here -KERNEL_CLASS='App\Kernel' -APP_SECRET='$ecretf0rt3st' -SYMFONY_DEPRECATIONS_HELPER=999999 -PANTHER_APP_ENV=panther -PANTHER_ERROR_SCREENSHOT_DIR=./var/error-screenshots diff --git a/.gitignore b/.gitignore index 79ced3c..9a6ca43 100644 --- a/.gitignore +++ b/.gitignore @@ -1,22 +1,21 @@ +/.vscode/ -###> symfony/framework-bundle ### -/.env.local -/.env.local.php -/.env.*.local -/config/secrets/prod/prod.decrypt.private.php -/public/bundles/ -/var/ /vendor/ -###< symfony/framework-bundle ### -###> phpunit/phpunit ### -/phpunit.xml -.phpunit.result.cache -###< phpunit/phpunit ### +/database/yggtracker.mwb.bak -###> symfony/phpunit-bridge ### -.phpunit.result.cache -/phpunit.xml -###< symfony/phpunit-bridge ### +/src/public/api/*.json -.vscode \ No newline at end of file +/src/config/* +!/src/config/bootstrap.json +!/src/config/nodes.json +!/src/config/trackers.json +!/src/config/peers.json + +/src/public/sitemap.xml + +/src/storage/log/*.log + +/composer.lock + +*test* \ No newline at end of file diff --git a/README.md b/README.md index 6ab362a..e8eefd7 100644 --- a/README.md +++ b/README.md @@ -1,76 +1,55 @@ # YGGtracker -> [!NOTE] -> Take a look at [βtracker](https://github.com/yggverse/btracker) - the modern aggregation alternative written in Rust! +Distributed BitTorrent Registry for Yggdrasil -A social-oriented BitTorrent catalog for the [Yggdrasil](https://github.com/yggdrasil-network) network, written in the Symfony framework. +YGGtracker uses [Yggdrasil](https://github.com/yggdrasil-network/yggdrasil-go) IPv6 addresses to identify users without registration. -YGGtracker is a manually operated catalog and social network that allows users to share their torrents in the local network. Engine uses IPv6 `0200::/7` addresses to identify users without registration. +#### Nodes online -#### [Showcase](https://github.com/YGGverse/YGGtracker/wiki/Showcase) +YGGtracker is distributed index engine, default nodes list defined in [nodes.json](https://github.com/YGGverse/YGGtracker/blob/main/src/config/nodes.json) -![Pasted image 1](https://github.com/YGGverse/YGGtracker/assets/108541346/962f7850-01e1-4add-9dbe-c11b80108a75) +If you have launched new one, feel free to participate by PR. +#### Trackers + +Open trackers defined in [trackers.json](https://github.com/YGGverse/YGGtracker/blob/main/src/config/trackers.json) + +* Application appends initial trackers to all download links and magnet forms +* Trackers not in list will be cropped by the application filter +* Feel free to PR new yggdrasil tracker! + +#### Requirements + +``` +php8^ +php-pdo +php-mysql +php-curl +php-memcached +sphinxsearch +memcached +``` #### Installation -``` -symfony check:requirements -``` - ##### Production -Install stable release - -``` -composer create-project yggverse/yggtracker -``` +* `composer create-project yggverse/yggtracker` ##### Development -Latest codebase available in repository +* `git clone https://github.com/YGGverse/YGGtracker.git` +* `cd YGGtracker` +* `composer update` -``` -git clone https://github.com/YGGverse/YGGtracker.git -cd YGGtracker -composer update -symfony server:start -``` +#### Setup +* Server configuration `/example/environment` +* The web root dir is `/src/public` +* Deploy the database using [MySQL Workbench](https://www.mysql.com/products/workbench) project presented in the `/database` folder +* Install [Sphinx Search Server](https://sphinxsearch.com) +* Configuration examples presented at `/example/environment` folder. On first app launch, configuration file will be auto-generated in `/src/config` +* Make sure `/src/api` folder writable -##### Database - -New installation - -``` -php bin/console doctrine:schema:update --force -``` - -Existing DB upgrade - -``` -php bin/console doctrine:migrations:migrate -``` - -##### Crontab - -* `* * * * * /crontab/torrent/scrape/{%app.key%}` - update seeding stats - -##### FTP - -Setup anonymous read-only access to `/var/ftp` catalog ([read more](https://github.com/YGGverse/YGGtracker/wiki/Features#the-wanted)) - -##### App settings - -Custom settings could be provided in the `/.env.local` file by overwriting default `/.env` values - -#### Localization - -[![Crowdin](https://badges.crowdin.net/yggtracker/localized.svg)](https://crowdin.com/project/yggtracker) - -#### API - -[Wiki reference](https://github.com/YGGverse/YGGtracker/wiki/API) - -#### Contribution +#### Contribute Please make new branch for each PR @@ -79,40 +58,129 @@ git checkout main git checkout -b my-pr-branch-name ``` +#### Roadmap + +* [ ] BitTorrent protocol + + [ ] Protocol + + [ ] announce + + [ ] announce-list + + [ ] comment + + [ ] created by + + [ ] creation date + + [ ] info + + [ ] file-duration + + [ ] file-media + + [ ] files + + [ ] name + + [ ] piece length + + [ ] pieces + + [ ] private + + [ ] profiles + +* [ ] Magnet protocol + + [x] Exact Topic / xt + + [x] Display Name / dn + + [x] eXact Length / xl + + [x] Address Tracker / rt + + [x] Web Seed / ws + + [x] Acceptable Source / as + + [x] eXact Source / xs + + [x] Keyword Topic / kt + + [ ] Manifest Topic / mt + + [ ] Select Only / so + + [ ] PEer / x.pe + +* [ ] Catalog + + [x] Public levels + + [x] Sensitive filter + + [x] Comments + + [x] Scrape trackers + + [x] Peers + + [x] Completed + + [x] Leechers + + [x] Stars + + [x] Views + + [x] Downloads + + [x] Wanted + + [x] Threading comments + + [ ] Forks + +* [ ] Profile + + [ ] Listing + + [ ] Uploads + + [ ] Downloads + + [ ] Stars + + [ ] Following + + [ ] Followers + + [ ] Comments + + [ ] Settings + + [ ] Public name + + [ ] Downloads customization + + [ ] Address Tracker + + [ ] Web Seed + + [ ] Acceptable Source + + [ ] eXact Source + + [ ] Content filters + +* [x] API + + [x] Active (push) + + [x] Magnet + + [x] Edit + + [x] Download + + [x] Comment + + [x] Star + + [x] View + + [x] Passive (feed) + + [x] Manifest + + [x] Users + + [x] Magnets + + [x] Downloads + + [x] Comments + + [x] Stars + + [x] Views + +* [x] Export + + [x] Sitemap + + [x] RSS + + [x] Magnets + + [x] Comments + +* [x] Other + + [x] Moderation + + [x] UI + + [ ] CLI + + [ ] Installation tools + + +#### Donate to contributors + +* @d47081: + + + ![wakatime](https://wakatime.com/badge/user/0b7fe6c1-b091-4c98-b930-75cfee17c7a5/project/059ec567-2c65-4c65-a48e-51dcc366f1a0.svg) + + [BTC](https://www.blockchain.com/explorer/addresses/btc/bc1qngdf2kwty6djjqpk0ynkpq9wmlrmtm7e0c534y) | [LTC](https://live.blockcypher.com/ltc/address/LUSiqzKsfB1vBLvpu515DZktG9ioKqLyj7) | [XMR](835gSR1Uvka19gnWPkU2pyRozZugRZSPHDuFL6YajaAqjEtMwSPr4jafM8idRuBWo7AWD3pwFQSYRMRW9XezqrK4BEXBgXE) | [ZEPH](ZEPHsADHXqnhfWhXrRcXnyBQMucE3NM7Ng5ZVB99XwA38PTnbjLKpCwcQVgoie8EJuWozKgBiTmDFW4iY7fNEgSEWyAy4dotqtX) + + Support our server by order [Linux VPS](https://www.yourserver.se/portal/aff.php?aff=610) + + Inspiration by [SomaFM Deep Space One](https://somafm.com/deepspaceone/) + #### License * Engine sources [MIT License](https://github.com/YGGverse/YGGtracker/blob/main/LICENSE) -#### Versioning - -[Semantic Versioning 2.0.0](https://semver.org/#semantic-versioning-200) - #### Components -* [Symfony Framework](https://symfony.com) * [SVG icons](https://icons.getbootstrap.com) -* [Scrapper](https://github.com/medariox/scrapeer) / [Composer Edition](https://github.com/YGGverse/scrapeer) -* [Bencode](https://github.com/Rhilip/Bencode) -* [Transliteration](https://github.com/ashtokalo/php-translit) +* [PHP Scrapper](https://github.com/medariox/scrapeer) * [Identicons](https://github.com/dmester/jdenticon-php) -#### Support +#### Feedback -* [Issues](https://github.com/YGGverse/YGGtracker/issues) -* [Documentation](https://github.com/YGGverse/YGGtracker/wiki) -* [HowTo Yggdrasil](https://ygg.work.gd/yggdrasil:bittorrent:yggtracker) +[https://github.com/YGGverse/YGGtracker/issues](https://github.com/YGGverse/YGGtracker/issues) -#### Blog +#### Community * [Mastodon](https://mastodon.social/@YGGverse) -#### Integrations - -* [YGGtracker Search Plugin for qBittorrent](https://github.com/YGGverse/qbittorrent-yggtracker-search-plugin) -* [Crontab script that allows to receive wanted torrents from multiple YGGtracker nodes](https://github.com/YGGverse/yggtracker-wanted-torrents-receiver) - #### See also * [YGGo - YGGo! Distributed Web Search Engine ](https://github.com/YGGverse/YGGo) * [YGGwave ~ The Radio Catalog](https://github.com/YGGverse/YGGwave) -* [YGGstate - Yggdrasil Network Explorer](https://github.com/YGGverse/YGGstate) +* [YGGstate - Yggdrasil Network Explorer](https://github.com/YGGverse/YGGstate) \ No newline at end of file diff --git a/bin/console b/bin/console deleted file mode 100755 index c933dc5..0000000 --- a/bin/console +++ /dev/null @@ -1,17 +0,0 @@ -#!/usr/bin/env php -=8.1", - "ext-ctype": "*", - "ext-iconv": "*", - "ashtokalo/php-translit": "^0.2.0", - "doctrine/annotations": "^2.0", - "doctrine/doctrine-bundle": "^2.10", - "doctrine/doctrine-migrations-bundle": "^3.2", - "doctrine/orm": "^2.16", + "php": "^8.1", + "yggverse/cache": ">=0.3.0", + "yggverse/parser": ">=0.4.0", "jdenticon/jdenticon": "^1.0", - "league/commonmark": "^2.4", - "phpdocumentor/reflection-docblock": "^5.3", - "phpstan/phpdoc-parser": "^1.24", - "rhilip/bencode": "^2.3", - "symfony/asset": "6.3.*", - "symfony/console": "6.3.*", - "symfony/crowdin-translation-provider": "6.3.*", - "symfony/doctrine-messenger": "6.3.*", - "symfony/dotenv": "6.3.*", - "symfony/expression-language": "6.3.*", - "symfony/flex": "^2", - "symfony/form": "6.3.*", - "symfony/framework-bundle": "6.3.*", - "symfony/http-client": "6.3.*", - "symfony/intl": "6.3.*", - "symfony/mailer": "6.3.*", - "symfony/mime": "6.3.*", - "symfony/monolog-bundle": "^3.0", - "symfony/notifier": "6.3.*", - "symfony/process": "6.3.*", - "symfony/property-access": "6.3.*", - "symfony/property-info": "6.3.*", - "symfony/runtime": "6.3.*", - "symfony/security-bundle": "6.3.*", - "symfony/serializer": "6.3.*", - "symfony/string": "6.3.*", - "symfony/translation": "6.3.*", - "symfony/twig-bundle": "6.3.*", - "symfony/validator": "6.3.*", - "symfony/web-link": "6.3.*", - "symfony/yaml": "6.3.*", - "twig/extra-bundle": "^3.7", - "twig/intl-extra": "^3.7", - "twig/markdown-extra": "^3.7", - "twig/string-extra": "^3.7", - "twig/twig": "^2.12|^3.0", - "yggverse/scrapeer": "^0.5.4" - }, - "config": { - "allow-plugins": { - "php-http/discovery": true, - "symfony/flex": true, - "symfony/runtime": true - }, - "sort-packages": true + "christeredvartsen/php-bittorrent": "^2.0" }, + "license": "MIT", "autoload": { "psr-4": { - "App\\": "src/" + "Yggverse\\Yggtracker\\": "src/" } }, - "autoload-dev": { - "psr-4": { - "App\\Tests\\": "tests/" + "authors": [ + { + "name": "YGGverse" } - }, - "replace": { - "symfony/polyfill-ctype": "*", - "symfony/polyfill-iconv": "*", - "symfony/polyfill-php72": "*", - "symfony/polyfill-php73": "*", - "symfony/polyfill-php74": "*", - "symfony/polyfill-php80": "*", - "symfony/polyfill-php81": "*" - }, - "scripts": { - "auto-scripts": { - "cache:clear": "symfony-cmd", - "assets:install %PUBLIC_DIR%": "symfony-cmd" - }, - "post-install-cmd": [ - "@auto-scripts" - ], - "post-update-cmd": [ - "@auto-scripts" - ] - }, - "conflict": { - "symfony/symfony": "*" - }, - "extra": { - "symfony": { - "allow-contrib": false, - "require": "6.3.*" - } - }, - "require-dev": { - "phpunit/phpunit": "^9.5", - "symfony/browser-kit": "6.3.*", - "symfony/css-selector": "6.3.*", - "symfony/debug-bundle": "6.3.*", - "symfony/maker-bundle": "^1.0", - "symfony/phpunit-bridge": "^6.3", - "symfony/stopwatch": "6.3.*", - "symfony/web-profiler-bundle": "6.3.*" - } + ], + "minimum-stability": "alpha" } diff --git a/composer.lock b/composer.lock deleted file mode 100644 index efca9a6..0000000 --- a/composer.lock +++ /dev/null @@ -1,10456 +0,0 @@ -{ - "_readme": [ - "This file locks the dependencies of your project to a known state", - "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", - "This file is @generated automatically" - ], - "content-hash": "99ad25219a6bff24126d6f83ebd1756a", - "packages": [ - { - "name": "ashtokalo/php-translit", - "version": "0.2.0", - "source": { - "type": "git", - "url": "https://github.com/ashtokalo/php-translit.git", - "reference": "8ced36cbcd0ed8befb1388ef51935eb53bcfe5b3" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/ashtokalo/php-translit/zipball/8ced36cbcd0ed8befb1388ef51935eb53bcfe5b3", - "reference": "8ced36cbcd0ed8befb1388ef51935eb53bcfe5b3", - "shasum": "" - }, - "require": { - "php": ">=7.0" - }, - "require-dev": { - "phpunit/phpunit": "~7.0" - }, - "type": "library", - "autoload": { - "psr-4": { - "ashtokalo\\translit\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "description": "PHP library to convert text from one script to another.", - "keywords": [ - "latinization", - "romanization", - "translit", - "transliteration" - ], - "support": { - "issues": "https://github.com/ashtokalo/php-translit/issues", - "source": "https://github.com/ashtokalo/php-translit/tree/0.2.0" - }, - "time": "2022-09-26T09:05:24+00:00" - }, - { - "name": "dflydev/dot-access-data", - "version": "v3.0.2", - "source": { - "type": "git", - "url": "https://github.com/dflydev/dflydev-dot-access-data.git", - "reference": "f41715465d65213d644d3141a6a93081be5d3549" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/dflydev/dflydev-dot-access-data/zipball/f41715465d65213d644d3141a6a93081be5d3549", - "reference": "f41715465d65213d644d3141a6a93081be5d3549", - "shasum": "" - }, - "require": { - "php": "^7.1 || ^8.0" - }, - "require-dev": { - "phpstan/phpstan": "^0.12.42", - "phpunit/phpunit": "^7.5 || ^8.5 || ^9.3", - "scrutinizer/ocular": "1.6.0", - "squizlabs/php_codesniffer": "^3.5", - "vimeo/psalm": "^4.0.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "3.x-dev" - } - }, - "autoload": { - "psr-4": { - "Dflydev\\DotAccessData\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Dragonfly Development Inc.", - "email": "info@dflydev.com", - "homepage": "http://dflydev.com" - }, - { - "name": "Beau Simensen", - "email": "beau@dflydev.com", - "homepage": "http://beausimensen.com" - }, - { - "name": "Carlos Frutos", - "email": "carlos@kiwing.it", - "homepage": "https://github.com/cfrutos" - }, - { - "name": "Colin O'Dell", - "email": "colinodell@gmail.com", - "homepage": "https://www.colinodell.com" - } - ], - "description": "Given a deep data structure, access data by dot notation.", - "homepage": "https://github.com/dflydev/dflydev-dot-access-data", - "keywords": [ - "access", - "data", - "dot", - "notation" - ], - "support": { - "issues": "https://github.com/dflydev/dflydev-dot-access-data/issues", - "source": "https://github.com/dflydev/dflydev-dot-access-data/tree/v3.0.2" - }, - "time": "2022-10-27T11:44:00+00:00" - }, - { - "name": "doctrine/annotations", - "version": "2.0.1", - "source": { - "type": "git", - "url": "https://github.com/doctrine/annotations.git", - "reference": "e157ef3f3124bbf6fe7ce0ffd109e8a8ef284e7f" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/doctrine/annotations/zipball/e157ef3f3124bbf6fe7ce0ffd109e8a8ef284e7f", - "reference": "e157ef3f3124bbf6fe7ce0ffd109e8a8ef284e7f", - "shasum": "" - }, - "require": { - "doctrine/lexer": "^2 || ^3", - "ext-tokenizer": "*", - "php": "^7.2 || ^8.0", - "psr/cache": "^1 || ^2 || ^3" - }, - "require-dev": { - "doctrine/cache": "^2.0", - "doctrine/coding-standard": "^10", - "phpstan/phpstan": "^1.8.0", - "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5", - "symfony/cache": "^5.4 || ^6", - "vimeo/psalm": "^4.10" - }, - "suggest": { - "php": "PHP 8.0 or higher comes with attributes, a native replacement for annotations" - }, - "type": "library", - "autoload": { - "psr-4": { - "Doctrine\\Common\\Annotations\\": "lib/Doctrine/Common/Annotations" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Guilherme Blanco", - "email": "guilhermeblanco@gmail.com" - }, - { - "name": "Roman Borschel", - "email": "roman@code-factory.org" - }, - { - "name": "Benjamin Eberlei", - "email": "kontakt@beberlei.de" - }, - { - "name": "Jonathan Wage", - "email": "jonwage@gmail.com" - }, - { - "name": "Johannes Schmitt", - "email": "schmittjoh@gmail.com" - } - ], - "description": "Docblock Annotations Parser", - "homepage": "https://www.doctrine-project.org/projects/annotations.html", - "keywords": [ - "annotations", - "docblock", - "parser" - ], - "support": { - "issues": "https://github.com/doctrine/annotations/issues", - "source": "https://github.com/doctrine/annotations/tree/2.0.1" - }, - "time": "2023-02-02T22:02:53+00:00" - }, - { - "name": "doctrine/cache", - "version": "2.2.0", - "source": { - "type": "git", - "url": "https://github.com/doctrine/cache.git", - "reference": "1ca8f21980e770095a31456042471a57bc4c68fb" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/doctrine/cache/zipball/1ca8f21980e770095a31456042471a57bc4c68fb", - "reference": "1ca8f21980e770095a31456042471a57bc4c68fb", - "shasum": "" - }, - "require": { - "php": "~7.1 || ^8.0" - }, - "conflict": { - "doctrine/common": ">2.2,<2.4" - }, - "require-dev": { - "cache/integration-tests": "dev-master", - "doctrine/coding-standard": "^9", - "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5", - "psr/cache": "^1.0 || ^2.0 || ^3.0", - "symfony/cache": "^4.4 || ^5.4 || ^6", - "symfony/var-exporter": "^4.4 || ^5.4 || ^6" - }, - "type": "library", - "autoload": { - "psr-4": { - "Doctrine\\Common\\Cache\\": "lib/Doctrine/Common/Cache" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Guilherme Blanco", - "email": "guilhermeblanco@gmail.com" - }, - { - "name": "Roman Borschel", - "email": "roman@code-factory.org" - }, - { - "name": "Benjamin Eberlei", - "email": "kontakt@beberlei.de" - }, - { - "name": "Jonathan Wage", - "email": "jonwage@gmail.com" - }, - { - "name": "Johannes Schmitt", - "email": "schmittjoh@gmail.com" - } - ], - "description": "PHP Doctrine Cache library is a popular cache implementation that supports many different drivers such as redis, memcache, apc, mongodb and others.", - "homepage": "https://www.doctrine-project.org/projects/cache.html", - "keywords": [ - "abstraction", - "apcu", - "cache", - "caching", - "couchdb", - "memcached", - "php", - "redis", - "xcache" - ], - "support": { - "issues": "https://github.com/doctrine/cache/issues", - "source": "https://github.com/doctrine/cache/tree/2.2.0" - }, - "funding": [ - { - "url": "https://www.doctrine-project.org/sponsorship.html", - "type": "custom" - }, - { - "url": "https://www.patreon.com/phpdoctrine", - "type": "patreon" - }, - { - "url": "https://tidelift.com/funding/github/packagist/doctrine%2Fcache", - "type": "tidelift" - } - ], - "time": "2022-05-20T20:07:39+00:00" - }, - { - "name": "doctrine/collections", - "version": "2.1.4", - "source": { - "type": "git", - "url": "https://github.com/doctrine/collections.git", - "reference": "72328a11443a0de79967104ad36ba7b30bded134" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/doctrine/collections/zipball/72328a11443a0de79967104ad36ba7b30bded134", - "reference": "72328a11443a0de79967104ad36ba7b30bded134", - "shasum": "" - }, - "require": { - "doctrine/deprecations": "^1", - "php": "^8.1" - }, - "require-dev": { - "doctrine/coding-standard": "^12", - "ext-json": "*", - "phpstan/phpstan": "^1.8", - "phpstan/phpstan-phpunit": "^1.0", - "phpunit/phpunit": "^9.5", - "vimeo/psalm": "^5.11" - }, - "type": "library", - "autoload": { - "psr-4": { - "Doctrine\\Common\\Collections\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Guilherme Blanco", - "email": "guilhermeblanco@gmail.com" - }, - { - "name": "Roman Borschel", - "email": "roman@code-factory.org" - }, - { - "name": "Benjamin Eberlei", - "email": "kontakt@beberlei.de" - }, - { - "name": "Jonathan Wage", - "email": "jonwage@gmail.com" - }, - { - "name": "Johannes Schmitt", - "email": "schmittjoh@gmail.com" - } - ], - "description": "PHP Doctrine Collections library that adds additional functionality on top of PHP arrays.", - "homepage": "https://www.doctrine-project.org/projects/collections.html", - "keywords": [ - "array", - "collections", - "iterators", - "php" - ], - "support": { - "issues": "https://github.com/doctrine/collections/issues", - "source": "https://github.com/doctrine/collections/tree/2.1.4" - }, - "funding": [ - { - "url": "https://www.doctrine-project.org/sponsorship.html", - "type": "custom" - }, - { - "url": "https://www.patreon.com/phpdoctrine", - "type": "patreon" - }, - { - "url": "https://tidelift.com/funding/github/packagist/doctrine%2Fcollections", - "type": "tidelift" - } - ], - "time": "2023-10-03T09:22:33+00:00" - }, - { - "name": "doctrine/common", - "version": "3.4.3", - "source": { - "type": "git", - "url": "https://github.com/doctrine/common.git", - "reference": "8b5e5650391f851ed58910b3e3d48a71062eeced" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/doctrine/common/zipball/8b5e5650391f851ed58910b3e3d48a71062eeced", - "reference": "8b5e5650391f851ed58910b3e3d48a71062eeced", - "shasum": "" - }, - "require": { - "doctrine/persistence": "^2.0 || ^3.0", - "php": "^7.1 || ^8.0" - }, - "require-dev": { - "doctrine/coding-standard": "^9.0 || ^10.0", - "doctrine/collections": "^1", - "phpstan/phpstan": "^1.4.1", - "phpstan/phpstan-phpunit": "^1", - "phpunit/phpunit": "^7.5.20 || ^8.5 || ^9.0", - "squizlabs/php_codesniffer": "^3.0", - "symfony/phpunit-bridge": "^6.1", - "vimeo/psalm": "^4.4" - }, - "type": "library", - "autoload": { - "psr-4": { - "Doctrine\\Common\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Guilherme Blanco", - "email": "guilhermeblanco@gmail.com" - }, - { - "name": "Roman Borschel", - "email": "roman@code-factory.org" - }, - { - "name": "Benjamin Eberlei", - "email": "kontakt@beberlei.de" - }, - { - "name": "Jonathan Wage", - "email": "jonwage@gmail.com" - }, - { - "name": "Johannes Schmitt", - "email": "schmittjoh@gmail.com" - }, - { - "name": "Marco Pivetta", - "email": "ocramius@gmail.com" - } - ], - "description": "PHP Doctrine Common project is a library that provides additional functionality that other Doctrine projects depend on such as better reflection support, proxies and much more.", - "homepage": "https://www.doctrine-project.org/projects/common.html", - "keywords": [ - "common", - "doctrine", - "php" - ], - "support": { - "issues": "https://github.com/doctrine/common/issues", - "source": "https://github.com/doctrine/common/tree/3.4.3" - }, - "funding": [ - { - "url": "https://www.doctrine-project.org/sponsorship.html", - "type": "custom" - }, - { - "url": "https://www.patreon.com/phpdoctrine", - "type": "patreon" - }, - { - "url": "https://tidelift.com/funding/github/packagist/doctrine%2Fcommon", - "type": "tidelift" - } - ], - "time": "2022-10-09T11:47:59+00:00" - }, - { - "name": "doctrine/dbal", - "version": "3.7.2", - "source": { - "type": "git", - "url": "https://github.com/doctrine/dbal.git", - "reference": "0ac3c270590e54910715e9a1a044cc368df282b2" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/doctrine/dbal/zipball/0ac3c270590e54910715e9a1a044cc368df282b2", - "reference": "0ac3c270590e54910715e9a1a044cc368df282b2", - "shasum": "" - }, - "require": { - "composer-runtime-api": "^2", - "doctrine/cache": "^1.11|^2.0", - "doctrine/deprecations": "^0.5.3|^1", - "doctrine/event-manager": "^1|^2", - "php": "^7.4 || ^8.0", - "psr/cache": "^1|^2|^3", - "psr/log": "^1|^2|^3" - }, - "require-dev": { - "doctrine/coding-standard": "12.0.0", - "fig/log-test": "^1", - "jetbrains/phpstorm-stubs": "2023.1", - "phpstan/phpstan": "1.10.42", - "phpstan/phpstan-strict-rules": "^1.5", - "phpunit/phpunit": "9.6.13", - "psalm/plugin-phpunit": "0.18.4", - "slevomat/coding-standard": "8.13.1", - "squizlabs/php_codesniffer": "3.7.2", - "symfony/cache": "^5.4|^6.0", - "symfony/console": "^4.4|^5.4|^6.0", - "vimeo/psalm": "4.30.0" - }, - "suggest": { - "symfony/console": "For helpful console commands such as SQL execution and import of files." - }, - "bin": [ - "bin/doctrine-dbal" - ], - "type": "library", - "autoload": { - "psr-4": { - "Doctrine\\DBAL\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Guilherme Blanco", - "email": "guilhermeblanco@gmail.com" - }, - { - "name": "Roman Borschel", - "email": "roman@code-factory.org" - }, - { - "name": "Benjamin Eberlei", - "email": "kontakt@beberlei.de" - }, - { - "name": "Jonathan Wage", - "email": "jonwage@gmail.com" - } - ], - "description": "Powerful PHP database abstraction layer (DBAL) with many features for database schema introspection and management.", - "homepage": "https://www.doctrine-project.org/projects/dbal.html", - "keywords": [ - "abstraction", - "database", - "db2", - "dbal", - "mariadb", - "mssql", - "mysql", - "oci8", - "oracle", - "pdo", - "pgsql", - "postgresql", - "queryobject", - "sasql", - "sql", - "sqlite", - "sqlserver", - "sqlsrv" - ], - "support": { - "issues": "https://github.com/doctrine/dbal/issues", - "source": "https://github.com/doctrine/dbal/tree/3.7.2" - }, - "funding": [ - { - "url": "https://www.doctrine-project.org/sponsorship.html", - "type": "custom" - }, - { - "url": "https://www.patreon.com/phpdoctrine", - "type": "patreon" - }, - { - "url": "https://tidelift.com/funding/github/packagist/doctrine%2Fdbal", - "type": "tidelift" - } - ], - "time": "2023-11-19T08:06:58+00:00" - }, - { - "name": "doctrine/deprecations", - "version": "1.1.2", - "source": { - "type": "git", - "url": "https://github.com/doctrine/deprecations.git", - "reference": "4f2d4f2836e7ec4e7a8625e75c6aa916004db931" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/doctrine/deprecations/zipball/4f2d4f2836e7ec4e7a8625e75c6aa916004db931", - "reference": "4f2d4f2836e7ec4e7a8625e75c6aa916004db931", - "shasum": "" - }, - "require": { - "php": "^7.1 || ^8.0" - }, - "require-dev": { - "doctrine/coding-standard": "^9", - "phpstan/phpstan": "1.4.10 || 1.10.15", - "phpstan/phpstan-phpunit": "^1.0", - "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5", - "psalm/plugin-phpunit": "0.18.4", - "psr/log": "^1 || ^2 || ^3", - "vimeo/psalm": "4.30.0 || 5.12.0" - }, - "suggest": { - "psr/log": "Allows logging deprecations via PSR-3 logger implementation" - }, - "type": "library", - "autoload": { - "psr-4": { - "Doctrine\\Deprecations\\": "lib/Doctrine/Deprecations" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "description": "A small layer on top of trigger_error(E_USER_DEPRECATED) or PSR-3 logging with options to disable all deprecations or selectively for packages.", - "homepage": "https://www.doctrine-project.org/", - "support": { - "issues": "https://github.com/doctrine/deprecations/issues", - "source": "https://github.com/doctrine/deprecations/tree/1.1.2" - }, - "time": "2023-09-27T20:04:15+00:00" - }, - { - "name": "doctrine/doctrine-bundle", - "version": "2.11.1", - "source": { - "type": "git", - "url": "https://github.com/doctrine/DoctrineBundle.git", - "reference": "4089f1424b724786c062aea50aae5f773449b94b" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/doctrine/DoctrineBundle/zipball/4089f1424b724786c062aea50aae5f773449b94b", - "reference": "4089f1424b724786c062aea50aae5f773449b94b", - "shasum": "" - }, - "require": { - "doctrine/cache": "^1.11 || ^2.0", - "doctrine/dbal": "^3.7.0 || ^4.0", - "doctrine/persistence": "^2.2 || ^3", - "doctrine/sql-formatter": "^1.0.1", - "php": "^7.4 || ^8.0", - "symfony/cache": "^5.4 || ^6.0 || ^7.0", - "symfony/config": "^5.4 || ^6.0 || ^7.0", - "symfony/console": "^5.4 || ^6.0 || ^7.0", - "symfony/dependency-injection": "^5.4 || ^6.0 || ^7.0", - "symfony/deprecation-contracts": "^2.1 || ^3", - "symfony/doctrine-bridge": "^5.4.19 || ^6.0.7 || ^7.0", - "symfony/framework-bundle": "^5.4 || ^6.0 || ^7.0", - "symfony/polyfill-php80": "^1.15", - "symfony/service-contracts": "^1.1.1 || ^2.0 || ^3" - }, - "conflict": { - "doctrine/annotations": ">=3.0", - "doctrine/orm": "<2.14 || >=4.0", - "twig/twig": "<1.34 || >=2.0 <2.4" - }, - "require-dev": { - "doctrine/annotations": "^1 || ^2", - "doctrine/coding-standard": "^12", - "doctrine/deprecations": "^1.0", - "doctrine/orm": "^2.14 || ^3.0", - "friendsofphp/proxy-manager-lts": "^1.0", - "phpunit/phpunit": "^9.5.26 || ^10.0", - "psalm/plugin-phpunit": "^0.18.4", - "psalm/plugin-symfony": "^4", - "psr/log": "^1.1.4 || ^2.0 || ^3.0", - "symfony/phpunit-bridge": "^6.1 || ^7.0", - "symfony/property-info": "^5.4 || ^6.0 || ^7.0", - "symfony/proxy-manager-bridge": "^5.4 || ^6.0 || ^7.0", - "symfony/security-bundle": "^5.4 || ^6.0 || ^7.0", - "symfony/string": "^5.4 || ^6.0 || ^7.0", - "symfony/twig-bridge": "^5.4 || ^6.0 || ^7.0", - "symfony/validator": "^5.4 || ^6.0 || ^7.0", - "symfony/var-exporter": "^5.4 || ^6.2 || ^7.0", - "symfony/web-profiler-bundle": "^5.4 || ^6.0 || ^7.0", - "symfony/yaml": "^5.4 || ^6.0 || ^7.0", - "twig/twig": "^1.34 || ^2.12 || ^3.0", - "vimeo/psalm": "^4.30" - }, - "suggest": { - "doctrine/orm": "The Doctrine ORM integration is optional in the bundle.", - "ext-pdo": "*", - "symfony/web-profiler-bundle": "To use the data collector." - }, - "type": "symfony-bundle", - "autoload": { - "psr-4": { - "Doctrine\\Bundle\\DoctrineBundle\\": "" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Benjamin Eberlei", - "email": "kontakt@beberlei.de" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - }, - { - "name": "Doctrine Project", - "homepage": "https://www.doctrine-project.org/" - } - ], - "description": "Symfony DoctrineBundle", - "homepage": "https://www.doctrine-project.org", - "keywords": [ - "database", - "dbal", - "orm", - "persistence" - ], - "support": { - "issues": "https://github.com/doctrine/DoctrineBundle/issues", - "source": "https://github.com/doctrine/DoctrineBundle/tree/2.11.1" - }, - "funding": [ - { - "url": "https://www.doctrine-project.org/sponsorship.html", - "type": "custom" - }, - { - "url": "https://www.patreon.com/phpdoctrine", - "type": "patreon" - }, - { - "url": "https://tidelift.com/funding/github/packagist/doctrine%2Fdoctrine-bundle", - "type": "tidelift" - } - ], - "time": "2023-11-15T20:01:50+00:00" - }, - { - "name": "doctrine/doctrine-migrations-bundle", - "version": "3.3.0", - "source": { - "type": "git", - "url": "https://github.com/doctrine/DoctrineMigrationsBundle.git", - "reference": "1dd42906a5fb9c5960723e2ebb45c68006493835" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/doctrine/DoctrineMigrationsBundle/zipball/1dd42906a5fb9c5960723e2ebb45c68006493835", - "reference": "1dd42906a5fb9c5960723e2ebb45c68006493835", - "shasum": "" - }, - "require": { - "doctrine/doctrine-bundle": "^2.4", - "doctrine/migrations": "^3.2", - "php": "^7.2|^8.0", - "symfony/deprecation-contracts": "^2.1 || ^3", - "symfony/framework-bundle": "^5.4 || ^6.0 || ^7.0" - }, - "require-dev": { - "doctrine/coding-standard": "^12", - "doctrine/orm": "^2.6 || ^3", - "doctrine/persistence": "^2.0 || ^3 ", - "phpstan/phpstan": "^1.4", - "phpstan/phpstan-deprecation-rules": "^1", - "phpstan/phpstan-phpunit": "^1", - "phpstan/phpstan-strict-rules": "^1.1", - "phpstan/phpstan-symfony": "^1.3", - "phpunit/phpunit": "^8.5|^9.5", - "psalm/plugin-phpunit": "^0.18.4", - "psalm/plugin-symfony": "^3 || ^5", - "symfony/phpunit-bridge": "^6.3 || ^7", - "symfony/var-exporter": "^5.4 || ^6 || ^7", - "vimeo/psalm": "^4.30 || ^5.15" - }, - "type": "symfony-bundle", - "autoload": { - "psr-4": { - "Doctrine\\Bundle\\MigrationsBundle\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Doctrine Project", - "homepage": "https://www.doctrine-project.org" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony DoctrineMigrationsBundle", - "homepage": "https://www.doctrine-project.org", - "keywords": [ - "dbal", - "migrations", - "schema" - ], - "support": { - "issues": "https://github.com/doctrine/DoctrineMigrationsBundle/issues", - "source": "https://github.com/doctrine/DoctrineMigrationsBundle/tree/3.3.0" - }, - "funding": [ - { - "url": "https://www.doctrine-project.org/sponsorship.html", - "type": "custom" - }, - { - "url": "https://www.patreon.com/phpdoctrine", - "type": "patreon" - }, - { - "url": "https://tidelift.com/funding/github/packagist/doctrine%2Fdoctrine-migrations-bundle", - "type": "tidelift" - } - ], - "time": "2023-11-13T19:44:41+00:00" - }, - { - "name": "doctrine/event-manager", - "version": "2.0.0", - "source": { - "type": "git", - "url": "https://github.com/doctrine/event-manager.git", - "reference": "750671534e0241a7c50ea5b43f67e23eb5c96f32" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/doctrine/event-manager/zipball/750671534e0241a7c50ea5b43f67e23eb5c96f32", - "reference": "750671534e0241a7c50ea5b43f67e23eb5c96f32", - "shasum": "" - }, - "require": { - "php": "^8.1" - }, - "conflict": { - "doctrine/common": "<2.9" - }, - "require-dev": { - "doctrine/coding-standard": "^10", - "phpstan/phpstan": "^1.8.8", - "phpunit/phpunit": "^9.5", - "vimeo/psalm": "^4.28" - }, - "type": "library", - "autoload": { - "psr-4": { - "Doctrine\\Common\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Guilherme Blanco", - "email": "guilhermeblanco@gmail.com" - }, - { - "name": "Roman Borschel", - "email": "roman@code-factory.org" - }, - { - "name": "Benjamin Eberlei", - "email": "kontakt@beberlei.de" - }, - { - "name": "Jonathan Wage", - "email": "jonwage@gmail.com" - }, - { - "name": "Johannes Schmitt", - "email": "schmittjoh@gmail.com" - }, - { - "name": "Marco Pivetta", - "email": "ocramius@gmail.com" - } - ], - "description": "The Doctrine Event Manager is a simple PHP event system that was built to be used with the various Doctrine projects.", - "homepage": "https://www.doctrine-project.org/projects/event-manager.html", - "keywords": [ - "event", - "event dispatcher", - "event manager", - "event system", - "events" - ], - "support": { - "issues": "https://github.com/doctrine/event-manager/issues", - "source": "https://github.com/doctrine/event-manager/tree/2.0.0" - }, - "funding": [ - { - "url": "https://www.doctrine-project.org/sponsorship.html", - "type": "custom" - }, - { - "url": "https://www.patreon.com/phpdoctrine", - "type": "patreon" - }, - { - "url": "https://tidelift.com/funding/github/packagist/doctrine%2Fevent-manager", - "type": "tidelift" - } - ], - "time": "2022-10-12T20:59:15+00:00" - }, - { - "name": "doctrine/inflector", - "version": "2.0.8", - "source": { - "type": "git", - "url": "https://github.com/doctrine/inflector.git", - "reference": "f9301a5b2fb1216b2b08f02ba04dc45423db6bff" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/doctrine/inflector/zipball/f9301a5b2fb1216b2b08f02ba04dc45423db6bff", - "reference": "f9301a5b2fb1216b2b08f02ba04dc45423db6bff", - "shasum": "" - }, - "require": { - "php": "^7.2 || ^8.0" - }, - "require-dev": { - "doctrine/coding-standard": "^11.0", - "phpstan/phpstan": "^1.8", - "phpstan/phpstan-phpunit": "^1.1", - "phpstan/phpstan-strict-rules": "^1.3", - "phpunit/phpunit": "^8.5 || ^9.5", - "vimeo/psalm": "^4.25 || ^5.4" - }, - "type": "library", - "autoload": { - "psr-4": { - "Doctrine\\Inflector\\": "lib/Doctrine/Inflector" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Guilherme Blanco", - "email": "guilhermeblanco@gmail.com" - }, - { - "name": "Roman Borschel", - "email": "roman@code-factory.org" - }, - { - "name": "Benjamin Eberlei", - "email": "kontakt@beberlei.de" - }, - { - "name": "Jonathan Wage", - "email": "jonwage@gmail.com" - }, - { - "name": "Johannes Schmitt", - "email": "schmittjoh@gmail.com" - } - ], - "description": "PHP Doctrine Inflector is a small library that can perform string manipulations with regard to upper/lowercase and singular/plural forms of words.", - "homepage": "https://www.doctrine-project.org/projects/inflector.html", - "keywords": [ - "inflection", - "inflector", - "lowercase", - "manipulation", - "php", - "plural", - "singular", - "strings", - "uppercase", - "words" - ], - "support": { - "issues": "https://github.com/doctrine/inflector/issues", - "source": "https://github.com/doctrine/inflector/tree/2.0.8" - }, - "funding": [ - { - "url": "https://www.doctrine-project.org/sponsorship.html", - "type": "custom" - }, - { - "url": "https://www.patreon.com/phpdoctrine", - "type": "patreon" - }, - { - "url": "https://tidelift.com/funding/github/packagist/doctrine%2Finflector", - "type": "tidelift" - } - ], - "time": "2023-06-16T13:40:37+00:00" - }, - { - "name": "doctrine/instantiator", - "version": "2.0.0", - "source": { - "type": "git", - "url": "https://github.com/doctrine/instantiator.git", - "reference": "c6222283fa3f4ac679f8b9ced9a4e23f163e80d0" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/doctrine/instantiator/zipball/c6222283fa3f4ac679f8b9ced9a4e23f163e80d0", - "reference": "c6222283fa3f4ac679f8b9ced9a4e23f163e80d0", - "shasum": "" - }, - "require": { - "php": "^8.1" - }, - "require-dev": { - "doctrine/coding-standard": "^11", - "ext-pdo": "*", - "ext-phar": "*", - "phpbench/phpbench": "^1.2", - "phpstan/phpstan": "^1.9.4", - "phpstan/phpstan-phpunit": "^1.3", - "phpunit/phpunit": "^9.5.27", - "vimeo/psalm": "^5.4" - }, - "type": "library", - "autoload": { - "psr-4": { - "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Marco Pivetta", - "email": "ocramius@gmail.com", - "homepage": "https://ocramius.github.io/" - } - ], - "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors", - "homepage": "https://www.doctrine-project.org/projects/instantiator.html", - "keywords": [ - "constructor", - "instantiate" - ], - "support": { - "issues": "https://github.com/doctrine/instantiator/issues", - "source": "https://github.com/doctrine/instantiator/tree/2.0.0" - }, - "funding": [ - { - "url": "https://www.doctrine-project.org/sponsorship.html", - "type": "custom" - }, - { - "url": "https://www.patreon.com/phpdoctrine", - "type": "patreon" - }, - { - "url": "https://tidelift.com/funding/github/packagist/doctrine%2Finstantiator", - "type": "tidelift" - } - ], - "time": "2022-12-30T00:23:10+00:00" - }, - { - "name": "doctrine/lexer", - "version": "2.1.0", - "source": { - "type": "git", - "url": "https://github.com/doctrine/lexer.git", - "reference": "39ab8fcf5a51ce4b85ca97c7a7d033eb12831124" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/doctrine/lexer/zipball/39ab8fcf5a51ce4b85ca97c7a7d033eb12831124", - "reference": "39ab8fcf5a51ce4b85ca97c7a7d033eb12831124", - "shasum": "" - }, - "require": { - "doctrine/deprecations": "^1.0", - "php": "^7.1 || ^8.0" - }, - "require-dev": { - "doctrine/coding-standard": "^9 || ^10", - "phpstan/phpstan": "^1.3", - "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5", - "psalm/plugin-phpunit": "^0.18.3", - "vimeo/psalm": "^4.11 || ^5.0" - }, - "type": "library", - "autoload": { - "psr-4": { - "Doctrine\\Common\\Lexer\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Guilherme Blanco", - "email": "guilhermeblanco@gmail.com" - }, - { - "name": "Roman Borschel", - "email": "roman@code-factory.org" - }, - { - "name": "Johannes Schmitt", - "email": "schmittjoh@gmail.com" - } - ], - "description": "PHP Doctrine Lexer parser library that can be used in Top-Down, Recursive Descent Parsers.", - "homepage": "https://www.doctrine-project.org/projects/lexer.html", - "keywords": [ - "annotations", - "docblock", - "lexer", - "parser", - "php" - ], - "support": { - "issues": "https://github.com/doctrine/lexer/issues", - "source": "https://github.com/doctrine/lexer/tree/2.1.0" - }, - "funding": [ - { - "url": "https://www.doctrine-project.org/sponsorship.html", - "type": "custom" - }, - { - "url": "https://www.patreon.com/phpdoctrine", - "type": "patreon" - }, - { - "url": "https://tidelift.com/funding/github/packagist/doctrine%2Flexer", - "type": "tidelift" - } - ], - "time": "2022-12-14T08:49:07+00:00" - }, - { - "name": "doctrine/migrations", - "version": "3.7.2", - "source": { - "type": "git", - "url": "https://github.com/doctrine/migrations.git", - "reference": "47af29eef49f29ebee545947e8b2a4b3be318c8a" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/doctrine/migrations/zipball/47af29eef49f29ebee545947e8b2a4b3be318c8a", - "reference": "47af29eef49f29ebee545947e8b2a4b3be318c8a", - "shasum": "" - }, - "require": { - "composer-runtime-api": "^2", - "doctrine/dbal": "^3.5.1 || ^4", - "doctrine/deprecations": "^0.5.3 || ^1", - "doctrine/event-manager": "^1.2 || ^2.0", - "php": "^8.1", - "psr/log": "^1.1.3 || ^2 || ^3", - "symfony/console": "^5.4 || ^6.0 || ^7.0", - "symfony/stopwatch": "^5.4 || ^6.0 || ^7.0", - "symfony/var-exporter": "^6.2 || ^7.0" - }, - "conflict": { - "doctrine/orm": "<2.12 || >=4" - }, - "require-dev": { - "doctrine/coding-standard": "^12", - "doctrine/orm": "^2.13 || ^3", - "doctrine/persistence": "^2 || ^3", - "doctrine/sql-formatter": "^1.0", - "ext-pdo_sqlite": "*", - "phpstan/phpstan": "^1.10", - "phpstan/phpstan-deprecation-rules": "^1.1", - "phpstan/phpstan-phpunit": "^1.3", - "phpstan/phpstan-strict-rules": "^1.4", - "phpstan/phpstan-symfony": "^1.3", - "phpunit/phpunit": "^10.3", - "symfony/cache": "^5.4 || ^6.0 || ^7.0", - "symfony/process": "^5.4 || ^6.0 || ^7.0", - "symfony/yaml": "^5.4 || ^6.0 || ^7.0" - }, - "suggest": { - "doctrine/sql-formatter": "Allows to generate formatted SQL with the diff command.", - "symfony/yaml": "Allows the use of yaml for migration configuration files." - }, - "bin": [ - "bin/doctrine-migrations" - ], - "type": "library", - "autoload": { - "psr-4": { - "Doctrine\\Migrations\\": "lib/Doctrine/Migrations" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Benjamin Eberlei", - "email": "kontakt@beberlei.de" - }, - { - "name": "Jonathan Wage", - "email": "jonwage@gmail.com" - }, - { - "name": "Michael Simonson", - "email": "contact@mikesimonson.com" - } - ], - "description": "PHP Doctrine Migrations project offer additional functionality on top of the database abstraction layer (DBAL) for versioning your database schema and easily deploying changes to it. It is a very easy to use and a powerful tool.", - "homepage": "https://www.doctrine-project.org/projects/migrations.html", - "keywords": [ - "database", - "dbal", - "migrations" - ], - "support": { - "issues": "https://github.com/doctrine/migrations/issues", - "source": "https://github.com/doctrine/migrations/tree/3.7.2" - }, - "funding": [ - { - "url": "https://www.doctrine-project.org/sponsorship.html", - "type": "custom" - }, - { - "url": "https://www.patreon.com/phpdoctrine", - "type": "patreon" - }, - { - "url": "https://tidelift.com/funding/github/packagist/doctrine%2Fmigrations", - "type": "tidelift" - } - ], - "time": "2023-12-05T11:35:05+00:00" - }, - { - "name": "doctrine/orm", - "version": "2.17.1", - "source": { - "type": "git", - "url": "https://github.com/doctrine/orm.git", - "reference": "1a4fe6e0bb67762370937a7e6cee3da40a9122d1" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/doctrine/orm/zipball/1a4fe6e0bb67762370937a7e6cee3da40a9122d1", - "reference": "1a4fe6e0bb67762370937a7e6cee3da40a9122d1", - "shasum": "" - }, - "require": { - "composer-runtime-api": "^2", - "doctrine/cache": "^1.12.1 || ^2.1.1", - "doctrine/collections": "^1.5 || ^2.1", - "doctrine/common": "^3.0.3", - "doctrine/dbal": "^2.13.1 || ^3.2", - "doctrine/deprecations": "^0.5.3 || ^1", - "doctrine/event-manager": "^1.2 || ^2", - "doctrine/inflector": "^1.4 || ^2.0", - "doctrine/instantiator": "^1.3 || ^2", - "doctrine/lexer": "^2", - "doctrine/persistence": "^2.4 || ^3", - "ext-ctype": "*", - "php": "^7.1 || ^8.0", - "psr/cache": "^1 || ^2 || ^3", - "symfony/console": "^4.2 || ^5.0 || ^6.0 || ^7.0", - "symfony/polyfill-php72": "^1.23", - "symfony/polyfill-php80": "^1.16" - }, - "conflict": { - "doctrine/annotations": "<1.13 || >= 3.0" - }, - "require-dev": { - "doctrine/annotations": "^1.13 || ^2", - "doctrine/coding-standard": "^9.0.2 || ^12.0", - "phpbench/phpbench": "^0.16.10 || ^1.0", - "phpstan/phpstan": "~1.4.10 || 1.10.35", - "phpunit/phpunit": "^7.5 || ^8.5 || ^9.6", - "psr/log": "^1 || ^2 || ^3", - "squizlabs/php_codesniffer": "3.7.2", - "symfony/cache": "^4.4 || ^5.4 || ^6.0", - "symfony/var-exporter": "^4.4 || ^5.4 || ^6.2", - "symfony/yaml": "^3.4 || ^4.0 || ^5.0 || ^6.0", - "vimeo/psalm": "4.30.0 || 5.15.0" - }, - "suggest": { - "ext-dom": "Provides support for XSD validation for XML mapping files", - "symfony/cache": "Provides cache support for Setup Tool with doctrine/cache 2.0", - "symfony/yaml": "If you want to use YAML Metadata Mapping Driver" - }, - "bin": [ - "bin/doctrine" - ], - "type": "library", - "autoload": { - "psr-4": { - "Doctrine\\ORM\\": "lib/Doctrine/ORM" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Guilherme Blanco", - "email": "guilhermeblanco@gmail.com" - }, - { - "name": "Roman Borschel", - "email": "roman@code-factory.org" - }, - { - "name": "Benjamin Eberlei", - "email": "kontakt@beberlei.de" - }, - { - "name": "Jonathan Wage", - "email": "jonwage@gmail.com" - }, - { - "name": "Marco Pivetta", - "email": "ocramius@gmail.com" - } - ], - "description": "Object-Relational-Mapper for PHP", - "homepage": "https://www.doctrine-project.org/projects/orm.html", - "keywords": [ - "database", - "orm" - ], - "support": { - "issues": "https://github.com/doctrine/orm/issues", - "source": "https://github.com/doctrine/orm/tree/2.17.1" - }, - "time": "2023-11-17T06:25:40+00:00" - }, - { - "name": "doctrine/persistence", - "version": "3.2.0", - "source": { - "type": "git", - "url": "https://github.com/doctrine/persistence.git", - "reference": "63fee8c33bef740db6730eb2a750cd3da6495603" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/doctrine/persistence/zipball/63fee8c33bef740db6730eb2a750cd3da6495603", - "reference": "63fee8c33bef740db6730eb2a750cd3da6495603", - "shasum": "" - }, - "require": { - "doctrine/event-manager": "^1 || ^2", - "php": "^7.2 || ^8.0", - "psr/cache": "^1.0 || ^2.0 || ^3.0" - }, - "conflict": { - "doctrine/common": "<2.10" - }, - "require-dev": { - "composer/package-versions-deprecated": "^1.11", - "doctrine/coding-standard": "^11", - "doctrine/common": "^3.0", - "phpstan/phpstan": "1.9.4", - "phpstan/phpstan-phpunit": "^1", - "phpstan/phpstan-strict-rules": "^1.1", - "phpunit/phpunit": "^8.5 || ^9.5", - "symfony/cache": "^4.4 || ^5.4 || ^6.0", - "vimeo/psalm": "4.30.0 || 5.3.0" - }, - "type": "library", - "autoload": { - "psr-4": { - "Doctrine\\Persistence\\": "src/Persistence" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Guilherme Blanco", - "email": "guilhermeblanco@gmail.com" - }, - { - "name": "Roman Borschel", - "email": "roman@code-factory.org" - }, - { - "name": "Benjamin Eberlei", - "email": "kontakt@beberlei.de" - }, - { - "name": "Jonathan Wage", - "email": "jonwage@gmail.com" - }, - { - "name": "Johannes Schmitt", - "email": "schmittjoh@gmail.com" - }, - { - "name": "Marco Pivetta", - "email": "ocramius@gmail.com" - } - ], - "description": "The Doctrine Persistence project is a set of shared interfaces and functionality that the different Doctrine object mappers share.", - "homepage": "https://www.doctrine-project.org/projects/persistence.html", - "keywords": [ - "mapper", - "object", - "odm", - "orm", - "persistence" - ], - "support": { - "issues": "https://github.com/doctrine/persistence/issues", - "source": "https://github.com/doctrine/persistence/tree/3.2.0" - }, - "funding": [ - { - "url": "https://www.doctrine-project.org/sponsorship.html", - "type": "custom" - }, - { - "url": "https://www.patreon.com/phpdoctrine", - "type": "patreon" - }, - { - "url": "https://tidelift.com/funding/github/packagist/doctrine%2Fpersistence", - "type": "tidelift" - } - ], - "time": "2023-05-17T18:32:04+00:00" - }, - { - "name": "doctrine/sql-formatter", - "version": "1.1.3", - "source": { - "type": "git", - "url": "https://github.com/doctrine/sql-formatter.git", - "reference": "25a06c7bf4c6b8218f47928654252863ffc890a5" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/doctrine/sql-formatter/zipball/25a06c7bf4c6b8218f47928654252863ffc890a5", - "reference": "25a06c7bf4c6b8218f47928654252863ffc890a5", - "shasum": "" - }, - "require": { - "php": "^7.1 || ^8.0" - }, - "require-dev": { - "bamarni/composer-bin-plugin": "^1.4" - }, - "bin": [ - "bin/sql-formatter" - ], - "type": "library", - "autoload": { - "psr-4": { - "Doctrine\\SqlFormatter\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Jeremy Dorn", - "email": "jeremy@jeremydorn.com", - "homepage": "https://jeremydorn.com/" - } - ], - "description": "a PHP SQL highlighting library", - "homepage": "https://github.com/doctrine/sql-formatter/", - "keywords": [ - "highlight", - "sql" - ], - "support": { - "issues": "https://github.com/doctrine/sql-formatter/issues", - "source": "https://github.com/doctrine/sql-formatter/tree/1.1.3" - }, - "time": "2022-05-23T21:33:49+00:00" - }, - { - "name": "egulias/email-validator", - "version": "4.0.2", - "source": { - "type": "git", - "url": "https://github.com/egulias/EmailValidator.git", - "reference": "ebaaf5be6c0286928352e054f2d5125608e5405e" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/egulias/EmailValidator/zipball/ebaaf5be6c0286928352e054f2d5125608e5405e", - "reference": "ebaaf5be6c0286928352e054f2d5125608e5405e", - "shasum": "" - }, - "require": { - "doctrine/lexer": "^2.0 || ^3.0", - "php": ">=8.1", - "symfony/polyfill-intl-idn": "^1.26" - }, - "require-dev": { - "phpunit/phpunit": "^10.2", - "vimeo/psalm": "^5.12" - }, - "suggest": { - "ext-intl": "PHP Internationalization Libraries are required to use the SpoofChecking validation" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "4.0.x-dev" - } - }, - "autoload": { - "psr-4": { - "Egulias\\EmailValidator\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Eduardo Gulias Davis" - } - ], - "description": "A library for validating emails against several RFCs", - "homepage": "https://github.com/egulias/EmailValidator", - "keywords": [ - "email", - "emailvalidation", - "emailvalidator", - "validation", - "validator" - ], - "support": { - "issues": "https://github.com/egulias/EmailValidator/issues", - "source": "https://github.com/egulias/EmailValidator/tree/4.0.2" - }, - "funding": [ - { - "url": "https://github.com/egulias", - "type": "github" - } - ], - "time": "2023-10-06T06:47:41+00:00" - }, - { - "name": "jdenticon/jdenticon", - "version": "1.0.2", - "source": { - "type": "git", - "url": "https://github.com/dmester/jdenticon-php.git", - "reference": "cabb7a44c413c318392a341c5d3ca30fcdd57a6f" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/dmester/jdenticon-php/zipball/cabb7a44c413c318392a341c5d3ca30fcdd57a6f", - "reference": "cabb7a44c413c318392a341c5d3ca30fcdd57a6f", - "shasum": "" - }, - "require": { - "php": ">=5.3.0" - }, - "require-dev": { - "phpunit/phpunit": "^5.7" - }, - "type": "library", - "autoload": { - "psr-4": { - "Jdenticon\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Daniel Mester Pirttijärvi" - } - ], - "description": "Render PNG and SVG identicons.", - "homepage": "https://jdenticon.com/", - "keywords": [ - "avatar", - "identicon", - "jdenticon" - ], - "support": { - "docs": "https://jdenticon.com/php-api.html", - "issues": "https://github.com/dmester/jdenticon-php/issues", - "source": "https://github.com/dmester/jdenticon-php" - }, - "time": "2022-10-30T17:15:02+00:00" - }, - { - "name": "league/commonmark", - "version": "2.4.1", - "source": { - "type": "git", - "url": "https://github.com/thephpleague/commonmark.git", - "reference": "3669d6d5f7a47a93c08ddff335e6d945481a1dd5" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/thephpleague/commonmark/zipball/3669d6d5f7a47a93c08ddff335e6d945481a1dd5", - "reference": "3669d6d5f7a47a93c08ddff335e6d945481a1dd5", - "shasum": "" - }, - "require": { - "ext-mbstring": "*", - "league/config": "^1.1.1", - "php": "^7.4 || ^8.0", - "psr/event-dispatcher": "^1.0", - "symfony/deprecation-contracts": "^2.1 || ^3.0", - "symfony/polyfill-php80": "^1.16" - }, - "require-dev": { - "cebe/markdown": "^1.0", - "commonmark/cmark": "0.30.0", - "commonmark/commonmark.js": "0.30.0", - "composer/package-versions-deprecated": "^1.8", - "embed/embed": "^4.4", - "erusev/parsedown": "^1.0", - "ext-json": "*", - "github/gfm": "0.29.0", - "michelf/php-markdown": "^1.4 || ^2.0", - "nyholm/psr7": "^1.5", - "phpstan/phpstan": "^1.8.2", - "phpunit/phpunit": "^9.5.21", - "scrutinizer/ocular": "^1.8.1", - "symfony/finder": "^5.3 | ^6.0", - "symfony/yaml": "^2.3 | ^3.0 | ^4.0 | ^5.0 | ^6.0", - "unleashedtech/php-coding-standard": "^3.1.1", - "vimeo/psalm": "^4.24.0 || ^5.0.0" - }, - "suggest": { - "symfony/yaml": "v2.3+ required if using the Front Matter extension" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "2.5-dev" - } - }, - "autoload": { - "psr-4": { - "League\\CommonMark\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Colin O'Dell", - "email": "colinodell@gmail.com", - "homepage": "https://www.colinodell.com", - "role": "Lead Developer" - } - ], - "description": "Highly-extensible PHP Markdown parser which fully supports the CommonMark spec and GitHub-Flavored Markdown (GFM)", - "homepage": "https://commonmark.thephpleague.com", - "keywords": [ - "commonmark", - "flavored", - "gfm", - "github", - "github-flavored", - "markdown", - "md", - "parser" - ], - "support": { - "docs": "https://commonmark.thephpleague.com/", - "forum": "https://github.com/thephpleague/commonmark/discussions", - "issues": "https://github.com/thephpleague/commonmark/issues", - "rss": "https://github.com/thephpleague/commonmark/releases.atom", - "source": "https://github.com/thephpleague/commonmark" - }, - "funding": [ - { - "url": "https://www.colinodell.com/sponsor", - "type": "custom" - }, - { - "url": "https://www.paypal.me/colinpodell/10.00", - "type": "custom" - }, - { - "url": "https://github.com/colinodell", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/league/commonmark", - "type": "tidelift" - } - ], - "time": "2023-08-30T16:55:00+00:00" - }, - { - "name": "league/config", - "version": "v1.2.0", - "source": { - "type": "git", - "url": "https://github.com/thephpleague/config.git", - "reference": "754b3604fb2984c71f4af4a9cbe7b57f346ec1f3" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/thephpleague/config/zipball/754b3604fb2984c71f4af4a9cbe7b57f346ec1f3", - "reference": "754b3604fb2984c71f4af4a9cbe7b57f346ec1f3", - "shasum": "" - }, - "require": { - "dflydev/dot-access-data": "^3.0.1", - "nette/schema": "^1.2", - "php": "^7.4 || ^8.0" - }, - "require-dev": { - "phpstan/phpstan": "^1.8.2", - "phpunit/phpunit": "^9.5.5", - "scrutinizer/ocular": "^1.8.1", - "unleashedtech/php-coding-standard": "^3.1", - "vimeo/psalm": "^4.7.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "1.2-dev" - } - }, - "autoload": { - "psr-4": { - "League\\Config\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Colin O'Dell", - "email": "colinodell@gmail.com", - "homepage": "https://www.colinodell.com", - "role": "Lead Developer" - } - ], - "description": "Define configuration arrays with strict schemas and access values with dot notation", - "homepage": "https://config.thephpleague.com", - "keywords": [ - "array", - "config", - "configuration", - "dot", - "dot-access", - "nested", - "schema" - ], - "support": { - "docs": "https://config.thephpleague.com/", - "issues": "https://github.com/thephpleague/config/issues", - "rss": "https://github.com/thephpleague/config/releases.atom", - "source": "https://github.com/thephpleague/config" - }, - "funding": [ - { - "url": "https://www.colinodell.com/sponsor", - "type": "custom" - }, - { - "url": "https://www.paypal.me/colinpodell/10.00", - "type": "custom" - }, - { - "url": "https://github.com/colinodell", - "type": "github" - } - ], - "time": "2022-12-11T20:36:23+00:00" - }, - { - "name": "monolog/monolog", - "version": "3.5.0", - "source": { - "type": "git", - "url": "https://github.com/Seldaek/monolog.git", - "reference": "c915e2634718dbc8a4a15c61b0e62e7a44e14448" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/Seldaek/monolog/zipball/c915e2634718dbc8a4a15c61b0e62e7a44e14448", - "reference": "c915e2634718dbc8a4a15c61b0e62e7a44e14448", - "shasum": "" - }, - "require": { - "php": ">=8.1", - "psr/log": "^2.0 || ^3.0" - }, - "provide": { - "psr/log-implementation": "3.0.0" - }, - "require-dev": { - "aws/aws-sdk-php": "^3.0", - "doctrine/couchdb": "~1.0@dev", - "elasticsearch/elasticsearch": "^7 || ^8", - "ext-json": "*", - "graylog2/gelf-php": "^1.4.2 || ^2.0", - "guzzlehttp/guzzle": "^7.4.5", - "guzzlehttp/psr7": "^2.2", - "mongodb/mongodb": "^1.8", - "php-amqplib/php-amqplib": "~2.4 || ^3", - "phpstan/phpstan": "^1.9", - "phpstan/phpstan-deprecation-rules": "^1.0", - "phpstan/phpstan-strict-rules": "^1.4", - "phpunit/phpunit": "^10.1", - "predis/predis": "^1.1 || ^2", - "ruflin/elastica": "^7", - "symfony/mailer": "^5.4 || ^6", - "symfony/mime": "^5.4 || ^6" - }, - "suggest": { - "aws/aws-sdk-php": "Allow sending log messages to AWS services like DynamoDB", - "doctrine/couchdb": "Allow sending log messages to a CouchDB server", - "elasticsearch/elasticsearch": "Allow sending log messages to an Elasticsearch server via official client", - "ext-amqp": "Allow sending log messages to an AMQP server (1.0+ required)", - "ext-curl": "Required to send log messages using the IFTTTHandler, the LogglyHandler, the SendGridHandler, the SlackWebhookHandler or the TelegramBotHandler", - "ext-mbstring": "Allow to work properly with unicode symbols", - "ext-mongodb": "Allow sending log messages to a MongoDB server (via driver)", - "ext-openssl": "Required to send log messages using SSL", - "ext-sockets": "Allow sending log messages to a Syslog server (via UDP driver)", - "graylog2/gelf-php": "Allow sending log messages to a GrayLog2 server", - "mongodb/mongodb": "Allow sending log messages to a MongoDB server (via library)", - "php-amqplib/php-amqplib": "Allow sending log messages to an AMQP server using php-amqplib", - "rollbar/rollbar": "Allow sending log messages to Rollbar", - "ruflin/elastica": "Allow sending log messages to an Elastic Search server" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "3.x-dev" - } - }, - "autoload": { - "psr-4": { - "Monolog\\": "src/Monolog" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Jordi Boggiano", - "email": "j.boggiano@seld.be", - "homepage": "https://seld.be" - } - ], - "description": "Sends your logs to files, sockets, inboxes, databases and various web services", - "homepage": "https://github.com/Seldaek/monolog", - "keywords": [ - "log", - "logging", - "psr-3" - ], - "support": { - "issues": "https://github.com/Seldaek/monolog/issues", - "source": "https://github.com/Seldaek/monolog/tree/3.5.0" - }, - "funding": [ - { - "url": "https://github.com/Seldaek", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/monolog/monolog", - "type": "tidelift" - } - ], - "time": "2023-10-27T15:32:31+00:00" - }, - { - "name": "nette/schema", - "version": "v1.2.5", - "source": { - "type": "git", - "url": "https://github.com/nette/schema.git", - "reference": "0462f0166e823aad657c9224d0f849ecac1ba10a" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/nette/schema/zipball/0462f0166e823aad657c9224d0f849ecac1ba10a", - "reference": "0462f0166e823aad657c9224d0f849ecac1ba10a", - "shasum": "" - }, - "require": { - "nette/utils": "^2.5.7 || ^3.1.5 || ^4.0", - "php": "7.1 - 8.3" - }, - "require-dev": { - "nette/tester": "^2.3 || ^2.4", - "phpstan/phpstan-nette": "^1.0", - "tracy/tracy": "^2.7" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.2-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause", - "GPL-2.0-only", - "GPL-3.0-only" - ], - "authors": [ - { - "name": "David Grudl", - "homepage": "https://davidgrudl.com" - }, - { - "name": "Nette Community", - "homepage": "https://nette.org/contributors" - } - ], - "description": "📐 Nette Schema: validating data structures against a given Schema.", - "homepage": "https://nette.org", - "keywords": [ - "config", - "nette" - ], - "support": { - "issues": "https://github.com/nette/schema/issues", - "source": "https://github.com/nette/schema/tree/v1.2.5" - }, - "time": "2023-10-05T20:37:59+00:00" - }, - { - "name": "nette/utils", - "version": "v4.0.3", - "source": { - "type": "git", - "url": "https://github.com/nette/utils.git", - "reference": "a9d127dd6a203ce6d255b2e2db49759f7506e015" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/nette/utils/zipball/a9d127dd6a203ce6d255b2e2db49759f7506e015", - "reference": "a9d127dd6a203ce6d255b2e2db49759f7506e015", - "shasum": "" - }, - "require": { - "php": ">=8.0 <8.4" - }, - "conflict": { - "nette/finder": "<3", - "nette/schema": "<1.2.2" - }, - "require-dev": { - "jetbrains/phpstorm-attributes": "dev-master", - "nette/tester": "^2.5", - "phpstan/phpstan": "^1.0", - "tracy/tracy": "^2.9" - }, - "suggest": { - "ext-gd": "to use Image", - "ext-iconv": "to use Strings::webalize(), toAscii(), chr() and reverse()", - "ext-intl": "to use Strings::webalize(), toAscii(), normalize() and compare()", - "ext-json": "to use Nette\\Utils\\Json", - "ext-mbstring": "to use Strings::lower() etc...", - "ext-tokenizer": "to use Nette\\Utils\\Reflection::getUseStatements()" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "4.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause", - "GPL-2.0-only", - "GPL-3.0-only" - ], - "authors": [ - { - "name": "David Grudl", - "homepage": "https://davidgrudl.com" - }, - { - "name": "Nette Community", - "homepage": "https://nette.org/contributors" - } - ], - "description": "🛠 Nette Utils: lightweight utilities for string & array manipulation, image handling, safe JSON encoding/decoding, validation, slug or strong password generating etc.", - "homepage": "https://nette.org", - "keywords": [ - "array", - "core", - "datetime", - "images", - "json", - "nette", - "paginator", - "password", - "slugify", - "string", - "unicode", - "utf-8", - "utility", - "validation" - ], - "support": { - "issues": "https://github.com/nette/utils/issues", - "source": "https://github.com/nette/utils/tree/v4.0.3" - }, - "time": "2023-10-29T21:02:13+00:00" - }, - { - "name": "phpdocumentor/reflection-common", - "version": "2.2.0", - "source": { - "type": "git", - "url": "https://github.com/phpDocumentor/ReflectionCommon.git", - "reference": "1d01c49d4ed62f25aa84a747ad35d5a16924662b" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/1d01c49d4ed62f25aa84a747ad35d5a16924662b", - "reference": "1d01c49d4ed62f25aa84a747ad35d5a16924662b", - "shasum": "" - }, - "require": { - "php": "^7.2 || ^8.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-2.x": "2.x-dev" - } - }, - "autoload": { - "psr-4": { - "phpDocumentor\\Reflection\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Jaap van Otterdijk", - "email": "opensource@ijaap.nl" - } - ], - "description": "Common reflection classes used by phpdocumentor to reflect the code structure", - "homepage": "http://www.phpdoc.org", - "keywords": [ - "FQSEN", - "phpDocumentor", - "phpdoc", - "reflection", - "static analysis" - ], - "support": { - "issues": "https://github.com/phpDocumentor/ReflectionCommon/issues", - "source": "https://github.com/phpDocumentor/ReflectionCommon/tree/2.x" - }, - "time": "2020-06-27T09:03:43+00:00" - }, - { - "name": "phpdocumentor/reflection-docblock", - "version": "5.3.0", - "source": { - "type": "git", - "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", - "reference": "622548b623e81ca6d78b721c5e029f4ce664f170" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/622548b623e81ca6d78b721c5e029f4ce664f170", - "reference": "622548b623e81ca6d78b721c5e029f4ce664f170", - "shasum": "" - }, - "require": { - "ext-filter": "*", - "php": "^7.2 || ^8.0", - "phpdocumentor/reflection-common": "^2.2", - "phpdocumentor/type-resolver": "^1.3", - "webmozart/assert": "^1.9.1" - }, - "require-dev": { - "mockery/mockery": "~1.3.2", - "psalm/phar": "^4.8" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "5.x-dev" - } - }, - "autoload": { - "psr-4": { - "phpDocumentor\\Reflection\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Mike van Riel", - "email": "me@mikevanriel.com" - }, - { - "name": "Jaap van Otterdijk", - "email": "account@ijaap.nl" - } - ], - "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.", - "support": { - "issues": "https://github.com/phpDocumentor/ReflectionDocBlock/issues", - "source": "https://github.com/phpDocumentor/ReflectionDocBlock/tree/5.3.0" - }, - "time": "2021-10-19T17:43:47+00:00" - }, - { - "name": "phpdocumentor/type-resolver", - "version": "1.7.3", - "source": { - "type": "git", - "url": "https://github.com/phpDocumentor/TypeResolver.git", - "reference": "3219c6ee25c9ea71e3d9bbaf39c67c9ebd499419" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/3219c6ee25c9ea71e3d9bbaf39c67c9ebd499419", - "reference": "3219c6ee25c9ea71e3d9bbaf39c67c9ebd499419", - "shasum": "" - }, - "require": { - "doctrine/deprecations": "^1.0", - "php": "^7.4 || ^8.0", - "phpdocumentor/reflection-common": "^2.0", - "phpstan/phpdoc-parser": "^1.13" - }, - "require-dev": { - "ext-tokenizer": "*", - "phpbench/phpbench": "^1.2", - "phpstan/extension-installer": "^1.1", - "phpstan/phpstan": "^1.8", - "phpstan/phpstan-phpunit": "^1.1", - "phpunit/phpunit": "^9.5", - "rector/rector": "^0.13.9", - "vimeo/psalm": "^4.25" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-1.x": "1.x-dev" - } - }, - "autoload": { - "psr-4": { - "phpDocumentor\\Reflection\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Mike van Riel", - "email": "me@mikevanriel.com" - } - ], - "description": "A PSR-5 based resolver of Class names, Types and Structural Element Names", - "support": { - "issues": "https://github.com/phpDocumentor/TypeResolver/issues", - "source": "https://github.com/phpDocumentor/TypeResolver/tree/1.7.3" - }, - "time": "2023-08-12T11:01:26+00:00" - }, - { - "name": "phpstan/phpdoc-parser", - "version": "1.24.4", - "source": { - "type": "git", - "url": "https://github.com/phpstan/phpdoc-parser.git", - "reference": "6bd0c26f3786cd9b7c359675cb789e35a8e07496" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/6bd0c26f3786cd9b7c359675cb789e35a8e07496", - "reference": "6bd0c26f3786cd9b7c359675cb789e35a8e07496", - "shasum": "" - }, - "require": { - "php": "^7.2 || ^8.0" - }, - "require-dev": { - "doctrine/annotations": "^2.0", - "nikic/php-parser": "^4.15", - "php-parallel-lint/php-parallel-lint": "^1.2", - "phpstan/extension-installer": "^1.0", - "phpstan/phpstan": "^1.5", - "phpstan/phpstan-phpunit": "^1.1", - "phpstan/phpstan-strict-rules": "^1.0", - "phpunit/phpunit": "^9.5", - "symfony/process": "^5.2" - }, - "type": "library", - "autoload": { - "psr-4": { - "PHPStan\\PhpDocParser\\": [ - "src/" - ] - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "description": "PHPDoc parser with support for nullable, intersection and generic types", - "support": { - "issues": "https://github.com/phpstan/phpdoc-parser/issues", - "source": "https://github.com/phpstan/phpdoc-parser/tree/1.24.4" - }, - "time": "2023-11-26T18:29:22+00:00" - }, - { - "name": "psr/cache", - "version": "3.0.0", - "source": { - "type": "git", - "url": "https://github.com/php-fig/cache.git", - "reference": "aa5030cfa5405eccfdcb1083ce040c2cb8d253bf" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/php-fig/cache/zipball/aa5030cfa5405eccfdcb1083ce040c2cb8d253bf", - "reference": "aa5030cfa5405eccfdcb1083ce040c2cb8d253bf", - "shasum": "" - }, - "require": { - "php": ">=8.0.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev" - } - }, - "autoload": { - "psr-4": { - "Psr\\Cache\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "PHP-FIG", - "homepage": "https://www.php-fig.org/" - } - ], - "description": "Common interface for caching libraries", - "keywords": [ - "cache", - "psr", - "psr-6" - ], - "support": { - "source": "https://github.com/php-fig/cache/tree/3.0.0" - }, - "time": "2021-02-03T23:26:27+00:00" - }, - { - "name": "psr/clock", - "version": "1.0.0", - "source": { - "type": "git", - "url": "https://github.com/php-fig/clock.git", - "reference": "e41a24703d4560fd0acb709162f73b8adfc3aa0d" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/php-fig/clock/zipball/e41a24703d4560fd0acb709162f73b8adfc3aa0d", - "reference": "e41a24703d4560fd0acb709162f73b8adfc3aa0d", - "shasum": "" - }, - "require": { - "php": "^7.0 || ^8.0" - }, - "type": "library", - "autoload": { - "psr-4": { - "Psr\\Clock\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "PHP-FIG", - "homepage": "https://www.php-fig.org/" - } - ], - "description": "Common interface for reading the clock.", - "homepage": "https://github.com/php-fig/clock", - "keywords": [ - "clock", - "now", - "psr", - "psr-20", - "time" - ], - "support": { - "issues": "https://github.com/php-fig/clock/issues", - "source": "https://github.com/php-fig/clock/tree/1.0.0" - }, - "time": "2022-11-25T14:36:26+00:00" - }, - { - "name": "psr/container", - "version": "2.0.2", - "source": { - "type": "git", - "url": "https://github.com/php-fig/container.git", - "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/php-fig/container/zipball/c71ecc56dfe541dbd90c5360474fbc405f8d5963", - "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963", - "shasum": "" - }, - "require": { - "php": ">=7.4.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.0.x-dev" - } - }, - "autoload": { - "psr-4": { - "Psr\\Container\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "PHP-FIG", - "homepage": "https://www.php-fig.org/" - } - ], - "description": "Common Container Interface (PHP FIG PSR-11)", - "homepage": "https://github.com/php-fig/container", - "keywords": [ - "PSR-11", - "container", - "container-interface", - "container-interop", - "psr" - ], - "support": { - "issues": "https://github.com/php-fig/container/issues", - "source": "https://github.com/php-fig/container/tree/2.0.2" - }, - "time": "2021-11-05T16:47:00+00:00" - }, - { - "name": "psr/event-dispatcher", - "version": "1.0.0", - "source": { - "type": "git", - "url": "https://github.com/php-fig/event-dispatcher.git", - "reference": "dbefd12671e8a14ec7f180cab83036ed26714bb0" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/php-fig/event-dispatcher/zipball/dbefd12671e8a14ec7f180cab83036ed26714bb0", - "reference": "dbefd12671e8a14ec7f180cab83036ed26714bb0", - "shasum": "" - }, - "require": { - "php": ">=7.2.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev" - } - }, - "autoload": { - "psr-4": { - "Psr\\EventDispatcher\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "PHP-FIG", - "homepage": "http://www.php-fig.org/" - } - ], - "description": "Standard interfaces for event handling.", - "keywords": [ - "events", - "psr", - "psr-14" - ], - "support": { - "issues": "https://github.com/php-fig/event-dispatcher/issues", - "source": "https://github.com/php-fig/event-dispatcher/tree/1.0.0" - }, - "time": "2019-01-08T18:20:26+00:00" - }, - { - "name": "psr/link", - "version": "2.0.1", - "source": { - "type": "git", - "url": "https://github.com/php-fig/link.git", - "reference": "84b159194ecfd7eaa472280213976e96415433f7" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/php-fig/link/zipball/84b159194ecfd7eaa472280213976e96415433f7", - "reference": "84b159194ecfd7eaa472280213976e96415433f7", - "shasum": "" - }, - "require": { - "php": ">=8.0.0" - }, - "suggest": { - "fig/link-util": "Provides some useful PSR-13 utilities" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.0.x-dev" - } - }, - "autoload": { - "psr-4": { - "Psr\\Link\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "PHP-FIG", - "homepage": "http://www.php-fig.org/" - } - ], - "description": "Common interfaces for HTTP links", - "homepage": "https://github.com/php-fig/link", - "keywords": [ - "http", - "http-link", - "link", - "psr", - "psr-13", - "rest" - ], - "support": { - "source": "https://github.com/php-fig/link/tree/2.0.1" - }, - "time": "2021-03-11T23:00:27+00:00" - }, - { - "name": "psr/log", - "version": "3.0.0", - "source": { - "type": "git", - "url": "https://github.com/php-fig/log.git", - "reference": "fe5ea303b0887d5caefd3d431c3e61ad47037001" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/php-fig/log/zipball/fe5ea303b0887d5caefd3d431c3e61ad47037001", - "reference": "fe5ea303b0887d5caefd3d431c3e61ad47037001", - "shasum": "" - }, - "require": { - "php": ">=8.0.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.x-dev" - } - }, - "autoload": { - "psr-4": { - "Psr\\Log\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "PHP-FIG", - "homepage": "https://www.php-fig.org/" - } - ], - "description": "Common interface for logging libraries", - "homepage": "https://github.com/php-fig/log", - "keywords": [ - "log", - "psr", - "psr-3" - ], - "support": { - "source": "https://github.com/php-fig/log/tree/3.0.0" - }, - "time": "2021-07-14T16:46:02+00:00" - }, - { - "name": "rhilip/bencode", - "version": "v2.4.2", - "source": { - "type": "git", - "url": "https://github.com/Rhilip/Bencode.git", - "reference": "d5b51d02f73017834c53aa76aff2403fb753ac97" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/Rhilip/Bencode/zipball/d5b51d02f73017834c53aa76aff2403fb753ac97", - "reference": "d5b51d02f73017834c53aa76aff2403fb753ac97", - "shasum": "" - }, - "require": { - "php": "^7.3|^8.0" - }, - "require-dev": { - "ext-json": "*", - "phpunit/phpunit": "^9.0" - }, - "suggest": { - "php-64bit": "Running 64 bit is recommended to prevent integer overflow" - }, - "type": "library", - "autoload": { - "psr-4": { - "Rhilip\\Bencode\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Rhilip", - "email": "rhilipruan@gmail.com" - } - ], - "description": "A pure and simple PHP library for encoding and decoding Bencode data", - "keywords": [ - "bencode", - "bittorrent", - "torrent" - ], - "support": { - "issues": "https://github.com/Rhilip/Bencode/issues", - "source": "https://github.com/Rhilip/Bencode/tree/v2.4.2" - }, - "time": "2023-11-05T11:24:41+00:00" - }, - { - "name": "symfony/asset", - "version": "v6.3.8", - "source": { - "type": "git", - "url": "https://github.com/symfony/asset.git", - "reference": "b2382a403f2111836301623d89e9af3d84989525" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/asset/zipball/b2382a403f2111836301623d89e9af3d84989525", - "reference": "b2382a403f2111836301623d89e9af3d84989525", - "shasum": "" - }, - "require": { - "php": ">=8.1" - }, - "conflict": { - "symfony/http-foundation": "<5.4" - }, - "require-dev": { - "symfony/http-client": "^5.4|^6.0", - "symfony/http-foundation": "^5.4|^6.0", - "symfony/http-kernel": "^5.4|^6.0" - }, - "type": "library", - "autoload": { - "psr-4": { - "Symfony\\Component\\Asset\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Manages URL generation and versioning of web assets such as CSS stylesheets, JavaScript files and image files", - "homepage": "https://symfony.com", - "support": { - "source": "https://github.com/symfony/asset/tree/v6.3.8" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2023-10-31T08:07:48+00:00" - }, - { - "name": "symfony/cache", - "version": "v6.3.9", - "source": { - "type": "git", - "url": "https://github.com/symfony/cache.git", - "reference": "8c6e84272e4febbb1fed3c5b9f3c722537c2bd55" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/cache/zipball/8c6e84272e4febbb1fed3c5b9f3c722537c2bd55", - "reference": "8c6e84272e4febbb1fed3c5b9f3c722537c2bd55", - "shasum": "" - }, - "require": { - "php": ">=8.1", - "psr/cache": "^2.0|^3.0", - "psr/log": "^1.1|^2|^3", - "symfony/cache-contracts": "^2.5|^3", - "symfony/service-contracts": "^2.5|^3", - "symfony/var-exporter": "^6.3.6" - }, - "conflict": { - "doctrine/dbal": "<2.13.1", - "symfony/dependency-injection": "<5.4", - "symfony/http-kernel": "<5.4", - "symfony/var-dumper": "<5.4" - }, - "provide": { - "psr/cache-implementation": "2.0|3.0", - "psr/simple-cache-implementation": "1.0|2.0|3.0", - "symfony/cache-implementation": "1.1|2.0|3.0" - }, - "require-dev": { - "cache/integration-tests": "dev-master", - "doctrine/dbal": "^2.13.1|^3|^4", - "predis/predis": "^1.1|^2.0", - "psr/simple-cache": "^1.0|^2.0|^3.0", - "symfony/config": "^5.4|^6.0", - "symfony/dependency-injection": "^5.4|^6.0", - "symfony/filesystem": "^5.4|^6.0", - "symfony/http-kernel": "^5.4|^6.0", - "symfony/messenger": "^5.4|^6.0", - "symfony/var-dumper": "^5.4|^6.0" - }, - "type": "library", - "autoload": { - "psr-4": { - "Symfony\\Component\\Cache\\": "" - }, - "classmap": [ - "Traits/ValueWrapper.php" - ], - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Provides extended PSR-6, PSR-16 (and tags) implementations", - "homepage": "https://symfony.com", - "keywords": [ - "caching", - "psr6" - ], - "support": { - "source": "https://github.com/symfony/cache/tree/v6.3.9" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2023-11-24T13:24:35+00:00" - }, - { - "name": "symfony/cache-contracts", - "version": "v3.4.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/cache-contracts.git", - "reference": "1d74b127da04ffa87aa940abe15446fa89653778" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/cache-contracts/zipball/1d74b127da04ffa87aa940abe15446fa89653778", - "reference": "1d74b127da04ffa87aa940abe15446fa89653778", - "shasum": "" - }, - "require": { - "php": ">=8.1", - "psr/cache": "^3.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "3.4-dev" - }, - "thanks": { - "name": "symfony/contracts", - "url": "https://github.com/symfony/contracts" - } - }, - "autoload": { - "psr-4": { - "Symfony\\Contracts\\Cache\\": "" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Generic abstractions related to caching", - "homepage": "https://symfony.com", - "keywords": [ - "abstractions", - "contracts", - "decoupling", - "interfaces", - "interoperability", - "standards" - ], - "support": { - "source": "https://github.com/symfony/cache-contracts/tree/v3.4.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2023-09-25T12:52:38+00:00" - }, - { - "name": "symfony/clock", - "version": "v6.3.4", - "source": { - "type": "git", - "url": "https://github.com/symfony/clock.git", - "reference": "a74086d3db70d0f06ffd84480daa556248706e98" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/clock/zipball/a74086d3db70d0f06ffd84480daa556248706e98", - "reference": "a74086d3db70d0f06ffd84480daa556248706e98", - "shasum": "" - }, - "require": { - "php": ">=8.1", - "psr/clock": "^1.0" - }, - "provide": { - "psr/clock-implementation": "1.0" - }, - "type": "library", - "autoload": { - "files": [ - "Resources/now.php" - ], - "psr-4": { - "Symfony\\Component\\Clock\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Decouples applications from the system clock", - "homepage": "https://symfony.com", - "keywords": [ - "clock", - "psr20", - "time" - ], - "support": { - "source": "https://github.com/symfony/clock/tree/v6.3.4" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2023-07-31T11:35:03+00:00" - }, - { - "name": "symfony/config", - "version": "v6.3.8", - "source": { - "type": "git", - "url": "https://github.com/symfony/config.git", - "reference": "b7a63887960359e5b59b15826fa9f9be10acbe88" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/config/zipball/b7a63887960359e5b59b15826fa9f9be10acbe88", - "reference": "b7a63887960359e5b59b15826fa9f9be10acbe88", - "shasum": "" - }, - "require": { - "php": ">=8.1", - "symfony/deprecation-contracts": "^2.5|^3", - "symfony/filesystem": "^5.4|^6.0", - "symfony/polyfill-ctype": "~1.8" - }, - "conflict": { - "symfony/finder": "<5.4", - "symfony/service-contracts": "<2.5" - }, - "require-dev": { - "symfony/event-dispatcher": "^5.4|^6.0", - "symfony/finder": "^5.4|^6.0", - "symfony/messenger": "^5.4|^6.0", - "symfony/service-contracts": "^2.5|^3", - "symfony/yaml": "^5.4|^6.0" - }, - "type": "library", - "autoload": { - "psr-4": { - "Symfony\\Component\\Config\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Helps you find, load, combine, autofill and validate configuration values of any kind", - "homepage": "https://symfony.com", - "support": { - "source": "https://github.com/symfony/config/tree/v6.3.8" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2023-11-09T08:28:21+00:00" - }, - { - "name": "symfony/console", - "version": "v6.3.9", - "source": { - "type": "git", - "url": "https://github.com/symfony/console.git", - "reference": "0566dbd051f8648d980592c7849f5d90d2c7c60c" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/0566dbd051f8648d980592c7849f5d90d2c7c60c", - "reference": "0566dbd051f8648d980592c7849f5d90d2c7c60c", - "shasum": "" - }, - "require": { - "php": ">=8.1", - "symfony/deprecation-contracts": "^2.5|^3", - "symfony/polyfill-mbstring": "~1.0", - "symfony/service-contracts": "^2.5|^3", - "symfony/string": "^5.4|^6.0" - }, - "conflict": { - "symfony/dependency-injection": "<5.4", - "symfony/dotenv": "<5.4", - "symfony/event-dispatcher": "<5.4", - "symfony/lock": "<5.4", - "symfony/process": "<5.4" - }, - "provide": { - "psr/log-implementation": "1.0|2.0|3.0" - }, - "require-dev": { - "psr/log": "^1|^2|^3", - "symfony/config": "^5.4|^6.0", - "symfony/dependency-injection": "^5.4|^6.0", - "symfony/event-dispatcher": "^5.4|^6.0", - "symfony/lock": "^5.4|^6.0", - "symfony/process": "^5.4|^6.0", - "symfony/var-dumper": "^5.4|^6.0" - }, - "type": "library", - "autoload": { - "psr-4": { - "Symfony\\Component\\Console\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Eases the creation of beautiful and testable command line interfaces", - "homepage": "https://symfony.com", - "keywords": [ - "cli", - "command-line", - "console", - "terminal" - ], - "support": { - "source": "https://github.com/symfony/console/tree/v6.3.9" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2023-11-20T16:36:29+00:00" - }, - { - "name": "symfony/crowdin-translation-provider", - "version": "v6.3.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/crowdin-translation-provider.git", - "reference": "dea8d5a664780e9c36efc075fa758d435e4ef3a7" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/crowdin-translation-provider/zipball/dea8d5a664780e9c36efc075fa758d435e4ef3a7", - "reference": "dea8d5a664780e9c36efc075fa758d435e4ef3a7", - "shasum": "" - }, - "require": { - "php": ">=8.1", - "symfony/config": "^5.4|^6.0", - "symfony/http-client": "^5.4|^6.0", - "symfony/translation": "^5.4.21|^6.2.7" - }, - "type": "symfony-translation-bridge", - "autoload": { - "psr-4": { - "Symfony\\Component\\Translation\\Bridge\\Crowdin\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Andrii Bodnar", - "homepage": "https://github.com/andrii-bodnar" - }, - { - "name": "Mathieu Santostefano", - "homepage": "https://github.com/welcomattic" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony Crowdin Translation Provider Bridge", - "homepage": "https://symfony.com", - "keywords": [ - "crowdin", - "provider", - "translation" - ], - "support": { - "source": "https://github.com/symfony/crowdin-translation-provider/tree/v6.3.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2023-04-20T13:15:31+00:00" - }, - { - "name": "symfony/dependency-injection", - "version": "v6.3.10", - "source": { - "type": "git", - "url": "https://github.com/symfony/dependency-injection.git", - "reference": "51383a1d9d7e93d5c3c76ddc32672de1b3e82c77" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/51383a1d9d7e93d5c3c76ddc32672de1b3e82c77", - "reference": "51383a1d9d7e93d5c3c76ddc32672de1b3e82c77", - "shasum": "" - }, - "require": { - "php": ">=8.1", - "psr/container": "^1.1|^2.0", - "symfony/deprecation-contracts": "^2.5|^3", - "symfony/service-contracts": "^2.5|^3.0", - "symfony/var-exporter": "^6.2.10" - }, - "conflict": { - "ext-psr": "<1.1|>=2", - "symfony/config": "<6.1", - "symfony/finder": "<5.4", - "symfony/proxy-manager-bridge": "<6.3", - "symfony/yaml": "<5.4" - }, - "provide": { - "psr/container-implementation": "1.1|2.0", - "symfony/service-implementation": "1.1|2.0|3.0" - }, - "require-dev": { - "symfony/config": "^6.1", - "symfony/expression-language": "^5.4|^6.0", - "symfony/yaml": "^5.4|^6.0" - }, - "type": "library", - "autoload": { - "psr-4": { - "Symfony\\Component\\DependencyInjection\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Allows you to standardize and centralize the way objects are constructed in your application", - "homepage": "https://symfony.com", - "support": { - "source": "https://github.com/symfony/dependency-injection/tree/v6.3.10" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2023-12-01T14:25:58+00:00" - }, - { - "name": "symfony/deprecation-contracts", - "version": "v3.4.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/deprecation-contracts.git", - "reference": "7c3aff79d10325257a001fcf92d991f24fc967cf" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/7c3aff79d10325257a001fcf92d991f24fc967cf", - "reference": "7c3aff79d10325257a001fcf92d991f24fc967cf", - "shasum": "" - }, - "require": { - "php": ">=8.1" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "3.4-dev" - }, - "thanks": { - "name": "symfony/contracts", - "url": "https://github.com/symfony/contracts" - } - }, - "autoload": { - "files": [ - "function.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "A generic function and convention to trigger deprecation notices", - "homepage": "https://symfony.com", - "support": { - "source": "https://github.com/symfony/deprecation-contracts/tree/v3.4.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2023-05-23T14:45:45+00:00" - }, - { - "name": "symfony/doctrine-bridge", - "version": "v6.3.8", - "source": { - "type": "git", - "url": "https://github.com/symfony/doctrine-bridge.git", - "reference": "8842d289d41320a0f725e996b4e58d84af398a9e" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/doctrine-bridge/zipball/8842d289d41320a0f725e996b4e58d84af398a9e", - "reference": "8842d289d41320a0f725e996b4e58d84af398a9e", - "shasum": "" - }, - "require": { - "doctrine/event-manager": "^1.2|^2", - "doctrine/persistence": "^2|^3", - "php": ">=8.1", - "symfony/deprecation-contracts": "^2.5|^3", - "symfony/polyfill-ctype": "~1.8", - "symfony/polyfill-mbstring": "~1.0", - "symfony/service-contracts": "^2.5|^3" - }, - "conflict": { - "doctrine/annotations": "<1.13.1", - "doctrine/dbal": "<2.13.1", - "doctrine/lexer": "<1.1", - "doctrine/orm": "<2.12", - "symfony/cache": "<5.4", - "symfony/dependency-injection": "<6.2", - "symfony/form": "<5.4.21|>=6,<6.2.7", - "symfony/http-foundation": "<6.3", - "symfony/http-kernel": "<6.2", - "symfony/lock": "<6.3", - "symfony/messenger": "<5.4", - "symfony/property-info": "<5.4", - "symfony/security-bundle": "<5.4", - "symfony/security-core": "<6.0", - "symfony/validator": "<5.4.25|>=6,<6.2.12|>=6.3,<6.3.1" - }, - "require-dev": { - "doctrine/annotations": "^1.13.1|^2", - "doctrine/collections": "^1.0|^2.0", - "doctrine/data-fixtures": "^1.1", - "doctrine/dbal": "^2.13.1|^3|^4", - "doctrine/orm": "^2.12|^3", - "psr/log": "^1|^2|^3", - "symfony/cache": "^5.4|^6.0", - "symfony/config": "^5.4|^6.0", - "symfony/dependency-injection": "^6.2", - "symfony/doctrine-messenger": "^5.4|^6.0", - "symfony/expression-language": "^5.4|^6.0", - "symfony/form": "^5.4.21|^6.2.7", - "symfony/http-kernel": "^6.3", - "symfony/lock": "^6.3", - "symfony/messenger": "^5.4|^6.0", - "symfony/property-access": "^5.4|^6.0", - "symfony/property-info": "^5.4|^6.0", - "symfony/proxy-manager-bridge": "^5.4|^6.0", - "symfony/security-core": "^6.0", - "symfony/stopwatch": "^5.4|^6.0", - "symfony/translation": "^5.4|^6.0", - "symfony/uid": "^5.4|^6.0", - "symfony/validator": "^5.4.25|~6.2.12|^6.3.1", - "symfony/var-dumper": "^5.4|^6.0" - }, - "type": "symfony-bridge", - "autoload": { - "psr-4": { - "Symfony\\Bridge\\Doctrine\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Provides integration for Doctrine with various Symfony components", - "homepage": "https://symfony.com", - "support": { - "source": "https://github.com/symfony/doctrine-bridge/tree/v6.3.8" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2023-10-31T08:07:48+00:00" - }, - { - "name": "symfony/doctrine-messenger", - "version": "v6.3.10", - "source": { - "type": "git", - "url": "https://github.com/symfony/doctrine-messenger.git", - "reference": "b225f860450a34291bc5983f87d57fb7b9ef18b8" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/doctrine-messenger/zipball/b225f860450a34291bc5983f87d57fb7b9ef18b8", - "reference": "b225f860450a34291bc5983f87d57fb7b9ef18b8", - "shasum": "" - }, - "require": { - "doctrine/dbal": "^2.13|^3|^4", - "php": ">=8.1", - "symfony/messenger": "^5.4|^6.0", - "symfony/service-contracts": "^2.5|^3" - }, - "conflict": { - "doctrine/persistence": "<1.3" - }, - "require-dev": { - "doctrine/persistence": "^1.3|^2|^3", - "symfony/property-access": "^5.4|^6.0", - "symfony/serializer": "^5.4|^6.0" - }, - "type": "symfony-messenger-bridge", - "autoload": { - "psr-4": { - "Symfony\\Component\\Messenger\\Bridge\\Doctrine\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony Doctrine Messenger Bridge", - "homepage": "https://symfony.com", - "support": { - "source": "https://github.com/symfony/doctrine-messenger/tree/v6.3.10" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2023-12-01T09:24:52+00:00" - }, - { - "name": "symfony/dotenv", - "version": "v6.3.7", - "source": { - "type": "git", - "url": "https://github.com/symfony/dotenv.git", - "reference": "7dfbe2976f3c1b7cfa8fac2212a050bfa9bd7d9e" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/dotenv/zipball/7dfbe2976f3c1b7cfa8fac2212a050bfa9bd7d9e", - "reference": "7dfbe2976f3c1b7cfa8fac2212a050bfa9bd7d9e", - "shasum": "" - }, - "require": { - "php": ">=8.1" - }, - "conflict": { - "symfony/console": "<5.4", - "symfony/process": "<5.4" - }, - "require-dev": { - "symfony/console": "^5.4|^6.0", - "symfony/process": "^5.4|^6.0" - }, - "type": "library", - "autoload": { - "psr-4": { - "Symfony\\Component\\Dotenv\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Registers environment variables from a .env file", - "homepage": "https://symfony.com", - "keywords": [ - "dotenv", - "env", - "environment" - ], - "support": { - "source": "https://github.com/symfony/dotenv/tree/v6.3.7" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2023-10-26T18:15:14+00:00" - }, - { - "name": "symfony/error-handler", - "version": "v6.3.5", - "source": { - "type": "git", - "url": "https://github.com/symfony/error-handler.git", - "reference": "1f69476b64fb47105c06beef757766c376b548c4" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/error-handler/zipball/1f69476b64fb47105c06beef757766c376b548c4", - "reference": "1f69476b64fb47105c06beef757766c376b548c4", - "shasum": "" - }, - "require": { - "php": ">=8.1", - "psr/log": "^1|^2|^3", - "symfony/var-dumper": "^5.4|^6.0" - }, - "conflict": { - "symfony/deprecation-contracts": "<2.5" - }, - "require-dev": { - "symfony/deprecation-contracts": "^2.5|^3", - "symfony/http-kernel": "^5.4|^6.0", - "symfony/serializer": "^5.4|^6.0" - }, - "bin": [ - "Resources/bin/patch-type-declarations" - ], - "type": "library", - "autoload": { - "psr-4": { - "Symfony\\Component\\ErrorHandler\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Provides tools to manage errors and ease debugging PHP code", - "homepage": "https://symfony.com", - "support": { - "source": "https://github.com/symfony/error-handler/tree/v6.3.5" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2023-09-12T06:57:20+00:00" - }, - { - "name": "symfony/event-dispatcher", - "version": "v6.3.2", - "source": { - "type": "git", - "url": "https://github.com/symfony/event-dispatcher.git", - "reference": "adb01fe097a4ee930db9258a3cc906b5beb5cf2e" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/adb01fe097a4ee930db9258a3cc906b5beb5cf2e", - "reference": "adb01fe097a4ee930db9258a3cc906b5beb5cf2e", - "shasum": "" - }, - "require": { - "php": ">=8.1", - "symfony/event-dispatcher-contracts": "^2.5|^3" - }, - "conflict": { - "symfony/dependency-injection": "<5.4", - "symfony/service-contracts": "<2.5" - }, - "provide": { - "psr/event-dispatcher-implementation": "1.0", - "symfony/event-dispatcher-implementation": "2.0|3.0" - }, - "require-dev": { - "psr/log": "^1|^2|^3", - "symfony/config": "^5.4|^6.0", - "symfony/dependency-injection": "^5.4|^6.0", - "symfony/error-handler": "^5.4|^6.0", - "symfony/expression-language": "^5.4|^6.0", - "symfony/http-foundation": "^5.4|^6.0", - "symfony/service-contracts": "^2.5|^3", - "symfony/stopwatch": "^5.4|^6.0" - }, - "type": "library", - "autoload": { - "psr-4": { - "Symfony\\Component\\EventDispatcher\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Provides tools that allow your application components to communicate with each other by dispatching events and listening to them", - "homepage": "https://symfony.com", - "support": { - "source": "https://github.com/symfony/event-dispatcher/tree/v6.3.2" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2023-07-06T06:56:43+00:00" - }, - { - "name": "symfony/event-dispatcher-contracts", - "version": "v3.4.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/event-dispatcher-contracts.git", - "reference": "a76aed96a42d2b521153fb382d418e30d18b59df" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/a76aed96a42d2b521153fb382d418e30d18b59df", - "reference": "a76aed96a42d2b521153fb382d418e30d18b59df", - "shasum": "" - }, - "require": { - "php": ">=8.1", - "psr/event-dispatcher": "^1" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "3.4-dev" - }, - "thanks": { - "name": "symfony/contracts", - "url": "https://github.com/symfony/contracts" - } - }, - "autoload": { - "psr-4": { - "Symfony\\Contracts\\EventDispatcher\\": "" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Generic abstractions related to dispatching event", - "homepage": "https://symfony.com", - "keywords": [ - "abstractions", - "contracts", - "decoupling", - "interfaces", - "interoperability", - "standards" - ], - "support": { - "source": "https://github.com/symfony/event-dispatcher-contracts/tree/v3.4.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2023-05-23T14:45:45+00:00" - }, - { - "name": "symfony/expression-language", - "version": "v6.3.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/expression-language.git", - "reference": "6d560c4c80e7e328708efd923f93ad67e6a0c1c0" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/expression-language/zipball/6d560c4c80e7e328708efd923f93ad67e6a0c1c0", - "reference": "6d560c4c80e7e328708efd923f93ad67e6a0c1c0", - "shasum": "" - }, - "require": { - "php": ">=8.1", - "symfony/cache": "^5.4|^6.0", - "symfony/deprecation-contracts": "^2.5|^3", - "symfony/service-contracts": "^2.5|^3" - }, - "type": "library", - "autoload": { - "psr-4": { - "Symfony\\Component\\ExpressionLanguage\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Provides an engine that can compile and evaluate expressions", - "homepage": "https://symfony.com", - "support": { - "source": "https://github.com/symfony/expression-language/tree/v6.3.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2023-04-28T16:05:33+00:00" - }, - { - "name": "symfony/filesystem", - "version": "v6.3.1", - "source": { - "type": "git", - "url": "https://github.com/symfony/filesystem.git", - "reference": "edd36776956f2a6fcf577edb5b05eb0e3bdc52ae" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/filesystem/zipball/edd36776956f2a6fcf577edb5b05eb0e3bdc52ae", - "reference": "edd36776956f2a6fcf577edb5b05eb0e3bdc52ae", - "shasum": "" - }, - "require": { - "php": ">=8.1", - "symfony/polyfill-ctype": "~1.8", - "symfony/polyfill-mbstring": "~1.8" - }, - "type": "library", - "autoload": { - "psr-4": { - "Symfony\\Component\\Filesystem\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Provides basic utilities for the filesystem", - "homepage": "https://symfony.com", - "support": { - "source": "https://github.com/symfony/filesystem/tree/v6.3.1" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2023-06-01T08:30:39+00:00" - }, - { - "name": "symfony/finder", - "version": "v6.3.5", - "source": { - "type": "git", - "url": "https://github.com/symfony/finder.git", - "reference": "a1b31d88c0e998168ca7792f222cbecee47428c4" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/a1b31d88c0e998168ca7792f222cbecee47428c4", - "reference": "a1b31d88c0e998168ca7792f222cbecee47428c4", - "shasum": "" - }, - "require": { - "php": ">=8.1" - }, - "require-dev": { - "symfony/filesystem": "^6.0" - }, - "type": "library", - "autoload": { - "psr-4": { - "Symfony\\Component\\Finder\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Finds files and directories via an intuitive fluent interface", - "homepage": "https://symfony.com", - "support": { - "source": "https://github.com/symfony/finder/tree/v6.3.5" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2023-09-26T12:56:25+00:00" - }, - { - "name": "symfony/flex", - "version": "v2.4.2", - "source": { - "type": "git", - "url": "https://github.com/symfony/flex.git", - "reference": "67ee785f1aedada76461de7a7ec10cd7f8ff8d36" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/flex/zipball/67ee785f1aedada76461de7a7ec10cd7f8ff8d36", - "reference": "67ee785f1aedada76461de7a7ec10cd7f8ff8d36", - "shasum": "" - }, - "require": { - "composer-plugin-api": "^2.1", - "php": ">=8.0" - }, - "require-dev": { - "composer/composer": "^2.1", - "symfony/dotenv": "^5.4|^6.0", - "symfony/filesystem": "^5.4|^6.0", - "symfony/phpunit-bridge": "^5.4|^6.0", - "symfony/process": "^5.4|^6.0" - }, - "type": "composer-plugin", - "extra": { - "class": "Symfony\\Flex\\Flex" - }, - "autoload": { - "psr-4": { - "Symfony\\Flex\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien.potencier@gmail.com" - } - ], - "description": "Composer plugin for Symfony", - "support": { - "issues": "https://github.com/symfony/flex/issues", - "source": "https://github.com/symfony/flex/tree/v2.4.2" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2023-12-05T14:09:35+00:00" - }, - { - "name": "symfony/form", - "version": "v6.3.10", - "source": { - "type": "git", - "url": "https://github.com/symfony/form.git", - "reference": "5afc7334b9d60dd0799612faf3d103b25bc60ae4" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/form/zipball/5afc7334b9d60dd0799612faf3d103b25bc60ae4", - "reference": "5afc7334b9d60dd0799612faf3d103b25bc60ae4", - "shasum": "" - }, - "require": { - "php": ">=8.1", - "symfony/deprecation-contracts": "^2.5|^3", - "symfony/event-dispatcher": "^5.4|^6.0", - "symfony/options-resolver": "^5.4|^6.0", - "symfony/polyfill-ctype": "~1.8", - "symfony/polyfill-intl-icu": "^1.21", - "symfony/polyfill-mbstring": "~1.0", - "symfony/property-access": "^5.4|^6.0", - "symfony/service-contracts": "^2.5|^3" - }, - "conflict": { - "symfony/console": "<5.4", - "symfony/dependency-injection": "<5.4", - "symfony/doctrine-bridge": "<5.4.21|>=6,<6.2.7", - "symfony/error-handler": "<5.4", - "symfony/framework-bundle": "<5.4", - "symfony/http-kernel": "<5.4", - "symfony/translation": "<5.4", - "symfony/translation-contracts": "<2.5", - "symfony/twig-bridge": "<6.3" - }, - "require-dev": { - "doctrine/collections": "^1.0|^2.0", - "symfony/config": "^5.4|^6.0", - "symfony/console": "^5.4|^6.0", - "symfony/dependency-injection": "^5.4|^6.0", - "symfony/expression-language": "^5.4|^6.0", - "symfony/html-sanitizer": "^6.1", - "symfony/http-foundation": "^5.4|^6.0", - "symfony/http-kernel": "^5.4|^6.0", - "symfony/intl": "^5.4|^6.0", - "symfony/security-core": "^6.2", - "symfony/security-csrf": "^5.4|^6.0", - "symfony/translation": "^5.4|^6.0", - "symfony/uid": "^5.4|^6.0", - "symfony/validator": "^5.4|^6.0", - "symfony/var-dumper": "^5.4|^6.0" - }, - "type": "library", - "autoload": { - "psr-4": { - "Symfony\\Component\\Form\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Allows to easily create, process and reuse HTML forms", - "homepage": "https://symfony.com", - "support": { - "source": "https://github.com/symfony/form/tree/v6.3.10" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2023-11-30T11:08:22+00:00" - }, - { - "name": "symfony/framework-bundle", - "version": "v6.3.9", - "source": { - "type": "git", - "url": "https://github.com/symfony/framework-bundle.git", - "reference": "f83d20092e98c3ae8b5874b8f0787546c5c61cda" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/framework-bundle/zipball/f83d20092e98c3ae8b5874b8f0787546c5c61cda", - "reference": "f83d20092e98c3ae8b5874b8f0787546c5c61cda", - "shasum": "" - }, - "require": { - "composer-runtime-api": ">=2.1", - "ext-xml": "*", - "php": ">=8.1", - "symfony/cache": "^5.4|^6.0", - "symfony/config": "^6.1", - "symfony/dependency-injection": "^6.3.1", - "symfony/deprecation-contracts": "^2.5|^3", - "symfony/error-handler": "^6.1", - "symfony/event-dispatcher": "^5.4|^6.0", - "symfony/filesystem": "^5.4|^6.0", - "symfony/finder": "^5.4|^6.0", - "symfony/http-foundation": "^6.3", - "symfony/http-kernel": "^6.3", - "symfony/polyfill-mbstring": "~1.0", - "symfony/routing": "^5.4|^6.0" - }, - "conflict": { - "doctrine/annotations": "<1.13.1", - "doctrine/persistence": "<1.3", - "phpdocumentor/reflection-docblock": "<3.2.2", - "phpdocumentor/type-resolver": "<1.4.0", - "symfony/asset": "<5.4", - "symfony/clock": "<6.3", - "symfony/console": "<5.4", - "symfony/dom-crawler": "<6.3", - "symfony/dotenv": "<5.4", - "symfony/form": "<5.4", - "symfony/http-client": "<6.3", - "symfony/lock": "<5.4", - "symfony/mailer": "<5.4", - "symfony/messenger": "<6.3", - "symfony/mime": "<6.2", - "symfony/property-access": "<5.4", - "symfony/property-info": "<5.4", - "symfony/security-core": "<5.4", - "symfony/security-csrf": "<5.4", - "symfony/serializer": "<6.3", - "symfony/stopwatch": "<5.4", - "symfony/translation": "<6.2.8", - "symfony/twig-bridge": "<5.4", - "symfony/twig-bundle": "<5.4", - "symfony/validator": "<6.3", - "symfony/web-profiler-bundle": "<5.4", - "symfony/workflow": "<5.4" - }, - "require-dev": { - "doctrine/annotations": "^1.13.1|^2", - "doctrine/persistence": "^1.3|^2|^3", - "phpdocumentor/reflection-docblock": "^3.0|^4.0|^5.0", - "symfony/asset": "^5.4|^6.0", - "symfony/asset-mapper": "^6.3", - "symfony/browser-kit": "^5.4|^6.0", - "symfony/clock": "^6.2", - "symfony/console": "^5.4.9|^6.0.9", - "symfony/css-selector": "^5.4|^6.0", - "symfony/dom-crawler": "^6.3", - "symfony/dotenv": "^5.4|^6.0", - "symfony/expression-language": "^5.4|^6.0", - "symfony/form": "^5.4|^6.0", - "symfony/html-sanitizer": "^6.1", - "symfony/http-client": "^6.3", - "symfony/lock": "^5.4|^6.0", - "symfony/mailer": "^5.4|^6.0", - "symfony/messenger": "^6.3", - "symfony/mime": "^6.2", - "symfony/notifier": "^5.4|^6.0", - "symfony/polyfill-intl-icu": "~1.0", - "symfony/process": "^5.4|^6.0", - "symfony/property-info": "^5.4|^6.0", - "symfony/rate-limiter": "^5.4|^6.0", - "symfony/scheduler": "^6.3", - "symfony/security-bundle": "^5.4|^6.0", - "symfony/semaphore": "^5.4|^6.0", - "symfony/serializer": "^6.3", - "symfony/stopwatch": "^5.4|^6.0", - "symfony/string": "^5.4|^6.0", - "symfony/translation": "^6.2.8", - "symfony/twig-bundle": "^5.4|^6.0", - "symfony/uid": "^5.4|^6.0", - "symfony/validator": "^6.3", - "symfony/web-link": "^5.4|^6.0", - "symfony/workflow": "^5.4|^6.0", - "symfony/yaml": "^5.4|^6.0", - "twig/twig": "^2.10|^3.0" - }, - "type": "symfony-bundle", - "autoload": { - "psr-4": { - "Symfony\\Bundle\\FrameworkBundle\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Provides a tight integration between Symfony components and the Symfony full-stack framework", - "homepage": "https://symfony.com", - "support": { - "source": "https://github.com/symfony/framework-bundle/tree/v6.3.9" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2023-11-24T10:25:33+00:00" - }, - { - "name": "symfony/http-client", - "version": "v6.3.8", - "source": { - "type": "git", - "url": "https://github.com/symfony/http-client.git", - "reference": "0314e2d49939a9831929d6fc81c01c6df137fd0a" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/http-client/zipball/0314e2d49939a9831929d6fc81c01c6df137fd0a", - "reference": "0314e2d49939a9831929d6fc81c01c6df137fd0a", - "shasum": "" - }, - "require": { - "php": ">=8.1", - "psr/log": "^1|^2|^3", - "symfony/deprecation-contracts": "^2.5|^3", - "symfony/http-client-contracts": "^3", - "symfony/service-contracts": "^2.5|^3" - }, - "conflict": { - "php-http/discovery": "<1.15", - "symfony/http-foundation": "<6.3" - }, - "provide": { - "php-http/async-client-implementation": "*", - "php-http/client-implementation": "*", - "psr/http-client-implementation": "1.0", - "symfony/http-client-implementation": "3.0" - }, - "require-dev": { - "amphp/amp": "^2.5", - "amphp/http-client": "^4.2.1", - "amphp/http-tunnel": "^1.0", - "amphp/socket": "^1.1", - "guzzlehttp/promises": "^1.4", - "nyholm/psr7": "^1.0", - "php-http/httplug": "^1.0|^2.0", - "psr/http-client": "^1.0", - "symfony/dependency-injection": "^5.4|^6.0", - "symfony/http-kernel": "^5.4|^6.0", - "symfony/process": "^5.4|^6.0", - "symfony/stopwatch": "^5.4|^6.0" - }, - "type": "library", - "autoload": { - "psr-4": { - "Symfony\\Component\\HttpClient\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Provides powerful methods to fetch HTTP resources synchronously or asynchronously", - "homepage": "https://symfony.com", - "keywords": [ - "http" - ], - "support": { - "source": "https://github.com/symfony/http-client/tree/v6.3.8" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2023-11-06T18:31:59+00:00" - }, - { - "name": "symfony/http-client-contracts", - "version": "v3.4.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/http-client-contracts.git", - "reference": "1ee70e699b41909c209a0c930f11034b93578654" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/http-client-contracts/zipball/1ee70e699b41909c209a0c930f11034b93578654", - "reference": "1ee70e699b41909c209a0c930f11034b93578654", - "shasum": "" - }, - "require": { - "php": ">=8.1" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "3.4-dev" - }, - "thanks": { - "name": "symfony/contracts", - "url": "https://github.com/symfony/contracts" - } - }, - "autoload": { - "psr-4": { - "Symfony\\Contracts\\HttpClient\\": "" - }, - "exclude-from-classmap": [ - "/Test/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Generic abstractions related to HTTP clients", - "homepage": "https://symfony.com", - "keywords": [ - "abstractions", - "contracts", - "decoupling", - "interfaces", - "interoperability", - "standards" - ], - "support": { - "source": "https://github.com/symfony/http-client-contracts/tree/v3.4.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2023-07-30T20:28:31+00:00" - }, - { - "name": "symfony/http-foundation", - "version": "v6.3.9", - "source": { - "type": "git", - "url": "https://github.com/symfony/http-foundation.git", - "reference": "49a04fd3a21edc9ce503ab78e9f342805fefe780" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/http-foundation/zipball/49a04fd3a21edc9ce503ab78e9f342805fefe780", - "reference": "49a04fd3a21edc9ce503ab78e9f342805fefe780", - "shasum": "" - }, - "require": { - "php": ">=8.1", - "symfony/deprecation-contracts": "^2.5|^3", - "symfony/polyfill-mbstring": "~1.1", - "symfony/polyfill-php83": "^1.27" - }, - "conflict": { - "symfony/cache": "<6.3" - }, - "require-dev": { - "doctrine/dbal": "^2.13.1|^3|^4", - "predis/predis": "^1.1|^2.0", - "symfony/cache": "^6.3", - "symfony/dependency-injection": "^5.4|^6.0", - "symfony/expression-language": "^5.4|^6.0", - "symfony/http-kernel": "^5.4.12|^6.0.12|^6.1.4", - "symfony/mime": "^5.4|^6.0", - "symfony/rate-limiter": "^5.2|^6.0" - }, - "type": "library", - "autoload": { - "psr-4": { - "Symfony\\Component\\HttpFoundation\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Defines an object-oriented layer for the HTTP specification", - "homepage": "https://symfony.com", - "support": { - "source": "https://github.com/symfony/http-foundation/tree/v6.3.9" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2023-11-20T16:36:29+00:00" - }, - { - "name": "symfony/http-kernel", - "version": "v6.3.10", - "source": { - "type": "git", - "url": "https://github.com/symfony/http-kernel.git", - "reference": "8d8e7aa60593fd0a2e3c1cea08cc687314841b61" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/http-kernel/zipball/8d8e7aa60593fd0a2e3c1cea08cc687314841b61", - "reference": "8d8e7aa60593fd0a2e3c1cea08cc687314841b61", - "shasum": "" - }, - "require": { - "php": ">=8.1", - "psr/log": "^1|^2|^3", - "symfony/deprecation-contracts": "^2.5|^3", - "symfony/error-handler": "^6.3", - "symfony/event-dispatcher": "^5.4|^6.0", - "symfony/http-foundation": "^6.3.4", - "symfony/polyfill-ctype": "^1.8" - }, - "conflict": { - "symfony/browser-kit": "<5.4", - "symfony/cache": "<5.4", - "symfony/config": "<6.1", - "symfony/console": "<5.4", - "symfony/dependency-injection": "<6.3.4", - "symfony/doctrine-bridge": "<5.4", - "symfony/form": "<5.4", - "symfony/http-client": "<5.4", - "symfony/http-client-contracts": "<2.5", - "symfony/mailer": "<5.4", - "symfony/messenger": "<5.4", - "symfony/translation": "<5.4", - "symfony/translation-contracts": "<2.5", - "symfony/twig-bridge": "<5.4", - "symfony/validator": "<5.4", - "symfony/var-dumper": "<6.3", - "twig/twig": "<2.13" - }, - "provide": { - "psr/log-implementation": "1.0|2.0|3.0" - }, - "require-dev": { - "psr/cache": "^1.0|^2.0|^3.0", - "symfony/browser-kit": "^5.4|^6.0", - "symfony/clock": "^6.2", - "symfony/config": "^6.1", - "symfony/console": "^5.4|^6.0", - "symfony/css-selector": "^5.4|^6.0", - "symfony/dependency-injection": "^6.3.4", - "symfony/dom-crawler": "^5.4|^6.0", - "symfony/expression-language": "^5.4|^6.0", - "symfony/finder": "^5.4|^6.0", - "symfony/http-client-contracts": "^2.5|^3", - "symfony/process": "^5.4|^6.0", - "symfony/property-access": "^5.4.5|^6.0.5", - "symfony/routing": "^5.4|^6.0", - "symfony/serializer": "^6.3", - "symfony/stopwatch": "^5.4|^6.0", - "symfony/translation": "^5.4|^6.0", - "symfony/translation-contracts": "^2.5|^3", - "symfony/uid": "^5.4|^6.0", - "symfony/validator": "^6.3", - "symfony/var-exporter": "^6.2", - "twig/twig": "^2.13|^3.0.4" - }, - "type": "library", - "autoload": { - "psr-4": { - "Symfony\\Component\\HttpKernel\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Provides a structured process for converting a Request into a Response", - "homepage": "https://symfony.com", - "support": { - "source": "https://github.com/symfony/http-kernel/tree/v6.3.10" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2023-12-01T16:57:27+00:00" - }, - { - "name": "symfony/intl", - "version": "v6.3.7", - "source": { - "type": "git", - "url": "https://github.com/symfony/intl.git", - "reference": "4cc98c05f2c55150a6aa5b3e20667f7a6d06cca9" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/intl/zipball/4cc98c05f2c55150a6aa5b3e20667f7a6d06cca9", - "reference": "4cc98c05f2c55150a6aa5b3e20667f7a6d06cca9", - "shasum": "" - }, - "require": { - "php": ">=8.1" - }, - "require-dev": { - "symfony/filesystem": "^5.4|^6.0", - "symfony/finder": "^5.4|^6.0", - "symfony/var-exporter": "^5.4|^6.0" - }, - "type": "library", - "autoload": { - "psr-4": { - "Symfony\\Component\\Intl\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Bernhard Schussek", - "email": "bschussek@gmail.com" - }, - { - "name": "Eriksen Costa", - "email": "eriksen.costa@infranology.com.br" - }, - { - "name": "Igor Wiedler", - "email": "igor@wiedler.ch" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Provides access to the localization data of the ICU library", - "homepage": "https://symfony.com", - "keywords": [ - "i18n", - "icu", - "internationalization", - "intl", - "l10n", - "localization" - ], - "support": { - "source": "https://github.com/symfony/intl/tree/v6.3.7" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2023-10-28T23:11:45+00:00" - }, - { - "name": "symfony/mailer", - "version": "v6.3.5", - "source": { - "type": "git", - "url": "https://github.com/symfony/mailer.git", - "reference": "d89611a7830d51b5e118bca38e390dea92f9ea06" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/mailer/zipball/d89611a7830d51b5e118bca38e390dea92f9ea06", - "reference": "d89611a7830d51b5e118bca38e390dea92f9ea06", - "shasum": "" - }, - "require": { - "egulias/email-validator": "^2.1.10|^3|^4", - "php": ">=8.1", - "psr/event-dispatcher": "^1", - "psr/log": "^1|^2|^3", - "symfony/event-dispatcher": "^5.4|^6.0", - "symfony/mime": "^6.2", - "symfony/service-contracts": "^2.5|^3" - }, - "conflict": { - "symfony/http-client-contracts": "<2.5", - "symfony/http-kernel": "<5.4", - "symfony/messenger": "<6.2", - "symfony/mime": "<6.2", - "symfony/twig-bridge": "<6.2.1" - }, - "require-dev": { - "symfony/console": "^5.4|^6.0", - "symfony/http-client": "^5.4|^6.0", - "symfony/messenger": "^6.2", - "symfony/twig-bridge": "^6.2" - }, - "type": "library", - "autoload": { - "psr-4": { - "Symfony\\Component\\Mailer\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Helps sending emails", - "homepage": "https://symfony.com", - "support": { - "source": "https://github.com/symfony/mailer/tree/v6.3.5" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2023-09-06T09:47:15+00:00" - }, - { - "name": "symfony/messenger", - "version": "v6.3.9", - "source": { - "type": "git", - "url": "https://github.com/symfony/messenger.git", - "reference": "096b151f955d5ac56cc61a3ca0e16b38ff093805" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/messenger/zipball/096b151f955d5ac56cc61a3ca0e16b38ff093805", - "reference": "096b151f955d5ac56cc61a3ca0e16b38ff093805", - "shasum": "" - }, - "require": { - "php": ">=8.1", - "psr/log": "^1|^2|^3", - "symfony/clock": "^6.3", - "symfony/deprecation-contracts": "^2.5|^3" - }, - "conflict": { - "symfony/console": "<6.3", - "symfony/event-dispatcher": "<5.4", - "symfony/event-dispatcher-contracts": "<2.5", - "symfony/framework-bundle": "<5.4", - "symfony/http-kernel": "<5.4", - "symfony/serializer": "<5.4" - }, - "require-dev": { - "psr/cache": "^1.0|^2.0|^3.0", - "symfony/console": "^6.3", - "symfony/dependency-injection": "^5.4|^6.0", - "symfony/event-dispatcher": "^5.4|^6.0", - "symfony/http-kernel": "^5.4|^6.0", - "symfony/process": "^5.4|^6.0", - "symfony/property-access": "^5.4|^6.0", - "symfony/rate-limiter": "^5.4|^6.0", - "symfony/routing": "^5.4|^6.0", - "symfony/serializer": "^5.4|^6.0", - "symfony/service-contracts": "^2.5|^3", - "symfony/stopwatch": "^5.4|^6.0", - "symfony/validator": "^5.4|^6.0" - }, - "type": "library", - "autoload": { - "psr-4": { - "Symfony\\Component\\Messenger\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Samuel Roze", - "email": "samuel.roze@gmail.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Helps applications send and receive messages to/from other applications or via message queues", - "homepage": "https://symfony.com", - "support": { - "source": "https://github.com/symfony/messenger/tree/v6.3.9" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2023-11-22T19:13:10+00:00" - }, - { - "name": "symfony/mime", - "version": "v6.3.5", - "source": { - "type": "git", - "url": "https://github.com/symfony/mime.git", - "reference": "d5179eedf1cb2946dbd760475ebf05c251ef6a6e" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/mime/zipball/d5179eedf1cb2946dbd760475ebf05c251ef6a6e", - "reference": "d5179eedf1cb2946dbd760475ebf05c251ef6a6e", - "shasum": "" - }, - "require": { - "php": ">=8.1", - "symfony/deprecation-contracts": "^2.5|^3", - "symfony/polyfill-intl-idn": "^1.10", - "symfony/polyfill-mbstring": "^1.0" - }, - "conflict": { - "egulias/email-validator": "~3.0.0", - "phpdocumentor/reflection-docblock": "<3.2.2", - "phpdocumentor/type-resolver": "<1.4.0", - "symfony/mailer": "<5.4", - "symfony/serializer": "<6.2.13|>=6.3,<6.3.2" - }, - "require-dev": { - "egulias/email-validator": "^2.1.10|^3.1|^4", - "league/html-to-markdown": "^5.0", - "phpdocumentor/reflection-docblock": "^3.0|^4.0|^5.0", - "symfony/dependency-injection": "^5.4|^6.0", - "symfony/property-access": "^5.4|^6.0", - "symfony/property-info": "^5.4|^6.0", - "symfony/serializer": "~6.2.13|^6.3.2" - }, - "type": "library", - "autoload": { - "psr-4": { - "Symfony\\Component\\Mime\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Allows manipulating MIME messages", - "homepage": "https://symfony.com", - "keywords": [ - "mime", - "mime-type" - ], - "support": { - "source": "https://github.com/symfony/mime/tree/v6.3.5" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2023-09-29T06:59:36+00:00" - }, - { - "name": "symfony/monolog-bridge", - "version": "v6.3.8", - "source": { - "type": "git", - "url": "https://github.com/symfony/monolog-bridge.git", - "reference": "2bbfc8bd9d6f966b69eda20c66762580a0410c78" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/monolog-bridge/zipball/2bbfc8bd9d6f966b69eda20c66762580a0410c78", - "reference": "2bbfc8bd9d6f966b69eda20c66762580a0410c78", - "shasum": "" - }, - "require": { - "monolog/monolog": "^1.25.1|^2|^3", - "php": ">=8.1", - "symfony/http-kernel": "^5.4|^6.0", - "symfony/service-contracts": "^2.5|^3" - }, - "conflict": { - "symfony/console": "<5.4", - "symfony/http-foundation": "<5.4", - "symfony/security-core": "<6.0" - }, - "require-dev": { - "symfony/console": "^5.4|^6.0", - "symfony/http-client": "^5.4|^6.0", - "symfony/mailer": "^5.4|^6.0", - "symfony/messenger": "^5.4|^6.0", - "symfony/mime": "^5.4|^6.0", - "symfony/security-core": "^6.0", - "symfony/var-dumper": "^5.4|^6.0" - }, - "type": "symfony-bridge", - "autoload": { - "psr-4": { - "Symfony\\Bridge\\Monolog\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Provides integration for Monolog with various Symfony components", - "homepage": "https://symfony.com", - "support": { - "source": "https://github.com/symfony/monolog-bridge/tree/v6.3.8" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2023-10-31T08:07:48+00:00" - }, - { - "name": "symfony/monolog-bundle", - "version": "v3.10.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/monolog-bundle.git", - "reference": "414f951743f4aa1fd0f5bf6a0e9c16af3fe7f181" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/monolog-bundle/zipball/414f951743f4aa1fd0f5bf6a0e9c16af3fe7f181", - "reference": "414f951743f4aa1fd0f5bf6a0e9c16af3fe7f181", - "shasum": "" - }, - "require": { - "monolog/monolog": "^1.25.1 || ^2.0 || ^3.0", - "php": ">=7.2.5", - "symfony/config": "^5.4 || ^6.0 || ^7.0", - "symfony/dependency-injection": "^5.4 || ^6.0 || ^7.0", - "symfony/http-kernel": "^5.4 || ^6.0 || ^7.0", - "symfony/monolog-bridge": "^5.4 || ^6.0 || ^7.0" - }, - "require-dev": { - "symfony/console": "^5.4 || ^6.0 || ^7.0", - "symfony/phpunit-bridge": "^6.3 || ^7.0", - "symfony/yaml": "^5.4 || ^6.0 || ^7.0" - }, - "type": "symfony-bundle", - "extra": { - "branch-alias": { - "dev-master": "3.x-dev" - } - }, - "autoload": { - "psr-4": { - "Symfony\\Bundle\\MonologBundle\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony MonologBundle", - "homepage": "https://symfony.com", - "keywords": [ - "log", - "logging" - ], - "support": { - "issues": "https://github.com/symfony/monolog-bundle/issues", - "source": "https://github.com/symfony/monolog-bundle/tree/v3.10.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2023-11-06T17:08:13+00:00" - }, - { - "name": "symfony/notifier", - "version": "v6.3.6", - "source": { - "type": "git", - "url": "https://github.com/symfony/notifier.git", - "reference": "2e39d4a9a96e25d127ffe30171127f6ef73934df" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/notifier/zipball/2e39d4a9a96e25d127ffe30171127f6ef73934df", - "reference": "2e39d4a9a96e25d127ffe30171127f6ef73934df", - "shasum": "" - }, - "require": { - "php": ">=8.1", - "psr/log": "^1|^2|^3" - }, - "conflict": { - "symfony/event-dispatcher": "<5.4", - "symfony/event-dispatcher-contracts": "<2.5", - "symfony/http-client-contracts": "<2.5", - "symfony/http-kernel": "<5.4" - }, - "require-dev": { - "symfony/event-dispatcher-contracts": "^2.5|^3", - "symfony/http-client-contracts": "^2.5|^3", - "symfony/http-foundation": "^5.4|^6.0", - "symfony/messenger": "^5.4|^6.0" - }, - "type": "library", - "autoload": { - "psr-4": { - "Symfony\\Component\\Notifier\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Sends notifications via one or more channels (email, SMS, ...)", - "homepage": "https://symfony.com", - "keywords": [ - "notification", - "notifier" - ], - "support": { - "source": "https://github.com/symfony/notifier/tree/v6.3.6" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2023-10-07T07:32:05+00:00" - }, - { - "name": "symfony/options-resolver", - "version": "v6.3.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/options-resolver.git", - "reference": "a10f19f5198d589d5c33333cffe98dc9820332dd" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/options-resolver/zipball/a10f19f5198d589d5c33333cffe98dc9820332dd", - "reference": "a10f19f5198d589d5c33333cffe98dc9820332dd", - "shasum": "" - }, - "require": { - "php": ">=8.1", - "symfony/deprecation-contracts": "^2.5|^3" - }, - "type": "library", - "autoload": { - "psr-4": { - "Symfony\\Component\\OptionsResolver\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Provides an improved replacement for the array_replace PHP function", - "homepage": "https://symfony.com", - "keywords": [ - "config", - "configuration", - "options" - ], - "support": { - "source": "https://github.com/symfony/options-resolver/tree/v6.3.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2023-05-12T14:21:09+00:00" - }, - { - "name": "symfony/password-hasher", - "version": "v6.3.8", - "source": { - "type": "git", - "url": "https://github.com/symfony/password-hasher.git", - "reference": "82161c4bebf77900372083ec6e484b5f055b0cba" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/password-hasher/zipball/82161c4bebf77900372083ec6e484b5f055b0cba", - "reference": "82161c4bebf77900372083ec6e484b5f055b0cba", - "shasum": "" - }, - "require": { - "php": ">=8.1" - }, - "conflict": { - "symfony/security-core": "<5.4" - }, - "require-dev": { - "symfony/console": "^5.4|^6.0", - "symfony/security-core": "^5.4|^6.0" - }, - "type": "library", - "autoload": { - "psr-4": { - "Symfony\\Component\\PasswordHasher\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Robin Chalas", - "email": "robin.chalas@gmail.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Provides password hashing utilities", - "homepage": "https://symfony.com", - "keywords": [ - "hashing", - "password" - ], - "support": { - "source": "https://github.com/symfony/password-hasher/tree/v6.3.8" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2023-11-06T10:58:05+00:00" - }, - { - "name": "symfony/polyfill-intl-grapheme", - "version": "v1.28.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-intl-grapheme.git", - "reference": "875e90aeea2777b6f135677f618529449334a612" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/875e90aeea2777b6f135677f618529449334a612", - "reference": "875e90aeea2777b6f135677f618529449334a612", - "shasum": "" - }, - "require": { - "php": ">=7.1" - }, - "suggest": { - "ext-intl": "For best performance" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "1.28-dev" - }, - "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" - } - }, - "autoload": { - "files": [ - "bootstrap.php" - ], - "psr-4": { - "Symfony\\Polyfill\\Intl\\Grapheme\\": "" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony polyfill for intl's grapheme_* functions", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "grapheme", - "intl", - "polyfill", - "portable", - "shim" - ], - "support": { - "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.28.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2023-01-26T09:26:14+00:00" - }, - { - "name": "symfony/polyfill-intl-icu", - "version": "v1.28.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-intl-icu.git", - "reference": "e46b4da57951a16053cd751f63f4a24292788157" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-icu/zipball/e46b4da57951a16053cd751f63f4a24292788157", - "reference": "e46b4da57951a16053cd751f63f4a24292788157", - "shasum": "" - }, - "require": { - "php": ">=7.1" - }, - "suggest": { - "ext-intl": "For best performance and support of other locales than \"en\"" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "1.28-dev" - }, - "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" - } - }, - "autoload": { - "files": [ - "bootstrap.php" - ], - "psr-4": { - "Symfony\\Polyfill\\Intl\\Icu\\": "" - }, - "classmap": [ - "Resources/stubs" - ], - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony polyfill for intl's ICU-related data and classes", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "icu", - "intl", - "polyfill", - "portable", - "shim" - ], - "support": { - "source": "https://github.com/symfony/polyfill-intl-icu/tree/v1.28.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2023-03-21T17:27:24+00:00" - }, - { - "name": "symfony/polyfill-intl-idn", - "version": "v1.28.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-intl-idn.git", - "reference": "ecaafce9f77234a6a449d29e49267ba10499116d" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-idn/zipball/ecaafce9f77234a6a449d29e49267ba10499116d", - "reference": "ecaafce9f77234a6a449d29e49267ba10499116d", - "shasum": "" - }, - "require": { - "php": ">=7.1", - "symfony/polyfill-intl-normalizer": "^1.10", - "symfony/polyfill-php72": "^1.10" - }, - "suggest": { - "ext-intl": "For best performance" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "1.28-dev" - }, - "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" - } - }, - "autoload": { - "files": [ - "bootstrap.php" - ], - "psr-4": { - "Symfony\\Polyfill\\Intl\\Idn\\": "" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Laurent Bassin", - "email": "laurent@bassin.info" - }, - { - "name": "Trevor Rowbotham", - "email": "trevor.rowbotham@pm.me" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony polyfill for intl's idn_to_ascii and idn_to_utf8 functions", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "idn", - "intl", - "polyfill", - "portable", - "shim" - ], - "support": { - "source": "https://github.com/symfony/polyfill-intl-idn/tree/v1.28.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2023-01-26T09:30:37+00:00" - }, - { - "name": "symfony/polyfill-intl-normalizer", - "version": "v1.28.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-intl-normalizer.git", - "reference": "8c4ad05dd0120b6a53c1ca374dca2ad0a1c4ed92" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/8c4ad05dd0120b6a53c1ca374dca2ad0a1c4ed92", - "reference": "8c4ad05dd0120b6a53c1ca374dca2ad0a1c4ed92", - "shasum": "" - }, - "require": { - "php": ">=7.1" - }, - "suggest": { - "ext-intl": "For best performance" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "1.28-dev" - }, - "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" - } - }, - "autoload": { - "files": [ - "bootstrap.php" - ], - "psr-4": { - "Symfony\\Polyfill\\Intl\\Normalizer\\": "" - }, - "classmap": [ - "Resources/stubs" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony polyfill for intl's Normalizer class and related functions", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "intl", - "normalizer", - "polyfill", - "portable", - "shim" - ], - "support": { - "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.28.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2023-01-26T09:26:14+00:00" - }, - { - "name": "symfony/polyfill-mbstring", - "version": "v1.28.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "42292d99c55abe617799667f454222c54c60e229" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/42292d99c55abe617799667f454222c54c60e229", - "reference": "42292d99c55abe617799667f454222c54c60e229", - "shasum": "" - }, - "require": { - "php": ">=7.1" - }, - "provide": { - "ext-mbstring": "*" - }, - "suggest": { - "ext-mbstring": "For best performance" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "1.28-dev" - }, - "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" - } - }, - "autoload": { - "files": [ - "bootstrap.php" - ], - "psr-4": { - "Symfony\\Polyfill\\Mbstring\\": "" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony polyfill for the Mbstring extension", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "mbstring", - "polyfill", - "portable", - "shim" - ], - "support": { - "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.28.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2023-07-28T09:04:16+00:00" - }, - { - "name": "symfony/polyfill-php83", - "version": "v1.28.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-php83.git", - "reference": "b0f46ebbeeeda3e9d2faebdfbf4b4eae9b59fa11" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php83/zipball/b0f46ebbeeeda3e9d2faebdfbf4b4eae9b59fa11", - "reference": "b0f46ebbeeeda3e9d2faebdfbf4b4eae9b59fa11", - "shasum": "" - }, - "require": { - "php": ">=7.1", - "symfony/polyfill-php80": "^1.14" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "1.28-dev" - }, - "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" - } - }, - "autoload": { - "files": [ - "bootstrap.php" - ], - "psr-4": { - "Symfony\\Polyfill\\Php83\\": "" - }, - "classmap": [ - "Resources/stubs" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony polyfill backporting some PHP 8.3+ features to lower PHP versions", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "polyfill", - "portable", - "shim" - ], - "support": { - "source": "https://github.com/symfony/polyfill-php83/tree/v1.28.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2023-08-16T06:22:46+00:00" - }, - { - "name": "symfony/process", - "version": "v6.3.4", - "source": { - "type": "git", - "url": "https://github.com/symfony/process.git", - "reference": "0b5c29118f2e980d455d2e34a5659f4579847c54" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/0b5c29118f2e980d455d2e34a5659f4579847c54", - "reference": "0b5c29118f2e980d455d2e34a5659f4579847c54", - "shasum": "" - }, - "require": { - "php": ">=8.1" - }, - "type": "library", - "autoload": { - "psr-4": { - "Symfony\\Component\\Process\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Executes commands in sub-processes", - "homepage": "https://symfony.com", - "support": { - "source": "https://github.com/symfony/process/tree/v6.3.4" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2023-08-07T10:39:22+00:00" - }, - { - "name": "symfony/property-access", - "version": "v6.3.2", - "source": { - "type": "git", - "url": "https://github.com/symfony/property-access.git", - "reference": "2dc4f9da444b8f8ff592e95d570caad67924f1d0" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/property-access/zipball/2dc4f9da444b8f8ff592e95d570caad67924f1d0", - "reference": "2dc4f9da444b8f8ff592e95d570caad67924f1d0", - "shasum": "" - }, - "require": { - "php": ">=8.1", - "symfony/deprecation-contracts": "^2.5|^3", - "symfony/property-info": "^5.4|^6.0" - }, - "require-dev": { - "symfony/cache": "^5.4|^6.0" - }, - "type": "library", - "autoload": { - "psr-4": { - "Symfony\\Component\\PropertyAccess\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Provides functions to read and write from/to an object or array using a simple string notation", - "homepage": "https://symfony.com", - "keywords": [ - "access", - "array", - "extraction", - "index", - "injection", - "object", - "property", - "property-path", - "reflection" - ], - "support": { - "source": "https://github.com/symfony/property-access/tree/v6.3.2" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2023-07-13T15:26:11+00:00" - }, - { - "name": "symfony/property-info", - "version": "v6.3.9", - "source": { - "type": "git", - "url": "https://github.com/symfony/property-info.git", - "reference": "664ae7ad443d7cc591ff3e15496b954e4cefe729" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/property-info/zipball/664ae7ad443d7cc591ff3e15496b954e4cefe729", - "reference": "664ae7ad443d7cc591ff3e15496b954e4cefe729", - "shasum": "" - }, - "require": { - "php": ">=8.1", - "symfony/string": "^5.4|^6.0" - }, - "conflict": { - "phpdocumentor/reflection-docblock": "<5.2", - "phpdocumentor/type-resolver": "<1.5.1", - "symfony/dependency-injection": "<5.4" - }, - "require-dev": { - "doctrine/annotations": "^1.10.4|^2", - "phpdocumentor/reflection-docblock": "^5.2", - "phpstan/phpdoc-parser": "^1.0", - "symfony/cache": "^5.4|^6.0", - "symfony/dependency-injection": "^5.4|^6.0", - "symfony/serializer": "^5.4|^6.0" - }, - "type": "library", - "autoload": { - "psr-4": { - "Symfony\\Component\\PropertyInfo\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Kévin Dunglas", - "email": "dunglas@gmail.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Extracts information about PHP class' properties using metadata of popular sources", - "homepage": "https://symfony.com", - "keywords": [ - "doctrine", - "phpdoc", - "property", - "symfony", - "type", - "validator" - ], - "support": { - "source": "https://github.com/symfony/property-info/tree/v6.3.9" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2023-11-24T11:57:32+00:00" - }, - { - "name": "symfony/routing", - "version": "v6.3.10", - "source": { - "type": "git", - "url": "https://github.com/symfony/routing.git", - "reference": "cb7404232d49dd11cc971b832fcbd49e7c22b049" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/routing/zipball/cb7404232d49dd11cc971b832fcbd49e7c22b049", - "reference": "cb7404232d49dd11cc971b832fcbd49e7c22b049", - "shasum": "" - }, - "require": { - "php": ">=8.1", - "symfony/deprecation-contracts": "^2.5|^3" - }, - "conflict": { - "doctrine/annotations": "<1.12", - "symfony/config": "<6.2", - "symfony/dependency-injection": "<5.4", - "symfony/yaml": "<5.4" - }, - "require-dev": { - "doctrine/annotations": "^1.12|^2", - "psr/log": "^1|^2|^3", - "symfony/config": "^6.2", - "symfony/dependency-injection": "^5.4|^6.0", - "symfony/expression-language": "^5.4|^6.0", - "symfony/http-foundation": "^5.4|^6.0", - "symfony/yaml": "^5.4|^6.0" - }, - "type": "library", - "autoload": { - "psr-4": { - "Symfony\\Component\\Routing\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Maps an HTTP request to a set of configuration variables", - "homepage": "https://symfony.com", - "keywords": [ - "router", - "routing", - "uri", - "url" - ], - "support": { - "source": "https://github.com/symfony/routing/tree/v6.3.10" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2023-12-01T14:25:58+00:00" - }, - { - "name": "symfony/runtime", - "version": "v6.3.2", - "source": { - "type": "git", - "url": "https://github.com/symfony/runtime.git", - "reference": "d5c09493647a0c1a16e6c8da308098e840d1164f" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/runtime/zipball/d5c09493647a0c1a16e6c8da308098e840d1164f", - "reference": "d5c09493647a0c1a16e6c8da308098e840d1164f", - "shasum": "" - }, - "require": { - "composer-plugin-api": "^1.0|^2.0", - "php": ">=8.1" - }, - "conflict": { - "symfony/dotenv": "<5.4" - }, - "require-dev": { - "composer/composer": "^1.0.2|^2.0", - "symfony/console": "^5.4.9|^6.0.9", - "symfony/dotenv": "^5.4|^6.0", - "symfony/http-foundation": "^5.4|^6.0", - "symfony/http-kernel": "^5.4|^6.0" - }, - "type": "composer-plugin", - "extra": { - "class": "Symfony\\Component\\Runtime\\Internal\\ComposerPlugin" - }, - "autoload": { - "psr-4": { - "Symfony\\Component\\Runtime\\": "", - "Symfony\\Runtime\\Symfony\\Component\\": "Internal/" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Enables decoupling PHP applications from global state", - "homepage": "https://symfony.com", - "keywords": [ - "runtime" - ], - "support": { - "source": "https://github.com/symfony/runtime/tree/v6.3.2" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2023-07-16T17:05:46+00:00" - }, - { - "name": "symfony/security-bundle", - "version": "v6.3.8", - "source": { - "type": "git", - "url": "https://github.com/symfony/security-bundle.git", - "reference": "57889ebb1ac3403d550c787c4fde127261abacb6" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/security-bundle/zipball/57889ebb1ac3403d550c787c4fde127261abacb6", - "reference": "57889ebb1ac3403d550c787c4fde127261abacb6", - "shasum": "" - }, - "require": { - "composer-runtime-api": ">=2.1", - "ext-xml": "*", - "php": ">=8.1", - "symfony/clock": "^6.3", - "symfony/config": "^6.1", - "symfony/dependency-injection": "^6.2", - "symfony/deprecation-contracts": "^2.5|^3", - "symfony/event-dispatcher": "^5.4|^6.0", - "symfony/http-foundation": "^6.2", - "symfony/http-kernel": "^6.2", - "symfony/password-hasher": "^5.4|^6.0", - "symfony/security-core": "^6.2", - "symfony/security-csrf": "^5.4|^6.0", - "symfony/security-http": "^6.3.6", - "symfony/service-contracts": "^2.5|^3" - }, - "conflict": { - "symfony/browser-kit": "<5.4", - "symfony/console": "<5.4", - "symfony/framework-bundle": "<6.3", - "symfony/http-client": "<5.4", - "symfony/ldap": "<5.4", - "symfony/twig-bundle": "<5.4" - }, - "require-dev": { - "doctrine/annotations": "^1.10.4|^2", - "symfony/asset": "^5.4|^6.0", - "symfony/browser-kit": "^5.4|^6.0", - "symfony/console": "^5.4|^6.0", - "symfony/css-selector": "^5.4|^6.0", - "symfony/dom-crawler": "^5.4|^6.0", - "symfony/expression-language": "^5.4|^6.0", - "symfony/form": "^5.4|^6.0", - "symfony/framework-bundle": "^6.3", - "symfony/http-client": "^5.4|^6.0", - "symfony/ldap": "^5.4|^6.0", - "symfony/process": "^5.4|^6.0", - "symfony/rate-limiter": "^5.4|^6.0", - "symfony/serializer": "^5.4|^6.0", - "symfony/translation": "^5.4|^6.0", - "symfony/twig-bridge": "^5.4|^6.0", - "symfony/twig-bundle": "^5.4|^6.0", - "symfony/validator": "^5.4|^6.0", - "symfony/yaml": "^5.4|^6.0", - "twig/twig": "^2.13|^3.0.4", - "web-token/jwt-checker": "^3.1", - "web-token/jwt-signature-algorithm-ecdsa": "^3.1", - "web-token/jwt-signature-algorithm-eddsa": "^3.1", - "web-token/jwt-signature-algorithm-hmac": "^3.1", - "web-token/jwt-signature-algorithm-none": "^3.1", - "web-token/jwt-signature-algorithm-rsa": "^3.1" - }, - "type": "symfony-bundle", - "autoload": { - "psr-4": { - "Symfony\\Bundle\\SecurityBundle\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Provides a tight integration of the Security component into the Symfony full-stack framework", - "homepage": "https://symfony.com", - "support": { - "source": "https://github.com/symfony/security-bundle/tree/v6.3.8" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2023-11-09T09:33:10+00:00" - }, - { - "name": "symfony/security-core", - "version": "v6.3.7", - "source": { - "type": "git", - "url": "https://github.com/symfony/security-core.git", - "reference": "7ceb30fed93f5ea40ccde3173d1f7712527c0d62" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/security-core/zipball/7ceb30fed93f5ea40ccde3173d1f7712527c0d62", - "reference": "7ceb30fed93f5ea40ccde3173d1f7712527c0d62", - "shasum": "" - }, - "require": { - "php": ">=8.1", - "symfony/deprecation-contracts": "^2.5|^3", - "symfony/event-dispatcher-contracts": "^2.5|^3", - "symfony/password-hasher": "^5.4|^6.0", - "symfony/service-contracts": "^2.5|^3" - }, - "conflict": { - "symfony/event-dispatcher": "<5.4", - "symfony/http-foundation": "<5.4", - "symfony/ldap": "<5.4", - "symfony/security-guard": "<5.4", - "symfony/validator": "<5.4" - }, - "require-dev": { - "psr/cache": "^1.0|^2.0|^3.0", - "psr/container": "^1.1|^2.0", - "psr/log": "^1|^2|^3", - "symfony/cache": "^5.4|^6.0", - "symfony/event-dispatcher": "^5.4|^6.0", - "symfony/expression-language": "^5.4|^6.0", - "symfony/http-foundation": "^5.4|^6.0", - "symfony/ldap": "^5.4|^6.0", - "symfony/string": "^5.4|^6.0", - "symfony/translation": "^5.4|^6.0", - "symfony/validator": "^5.4|^6.0" - }, - "type": "library", - "autoload": { - "psr-4": { - "Symfony\\Component\\Security\\Core\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony Security Component - Core Library", - "homepage": "https://symfony.com", - "support": { - "source": "https://github.com/symfony/security-core/tree/v6.3.7" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2023-10-28T23:11:45+00:00" - }, - { - "name": "symfony/security-csrf", - "version": "v6.3.2", - "source": { - "type": "git", - "url": "https://github.com/symfony/security-csrf.git", - "reference": "63d7b098c448cbddb46ea5eda33b68c1ece6eb5b" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/security-csrf/zipball/63d7b098c448cbddb46ea5eda33b68c1ece6eb5b", - "reference": "63d7b098c448cbddb46ea5eda33b68c1ece6eb5b", - "shasum": "" - }, - "require": { - "php": ">=8.1", - "symfony/security-core": "^5.4|^6.0" - }, - "conflict": { - "symfony/http-foundation": "<5.4" - }, - "require-dev": { - "symfony/http-foundation": "^5.4|^6.0" - }, - "type": "library", - "autoload": { - "psr-4": { - "Symfony\\Component\\Security\\Csrf\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony Security Component - CSRF Library", - "homepage": "https://symfony.com", - "support": { - "source": "https://github.com/symfony/security-csrf/tree/v6.3.2" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2023-07-05T08:41:27+00:00" - }, - { - "name": "symfony/security-http", - "version": "v6.3.8", - "source": { - "type": "git", - "url": "https://github.com/symfony/security-http.git", - "reference": "19f7b5f5d20879a976d6d376e359bc975dfc6002" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/security-http/zipball/19f7b5f5d20879a976d6d376e359bc975dfc6002", - "reference": "19f7b5f5d20879a976d6d376e359bc975dfc6002", - "shasum": "" - }, - "require": { - "php": ">=8.1", - "symfony/deprecation-contracts": "^2.5|^3", - "symfony/http-foundation": "^5.4|^6.0", - "symfony/http-kernel": "^6.3", - "symfony/polyfill-mbstring": "~1.0", - "symfony/property-access": "^5.4|^6.0", - "symfony/security-core": "^6.3", - "symfony/service-contracts": "^2.5|^3" - }, - "conflict": { - "symfony/clock": "<6.3", - "symfony/event-dispatcher": "<5.4.9|>=6,<6.0.9", - "symfony/http-client-contracts": "<3.0", - "symfony/security-bundle": "<5.4", - "symfony/security-csrf": "<5.4" - }, - "require-dev": { - "psr/log": "^1|^2|^3", - "symfony/cache": "^5.4|^6.0", - "symfony/clock": "^6.3", - "symfony/expression-language": "^5.4|^6.0", - "symfony/http-client-contracts": "^3.0", - "symfony/rate-limiter": "^5.4|^6.0", - "symfony/routing": "^5.4|^6.0", - "symfony/security-csrf": "^5.4|^6.0", - "symfony/translation": "^5.4|^6.0", - "web-token/jwt-checker": "^3.1", - "web-token/jwt-signature-algorithm-ecdsa": "^3.1" - }, - "type": "library", - "autoload": { - "psr-4": { - "Symfony\\Component\\Security\\Http\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony Security Component - HTTP Integration", - "homepage": "https://symfony.com", - "support": { - "source": "https://github.com/symfony/security-http/tree/v6.3.8" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2023-11-09T21:20:12+00:00" - }, - { - "name": "symfony/serializer", - "version": "v6.3.10", - "source": { - "type": "git", - "url": "https://github.com/symfony/serializer.git", - "reference": "6eee0fd95f5caa1e77cab29552620ebf8e5b1a5f" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/serializer/zipball/6eee0fd95f5caa1e77cab29552620ebf8e5b1a5f", - "reference": "6eee0fd95f5caa1e77cab29552620ebf8e5b1a5f", - "shasum": "" - }, - "require": { - "php": ">=8.1", - "symfony/deprecation-contracts": "^2.5|^3", - "symfony/polyfill-ctype": "~1.8" - }, - "conflict": { - "doctrine/annotations": "<1.12", - "phpdocumentor/reflection-docblock": "<3.2.2", - "phpdocumentor/type-resolver": "<1.4.0", - "symfony/dependency-injection": "<5.4", - "symfony/property-access": "<5.4", - "symfony/property-info": "<5.4.24|>=6,<6.2.11", - "symfony/uid": "<5.4", - "symfony/yaml": "<5.4" - }, - "require-dev": { - "doctrine/annotations": "^1.12|^2", - "phpdocumentor/reflection-docblock": "^3.2|^4.0|^5.0", - "symfony/cache": "^5.4|^6.0", - "symfony/config": "^5.4|^6.0", - "symfony/console": "^5.4|^6.0", - "symfony/dependency-injection": "^5.4|^6.0", - "symfony/error-handler": "^5.4|^6.0", - "symfony/filesystem": "^5.4|^6.0", - "symfony/form": "^5.4|^6.0", - "symfony/http-foundation": "^5.4|^6.0", - "symfony/http-kernel": "^5.4|^6.0", - "symfony/mime": "^5.4|^6.0", - "symfony/property-access": "^5.4|^6.0", - "symfony/property-info": "^5.4.24|^6.2.11", - "symfony/uid": "^5.4|^6.0", - "symfony/validator": "^5.4|^6.0", - "symfony/var-dumper": "^5.4|^6.0", - "symfony/var-exporter": "^5.4|^6.0", - "symfony/yaml": "^5.4|^6.0" - }, - "type": "library", - "autoload": { - "psr-4": { - "Symfony\\Component\\Serializer\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Handles serializing and deserializing data structures, including object graphs, into array structures or other formats like XML and JSON.", - "homepage": "https://symfony.com", - "support": { - "source": "https://github.com/symfony/serializer/tree/v6.3.10" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2023-12-01T14:25:58+00:00" - }, - { - "name": "symfony/service-contracts", - "version": "v3.4.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/service-contracts.git", - "reference": "b3313c2dbffaf71c8de2934e2ea56ed2291a3838" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/service-contracts/zipball/b3313c2dbffaf71c8de2934e2ea56ed2291a3838", - "reference": "b3313c2dbffaf71c8de2934e2ea56ed2291a3838", - "shasum": "" - }, - "require": { - "php": ">=8.1", - "psr/container": "^2.0" - }, - "conflict": { - "ext-psr": "<1.1|>=2" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "3.4-dev" - }, - "thanks": { - "name": "symfony/contracts", - "url": "https://github.com/symfony/contracts" - } - }, - "autoload": { - "psr-4": { - "Symfony\\Contracts\\Service\\": "" - }, - "exclude-from-classmap": [ - "/Test/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Generic abstractions related to writing services", - "homepage": "https://symfony.com", - "keywords": [ - "abstractions", - "contracts", - "decoupling", - "interfaces", - "interoperability", - "standards" - ], - "support": { - "source": "https://github.com/symfony/service-contracts/tree/v3.4.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2023-07-30T20:28:31+00:00" - }, - { - "name": "symfony/stopwatch", - "version": "v6.3.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/stopwatch.git", - "reference": "fc47f1015ec80927ff64ba9094dfe8b9d48fe9f2" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/stopwatch/zipball/fc47f1015ec80927ff64ba9094dfe8b9d48fe9f2", - "reference": "fc47f1015ec80927ff64ba9094dfe8b9d48fe9f2", - "shasum": "" - }, - "require": { - "php": ">=8.1", - "symfony/service-contracts": "^2.5|^3" - }, - "type": "library", - "autoload": { - "psr-4": { - "Symfony\\Component\\Stopwatch\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Provides a way to profile code", - "homepage": "https://symfony.com", - "support": { - "source": "https://github.com/symfony/stopwatch/tree/v6.3.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2023-02-16T10:14:28+00:00" - }, - { - "name": "symfony/string", - "version": "v6.3.9", - "source": { - "type": "git", - "url": "https://github.com/symfony/string.git", - "reference": "56427887aeaf540e9bbd121ad6c43f14ad3ce136" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/string/zipball/56427887aeaf540e9bbd121ad6c43f14ad3ce136", - "reference": "56427887aeaf540e9bbd121ad6c43f14ad3ce136", - "shasum": "" - }, - "require": { - "php": ">=8.1", - "symfony/polyfill-ctype": "~1.8", - "symfony/polyfill-intl-grapheme": "~1.0", - "symfony/polyfill-intl-normalizer": "~1.0", - "symfony/polyfill-mbstring": "~1.0" - }, - "conflict": { - "symfony/translation-contracts": "<2.5" - }, - "require-dev": { - "symfony/error-handler": "^5.4|^6.0", - "symfony/http-client": "^5.4|^6.0", - "symfony/intl": "^6.2", - "symfony/translation-contracts": "^2.5|^3.0", - "symfony/var-exporter": "^5.4|^6.0" - }, - "type": "library", - "autoload": { - "files": [ - "Resources/functions.php" - ], - "psr-4": { - "Symfony\\Component\\String\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Provides an object-oriented API to strings and deals with bytes, UTF-8 code points and grapheme clusters in a unified way", - "homepage": "https://symfony.com", - "keywords": [ - "grapheme", - "i18n", - "string", - "unicode", - "utf-8", - "utf8" - ], - "support": { - "source": "https://github.com/symfony/string/tree/v6.3.9" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2023-11-28T20:40:29+00:00" - }, - { - "name": "symfony/translation", - "version": "v6.3.7", - "source": { - "type": "git", - "url": "https://github.com/symfony/translation.git", - "reference": "30212e7c87dcb79c83f6362b00bde0e0b1213499" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/translation/zipball/30212e7c87dcb79c83f6362b00bde0e0b1213499", - "reference": "30212e7c87dcb79c83f6362b00bde0e0b1213499", - "shasum": "" - }, - "require": { - "php": ">=8.1", - "symfony/deprecation-contracts": "^2.5|^3", - "symfony/polyfill-mbstring": "~1.0", - "symfony/translation-contracts": "^2.5|^3.0" - }, - "conflict": { - "symfony/config": "<5.4", - "symfony/console": "<5.4", - "symfony/dependency-injection": "<5.4", - "symfony/http-client-contracts": "<2.5", - "symfony/http-kernel": "<5.4", - "symfony/service-contracts": "<2.5", - "symfony/twig-bundle": "<5.4", - "symfony/yaml": "<5.4" - }, - "provide": { - "symfony/translation-implementation": "2.3|3.0" - }, - "require-dev": { - "nikic/php-parser": "^4.13", - "psr/log": "^1|^2|^3", - "symfony/config": "^5.4|^6.0", - "symfony/console": "^5.4|^6.0", - "symfony/dependency-injection": "^5.4|^6.0", - "symfony/finder": "^5.4|^6.0", - "symfony/http-client-contracts": "^2.5|^3.0", - "symfony/http-kernel": "^5.4|^6.0", - "symfony/intl": "^5.4|^6.0", - "symfony/polyfill-intl-icu": "^1.21", - "symfony/routing": "^5.4|^6.0", - "symfony/service-contracts": "^2.5|^3", - "symfony/yaml": "^5.4|^6.0" - }, - "type": "library", - "autoload": { - "files": [ - "Resources/functions.php" - ], - "psr-4": { - "Symfony\\Component\\Translation\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Provides tools to internationalize your application", - "homepage": "https://symfony.com", - "support": { - "source": "https://github.com/symfony/translation/tree/v6.3.7" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2023-10-28T23:11:45+00:00" - }, - { - "name": "symfony/translation-contracts", - "version": "v3.4.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/translation-contracts.git", - "reference": "dee0c6e5b4c07ce851b462530088e64b255ac9c5" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/translation-contracts/zipball/dee0c6e5b4c07ce851b462530088e64b255ac9c5", - "reference": "dee0c6e5b4c07ce851b462530088e64b255ac9c5", - "shasum": "" - }, - "require": { - "php": ">=8.1" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "3.4-dev" - }, - "thanks": { - "name": "symfony/contracts", - "url": "https://github.com/symfony/contracts" - } - }, - "autoload": { - "psr-4": { - "Symfony\\Contracts\\Translation\\": "" - }, - "exclude-from-classmap": [ - "/Test/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Generic abstractions related to translation", - "homepage": "https://symfony.com", - "keywords": [ - "abstractions", - "contracts", - "decoupling", - "interfaces", - "interoperability", - "standards" - ], - "support": { - "source": "https://github.com/symfony/translation-contracts/tree/v3.4.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2023-07-25T15:08:44+00:00" - }, - { - "name": "symfony/twig-bridge", - "version": "v6.3.8", - "source": { - "type": "git", - "url": "https://github.com/symfony/twig-bridge.git", - "reference": "c51407623959a626784ff302419026f56dc4e1ba" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/twig-bridge/zipball/c51407623959a626784ff302419026f56dc4e1ba", - "reference": "c51407623959a626784ff302419026f56dc4e1ba", - "shasum": "" - }, - "require": { - "php": ">=8.1", - "symfony/translation-contracts": "^2.5|^3", - "twig/twig": "^2.13|^3.0.4" - }, - "conflict": { - "phpdocumentor/reflection-docblock": "<3.2.2", - "phpdocumentor/type-resolver": "<1.4.0", - "symfony/console": "<5.4", - "symfony/form": "<6.3", - "symfony/http-foundation": "<5.4", - "symfony/http-kernel": "<6.2", - "symfony/mime": "<6.2", - "symfony/translation": "<5.4", - "symfony/workflow": "<5.4" - }, - "require-dev": { - "doctrine/annotations": "^1.12|^2", - "egulias/email-validator": "^2.1.10|^3|^4", - "league/html-to-markdown": "^5.0", - "phpdocumentor/reflection-docblock": "^3.0|^4.0|^5.0", - "symfony/asset": "^5.4|^6.0", - "symfony/asset-mapper": "^6.3", - "symfony/console": "^5.4|^6.0", - "symfony/dependency-injection": "^5.4|^6.0", - "symfony/expression-language": "^5.4|^6.0", - "symfony/finder": "^5.4|^6.0", - "symfony/form": "^6.3", - "symfony/html-sanitizer": "^6.1", - "symfony/http-foundation": "^5.4|^6.0", - "symfony/http-kernel": "^6.2", - "symfony/intl": "^5.4|^6.0", - "symfony/mime": "^6.2", - "symfony/polyfill-intl-icu": "~1.0", - "symfony/property-info": "^5.4|^6.0", - "symfony/routing": "^5.4|^6.0", - "symfony/security-acl": "^2.8|^3.0", - "symfony/security-core": "^5.4|^6.0", - "symfony/security-csrf": "^5.4|^6.0", - "symfony/security-http": "^5.4|^6.0", - "symfony/serializer": "^6.2", - "symfony/stopwatch": "^5.4|^6.0", - "symfony/translation": "^6.1", - "symfony/web-link": "^5.4|^6.0", - "symfony/workflow": "^5.4|^6.0", - "symfony/yaml": "^5.4|^6.0", - "twig/cssinliner-extra": "^2.12|^3", - "twig/inky-extra": "^2.12|^3", - "twig/markdown-extra": "^2.12|^3" - }, - "type": "symfony-bridge", - "autoload": { - "psr-4": { - "Symfony\\Bridge\\Twig\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Provides integration for Twig with various Symfony components", - "homepage": "https://symfony.com", - "support": { - "source": "https://github.com/symfony/twig-bridge/tree/v6.3.8" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2023-11-09T21:20:12+00:00" - }, - { - "name": "symfony/twig-bundle", - "version": "v6.3.8", - "source": { - "type": "git", - "url": "https://github.com/symfony/twig-bundle.git", - "reference": "82429320fe931dd50825ec08140c54b3a315bf79" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/twig-bundle/zipball/82429320fe931dd50825ec08140c54b3a315bf79", - "reference": "82429320fe931dd50825ec08140c54b3a315bf79", - "shasum": "" - }, - "require": { - "composer-runtime-api": ">=2.1", - "php": ">=8.1", - "symfony/config": "^6.1", - "symfony/dependency-injection": "^6.1", - "symfony/http-foundation": "^5.4|^6.0", - "symfony/http-kernel": "^6.2", - "symfony/twig-bridge": "^6.3", - "twig/twig": "^2.13|^3.0.4" - }, - "conflict": { - "symfony/framework-bundle": "<5.4", - "symfony/translation": "<5.4" - }, - "require-dev": { - "doctrine/annotations": "^1.10.4|^2", - "symfony/asset": "^5.4|^6.0", - "symfony/expression-language": "^5.4|^6.0", - "symfony/finder": "^5.4|^6.0", - "symfony/form": "^5.4|^6.0", - "symfony/framework-bundle": "^5.4|^6.0", - "symfony/routing": "^5.4|^6.0", - "symfony/stopwatch": "^5.4|^6.0", - "symfony/translation": "^5.4|^6.0", - "symfony/web-link": "^5.4|^6.0", - "symfony/yaml": "^5.4|^6.0" - }, - "type": "symfony-bundle", - "autoload": { - "psr-4": { - "Symfony\\Bundle\\TwigBundle\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Provides a tight integration of Twig into the Symfony full-stack framework", - "homepage": "https://symfony.com", - "support": { - "source": "https://github.com/symfony/twig-bundle/tree/v6.3.8" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2023-10-31T08:07:48+00:00" - }, - { - "name": "symfony/validator", - "version": "v6.3.9", - "source": { - "type": "git", - "url": "https://github.com/symfony/validator.git", - "reference": "c118889931856af47b0732b609f3ac2ddccd1da6" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/validator/zipball/c118889931856af47b0732b609f3ac2ddccd1da6", - "reference": "c118889931856af47b0732b609f3ac2ddccd1da6", - "shasum": "" - }, - "require": { - "php": ">=8.1", - "symfony/deprecation-contracts": "^2.5|^3", - "symfony/polyfill-ctype": "~1.8", - "symfony/polyfill-mbstring": "~1.0", - "symfony/polyfill-php83": "^1.27", - "symfony/translation-contracts": "^2.5|^3" - }, - "conflict": { - "doctrine/annotations": "<1.13", - "doctrine/lexer": "<1.1", - "symfony/dependency-injection": "<5.4", - "symfony/expression-language": "<5.4", - "symfony/http-kernel": "<5.4", - "symfony/intl": "<5.4", - "symfony/property-info": "<5.4", - "symfony/translation": "<5.4", - "symfony/yaml": "<5.4" - }, - "require-dev": { - "doctrine/annotations": "^1.13|^2", - "egulias/email-validator": "^2.1.10|^3|^4", - "symfony/cache": "^5.4|^6.0", - "symfony/config": "^5.4|^6.0", - "symfony/console": "^5.4|^6.0", - "symfony/dependency-injection": "^5.4|^6.0", - "symfony/expression-language": "^5.4|^6.0", - "symfony/finder": "^5.4|^6.0", - "symfony/http-client": "^5.4|^6.0", - "symfony/http-foundation": "^5.4|^6.0", - "symfony/http-kernel": "^5.4|^6.0", - "symfony/intl": "^5.4|^6.0", - "symfony/mime": "^5.4|^6.0", - "symfony/property-access": "^5.4|^6.0", - "symfony/property-info": "^5.4|^6.0", - "symfony/translation": "^5.4|^6.0", - "symfony/yaml": "^5.4|^6.0" - }, - "type": "library", - "autoload": { - "psr-4": { - "Symfony\\Component\\Validator\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Provides tools to validate values", - "homepage": "https://symfony.com", - "support": { - "source": "https://github.com/symfony/validator/tree/v6.3.9" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2023-11-29T07:44:47+00:00" - }, - { - "name": "symfony/var-dumper", - "version": "v6.3.8", - "source": { - "type": "git", - "url": "https://github.com/symfony/var-dumper.git", - "reference": "81acabba9046550e89634876ca64bfcd3c06aa0a" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/var-dumper/zipball/81acabba9046550e89634876ca64bfcd3c06aa0a", - "reference": "81acabba9046550e89634876ca64bfcd3c06aa0a", - "shasum": "" - }, - "require": { - "php": ">=8.1", - "symfony/deprecation-contracts": "^2.5|^3", - "symfony/polyfill-mbstring": "~1.0" - }, - "conflict": { - "symfony/console": "<5.4" - }, - "require-dev": { - "ext-iconv": "*", - "symfony/console": "^5.4|^6.0", - "symfony/http-kernel": "^5.4|^6.0", - "symfony/process": "^5.4|^6.0", - "symfony/uid": "^5.4|^6.0", - "twig/twig": "^2.13|^3.0.4" - }, - "bin": [ - "Resources/bin/var-dump-server" - ], - "type": "library", - "autoload": { - "files": [ - "Resources/functions/dump.php" - ], - "psr-4": { - "Symfony\\Component\\VarDumper\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Provides mechanisms for walking through any arbitrary PHP variable", - "homepage": "https://symfony.com", - "keywords": [ - "debug", - "dump" - ], - "support": { - "source": "https://github.com/symfony/var-dumper/tree/v6.3.8" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2023-11-08T10:42:36+00:00" - }, - { - "name": "symfony/var-exporter", - "version": "v6.3.10", - "source": { - "type": "git", - "url": "https://github.com/symfony/var-exporter.git", - "reference": "7bfcf232a9c7e4acad00e96774e340eb86d10bf0" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/var-exporter/zipball/7bfcf232a9c7e4acad00e96774e340eb86d10bf0", - "reference": "7bfcf232a9c7e4acad00e96774e340eb86d10bf0", - "shasum": "" - }, - "require": { - "php": ">=8.1" - }, - "require-dev": { - "symfony/var-dumper": "^5.4|^6.0" - }, - "type": "library", - "autoload": { - "psr-4": { - "Symfony\\Component\\VarExporter\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Allows exporting any serializable PHP data structure to plain PHP code", - "homepage": "https://symfony.com", - "keywords": [ - "clone", - "construct", - "export", - "hydrate", - "instantiate", - "lazy-loading", - "proxy", - "serialize" - ], - "support": { - "source": "https://github.com/symfony/var-exporter/tree/v6.3.10" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2023-11-29T16:00:50+00:00" - }, - { - "name": "symfony/web-link", - "version": "v6.3.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/web-link.git", - "reference": "0989ca617d0703cdca501a245f10e194ff22315b" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/web-link/zipball/0989ca617d0703cdca501a245f10e194ff22315b", - "reference": "0989ca617d0703cdca501a245f10e194ff22315b", - "shasum": "" - }, - "require": { - "php": ">=8.1", - "psr/link": "^1.1|^2.0" - }, - "conflict": { - "symfony/http-kernel": "<5.4" - }, - "provide": { - "psr/link-implementation": "1.0|2.0" - }, - "require-dev": { - "symfony/http-kernel": "^5.4|^6.0" - }, - "type": "library", - "autoload": { - "psr-4": { - "Symfony\\Component\\WebLink\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Kévin Dunglas", - "email": "dunglas@gmail.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Manages links between resources", - "homepage": "https://symfony.com", - "keywords": [ - "dns-prefetch", - "http", - "http2", - "link", - "performance", - "prefetch", - "preload", - "prerender", - "psr13", - "push" - ], - "support": { - "source": "https://github.com/symfony/web-link/tree/v6.3.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2023-04-21T14:41:17+00:00" - }, - { - "name": "symfony/yaml", - "version": "v6.3.8", - "source": { - "type": "git", - "url": "https://github.com/symfony/yaml.git", - "reference": "3493af8a8dad7fa91c77fa473ba23ecd95334a92" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/yaml/zipball/3493af8a8dad7fa91c77fa473ba23ecd95334a92", - "reference": "3493af8a8dad7fa91c77fa473ba23ecd95334a92", - "shasum": "" - }, - "require": { - "php": ">=8.1", - "symfony/deprecation-contracts": "^2.5|^3", - "symfony/polyfill-ctype": "^1.8" - }, - "conflict": { - "symfony/console": "<5.4" - }, - "require-dev": { - "symfony/console": "^5.4|^6.0" - }, - "bin": [ - "Resources/bin/yaml-lint" - ], - "type": "library", - "autoload": { - "psr-4": { - "Symfony\\Component\\Yaml\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Loads and dumps YAML files", - "homepage": "https://symfony.com", - "support": { - "source": "https://github.com/symfony/yaml/tree/v6.3.8" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2023-11-06T10:58:05+00:00" - }, - { - "name": "twig/extra-bundle", - "version": "v3.8.0", - "source": { - "type": "git", - "url": "https://github.com/twigphp/twig-extra-bundle.git", - "reference": "32807183753de0388c8e59f7ac2d13bb47311140" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/twigphp/twig-extra-bundle/zipball/32807183753de0388c8e59f7ac2d13bb47311140", - "reference": "32807183753de0388c8e59f7ac2d13bb47311140", - "shasum": "" - }, - "require": { - "php": ">=7.2.5", - "symfony/framework-bundle": "^5.4|^6.0|^7.0", - "symfony/twig-bundle": "^5.4|^6.0|^7.0", - "twig/twig": "^3.0" - }, - "require-dev": { - "league/commonmark": "^1.0|^2.0", - "symfony/phpunit-bridge": "^6.4|^7.0", - "twig/cache-extra": "^3.0", - "twig/cssinliner-extra": "^2.12|^3.0", - "twig/html-extra": "^2.12|^3.0", - "twig/inky-extra": "^2.12|^3.0", - "twig/intl-extra": "^2.12|^3.0", - "twig/markdown-extra": "^2.12|^3.0", - "twig/string-extra": "^2.12|^3.0" - }, - "type": "symfony-bundle", - "autoload": { - "psr-4": { - "Twig\\Extra\\TwigExtraBundle\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com", - "homepage": "http://fabien.potencier.org", - "role": "Lead Developer" - } - ], - "description": "A Symfony bundle for extra Twig extensions", - "homepage": "https://twig.symfony.com", - "keywords": [ - "bundle", - "extra", - "twig" - ], - "support": { - "source": "https://github.com/twigphp/twig-extra-bundle/tree/v3.8.0" - }, - "funding": [ - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/twig/twig", - "type": "tidelift" - } - ], - "time": "2023-11-21T14:02:01+00:00" - }, - { - "name": "twig/intl-extra", - "version": "v3.8.0", - "source": { - "type": "git", - "url": "https://github.com/twigphp/intl-extra.git", - "reference": "7b3db67c700735f473a265a97e1adaeba3e6ca0c" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/twigphp/intl-extra/zipball/7b3db67c700735f473a265a97e1adaeba3e6ca0c", - "reference": "7b3db67c700735f473a265a97e1adaeba3e6ca0c", - "shasum": "" - }, - "require": { - "php": ">=7.2.5", - "symfony/intl": "^5.4|^6.0|^7.0", - "twig/twig": "^3.0" - }, - "require-dev": { - "symfony/phpunit-bridge": "^6.4|^7.0" - }, - "type": "library", - "autoload": { - "psr-4": { - "Twig\\Extra\\Intl\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com", - "homepage": "http://fabien.potencier.org", - "role": "Lead Developer" - } - ], - "description": "A Twig extension for Intl", - "homepage": "https://twig.symfony.com", - "keywords": [ - "intl", - "twig" - ], - "support": { - "source": "https://github.com/twigphp/intl-extra/tree/v3.8.0" - }, - "funding": [ - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/twig/twig", - "type": "tidelift" - } - ], - "time": "2023-11-21T17:27:48+00:00" - }, - { - "name": "twig/markdown-extra", - "version": "v3.8.0", - "source": { - "type": "git", - "url": "https://github.com/twigphp/markdown-extra.git", - "reference": "b6e4954ab60030233df5d293886b5404558daac8" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/twigphp/markdown-extra/zipball/b6e4954ab60030233df5d293886b5404558daac8", - "reference": "b6e4954ab60030233df5d293886b5404558daac8", - "shasum": "" - }, - "require": { - "php": ">=7.2.5", - "twig/twig": "^3.0" - }, - "require-dev": { - "erusev/parsedown": "^1.7", - "league/commonmark": "^1.0|^2.0", - "league/html-to-markdown": "^4.8|^5.0", - "michelf/php-markdown": "^1.8|^2.0", - "symfony/phpunit-bridge": "^6.4|^7.0" - }, - "type": "library", - "autoload": { - "psr-4": { - "Twig\\Extra\\Markdown\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com", - "homepage": "http://fabien.potencier.org", - "role": "Lead Developer" - } - ], - "description": "A Twig extension for Markdown", - "homepage": "https://twig.symfony.com", - "keywords": [ - "html", - "markdown", - "twig" - ], - "support": { - "source": "https://github.com/twigphp/markdown-extra/tree/v3.8.0" - }, - "funding": [ - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/twig/twig", - "type": "tidelift" - } - ], - "time": "2023-11-21T14:02:01+00:00" - }, - { - "name": "twig/string-extra", - "version": "v3.8.0", - "source": { - "type": "git", - "url": "https://github.com/twigphp/string-extra.git", - "reference": "b0c9037d96baff79abe368dc092a59b726517548" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/twigphp/string-extra/zipball/b0c9037d96baff79abe368dc092a59b726517548", - "reference": "b0c9037d96baff79abe368dc092a59b726517548", - "shasum": "" - }, - "require": { - "php": ">=7.2.5", - "symfony/string": "^5.4|^6.0|^7.0", - "symfony/translation-contracts": "^1.1|^2|^3", - "twig/twig": "^3.0" - }, - "require-dev": { - "symfony/phpunit-bridge": "^6.4|^7.0" - }, - "type": "library", - "autoload": { - "psr-4": { - "Twig\\Extra\\String\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com", - "homepage": "http://fabien.potencier.org", - "role": "Lead Developer" - } - ], - "description": "A Twig extension for Symfony String", - "homepage": "https://twig.symfony.com", - "keywords": [ - "html", - "string", - "twig", - "unicode" - ], - "support": { - "source": "https://github.com/twigphp/string-extra/tree/v3.8.0" - }, - "funding": [ - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/twig/twig", - "type": "tidelift" - } - ], - "time": "2023-11-21T14:02:01+00:00" - }, - { - "name": "twig/twig", - "version": "v3.8.0", - "source": { - "type": "git", - "url": "https://github.com/twigphp/Twig.git", - "reference": "9d15f0ac07f44dc4217883ec6ae02fd555c6f71d" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/twigphp/Twig/zipball/9d15f0ac07f44dc4217883ec6ae02fd555c6f71d", - "reference": "9d15f0ac07f44dc4217883ec6ae02fd555c6f71d", - "shasum": "" - }, - "require": { - "php": ">=7.2.5", - "symfony/polyfill-ctype": "^1.8", - "symfony/polyfill-mbstring": "^1.3", - "symfony/polyfill-php80": "^1.22" - }, - "require-dev": { - "psr/container": "^1.0|^2.0", - "symfony/phpunit-bridge": "^5.4.9|^6.3|^7.0" - }, - "type": "library", - "autoload": { - "psr-4": { - "Twig\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com", - "homepage": "http://fabien.potencier.org", - "role": "Lead Developer" - }, - { - "name": "Twig Team", - "role": "Contributors" - }, - { - "name": "Armin Ronacher", - "email": "armin.ronacher@active-4.com", - "role": "Project Founder" - } - ], - "description": "Twig, the flexible, fast, and secure template language for PHP", - "homepage": "https://twig.symfony.com", - "keywords": [ - "templating" - ], - "support": { - "issues": "https://github.com/twigphp/Twig/issues", - "source": "https://github.com/twigphp/Twig/tree/v3.8.0" - }, - "funding": [ - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/twig/twig", - "type": "tidelift" - } - ], - "time": "2023-11-21T18:54:41+00:00" - }, - { - "name": "webmozart/assert", - "version": "1.11.0", - "source": { - "type": "git", - "url": "https://github.com/webmozarts/assert.git", - "reference": "11cb2199493b2f8a3b53e7f19068fc6aac760991" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/webmozarts/assert/zipball/11cb2199493b2f8a3b53e7f19068fc6aac760991", - "reference": "11cb2199493b2f8a3b53e7f19068fc6aac760991", - "shasum": "" - }, - "require": { - "ext-ctype": "*", - "php": "^7.2 || ^8.0" - }, - "conflict": { - "phpstan/phpstan": "<0.12.20", - "vimeo/psalm": "<4.6.1 || 4.6.2" - }, - "require-dev": { - "phpunit/phpunit": "^8.5.13" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.10-dev" - } - }, - "autoload": { - "psr-4": { - "Webmozart\\Assert\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Bernhard Schussek", - "email": "bschussek@gmail.com" - } - ], - "description": "Assertions to validate method input/output with nice error messages.", - "keywords": [ - "assert", - "check", - "validate" - ], - "support": { - "issues": "https://github.com/webmozarts/assert/issues", - "source": "https://github.com/webmozarts/assert/tree/1.11.0" - }, - "time": "2022-06-03T18:03:27+00:00" - }, - { - "name": "yggverse/scrapeer", - "version": "0.5.4", - "source": { - "type": "git", - "url": "https://github.com/YGGverse/scrapeer.git", - "reference": "3b9d15c9706a844bf1428812bb938370e907b4f3" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/YGGverse/scrapeer/zipball/3b9d15c9706a844bf1428812bb938370e907b4f3", - "reference": "3b9d15c9706a844bf1428812bb938370e907b4f3", - "shasum": "" - }, - "type": "library", - "autoload": { - "psr-4": { - "Yggverse\\Scrapeer\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "CC-BY-SA-3.0" - ], - "authors": [ - { - "name": "medariox", - "homepage": "https://github.com/medariox/scrapeer" - }, - { - "name": "YGGverse", - "homepage": "https://github.com/YGGverse/scrapeer" - } - ], - "description": "Essential PHP library that scrapes HTTP(S) and UDP trackers for torrent information", - "support": { - "issues": "https://github.com/YGGverse/scrapeer/issues", - "source": "https://github.com/YGGverse/scrapeer/tree/0.5.4" - }, - "time": "2023-10-09T01:47:30+00:00" - } - ], - "packages-dev": [ - { - "name": "masterminds/html5", - "version": "2.8.1", - "source": { - "type": "git", - "url": "https://github.com/Masterminds/html5-php.git", - "reference": "f47dcf3c70c584de14f21143c55d9939631bc6cf" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/Masterminds/html5-php/zipball/f47dcf3c70c584de14f21143c55d9939631bc6cf", - "reference": "f47dcf3c70c584de14f21143c55d9939631bc6cf", - "shasum": "" - }, - "require": { - "ext-dom": "*", - "php": ">=5.3.0" - }, - "require-dev": { - "phpunit/phpunit": "^4.8.35 || ^5.7.21 || ^6 || ^7 || ^8" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.7-dev" - } - }, - "autoload": { - "psr-4": { - "Masterminds\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Matt Butcher", - "email": "technosophos@gmail.com" - }, - { - "name": "Matt Farina", - "email": "matt@mattfarina.com" - }, - { - "name": "Asmir Mustafic", - "email": "goetas@gmail.com" - } - ], - "description": "An HTML5 parser and serializer.", - "homepage": "http://masterminds.github.io/html5-php", - "keywords": [ - "HTML5", - "dom", - "html", - "parser", - "querypath", - "serializer", - "xml" - ], - "support": { - "issues": "https://github.com/Masterminds/html5-php/issues", - "source": "https://github.com/Masterminds/html5-php/tree/2.8.1" - }, - "time": "2023-05-10T11:58:31+00:00" - }, - { - "name": "myclabs/deep-copy", - "version": "1.11.1", - "source": { - "type": "git", - "url": "https://github.com/myclabs/DeepCopy.git", - "reference": "7284c22080590fb39f2ffa3e9057f10a4ddd0e0c" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/7284c22080590fb39f2ffa3e9057f10a4ddd0e0c", - "reference": "7284c22080590fb39f2ffa3e9057f10a4ddd0e0c", - "shasum": "" - }, - "require": { - "php": "^7.1 || ^8.0" - }, - "conflict": { - "doctrine/collections": "<1.6.8", - "doctrine/common": "<2.13.3 || >=3,<3.2.2" - }, - "require-dev": { - "doctrine/collections": "^1.6.8", - "doctrine/common": "^2.13.3 || ^3.2.2", - "phpunit/phpunit": "^7.5.20 || ^8.5.23 || ^9.5.13" - }, - "type": "library", - "autoload": { - "files": [ - "src/DeepCopy/deep_copy.php" - ], - "psr-4": { - "DeepCopy\\": "src/DeepCopy/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "description": "Create deep copies (clones) of your objects", - "keywords": [ - "clone", - "copy", - "duplicate", - "object", - "object graph" - ], - "support": { - "issues": "https://github.com/myclabs/DeepCopy/issues", - "source": "https://github.com/myclabs/DeepCopy/tree/1.11.1" - }, - "funding": [ - { - "url": "https://tidelift.com/funding/github/packagist/myclabs/deep-copy", - "type": "tidelift" - } - ], - "time": "2023-03-08T13:26:56+00:00" - }, - { - "name": "nikic/php-parser", - "version": "v4.17.1", - "source": { - "type": "git", - "url": "https://github.com/nikic/PHP-Parser.git", - "reference": "a6303e50c90c355c7eeee2c4a8b27fe8dc8fef1d" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/a6303e50c90c355c7eeee2c4a8b27fe8dc8fef1d", - "reference": "a6303e50c90c355c7eeee2c4a8b27fe8dc8fef1d", - "shasum": "" - }, - "require": { - "ext-tokenizer": "*", - "php": ">=7.0" - }, - "require-dev": { - "ircmaxell/php-yacc": "^0.0.7", - "phpunit/phpunit": "^6.5 || ^7.0 || ^8.0 || ^9.0" - }, - "bin": [ - "bin/php-parse" - ], - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "4.9-dev" - } - }, - "autoload": { - "psr-4": { - "PhpParser\\": "lib/PhpParser" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Nikita Popov" - } - ], - "description": "A PHP parser written in PHP", - "keywords": [ - "parser", - "php" - ], - "support": { - "issues": "https://github.com/nikic/PHP-Parser/issues", - "source": "https://github.com/nikic/PHP-Parser/tree/v4.17.1" - }, - "time": "2023-08-13T19:53:39+00:00" - }, - { - "name": "phar-io/manifest", - "version": "2.0.3", - "source": { - "type": "git", - "url": "https://github.com/phar-io/manifest.git", - "reference": "97803eca37d319dfa7826cc2437fc020857acb53" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phar-io/manifest/zipball/97803eca37d319dfa7826cc2437fc020857acb53", - "reference": "97803eca37d319dfa7826cc2437fc020857acb53", - "shasum": "" - }, - "require": { - "ext-dom": "*", - "ext-phar": "*", - "ext-xmlwriter": "*", - "phar-io/version": "^3.0.1", - "php": "^7.2 || ^8.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.0.x-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Arne Blankerts", - "email": "arne@blankerts.de", - "role": "Developer" - }, - { - "name": "Sebastian Heuer", - "email": "sebastian@phpeople.de", - "role": "Developer" - }, - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "Developer" - } - ], - "description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)", - "support": { - "issues": "https://github.com/phar-io/manifest/issues", - "source": "https://github.com/phar-io/manifest/tree/2.0.3" - }, - "time": "2021-07-20T11:28:43+00:00" - }, - { - "name": "phar-io/version", - "version": "3.2.1", - "source": { - "type": "git", - "url": "https://github.com/phar-io/version.git", - "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phar-io/version/zipball/4f7fd7836c6f332bb2933569e566a0d6c4cbed74", - "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74", - "shasum": "" - }, - "require": { - "php": "^7.2 || ^8.0" - }, - "type": "library", - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Arne Blankerts", - "email": "arne@blankerts.de", - "role": "Developer" - }, - { - "name": "Sebastian Heuer", - "email": "sebastian@phpeople.de", - "role": "Developer" - }, - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "Developer" - } - ], - "description": "Library for handling version information and constraints", - "support": { - "issues": "https://github.com/phar-io/version/issues", - "source": "https://github.com/phar-io/version/tree/3.2.1" - }, - "time": "2022-02-21T01:04:05+00:00" - }, - { - "name": "phpunit/php-code-coverage", - "version": "9.2.29", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "6a3a87ac2bbe33b25042753df8195ba4aa534c76" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/6a3a87ac2bbe33b25042753df8195ba4aa534c76", - "reference": "6a3a87ac2bbe33b25042753df8195ba4aa534c76", - "shasum": "" - }, - "require": { - "ext-dom": "*", - "ext-libxml": "*", - "ext-xmlwriter": "*", - "nikic/php-parser": "^4.15", - "php": ">=7.3", - "phpunit/php-file-iterator": "^3.0.3", - "phpunit/php-text-template": "^2.0.2", - "sebastian/code-unit-reverse-lookup": "^2.0.2", - "sebastian/complexity": "^2.0", - "sebastian/environment": "^5.1.2", - "sebastian/lines-of-code": "^1.0.3", - "sebastian/version": "^3.0.1", - "theseer/tokenizer": "^1.2.0" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" - }, - "suggest": { - "ext-pcov": "PHP extension that provides line coverage", - "ext-xdebug": "PHP extension that provides line coverage as well as branch and path coverage" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "9.2-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.", - "homepage": "https://github.com/sebastianbergmann/php-code-coverage", - "keywords": [ - "coverage", - "testing", - "xunit" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", - "security": "https://github.com/sebastianbergmann/php-code-coverage/security/policy", - "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.29" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2023-09-19T04:57:46+00:00" - }, - { - "name": "phpunit/php-file-iterator", - "version": "3.0.6", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-file-iterator.git", - "reference": "cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf", - "reference": "cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf", - "shasum": "" - }, - "require": { - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "FilterIterator implementation that filters files based on a list of suffixes.", - "homepage": "https://github.com/sebastianbergmann/php-file-iterator/", - "keywords": [ - "filesystem", - "iterator" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/php-file-iterator/issues", - "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/3.0.6" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2021-12-02T12:48:52+00:00" - }, - { - "name": "phpunit/php-invoker", - "version": "3.1.1", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-invoker.git", - "reference": "5a10147d0aaf65b58940a0b72f71c9ac0423cc67" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-invoker/zipball/5a10147d0aaf65b58940a0b72f71c9ac0423cc67", - "reference": "5a10147d0aaf65b58940a0b72f71c9ac0423cc67", - "shasum": "" - }, - "require": { - "php": ">=7.3" - }, - "require-dev": { - "ext-pcntl": "*", - "phpunit/phpunit": "^9.3" - }, - "suggest": { - "ext-pcntl": "*" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.1-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Invoke callables with a timeout", - "homepage": "https://github.com/sebastianbergmann/php-invoker/", - "keywords": [ - "process" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/php-invoker/issues", - "source": "https://github.com/sebastianbergmann/php-invoker/tree/3.1.1" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-09-28T05:58:55+00:00" - }, - { - "name": "phpunit/php-text-template", - "version": "2.0.4", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-text-template.git", - "reference": "5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28", - "reference": "5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28", - "shasum": "" - }, - "require": { - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Simple template engine.", - "homepage": "https://github.com/sebastianbergmann/php-text-template/", - "keywords": [ - "template" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/php-text-template/issues", - "source": "https://github.com/sebastianbergmann/php-text-template/tree/2.0.4" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-10-26T05:33:50+00:00" - }, - { - "name": "phpunit/php-timer", - "version": "5.0.3", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-timer.git", - "reference": "5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2", - "reference": "5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2", - "shasum": "" - }, - "require": { - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "5.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Utility class for timing", - "homepage": "https://github.com/sebastianbergmann/php-timer/", - "keywords": [ - "timer" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/php-timer/issues", - "source": "https://github.com/sebastianbergmann/php-timer/tree/5.0.3" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-10-26T13:16:10+00:00" - }, - { - "name": "phpunit/phpunit", - "version": "9.6.15", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "05017b80304e0eb3f31d90194a563fd53a6021f1" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/05017b80304e0eb3f31d90194a563fd53a6021f1", - "reference": "05017b80304e0eb3f31d90194a563fd53a6021f1", - "shasum": "" - }, - "require": { - "doctrine/instantiator": "^1.3.1 || ^2", - "ext-dom": "*", - "ext-json": "*", - "ext-libxml": "*", - "ext-mbstring": "*", - "ext-xml": "*", - "ext-xmlwriter": "*", - "myclabs/deep-copy": "^1.10.1", - "phar-io/manifest": "^2.0.3", - "phar-io/version": "^3.0.2", - "php": ">=7.3", - "phpunit/php-code-coverage": "^9.2.28", - "phpunit/php-file-iterator": "^3.0.5", - "phpunit/php-invoker": "^3.1.1", - "phpunit/php-text-template": "^2.0.3", - "phpunit/php-timer": "^5.0.2", - "sebastian/cli-parser": "^1.0.1", - "sebastian/code-unit": "^1.0.6", - "sebastian/comparator": "^4.0.8", - "sebastian/diff": "^4.0.3", - "sebastian/environment": "^5.1.3", - "sebastian/exporter": "^4.0.5", - "sebastian/global-state": "^5.0.1", - "sebastian/object-enumerator": "^4.0.3", - "sebastian/resource-operations": "^3.0.3", - "sebastian/type": "^3.2", - "sebastian/version": "^3.0.2" - }, - "suggest": { - "ext-soap": "To be able to generate mocks based on WSDL files", - "ext-xdebug": "PHP extension that provides line coverage as well as branch and path coverage" - }, - "bin": [ - "phpunit" - ], - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "9.6-dev" - } - }, - "autoload": { - "files": [ - "src/Framework/Assert/Functions.php" - ], - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "The PHP Unit Testing framework.", - "homepage": "https://phpunit.de/", - "keywords": [ - "phpunit", - "testing", - "xunit" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/phpunit/issues", - "security": "https://github.com/sebastianbergmann/phpunit/security/policy", - "source": "https://github.com/sebastianbergmann/phpunit/tree/9.6.15" - }, - "funding": [ - { - "url": "https://phpunit.de/sponsors.html", - "type": "custom" - }, - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/phpunit/phpunit", - "type": "tidelift" - } - ], - "time": "2023-12-01T16:55:19+00:00" - }, - { - "name": "sebastian/cli-parser", - "version": "1.0.1", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/cli-parser.git", - "reference": "442e7c7e687e42adc03470c7b668bc4b2402c0b2" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/442e7c7e687e42adc03470c7b668bc4b2402c0b2", - "reference": "442e7c7e687e42adc03470c7b668bc4b2402c0b2", - "shasum": "" - }, - "require": { - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Library for parsing CLI options", - "homepage": "https://github.com/sebastianbergmann/cli-parser", - "support": { - "issues": "https://github.com/sebastianbergmann/cli-parser/issues", - "source": "https://github.com/sebastianbergmann/cli-parser/tree/1.0.1" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-09-28T06:08:49+00:00" - }, - { - "name": "sebastian/code-unit", - "version": "1.0.8", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/code-unit.git", - "reference": "1fc9f64c0927627ef78ba436c9b17d967e68e120" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/code-unit/zipball/1fc9f64c0927627ef78ba436c9b17d967e68e120", - "reference": "1fc9f64c0927627ef78ba436c9b17d967e68e120", - "shasum": "" - }, - "require": { - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Collection of value objects that represent the PHP code units", - "homepage": "https://github.com/sebastianbergmann/code-unit", - "support": { - "issues": "https://github.com/sebastianbergmann/code-unit/issues", - "source": "https://github.com/sebastianbergmann/code-unit/tree/1.0.8" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-10-26T13:08:54+00:00" - }, - { - "name": "sebastian/code-unit-reverse-lookup", - "version": "2.0.3", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git", - "reference": "ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5", - "reference": "ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5", - "shasum": "" - }, - "require": { - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Looks up which function or method a line of code belongs to", - "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/", - "support": { - "issues": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/issues", - "source": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/tree/2.0.3" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-09-28T05:30:19+00:00" - }, - { - "name": "sebastian/comparator", - "version": "4.0.8", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/comparator.git", - "reference": "fa0f136dd2334583309d32b62544682ee972b51a" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/fa0f136dd2334583309d32b62544682ee972b51a", - "reference": "fa0f136dd2334583309d32b62544682ee972b51a", - "shasum": "" - }, - "require": { - "php": ">=7.3", - "sebastian/diff": "^4.0", - "sebastian/exporter": "^4.0" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "4.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - }, - { - "name": "Jeff Welch", - "email": "whatthejeff@gmail.com" - }, - { - "name": "Volker Dusch", - "email": "github@wallbash.com" - }, - { - "name": "Bernhard Schussek", - "email": "bschussek@2bepublished.at" - } - ], - "description": "Provides the functionality to compare PHP values for equality", - "homepage": "https://github.com/sebastianbergmann/comparator", - "keywords": [ - "comparator", - "compare", - "equality" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/comparator/issues", - "source": "https://github.com/sebastianbergmann/comparator/tree/4.0.8" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2022-09-14T12:41:17+00:00" - }, - { - "name": "sebastian/complexity", - "version": "2.0.2", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/complexity.git", - "reference": "739b35e53379900cc9ac327b2147867b8b6efd88" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/739b35e53379900cc9ac327b2147867b8b6efd88", - "reference": "739b35e53379900cc9ac327b2147867b8b6efd88", - "shasum": "" - }, - "require": { - "nikic/php-parser": "^4.7", - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Library for calculating the complexity of PHP code units", - "homepage": "https://github.com/sebastianbergmann/complexity", - "support": { - "issues": "https://github.com/sebastianbergmann/complexity/issues", - "source": "https://github.com/sebastianbergmann/complexity/tree/2.0.2" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-10-26T15:52:27+00:00" - }, - { - "name": "sebastian/diff", - "version": "4.0.5", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/diff.git", - "reference": "74be17022044ebaaecfdf0c5cd504fc9cd5a7131" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/74be17022044ebaaecfdf0c5cd504fc9cd5a7131", - "reference": "74be17022044ebaaecfdf0c5cd504fc9cd5a7131", - "shasum": "" - }, - "require": { - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.3", - "symfony/process": "^4.2 || ^5" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "4.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - }, - { - "name": "Kore Nordmann", - "email": "mail@kore-nordmann.de" - } - ], - "description": "Diff implementation", - "homepage": "https://github.com/sebastianbergmann/diff", - "keywords": [ - "diff", - "udiff", - "unidiff", - "unified diff" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/diff/issues", - "source": "https://github.com/sebastianbergmann/diff/tree/4.0.5" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2023-05-07T05:35:17+00:00" - }, - { - "name": "sebastian/environment", - "version": "5.1.5", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/environment.git", - "reference": "830c43a844f1f8d5b7a1f6d6076b784454d8b7ed" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/830c43a844f1f8d5b7a1f6d6076b784454d8b7ed", - "reference": "830c43a844f1f8d5b7a1f6d6076b784454d8b7ed", - "shasum": "" - }, - "require": { - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" - }, - "suggest": { - "ext-posix": "*" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "5.1-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Provides functionality to handle HHVM/PHP environments", - "homepage": "http://www.github.com/sebastianbergmann/environment", - "keywords": [ - "Xdebug", - "environment", - "hhvm" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/environment/issues", - "source": "https://github.com/sebastianbergmann/environment/tree/5.1.5" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2023-02-03T06:03:51+00:00" - }, - { - "name": "sebastian/exporter", - "version": "4.0.5", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/exporter.git", - "reference": "ac230ed27f0f98f597c8a2b6eb7ac563af5e5b9d" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/ac230ed27f0f98f597c8a2b6eb7ac563af5e5b9d", - "reference": "ac230ed27f0f98f597c8a2b6eb7ac563af5e5b9d", - "shasum": "" - }, - "require": { - "php": ">=7.3", - "sebastian/recursion-context": "^4.0" - }, - "require-dev": { - "ext-mbstring": "*", - "phpunit/phpunit": "^9.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "4.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - }, - { - "name": "Jeff Welch", - "email": "whatthejeff@gmail.com" - }, - { - "name": "Volker Dusch", - "email": "github@wallbash.com" - }, - { - "name": "Adam Harvey", - "email": "aharvey@php.net" - }, - { - "name": "Bernhard Schussek", - "email": "bschussek@gmail.com" - } - ], - "description": "Provides the functionality to export PHP variables for visualization", - "homepage": "https://www.github.com/sebastianbergmann/exporter", - "keywords": [ - "export", - "exporter" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/exporter/issues", - "source": "https://github.com/sebastianbergmann/exporter/tree/4.0.5" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2022-09-14T06:03:37+00:00" - }, - { - "name": "sebastian/global-state", - "version": "5.0.6", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/global-state.git", - "reference": "bde739e7565280bda77be70044ac1047bc007e34" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/bde739e7565280bda77be70044ac1047bc007e34", - "reference": "bde739e7565280bda77be70044ac1047bc007e34", - "shasum": "" - }, - "require": { - "php": ">=7.3", - "sebastian/object-reflector": "^2.0", - "sebastian/recursion-context": "^4.0" - }, - "require-dev": { - "ext-dom": "*", - "phpunit/phpunit": "^9.3" - }, - "suggest": { - "ext-uopz": "*" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "5.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Snapshotting of global state", - "homepage": "http://www.github.com/sebastianbergmann/global-state", - "keywords": [ - "global state" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/global-state/issues", - "source": "https://github.com/sebastianbergmann/global-state/tree/5.0.6" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2023-08-02T09:26:13+00:00" - }, - { - "name": "sebastian/lines-of-code", - "version": "1.0.3", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/lines-of-code.git", - "reference": "c1c2e997aa3146983ed888ad08b15470a2e22ecc" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/c1c2e997aa3146983ed888ad08b15470a2e22ecc", - "reference": "c1c2e997aa3146983ed888ad08b15470a2e22ecc", - "shasum": "" - }, - "require": { - "nikic/php-parser": "^4.6", - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Library for counting the lines of code in PHP source code", - "homepage": "https://github.com/sebastianbergmann/lines-of-code", - "support": { - "issues": "https://github.com/sebastianbergmann/lines-of-code/issues", - "source": "https://github.com/sebastianbergmann/lines-of-code/tree/1.0.3" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-11-28T06:42:11+00:00" - }, - { - "name": "sebastian/object-enumerator", - "version": "4.0.4", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/object-enumerator.git", - "reference": "5c9eeac41b290a3712d88851518825ad78f45c71" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/5c9eeac41b290a3712d88851518825ad78f45c71", - "reference": "5c9eeac41b290a3712d88851518825ad78f45c71", - "shasum": "" - }, - "require": { - "php": ">=7.3", - "sebastian/object-reflector": "^2.0", - "sebastian/recursion-context": "^4.0" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "4.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Traverses array structures and object graphs to enumerate all referenced objects", - "homepage": "https://github.com/sebastianbergmann/object-enumerator/", - "support": { - "issues": "https://github.com/sebastianbergmann/object-enumerator/issues", - "source": "https://github.com/sebastianbergmann/object-enumerator/tree/4.0.4" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-10-26T13:12:34+00:00" - }, - { - "name": "sebastian/object-reflector", - "version": "2.0.4", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/object-reflector.git", - "reference": "b4f479ebdbf63ac605d183ece17d8d7fe49c15c7" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/b4f479ebdbf63ac605d183ece17d8d7fe49c15c7", - "reference": "b4f479ebdbf63ac605d183ece17d8d7fe49c15c7", - "shasum": "" - }, - "require": { - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Allows reflection of object attributes, including inherited and non-public ones", - "homepage": "https://github.com/sebastianbergmann/object-reflector/", - "support": { - "issues": "https://github.com/sebastianbergmann/object-reflector/issues", - "source": "https://github.com/sebastianbergmann/object-reflector/tree/2.0.4" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-10-26T13:14:26+00:00" - }, - { - "name": "sebastian/recursion-context", - "version": "4.0.5", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/recursion-context.git", - "reference": "e75bd0f07204fec2a0af9b0f3cfe97d05f92efc1" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/e75bd0f07204fec2a0af9b0f3cfe97d05f92efc1", - "reference": "e75bd0f07204fec2a0af9b0f3cfe97d05f92efc1", - "shasum": "" - }, - "require": { - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "4.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - }, - { - "name": "Jeff Welch", - "email": "whatthejeff@gmail.com" - }, - { - "name": "Adam Harvey", - "email": "aharvey@php.net" - } - ], - "description": "Provides functionality to recursively process PHP variables", - "homepage": "https://github.com/sebastianbergmann/recursion-context", - "support": { - "issues": "https://github.com/sebastianbergmann/recursion-context/issues", - "source": "https://github.com/sebastianbergmann/recursion-context/tree/4.0.5" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2023-02-03T06:07:39+00:00" - }, - { - "name": "sebastian/resource-operations", - "version": "3.0.3", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/resource-operations.git", - "reference": "0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8", - "reference": "0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8", - "shasum": "" - }, - "require": { - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Provides a list of PHP built-in functions that operate on resources", - "homepage": "https://www.github.com/sebastianbergmann/resource-operations", - "support": { - "issues": "https://github.com/sebastianbergmann/resource-operations/issues", - "source": "https://github.com/sebastianbergmann/resource-operations/tree/3.0.3" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-09-28T06:45:17+00:00" - }, - { - "name": "sebastian/type", - "version": "3.2.1", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/type.git", - "reference": "75e2c2a32f5e0b3aef905b9ed0b179b953b3d7c7" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/75e2c2a32f5e0b3aef905b9ed0b179b953b3d7c7", - "reference": "75e2c2a32f5e0b3aef905b9ed0b179b953b3d7c7", - "shasum": "" - }, - "require": { - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.5" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.2-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Collection of value objects that represent the types of the PHP type system", - "homepage": "https://github.com/sebastianbergmann/type", - "support": { - "issues": "https://github.com/sebastianbergmann/type/issues", - "source": "https://github.com/sebastianbergmann/type/tree/3.2.1" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2023-02-03T06:13:03+00:00" - }, - { - "name": "sebastian/version", - "version": "3.0.2", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/version.git", - "reference": "c6c1022351a901512170118436c764e473f6de8c" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/c6c1022351a901512170118436c764e473f6de8c", - "reference": "c6c1022351a901512170118436c764e473f6de8c", - "shasum": "" - }, - "require": { - "php": ">=7.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Library that helps with managing the version number of Git-hosted PHP projects", - "homepage": "https://github.com/sebastianbergmann/version", - "support": { - "issues": "https://github.com/sebastianbergmann/version/issues", - "source": "https://github.com/sebastianbergmann/version/tree/3.0.2" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-09-28T06:39:44+00:00" - }, - { - "name": "symfony/browser-kit", - "version": "v6.3.8", - "source": { - "type": "git", - "url": "https://github.com/symfony/browser-kit.git", - "reference": "e270297dbee59168274c2b535ab1bccd593e6ffe" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/browser-kit/zipball/e270297dbee59168274c2b535ab1bccd593e6ffe", - "reference": "e270297dbee59168274c2b535ab1bccd593e6ffe", - "shasum": "" - }, - "require": { - "php": ">=8.1", - "symfony/dom-crawler": "^5.4|^6.0" - }, - "require-dev": { - "symfony/css-selector": "^5.4|^6.0", - "symfony/http-client": "^5.4|^6.0", - "symfony/mime": "^5.4|^6.0", - "symfony/process": "^5.4|^6.0" - }, - "type": "library", - "autoload": { - "psr-4": { - "Symfony\\Component\\BrowserKit\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Simulates the behavior of a web browser, allowing you to make requests, click on links and submit forms programmatically", - "homepage": "https://symfony.com", - "support": { - "source": "https://github.com/symfony/browser-kit/tree/v6.3.8" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2023-10-31T08:07:48+00:00" - }, - { - "name": "symfony/css-selector", - "version": "v6.3.2", - "source": { - "type": "git", - "url": "https://github.com/symfony/css-selector.git", - "reference": "883d961421ab1709877c10ac99451632a3d6fa57" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/css-selector/zipball/883d961421ab1709877c10ac99451632a3d6fa57", - "reference": "883d961421ab1709877c10ac99451632a3d6fa57", - "shasum": "" - }, - "require": { - "php": ">=8.1" - }, - "type": "library", - "autoload": { - "psr-4": { - "Symfony\\Component\\CssSelector\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Jean-François Simon", - "email": "jeanfrancois.simon@sensiolabs.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Converts CSS selectors to XPath expressions", - "homepage": "https://symfony.com", - "support": { - "source": "https://github.com/symfony/css-selector/tree/v6.3.2" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2023-07-12T16:00:22+00:00" - }, - { - "name": "symfony/debug-bundle", - "version": "v6.3.2", - "source": { - "type": "git", - "url": "https://github.com/symfony/debug-bundle.git", - "reference": "3f04a578e1a9f1d7da84a87b690c03123e5d8c31" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/debug-bundle/zipball/3f04a578e1a9f1d7da84a87b690c03123e5d8c31", - "reference": "3f04a578e1a9f1d7da84a87b690c03123e5d8c31", - "shasum": "" - }, - "require": { - "ext-xml": "*", - "php": ">=8.1", - "symfony/dependency-injection": "^5.4|^6.0", - "symfony/http-kernel": "^5.4|^6.0", - "symfony/twig-bridge": "^5.4|^6.0", - "symfony/var-dumper": "^5.4|^6.0" - }, - "conflict": { - "symfony/config": "<5.4", - "symfony/dependency-injection": "<5.4" - }, - "require-dev": { - "symfony/config": "^5.4|^6.0", - "symfony/web-profiler-bundle": "^5.4|^6.0" - }, - "type": "symfony-bundle", - "autoload": { - "psr-4": { - "Symfony\\Bundle\\DebugBundle\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Provides a tight integration of the Symfony VarDumper component and the ServerLogCommand from MonologBridge into the Symfony full-stack framework", - "homepage": "https://symfony.com", - "support": { - "source": "https://github.com/symfony/debug-bundle/tree/v6.3.2" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2023-07-13T14:29:38+00:00" - }, - { - "name": "symfony/dom-crawler", - "version": "v6.3.9", - "source": { - "type": "git", - "url": "https://github.com/symfony/dom-crawler.git", - "reference": "b7065c123ae977a008568a3d016a17a110df7a8e" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/dom-crawler/zipball/b7065c123ae977a008568a3d016a17a110df7a8e", - "reference": "b7065c123ae977a008568a3d016a17a110df7a8e", - "shasum": "" - }, - "require": { - "masterminds/html5": "^2.6", - "php": ">=8.1", - "symfony/polyfill-ctype": "~1.8", - "symfony/polyfill-mbstring": "~1.0" - }, - "require-dev": { - "symfony/css-selector": "^5.4|^6.0" - }, - "type": "library", - "autoload": { - "psr-4": { - "Symfony\\Component\\DomCrawler\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Eases DOM navigation for HTML and XML documents", - "homepage": "https://symfony.com", - "support": { - "source": "https://github.com/symfony/dom-crawler/tree/v6.3.9" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2023-11-20T16:36:29+00:00" - }, - { - "name": "symfony/maker-bundle", - "version": "v1.52.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/maker-bundle.git", - "reference": "112f9466c94a46ca33dc441eee59a12cd1790757" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/maker-bundle/zipball/112f9466c94a46ca33dc441eee59a12cd1790757", - "reference": "112f9466c94a46ca33dc441eee59a12cd1790757", - "shasum": "" - }, - "require": { - "doctrine/inflector": "^2.0", - "nikic/php-parser": "^4.11", - "php": ">=8.1", - "symfony/config": "^6.3|^7.0", - "symfony/console": "^6.3|^7.0", - "symfony/dependency-injection": "^6.3|^7.0", - "symfony/deprecation-contracts": "^2.2|^3", - "symfony/filesystem": "^6.3|^7.0", - "symfony/finder": "^6.3|^7.0", - "symfony/framework-bundle": "^6.3|^7.0", - "symfony/http-kernel": "^6.3|^7.0", - "symfony/process": "^6.3|^7.0" - }, - "conflict": { - "doctrine/doctrine-bundle": "<2.4", - "doctrine/orm": "<2.10" - }, - "require-dev": { - "composer/semver": "^3.0", - "doctrine/doctrine-bundle": "^2.5.0", - "doctrine/orm": "^2.10.0", - "symfony/http-client": "^6.3|^7.0", - "symfony/phpunit-bridge": "^6.3|^7.0", - "symfony/security-core": "^6.3|^7.0", - "symfony/yaml": "^6.3|^7.0", - "twig/twig": "^2.0|^3.0" - }, - "type": "symfony-bundle", - "extra": { - "branch-alias": { - "dev-main": "1.x-dev" - } - }, - "autoload": { - "psr-4": { - "Symfony\\Bundle\\MakerBundle\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony Maker helps you create empty commands, controllers, form classes, tests and more so you can forget about writing boilerplate code.", - "homepage": "https://symfony.com/doc/current/bundles/SymfonyMakerBundle/index.html", - "keywords": [ - "code generator", - "dev", - "generator", - "scaffold", - "scaffolding" - ], - "support": { - "issues": "https://github.com/symfony/maker-bundle/issues", - "source": "https://github.com/symfony/maker-bundle/tree/v1.52.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2023-10-31T18:23:49+00:00" - }, - { - "name": "symfony/phpunit-bridge", - "version": "v6.4.1", - "source": { - "type": "git", - "url": "https://github.com/symfony/phpunit-bridge.git", - "reference": "cca5373a41d45edbeaf38b7b67f376da2205ff95" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/phpunit-bridge/zipball/cca5373a41d45edbeaf38b7b67f376da2205ff95", - "reference": "cca5373a41d45edbeaf38b7b67f376da2205ff95", - "shasum": "" - }, - "require": { - "php": ">=7.1.3" - }, - "conflict": { - "phpunit/phpunit": "<7.5|9.1.2" - }, - "require-dev": { - "symfony/deprecation-contracts": "^2.5|^3.0", - "symfony/error-handler": "^5.4|^6.0|^7.0", - "symfony/polyfill-php81": "^1.27" - }, - "bin": [ - "bin/simple-phpunit" - ], - "type": "symfony-bridge", - "extra": { - "thanks": { - "name": "phpunit/phpunit", - "url": "https://github.com/sebastianbergmann/phpunit" - } - }, - "autoload": { - "files": [ - "bootstrap.php" - ], - "psr-4": { - "Symfony\\Bridge\\PhpUnit\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Provides utilities for PHPUnit, especially user deprecation notices management", - "homepage": "https://symfony.com", - "support": { - "source": "https://github.com/symfony/phpunit-bridge/tree/v6.4.1" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2023-12-01T09:25:07+00:00" - }, - { - "name": "symfony/web-profiler-bundle", - "version": "v6.3.8", - "source": { - "type": "git", - "url": "https://github.com/symfony/web-profiler-bundle.git", - "reference": "4167c20cbdbb1152007fa731718c8c0362f28617" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/web-profiler-bundle/zipball/4167c20cbdbb1152007fa731718c8c0362f28617", - "reference": "4167c20cbdbb1152007fa731718c8c0362f28617", - "shasum": "" - }, - "require": { - "php": ">=8.1", - "symfony/config": "^5.4|^6.0", - "symfony/framework-bundle": "^5.4|^6.0,<6.4", - "symfony/http-kernel": "^6.3", - "symfony/routing": "^5.4|^6.0", - "symfony/twig-bundle": "^5.4|^6.0", - "twig/twig": "^2.13|^3.0.4" - }, - "conflict": { - "symfony/form": "<5.4", - "symfony/mailer": "<5.4", - "symfony/messenger": "<5.4" - }, - "require-dev": { - "symfony/browser-kit": "^5.4|^6.0", - "symfony/console": "^5.4|^6.0", - "symfony/css-selector": "^5.4|^6.0", - "symfony/stopwatch": "^5.4|^6.0" - }, - "type": "symfony-bundle", - "autoload": { - "psr-4": { - "Symfony\\Bundle\\WebProfilerBundle\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Provides a development tool that gives detailed information about the execution of any request", - "homepage": "https://symfony.com", - "keywords": [ - "dev" - ], - "support": { - "source": "https://github.com/symfony/web-profiler-bundle/tree/v6.3.8" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2023-10-31T14:41:59+00:00" - }, - { - "name": "theseer/tokenizer", - "version": "1.2.2", - "source": { - "type": "git", - "url": "https://github.com/theseer/tokenizer.git", - "reference": "b2ad5003ca10d4ee50a12da31de12a5774ba6b96" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/theseer/tokenizer/zipball/b2ad5003ca10d4ee50a12da31de12a5774ba6b96", - "reference": "b2ad5003ca10d4ee50a12da31de12a5774ba6b96", - "shasum": "" - }, - "require": { - "ext-dom": "*", - "ext-tokenizer": "*", - "ext-xmlwriter": "*", - "php": "^7.2 || ^8.0" - }, - "type": "library", - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Arne Blankerts", - "email": "arne@blankerts.de", - "role": "Developer" - } - ], - "description": "A small library for converting tokenized PHP source code into XML and potentially other formats", - "support": { - "issues": "https://github.com/theseer/tokenizer/issues", - "source": "https://github.com/theseer/tokenizer/tree/1.2.2" - }, - "funding": [ - { - "url": "https://github.com/theseer", - "type": "github" - } - ], - "time": "2023-11-20T00:12:19+00:00" - } - ], - "aliases": [], - "minimum-stability": "stable", - "stability-flags": [], - "prefer-stable": true, - "prefer-lowest": false, - "platform": { - "php": ">=8.1", - "ext-ctype": "*", - "ext-iconv": "*" - }, - "platform-dev": [], - "plugin-api-version": "2.3.0" -} diff --git a/config/bundles.php b/config/bundles.php deleted file mode 100644 index 0457f99..0000000 --- a/config/bundles.php +++ /dev/null @@ -1,14 +0,0 @@ - ['all' => true], - Doctrine\Bundle\DoctrineBundle\DoctrineBundle::class => ['all' => true], - Doctrine\Bundle\MigrationsBundle\DoctrineMigrationsBundle::class => ['all' => true], - Symfony\Bundle\DebugBundle\DebugBundle::class => ['dev' => true], - Symfony\Bundle\TwigBundle\TwigBundle::class => ['all' => true], - Symfony\Bundle\WebProfilerBundle\WebProfilerBundle::class => ['dev' => true, 'test' => true], - Twig\Extra\TwigExtraBundle\TwigExtraBundle::class => ['all' => true], - Symfony\Bundle\SecurityBundle\SecurityBundle::class => ['all' => true], - Symfony\Bundle\MonologBundle\MonologBundle::class => ['all' => true], - Symfony\Bundle\MakerBundle\MakerBundle::class => ['dev' => true], -]; diff --git a/config/packages/cache.yaml b/config/packages/cache.yaml deleted file mode 100644 index 6899b72..0000000 --- a/config/packages/cache.yaml +++ /dev/null @@ -1,19 +0,0 @@ -framework: - cache: - # Unique name of your app: used to compute stable namespaces for cache keys. - #prefix_seed: your_vendor_name/app_name - - # The "app" cache stores to the filesystem by default. - # The data in this cache should persist between deploys. - # Other options include: - - # Redis - #app: cache.adapter.redis - #default_redis_provider: redis://localhost - - # APCu (not recommended with heavy random-write workloads as memory fragmentation can cause perf issues) - #app: cache.adapter.apcu - - # Namespaced pools use the above "app" backend by default - #pools: - #my.dedicated.cache: null diff --git a/config/packages/debug.yaml b/config/packages/debug.yaml deleted file mode 100644 index ad874af..0000000 --- a/config/packages/debug.yaml +++ /dev/null @@ -1,5 +0,0 @@ -when@dev: - debug: - # Forwards VarDumper Data clones to a centralized server allowing to inspect dumps on CLI or in your browser. - # See the "server:dump" command to start a new server. - dump_destination: "tcp://%env(VAR_DUMPER_SERVER)%" diff --git a/config/packages/doctrine.yaml b/config/packages/doctrine.yaml deleted file mode 100644 index ec0f77e..0000000 --- a/config/packages/doctrine.yaml +++ /dev/null @@ -1,48 +0,0 @@ -doctrine: - dbal: - url: '%env(resolve:DATABASE_URL)%' - - # IMPORTANT: You MUST configure your server version, - # either here or in the DATABASE_URL env var (see .env file) - #server_version: '15' - - profiling_collect_backtrace: '%kernel.debug%' - orm: - auto_generate_proxy_classes: true - enable_lazy_ghost_objects: true - report_fields_where_declared: true - validate_xml_mapping: true - naming_strategy: doctrine.orm.naming_strategy.underscore_number_aware - auto_mapping: true - mappings: - App: - is_bundle: false - dir: '%kernel.project_dir%/src/Entity' - prefix: 'App\Entity' - alias: App - -when@test: - doctrine: - dbal: - # "TEST_TOKEN" is typically set by ParaTest - dbname_suffix: '_test%env(default::TEST_TOKEN)%' - -when@prod: - doctrine: - orm: - auto_generate_proxy_classes: false - proxy_dir: '%kernel.build_dir%/doctrine/orm/Proxies' - query_cache_driver: - type: pool - pool: doctrine.system_cache_pool - result_cache_driver: - type: pool - pool: doctrine.result_cache_pool - - framework: - cache: - pools: - doctrine.result_cache_pool: - adapter: cache.app - doctrine.system_cache_pool: - adapter: cache.system diff --git a/config/packages/doctrine_migrations.yaml b/config/packages/doctrine_migrations.yaml deleted file mode 100644 index 29231d9..0000000 --- a/config/packages/doctrine_migrations.yaml +++ /dev/null @@ -1,6 +0,0 @@ -doctrine_migrations: - migrations_paths: - # namespace is arbitrary but should be different from App\Migrations - # as migrations classes should NOT be autoloaded - 'DoctrineMigrations': '%kernel.project_dir%/migrations' - enable_profiler: false diff --git a/config/packages/framework.yaml b/config/packages/framework.yaml deleted file mode 100644 index 6d85c29..0000000 --- a/config/packages/framework.yaml +++ /dev/null @@ -1,25 +0,0 @@ -# see https://symfony.com/doc/current/reference/configuration/framework.html -framework: - secret: '%env(APP_SECRET)%' - #csrf_protection: true - http_method_override: false - handle_all_throwables: true - - # Enables session support. Note that the session will ONLY be started if you read or write from it. - # Remove or comment this section to explicitly disable session support. - session: - handler_id: null - cookie_secure: auto - cookie_samesite: lax - storage_factory_id: session.storage.factory.native - - #esi: true - #fragments: true - php_errors: - log: true - -when@test: - framework: - test: true - session: - storage_factory_id: session.storage.factory.mock_file diff --git a/config/packages/mailer.yaml b/config/packages/mailer.yaml deleted file mode 100644 index 56a650d..0000000 --- a/config/packages/mailer.yaml +++ /dev/null @@ -1,3 +0,0 @@ -framework: - mailer: - dsn: '%env(MAILER_DSN)%' diff --git a/config/packages/messenger.yaml b/config/packages/messenger.yaml deleted file mode 100644 index 587083a..0000000 --- a/config/packages/messenger.yaml +++ /dev/null @@ -1,24 +0,0 @@ -framework: - messenger: - failure_transport: failed - - transports: - # https://symfony.com/doc/current/messenger.html#transport-configuration - async: - dsn: '%env(MESSENGER_TRANSPORT_DSN)%' - options: - use_notify: true - check_delayed_interval: 60000 - retry_strategy: - max_retries: 3 - multiplier: 2 - failed: 'doctrine://default?queue_name=failed' - # sync: 'sync://' - - routing: - Symfony\Component\Mailer\Messenger\SendEmailMessage: async - Symfony\Component\Notifier\Message\ChatMessage: async - Symfony\Component\Notifier\Message\SmsMessage: async - - # Route your messages to the transports - # 'App\Message\YourMessage': async diff --git a/config/packages/monolog.yaml b/config/packages/monolog.yaml deleted file mode 100644 index 2b3726f..0000000 --- a/config/packages/monolog.yaml +++ /dev/null @@ -1,62 +0,0 @@ -monolog: - channels: - - deprecation # Deprecations are logged in the dedicated "deprecation" channel when it exists - -when@dev: - monolog: - handlers: - main: - type: stream - path: "%kernel.logs_dir%/%kernel.environment%.log" - level: debug - channels: ["!event"] - # uncomment to get logging in your browser - # you may have to allow bigger header sizes in your Web server configuration - #firephp: - # type: firephp - # level: info - #chromephp: - # type: chromephp - # level: info - console: - type: console - process_psr_3_messages: false - channels: ["!event", "!doctrine", "!console"] - -when@test: - monolog: - handlers: - main: - type: fingers_crossed - action_level: error - handler: nested - excluded_http_codes: [404, 405] - channels: ["!event"] - nested: - type: stream - path: "%kernel.logs_dir%/%kernel.environment%.log" - level: debug - -when@prod: - monolog: - handlers: - main: - type: fingers_crossed - action_level: error - handler: nested - excluded_http_codes: [404, 405] - buffer_size: 50 # How many messages should be saved? Prevent memory leaks - nested: - type: stream - # path: php://stderr - path: "%kernel.logs_dir%/%kernel.environment%.log" - level: debug - # formatter: monolog.formatter.json - console: - type: console - process_psr_3_messages: false - channels: ["!event", "!doctrine"] - deprecation: - type: stream - channels: [deprecation] - path: php://stderr diff --git a/config/packages/notifier.yaml b/config/packages/notifier.yaml deleted file mode 100644 index 7f4bed1..0000000 --- a/config/packages/notifier.yaml +++ /dev/null @@ -1,13 +0,0 @@ -framework: - notifier: - chatter_transports: - texter_transports: - crowdin: '%env(CROWDIN_DSN)%' - channel_policy: - # use chat/slack, chat/telegram, sms/twilio or sms/nexmo - urgent: ['email'] - high: ['email'] - medium: ['email'] - low: ['email'] - admin_recipients: - - { email: admin@example.com } diff --git a/config/packages/routing.yaml b/config/packages/routing.yaml deleted file mode 100644 index 4b766ce..0000000 --- a/config/packages/routing.yaml +++ /dev/null @@ -1,12 +0,0 @@ -framework: - router: - utf8: true - - # Configure how to generate URLs in non-HTTP contexts, such as CLI commands. - # See https://symfony.com/doc/current/routing.html#generating-urls-in-commands - #default_uri: http://localhost - -when@prod: - framework: - router: - strict_requirements: null diff --git a/config/packages/security.yaml b/config/packages/security.yaml deleted file mode 100644 index 367af25..0000000 --- a/config/packages/security.yaml +++ /dev/null @@ -1,39 +0,0 @@ -security: - # https://symfony.com/doc/current/security.html#registering-the-user-hashing-passwords - password_hashers: - Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface: 'auto' - # https://symfony.com/doc/current/security.html#loading-the-user-the-user-provider - providers: - users_in_memory: { memory: null } - firewalls: - dev: - pattern: ^/(_(profiler|wdt)|css|images|js)/ - security: false - main: - lazy: true - provider: users_in_memory - - # activate different ways to authenticate - # https://symfony.com/doc/current/security.html#the-firewall - - # https://symfony.com/doc/current/security/impersonating_user.html - # switch_user: true - - # Easy way to control access for large sections of your site - # Note: Only the *first* access control that matches will be used - access_control: - # - { path: ^/admin, roles: ROLE_ADMIN } - # - { path: ^/profile, roles: ROLE_USER } - -when@test: - security: - password_hashers: - # By default, password hashers are resource intensive and take time. This is - # important to generate secure password hashes. In tests however, secure hashes - # are not important, waste resources and increase test times. The following - # reduces the work factor to the lowest possible values. - Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface: - algorithm: auto - cost: 4 # Lowest possible value for bcrypt - time_cost: 3 # Lowest possible value for argon - memory_cost: 10 # Lowest possible value for argon diff --git a/config/packages/translation.yaml b/config/packages/translation.yaml deleted file mode 100644 index 210ba05..0000000 --- a/config/packages/translation.yaml +++ /dev/null @@ -1,17 +0,0 @@ -framework: - default_locale: en - translator: - default_path: '%kernel.project_dir%/translations' - fallbacks: - - en - providers: - crowdin: - dsn: '%env(CROWDIN_DSN)%' - domains: ['messages'] - locales: ['en','cs','nl','eo','fr', 'ja', 'ka','de','he','it','lv','pl','pt','ru','es','uk'] -# loco: -# dsn: '%env(LOCO_DSN)%' -# lokalise: -# dsn: '%env(LOKALISE_DSN)%' -# phrase: -# dsn: '%env(PHRASE_DSN)%' diff --git a/config/packages/twig.yaml b/config/packages/twig.yaml deleted file mode 100644 index 236f109..0000000 --- a/config/packages/twig.yaml +++ /dev/null @@ -1,10 +0,0 @@ -twig: - default_path: '%kernel.project_dir%/templates' - globals: - version: '%app.version%' - name: '%app.name%' - theme: '%app.theme%' - -when@test: - twig: - strict_variables: true diff --git a/config/packages/validator.yaml b/config/packages/validator.yaml deleted file mode 100644 index 0201281..0000000 --- a/config/packages/validator.yaml +++ /dev/null @@ -1,13 +0,0 @@ -framework: - validation: - email_validation_mode: html5 - - # Enables validator auto-mapping support. - # For instance, basic validation constraints will be inferred from Doctrine's metadata. - #auto_mapping: - # App\Entity\: [] - -when@test: - framework: - validation: - not_compromised_password: false diff --git a/config/packages/web_profiler.yaml b/config/packages/web_profiler.yaml deleted file mode 100644 index b946111..0000000 --- a/config/packages/web_profiler.yaml +++ /dev/null @@ -1,17 +0,0 @@ -when@dev: - web_profiler: - toolbar: true - intercept_redirects: false - - framework: - profiler: - only_exceptions: false - collect_serializer_data: true - -when@test: - web_profiler: - toolbar: false - intercept_redirects: false - - framework: - profiler: { collect: false } diff --git a/config/preload.php b/config/preload.php deleted file mode 100644 index 5ebcdb2..0000000 --- a/config/preload.php +++ /dev/null @@ -1,5 +0,0 @@ - doctrine/doctrine-bundle ### - database: - ports: - - "5432" -###< doctrine/doctrine-bundle ### - -###> symfony/mailer ### - mailer: - image: schickling/mailcatcher - ports: ["1025", "1080"] -###< symfony/mailer ### diff --git a/docker-compose.yml b/docker-compose.yml deleted file mode 100644 index 1067b9c..0000000 --- a/docker-compose.yml +++ /dev/null @@ -1,21 +0,0 @@ -version: '3' - -services: -###> doctrine/doctrine-bundle ### - database: - image: postgres:${POSTGRES_VERSION:-15}-alpine - environment: - POSTGRES_DB: ${POSTGRES_DB:-app} - # You should definitely change the password in production - POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-!ChangeMe!} - POSTGRES_USER: ${POSTGRES_USER:-app} - volumes: - - database_data:/var/lib/postgresql/data:rw - # You may use a bind-mounted host directory instead, so that it is harder to accidentally remove the volume and lose all your data! - # - ./docker/db/data:/var/lib/postgresql/data:rw -###< doctrine/doctrine-bundle ### - -volumes: -###> doctrine/doctrine-bundle ### - database_data: -###< doctrine/doctrine-bundle ### diff --git a/example/environment/crontab b/example/environment/crontab new file mode 100644 index 0000000..136ec32 --- /dev/null +++ b/example/environment/crontab @@ -0,0 +1,10 @@ +@reboot searchd +@reboot indexer --all --rotate + +* * * * * indexer magnet --rotate > /dev/null 2>&1 + +* * * * * /usr/bin/php /YGGtracker/src/crontab/scrape.php > /dev/null 2>&1 +* * * * * /usr/bin/php /YGGtracker/src/crontab/export/push.php > /dev/null 2>&1 +0 5 * * * /usr/bin/php /YGGtracker/src/crontab/import/feed.php > /dev/null 2>&1 +0 0 * * * /usr/bin/php /YGGtracker/src/crontab/export/feed.php > /dev/null 2>&1 +0 0 * * * /usr/bin/php /YGGtracker/src/crontab/sitemap.php > /dev/null 2>&1 \ No newline at end of file diff --git a/example/environment/env.example.php b/example/environment/env.example.php new file mode 100644 index 0000000..134afc5 --- /dev/null +++ b/example/environment/env.example.php @@ -0,0 +1,218 @@ +addSql('ALTER TABLE torrent ADD COLUMN status BOOLEAN DEFAULT 1'); - } - - public function down(Schema $schema): void - { - // this down() migration is auto-generated, please modify it to your needs - $this->addSql('CREATE TEMPORARY TABLE __temp__torrent AS SELECT id, user_id, added, scraped, locales, sensitive, approved, md5file, keywords, seeders, peers, leechers FROM torrent'); - $this->addSql('DROP TABLE torrent'); - $this->addSql('CREATE TABLE torrent (id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, user_id INTEGER NOT NULL, added INTEGER NOT NULL, scraped INTEGER DEFAULT NULL, locales CLOB NOT NULL --(DC2Type:simple_array) - , sensitive BOOLEAN NOT NULL, approved BOOLEAN NOT NULL, md5file VARCHAR(32) NOT NULL, keywords CLOB DEFAULT NULL --(DC2Type:simple_array) - , seeders INTEGER DEFAULT NULL, peers INTEGER DEFAULT NULL, leechers INTEGER DEFAULT NULL)'); - $this->addSql('INSERT INTO torrent (id, user_id, added, scraped, locales, sensitive, approved, md5file, keywords, seeders, peers, leechers) SELECT id, user_id, added, scraped, locales, sensitive, approved, md5file, keywords, seeders, peers, leechers FROM __temp__torrent'); - $this->addSql('DROP TABLE __temp__torrent'); - } -} diff --git a/migrations/Version20231029184600.php b/migrations/Version20231029184600.php deleted file mode 100644 index 634e2a1..0000000 --- a/migrations/Version20231029184600.php +++ /dev/null @@ -1,35 +0,0 @@ -addSql('CREATE TABLE torrent_poster (id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, torrent_id INTEGER NOT NULL, user_id INTEGER NOT NULL, added INTEGER NOT NULL, approved BOOLEAN NOT NULL, md5file VARCHAR(32) NOT NULL)'); - $this->addSql('ALTER TABLE user ADD COLUMN posters BOOLEAN NOT NULL DEFAULT 1'); - $this->addSql('ALTER TABLE torrent ADD COLUMN torrent_poster_id BOOLEAN NULL'); - } - - public function down(Schema $schema): void - { - // this down() migration is auto-generated, please modify it to your needs - $this->addSql('DROP TABLE torrent_poster'); - $this->addSql('ALTER TABLE user DROP COLUMN posters'); - $this->addSql('ALTER TABLE torrent DROP COLUMN torrent_poster_id'); - } -} diff --git a/migrations/Version20231030225418.php b/migrations/Version20231030225418.php deleted file mode 100644 index e43e71d..0000000 --- a/migrations/Version20231030225418.php +++ /dev/null @@ -1,31 +0,0 @@ -addSql('ALTER TABLE torrent_poster ADD COLUMN position BOOLEAN NOT NULL DEFAULT "center"'); - } - - public function down(Schema $schema): void - { - // this down() migration is auto-generated, please modify it to your needs - $this->addSql('ALTER TABLE torrent_poster DROP COLUMN position'); - } -} diff --git a/migrations/Version20231103235504.php b/migrations/Version20231103235504.php deleted file mode 100644 index 1ec3213..0000000 --- a/migrations/Version20231103235504.php +++ /dev/null @@ -1,37 +0,0 @@ -addSql('CREATE TABLE torrent_categories (id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, torrent_id INTEGER NOT NULL, user_id INTEGER NOT NULL, added INTEGER NOT NULL, value CLOB NOT NULL --(DC2Type:simple_array) - , approved BOOLEAN NOT NULL)'); - $this->addSql('ALTER TABLE user ADD COLUMN categories CLOB DEFAULT "other"'); - $this->addSql('ALTER TABLE torrent ADD COLUMN categories CLOB DEFAULT "other"'); - $this->addSql('UPDATE user SET categories = "movie,series,tv,animation,music,game,audiobook,podcast,book,archive,picture,software,other"'); - } - - public function down(Schema $schema): void - { - // this down() migration is auto-generated, please modify it to your needs - $this->addSql('DROP TABLE torrent_categories'); - $this->addSql('ALTER TABLE user DROP COLUMN categories'); - $this->addSql('ALTER TABLE torrent DROP COLUMN categories'); - } -} diff --git a/phpunit.xml.dist b/phpunit.xml.dist deleted file mode 100644 index 6c4bfed..0000000 --- a/phpunit.xml.dist +++ /dev/null @@ -1,38 +0,0 @@ - - - - - - - - - - - - - - - - tests - - - - - - src - - - - - - - - - - diff --git a/public/asset/default/css/common.css b/public/asset/default/css/common.css deleted file mode 100644 index 71856f1..0000000 --- a/public/asset/default/css/common.css +++ /dev/null @@ -1,128 +0,0 @@ -* { - border: 0; - margin: 0; - padding: 0; - box-sizing: border-box; - outline: none; -} - -:focus, -:focus-within, -:focus-visible, -:active, -:target, -:hover { - opacity: 1; - transition: opacity .2s ease-in-out; - -} - -body { - background: #282b3c; - color: #ccc; - font-family: Sans-serif; - font-size: 13px; -} - -a, -a:visited, -a:active { - color: #96d9a1; - text-decoration: none; - opacity: .9; -} - -h1, h2, h3, h4, h5 { - display: inline-block; - font-weight: normal; -} - -h1 { - font-size: 16px; -} - -h2 { - color: #ccc; - font-size: 14px; -} - -input, -button, -select, -textarea { - accent-color: #65916d; - background: #5d627d; - border: #5d627d 1px solid; - color: #ccc; - border-radius: 3px; - padding: 6px 8px; - opacity: .96; -} - -input[type="file"] { - padding: 4px 8px; -} - -/* -main input, -main button, -main select, -main textarea { - padding: 8px; -} -*/ -textarea:focus, -input:focus { - border: #65916d 1px solid; - color: #fff; -} - -select[multiple="multiple"] > option { - border-top: 1px #5d627d solid; - border-bottom: 1px #5d627d solid; - color: #fff; -} - -select[multiple="multiple"] > option:active, -select[multiple="multiple"] > option:focus, -select[multiple="multiple"] > option:focus-within, -select[multiple="multiple"] > option:checked { - border-top: 1px #65916d solid; - border-bottom: 1px #65916d solid; - background: linear-gradient(#65916d, #65916d); -} - -button, -input[type="submit"] { - cursor: pointer; -} - -textarea, -select[multiple="multiple"] { - min-height: 180px; -} - -textarea::placeholder, -input::placeholder { - color: #9698a5; - opacity: 1; -} - -input[type="text"]:hover, -textarea:hover { - background: #636884; -} - -td { - padding: 2px 0; - vertical-align: top; -} - -header a.logo { - color: #ccc; - font-size: 20px; -} - -header a.logo > span { - color: #96d9a1; -} \ No newline at end of file diff --git a/public/asset/default/css/framework.css b/public/asset/default/css/framework.css deleted file mode 100644 index 0ca71e6..0000000 --- a/public/asset/default/css/framework.css +++ /dev/null @@ -1,553 +0,0 @@ -.container { - position: relative; - overflow: hidden; - max-width: 748px; - margin: 0 auto; -} - -.row { - position: relative; - overflow: hidden; -} - -.column { - position: relative; - float: left; -} - -.word-break { - word-break: break-word; -} - -.overflow-auto { - overflow: auto; -} - -.float-left { - float: left; -} - -.float-right { - float: right; -} - -.text-center { - text-align: center; -} - -.text-left { - text-align: left; -} - -.text-right { - text-align: right; -} - -.text-color-green, -a.text-color-green, -a.text-color-green:active, -a.text-color-green:visited, -a.text-color-green:hover { - color: #96d9a1; -} - -.text-color-red, -a.text-color-red, -a.text-color-red:active, -a.text-color-red:visited, -a.text-color-red:hover { - color: #d77575; -} - -.text-color-pink, -a.text-color-pink, -a.text-color-pink:active, -a.text-color-pink:visited, -a.text-color-pink:hover { - color: #b55cab; -} - -.text-color-default, -a.text-color-default, -a.text-color-default:active, -a.text-color-default:visited, -a.text-color-default:hover { - color: #ccc; -} - -.text-color-white, -a.text-color-white, -a.text-color-white:active, -a.text-color-white:visited, -a.text-color-white:hover { - color: #fff; -} - -/* -.text-color-pink { - color: #a44399; -} -*/ - -.text-color-blue { - color: #5785b7; -} - -.text-color-night, -a.text-color-night, -a.text-color-night:active, -a.text-color-night:visited, -a.text-color-night:hover { - color: #838695; -} - -.label { - padding: 4px 8px; - border-radius: 3px; -} - -.label-green, -a.label-green, -a.label-green:active, -a.label-green:visited, -a.label-green:hover { - color: #fff; - background-color: #65916d; -} - -.button, -a.button, -a.button:active, -a.button:visited, -a.button:hover { - background: #5d627d; - border: #5d627d 1px solid; - color: #ccc; - padding: 6px 8px; - border-radius: 3px; - opacity: .96; - display: inline-block; -} - -.button-green, -a.button-green, -a.button-green:active, -a.button-green:visited, -a.button-green:hover { - color: #fff; - background-color: #65916d; - border: #65916d 1px solid; -} - -.button-green:hover { - color: #fff; - background-color: #709e79; -} - -.position-relative { - position: relative; -} - -.position-fixed { - position: fixed; -} - -.position-absolute { - position: absolute; -} - -.vertical-align-middle { - vertical-align: middle; -} - -.top-2-px { - top: 2px; -} - -.line-height-20-px { - line-height: 20px; -} - -.line-height-26-px { - line-height: 26px; -} - -.border-radius-3-px { - border-radius: 3px; -} - -.border-radius-50 { - border-radius: 50%; -} - -.border-color-pink-light { - border: 1px #9b6895 solid; -} - -.border-color-pink { - border: 1px #a44399 solid; -} - -.border-color-green { - border: 1px #65916d solid; -} - -.border-color-pink { - border-bottom: 1px #a44399 solid; -} - -.border-color-default { - border: 1px rgba(93, 98, 125, .6) solid; -} - -.border-bottom-default { - border-bottom: 1px rgba(93, 98, 125, .6) solid; -} - -.border-top-default { - border-top: 1px rgba(93, 98, 125, .6) solid; -} - -.border-bottom-dashed { - border-bottom: 1px rgba(93, 98, 125, .6) dashed; -} - -.border-top-dashed { - border-top: 1px rgba(93, 98, 125, .6) dashed; -} - -.border-width-2-px { - border-width: 2px; -} - -.background-poster { - background-position: center; - background-repeat: no-repeat; - background-size: cover; - background-blend-mode: soft-light; -} - -.background-color-night { - background-color: #34384f; -} - -.background-color-night-light { - background-color: #3d4159; -} - -.background-color-green { - background-color: #65916d; -} - -.background-color-hover-night-light:hover, -a.background-color-hover-night-light:hover, -a:active.background-color-hover-night-light:hover, -a:visited.background-color-hover-night-light:hover { - /*color: #fff;*/ - background-color: #3d4159; -} - -.background-color-red { - background-color: #9b4a4a; -} - -.cursor-default { - cursor: default; -} - -.cursor-help { - cursor: help; -} - -.font-weight-normal { - font-weight: normal -} - -.font-weight-200 { - font-weight: 200 -} - -.font-size-10-px { - font-size: 10px; -} - -.font-size-12-px { - font-size: 12px; -} - -.font-size-22-px { - font-size: 22px; -} - -.padding-0 { - padding: 0; -} - -.padding-x-0 { - padding-left: 0; - padding-right: 0; -} - -.padding-4-px { - padding: 4px; -} - -.padding-l-4-px { - padding-left: 4px; -} - -.padding-t-4-px { - padding-top: 4px; -} - -.padding-y-4-px { - padding-top: 4px; - padding-bottom: 4px; -} - -.padding-x-4-px { - padding-left: 4px; - padding-right: 4px; -} - -.padding-x-8-px { - padding-left: 8px; - padding-right: 8px; -} - -.padding-y-6-px { - padding-top: 6px; - padding-bottom: 6px; -} - -.padding-8-px { - padding: 8px; -} - -.padding-l-8-px { - padding-left: 8px; -} - -.padding-t-8-px { - padding-top: 8px; -} - -.padding-b-8-px { - padding-bottom: 8px; -} - -.padding-y-8-px { - padding-top: 8px; - padding-bottom: 8px; -} - -.padding-y-12-px { - padding-top: 12px; - padding-bottom: 12px; -} - -.padding-b-16-px { - padding-bottom: 16px; -} - -.padding-t-16-px { - padding-top: 16px; -} - -.padding-y-16-px { - padding-top: 16px; - padding-bottom: 16px; -} - -.padding-x-16-px { - padding-left: 16px; - padding-right: 16px; -} - -.padding-16-px { - padding: 16px; -} - -.padding-24-px { - padding: 24px; -} - -.padding-x-24-px { - padding-left: 24px; - padding-right: 24px; -} - -.padding-y-24-px { - padding-top: 24px; - padding-bottom: 24px; -} - -.margin-t-4-px { - margin-top: 4px; -} - -.margin-l-4-px { - margin-left: 4px; -} - -.margin-8-px { - margin: 8px; -} - -.margin-x-8-px { - margin-left: 8px; - margin-right: 8px; -} - -.margin-l-8-px { - margin-left: 8px; -} - -.margin-16-px { - margin: 16px; -} - -.margin-l-16-px { - margin-left: 16px; -} - -.margin-x-4-px { - margin-left: 4px; - margin-right: 4px; -} - -.margin-b-4-px { - margin-bottom: 4px; -} - -.margin-r-4-px { - margin-right: 4px; -} - -.margin-r-8-px { - margin-right: 8px; -} - -.margin-l-12-px { - margin-left: 12px; -} - -.margin-l-96-px { - margin-left: 96px; -} - -.margin-l--48-px { - margin-left: -48px; -} - -.margin-y-8-px { - margin-top: 8px; - margin-bottom: 8px; -} - -.margin-t-8-px { - margin-top: 8px; -} - -.margin-b-8-px { - margin-bottom: 8px; -} - -.margin-y-16-px { - margin-top: 16px; - margin-bottom: 16px; -} - -.margin-t-16-px { - margin-top: 16px; -} - -.margin-b-16-px { - margin-bottom: 16px; -} - -.margin-b-24-px { - margin-bottom: 24px; -} - -.display-block { - display: block; -} - -.display-inline-block { - display: inline-block; -} - -.display-flex { - display: flex; -} - -.opacity-0 { - opacity: 0; -} - -.opacity-06 { - opacity: .6; -} - -.opacity-hover-1:hover { - opacity: 1; - transition: opacity .2s; -} - -*:hover > .parent-hover-opacity-09 { - opacity: .9; - transition: opacity .2s; -} - -.blur-2 { - filter: blur(2px); -} - -.blur-hover-0:hover { - filter: blur(0); -} - -/* responsive rules */ - -.width-100 { - width: 100%; -} - -.width-50 { - width: 50%; -} - -.width-20 { - width: 20%; -} - -.width-80 { - width: 80%; -} - -.width-80-px { - width: 80px; -} - -.min-width-120-px { - min-width: 120px; -} - -.min-width-200-px { - min-width: 200px; -} - -@media (max-width: 1220px) { - - .width-tablet-100 { - width: 100%; - } -} - -@media (max-width: 512px) { - - .width-mobile-100 { - width: 100%; - } -} diff --git a/public/index.php b/public/index.php deleted file mode 100644 index 9982c21..0000000 --- a/public/index.php +++ /dev/null @@ -1,9 +0,0 @@ - '%app.locales%' - ], - methods: - [ - 'GET' - ] - )] - public function all( - Request $request, - UserService $userService, - ActivityService $activityService - ): Response - { - $user = $this->initUser( - $request, - $userService, - $activityService - ); - - $total = $activityService->findActivitiesTotal( - $user->getEvents() - ); - - $page = $request->get('page') ? (int) $request->get('page') : 1; - - return $this->render( - 'default/activity/list.html.twig', - [ - 'session' => [ - 'user' => $user - ], - 'activities' => $activityService->findLastActivities( - $user->getEvents(), - $this->getParameter('app.pagination'), - ($page - 1) * $this->getParameter('app.pagination') - ), - 'pagination' => - [ - 'page' => $page, - 'pages' => ceil($total / $this->getParameter('app.pagination')), - 'total' => $total - ] - ] - ); - } - - #[Route( - '/{_locale}/rss/activity', - name: 'rss_activity', - requirements: [ - '_locale' => '%app.locales%' - ], - methods: - [ - 'GET' - ] - )] - public function rssAll( - Request $request, - UserService $userService, - ActivityService $activityService - ): Response - { - $user = $this->initUser( - $request, - $userService, - $activityService - ); - - $total = $activityService->findActivitiesTotal( - $user->getEvents() - ); - - $response = new Response(); - $response->headers->set('Content-Type', 'text/xml'); - - return $this->render( - 'default/activity/list.rss.twig', - [ - 'session' => [ - 'user' => $user - ], - 'activities' => $activityService->findLastActivities( - $user->getEvents() - ) - ], - $response - ); - } - - #[Route( - '/{_locale}/rss/activity/user/{userId}', - name: 'rss_activity_user', - defaults: [ - 'userId' => 0 - ], - requirements: [ - '_locale' => '%app.locales%', - 'userId' => '\d+' - ], - methods: - [ - 'GET' - ] - )] - public function rssUser( - Request $request, - UserService $userService, - ActivityService $activityService - ): Response - { - $user = $this->initUser( - $request, - $userService, - $activityService - ); - - // Init target user - if (!$userTarget = $userService->getUser( - $request->get('userId') ? $request->get('userId') : $user->getId() - )) - { - throw $this->createNotFoundException(); - } - - $total = $activityService->findActivitiesTotalByUserId( - $userTarget->getId(), - $user->getEvents() - ); - - $response = new Response(); - $response->headers->set('Content-Type', 'text/xml'); - - return $this->render( - 'default/activity/list.rss.twig', - [ - 'session' => [ - 'user' => $user - ], - 'activities' => $activityService->findLastActivitiesByUserId( - $userTarget->getId(), - $userTarget->getEvents() - ) - ], - $response - ); - } - - #[Route( - '/{_locale}/rss/activity/torrent/{torrentId}', - name: 'rss_activity_torrent', - requirements: [ - '_locale' => '%app.locales%', - 'torrentId' => '\d+' - ], - methods: - [ - 'GET' - ] - )] - public function rssTorrent( - Request $request, - UserService $userService, - TorrentService $torrentService, - ActivityService $activityService - ): Response - { - $user = $this->initUser( - $request, - $userService, - $activityService - ); - - // Init torrent - if (!$torrent = $torrentService->getTorrent($request->get('torrentId'))) - { - throw $this->createNotFoundException(); - } - - // Get total activities - $total = $activityService->findActivitiesTotalByTorrentId( - $torrent->getId(), - $user->getEvents() - ); - - $response = new Response(); - $response->headers->set('Content-Type', 'text/xml'); - - return $this->render( - 'default/activity/list.rss.twig', - [ - 'session' => [ - 'user' => $user - ], - 'activities' => $activityService->findLastActivitiesByTorrentId( - $torrent->getId(), - $user->getEvents() - ) - ], - $response - ); - } - - public function event( - \App\Entity\User $user, - \App\Entity\Activity $activity, - ActivityService $activityService, - UserService $userService, - TorrentService $torrentService, - ?string $format = null, - ): Response - { - switch ($format) - { - case 'rss': - - $extension = '.rss.twig'; - - break; - - default: - - $extension = '.html.twig'; - } - - switch ($activity->getEvent()) - { - // User - case $activity::EVENT_USER_ADD: - - return $this->render( - 'default/activity/event/user/add' . $extension, - [ - 'id' => $activity->getId(), - 'id' => $activity->getId(), - 'added' => $activity->getAdded(), - 'user' => - [ - 'id' => $activity->getUserId(), - 'identicon' => $userService->identicon( - $userService->getUser( - $activity->getUserId() - )->getAddress() - ) - ] - ] - ); - - break; - - case $activity::EVENT_USER_APPROVE_ADD: - - return $this->render( - 'default/activity/event/user/approve/add' . $extension, - [ - 'id' => $activity->getId(), - 'added' => $activity->getAdded(), - 'user' => - [ - 'id' => $activity->getUserId(), - 'identicon' => $userService->identicon( - $userService->getUser( - $activity->getUserId() - )->getAddress() - ) - ], - 'to' => - [ - 'user' => - [ - 'id' => $activity->getData()['userId'], - 'identicon' => $userService->identicon( - $userService->getUser( - $activity->getData()['userId'] - )->getAddress() - ) - ] - ] - ] - ); - - break; - - case $activity::EVENT_USER_APPROVE_DELETE: - - return $this->render( - 'default/activity/event/user/approve/delete' . $extension, - [ - 'id' => $activity->getId(), - 'added' => $activity->getAdded(), - 'user' => - [ - 'id' => $activity->getUserId(), - 'identicon' => $userService->identicon( - $userService->getUser( - $activity->getUserId() - )->getAddress() - ) - ], - 'to' => - [ - 'user' => - [ - 'id' => $activity->getData()['userId'], - 'identicon' => $userService->identicon( - $userService->getUser( - $activity->getData()['userId'] - )->getAddress() - ) - ] - ] - ] - ); - - break; - - case $activity::EVENT_USER_MODERATOR_ADD: - - return $this->render( - 'default/activity/event/user/moderator/add' . $extension, - [ - 'id' => $activity->getId(), - 'added' => $activity->getAdded(), - 'user' => - [ - 'id' => $activity->getUserId(), - 'identicon' => $userService->identicon( - $userService->getUser( - $activity->getUserId() - )->getAddress() - ) - ], - 'to' => - [ - 'user' => - [ - 'id' => $activity->getData()['userId'], - 'identicon' => $userService->identicon( - $userService->getUser( - $activity->getData()['userId'] - )->getAddress() - ) - ] - ] - ] - ); - - break; - - case $activity::EVENT_USER_MODERATOR_DELETE: - - return $this->render( - 'default/activity/event/user/moderator/delete' . $extension, - [ - 'id' => $activity->getId(), - 'added' => $activity->getAdded(), - 'user' => - [ - 'id' => $activity->getUserId(), - 'identicon' => $userService->identicon( - $userService->getUser( - $activity->getUserId() - )->getAddress() - ) - ], - 'to' => - [ - 'user' => - [ - 'id' => $activity->getData()['userId'], - 'identicon' => $userService->identicon( - $userService->getUser( - $activity->getData()['userId'] - )->getAddress() - ) - ] - ] - ] - ); - - break; - - case $activity::EVENT_USER_STATUS_ADD: - - return $this->render( - 'default/activity/event/user/status/add' . $extension, - [ - 'id' => $activity->getId(), - 'added' => $activity->getAdded(), - 'user' => - [ - 'id' => $activity->getUserId(), - 'identicon' => $userService->identicon( - $userService->getUser( - $activity->getUserId() - )->getAddress() - ) - ], - 'to' => - [ - 'user' => - [ - 'id' => $activity->getData()['userId'], - 'identicon' => $userService->identicon( - $userService->getUser( - $activity->getData()['userId'] - )->getAddress() - ) - ] - ] - ] - ); - - break; - - case $activity::EVENT_USER_STATUS_DELETE: - - return $this->render( - 'default/activity/event/user/status/delete' . $extension, - [ - 'id' => $activity->getId(), - 'added' => $activity->getAdded(), - 'user' => - [ - 'id' => $activity->getUserId(), - 'identicon' => $userService->identicon( - $userService->getUser( - $activity->getUserId() - )->getAddress() - ) - ], - 'to' => - [ - 'user' => - [ - 'id' => $activity->getData()['userId'], - 'identicon' => $userService->identicon( - $userService->getUser( - $activity->getData()['userId'] - )->getAddress() - ) - ] - ] - ] - ); - - break; - - case $activity::EVENT_USER_STAR_ADD: - - return $this->render( - 'default/activity/event/user/star/add' . $extension, - [ - 'id' => $activity->getId(), - 'added' => $activity->getAdded(), - 'user' => - [ - 'id' => $activity->getUserId(), - 'identicon' => $userService->identicon( - $userService->getUser( - $activity->getUserId() - )->getAddress() - ) - ], - 'to' => - [ - 'user' => - [ - 'id' => $activity->getData()['userId'], - 'identicon' => $userService->identicon( - $userService->getUser( - $activity->getData()['userId'] - )->getAddress() - ) - ] - ] - ] - ); - - break; - - case $activity::EVENT_USER_STAR_DELETE: - - return $this->render( - 'default/activity/event/user/star/delete' . $extension, - [ - 'id' => $activity->getId(), - 'added' => $activity->getAdded(), - 'user' => - [ - 'id' => $activity->getUserId(), - 'identicon' => $userService->identicon( - $userService->getUser( - $activity->getUserId() - )->getAddress() - ) - ], - 'to' => - [ - 'user' => - [ - 'id' => $activity->getData()['userId'], - 'identicon' => $userService->identicon( - $userService->getUser( - $activity->getData()['userId'] - )->getAddress() - ) - ] - ] - ] - ); - - break; - - // Torrent - case $activity::EVENT_TORRENT_ADD: - - // Init torrent - if (!$torrent = $torrentService->getTorrent($activity->getTorrentId())) - { - throw $this->createNotFoundException(); - } - - return $this->render( - 'default/activity/event/torrent/add' . $extension, - [ - 'id' => $activity->getId(), - 'added' => $activity->getAdded(), - 'user' => - [ - 'id' => $activity->getUserId(), - 'identicon' => $userService->identicon( - $userService->getUser( - $activity->getUserId() - )->getAddress() - ) - ], - 'torrent' => - [ - 'id' => $torrent->getId(), - 'sensitive' => $torrent->isSensitive(), - 'approved' => $torrent->isApproved(), - 'status' => $torrent->isStatus(), - 'name' => $torrentService->readTorrentFileByTorrentId( - $torrent->getId() - )->getName() - ], - 'session' => - [ - 'user' => - [ - 'id' => $user->getId(), - 'sensitive' => $user->isSensitive(), - 'moderator' => $user->isModerator(), - 'owner' => $user->getId() === $torrent->getUserId(), - ] - ] - ] - ); - - break; - - case $activity::EVENT_TORRENT_APPROVE_ADD: - - // Init torrent - if (!$torrent = $torrentService->getTorrent($activity->getTorrentId())) - { - throw $this->createNotFoundException(); - } - - return $this->render( - 'default/activity/event/torrent/approve/add' . $extension, - [ - 'id' => $activity->getId(), - 'added' => $activity->getAdded(), - 'user' => - [ - 'id' => $activity->getUserId(), - 'identicon' => $userService->identicon( - $userService->getUser( - $activity->getUserId() - )->getAddress() - ) - ], - 'torrent' => - [ - 'id' => $torrent->getId(), - 'sensitive' => $torrent->isSensitive(), - 'approved' => $torrent->isApproved(), - 'status' => $torrent->isStatus(), - 'name' => $torrentService->readTorrentFileByTorrentId( - $torrent->getId() - )->getName() - ], - 'session' => - [ - 'user' => - [ - 'id' => $user->getId(), - 'sensitive' => $user->isSensitive(), - 'moderator' => $user->isModerator(), - 'owner' => $user->getId() === $torrent->getUserId(), - ] - ] - ] - ); - - break; - - case $activity::EVENT_TORRENT_APPROVE_DELETE: - - // Init torrent - if (!$torrent = $torrentService->getTorrent($activity->getTorrentId())) - { - throw $this->createNotFoundException(); - } - - return $this->render( - 'default/activity/event/torrent/approve/delete' . $extension, - [ - 'id' => $activity->getId(), - 'added' => $activity->getAdded(), - 'user' => - [ - 'id' => $activity->getUserId(), - 'identicon' => $userService->identicon( - $userService->getUser( - $activity->getUserId() - )->getAddress() - ) - ], - 'torrent' => - [ - 'id' => $torrent->getId(), - 'sensitive' => $torrent->isSensitive(), - 'approved' => $torrent->isApproved(), - 'status' => $torrent->isStatus(), - 'name' => $torrentService->readTorrentFileByTorrentId( - $torrent->getId() - )->getName() - ], - 'session' => - [ - 'user' => - [ - 'id' => $user->getId(), - 'sensitive' => $user->isSensitive(), - 'moderator' => $user->isModerator(), - 'owner' => $user->getId() === $torrent->getUserId(), - ] - ] - ] - ); - - break; - - // Torrent Download - case $activity::EVENT_TORRENT_DOWNLOAD_FILE_ADD: - - // Init torrent - if (!$torrent = $torrentService->getTorrent($activity->getTorrentId())) - { - throw $this->createNotFoundException(); - } - - return $this->render( - 'default/activity/event/torrent/download/file/add' . $extension, - [ - 'id' => $activity->getId(), - 'added' => $activity->getAdded(), - 'user' => - [ - 'id' => $activity->getUserId(), - 'identicon' => $userService->identicon( - $userService->getUser( - $activity->getUserId() - )->getAddress() - ) - ], - 'torrent' => - [ - 'id' => $torrent->getId(), - 'sensitive' => $torrent->isSensitive(), - 'approved' => $torrent->isApproved(), - 'status' => $torrent->isStatus(), - 'name' => $torrentService->readTorrentFileByTorrentId( - $torrent->getId() - )->getName() - ], - 'session' => - [ - 'user' => - [ - 'id' => $user->getId(), - 'sensitive' => $user->isSensitive(), - 'moderator' => $user->isModerator(), - 'owner' => $user->getId() === $torrent->getUserId(), - ] - ] - ] - ); - - break; - - case $activity::EVENT_TORRENT_DOWNLOAD_MAGNET_ADD: - - // Init torrent - if (!$torrent = $torrentService->getTorrent($activity->getTorrentId())) - { - throw $this->createNotFoundException(); - } - - return $this->render( - 'default/activity/event/torrent/download/magnet/add' . $extension, - [ - 'id' => $activity->getId(), - 'added' => $activity->getAdded(), - 'user' => - [ - 'id' => $activity->getUserId(), - 'identicon' => $userService->identicon( - $userService->getUser( - $activity->getUserId() - )->getAddress() - ) - ], - 'torrent' => - [ - 'id' => $torrent->getId(), - 'sensitive' => $torrent->isSensitive(), - 'approved' => $torrent->isApproved(), - 'status' => $torrent->isStatus(), - 'name' => $torrentService->readTorrentFileByTorrentId( - $torrent->getId() - )->getName() - ], - 'session' => - [ - 'user' => - [ - 'id' => $user->getId(), - 'sensitive' => $user->isSensitive(), - 'moderator' => $user->isModerator(), - 'owner' => $user->getId() === $torrent->getUserId(), - ] - ] - ] - ); - - break; - - // Torrent Wanted - case $activity::EVENT_TORRENT_WANTED_ADD: - - // Init torrent - if (!$torrent = $torrentService->getTorrent($activity->getTorrentId())) - { - throw $this->createNotFoundException(); - } - - return $this->render( - 'default/activity/event/torrent/wanted/add' . $extension, - [ - 'id' => $activity->getId(), - 'added' => $activity->getAdded(), - 'torrent' => - [ - 'id' => $torrent->getId(), - 'sensitive' => $torrent->isSensitive(), - 'approved' => $torrent->isApproved(), - 'status' => $torrent->isStatus(), - 'name' => $torrentService->readTorrentFileByTorrentId( - $torrent->getId() - )->getName() - ], - 'session' => - [ - 'user' => - [ - 'id' => $user->getId(), - 'sensitive' => $user->isSensitive(), - 'moderator' => $user->isModerator(), - 'owner' => $user->getId() === $torrent->getUserId(), - ] - ] - ] - ); - - break; - - // Torrent Status - case $activity::EVENT_TORRENT_STATUS_ADD: - - // Init torrent - if (!$torrent = $torrentService->getTorrent($activity->getTorrentId())) - { - throw $this->createNotFoundException(); - } - - return $this->render( - 'default/activity/event/torrent/status/add' . $extension, - [ - 'id' => $activity->getId(), - 'added' => $activity->getAdded(), - 'user' => - [ - 'id' => $activity->getUserId(), - 'identicon' => $userService->identicon( - $userService->getUser( - $activity->getUserId() - )->getAddress() - ) - ], - 'torrent' => - [ - 'id' => $torrent->getId(), - 'sensitive' => $torrent->isSensitive(), - 'approved' => $torrent->isApproved(), - 'status' => $torrent->isStatus(), - 'name' => $torrentService->readTorrentFileByTorrentId( - $torrent->getId() - )->getName() - ], - 'session' => - [ - 'user' => - [ - 'id' => $user->getId(), - 'sensitive' => $user->isSensitive(), - 'moderator' => $user->isModerator(), - 'owner' => $user->getId() === $torrent->getUserId(), - ] - ] - ] - ); - - break; - - case $activity::EVENT_TORRENT_STATUS_DELETE: - - // Init torrent - if (!$torrent = $torrentService->getTorrent($activity->getTorrentId())) - { - throw $this->createNotFoundException(); - } - - return $this->render( - 'default/activity/event/torrent/status/delete' . $extension, - [ - 'id' => $activity->getId(), - 'added' => $activity->getAdded(), - 'user' => - [ - 'id' => $activity->getUserId(), - 'identicon' => $userService->identicon( - $userService->getUser( - $activity->getUserId() - )->getAddress() - ) - ], - 'torrent' => - [ - 'id' => $torrent->getId(), - 'sensitive' => $torrent->isSensitive(), - 'approved' => $torrent->isApproved(), - 'status' => $torrent->isStatus(), - 'name' => $torrentService->readTorrentFileByTorrentId( - $torrent->getId() - )->getName() - ], - 'session' => - [ - 'user' => - [ - 'id' => $user->getId(), - 'sensitive' => $user->isSensitive(), - 'moderator' => $user->isModerator(), - 'owner' => $user->getId() === $torrent->getUserId(), - ] - ] - ] - ); - - break; - - /// Torrent Locales - case $activity::EVENT_TORRENT_LOCALES_ADD: - - // Init torrent - if (!$torrent = $torrentService->getTorrent($activity->getTorrentId())) - { - throw $this->createNotFoundException(); - } - - return $this->render( - 'default/activity/event/torrent/locales/add' . $extension, - [ - 'id' => $activity->getId(), - 'added' => $activity->getAdded(), - 'user' => - [ - 'id' => $activity->getUserId(), - 'identicon' => $userService->identicon( - $userService->getUser( - $activity->getUserId() - )->getAddress() - ) - ], - 'torrent' => - [ - 'id' => $torrent->getId(), - 'sensitive' => $torrent->isSensitive(), - 'approved' => $torrent->isApproved(), - 'status' => $torrent->isStatus(), - 'name' => $torrentService->readTorrentFileByTorrentId( - $torrent->getId() - )->getName(), - 'locales' => [ - 'id' => $activity->getData()['torrentLocalesId'], - 'exist' => $torrentService->getTorrentLocales( - $activity->getData()['torrentLocalesId'] // could be deleted by moderator, remove links - ) - ] - ], - 'session' => - [ - 'user' => - [ - 'id' => $user->getId(), - 'sensitive' => $user->isSensitive(), - 'moderator' => $user->isModerator(), - 'owner' => $user->getId() === $torrent->getUserId(), - ] - ] - ] - ); - - break; - - case $activity::EVENT_TORRENT_LOCALES_DELETE: - - // Init torrent - if (!$torrent = $torrentService->getTorrent($activity->getTorrentId())) - { - throw $this->createNotFoundException(); - } - - return $this->render( - 'default/activity/event/torrent/locales/delete' . $extension, - [ - 'id' => $activity->getId(), - 'added' => $activity->getAdded(), - 'user' => - [ - 'id' => $activity->getUserId(), - 'identicon' => $userService->identicon( - $userService->getUser( - $activity->getUserId() - )->getAddress() - ) - ], - 'torrent' => - [ - 'id' => $torrent->getId(), - 'sensitive' => $torrent->isSensitive(), - 'approved' => $torrent->isApproved(), - 'status' => $torrent->isStatus(), - 'name' => $torrentService->readTorrentFileByTorrentId( - $torrent->getId() - )->getName(), - 'locales' => [ - 'id' => $activity->getData()['torrentLocalesId'], - 'exist' => $torrentService->getTorrentLocales( - $activity->getData()['torrentLocalesId'] // could be deleted by moderator, remove links - ) - ] - ], - 'session' => - [ - 'user' => - [ - 'id' => $user->getId(), - 'sensitive' => $user->isSensitive(), - 'moderator' => $user->isModerator(), - 'owner' => $user->getId() === $torrent->getUserId(), - ] - ] - ] - ); - - break; - - case $activity::EVENT_TORRENT_LOCALES_APPROVE_ADD: - - // Init torrent - if (!$torrent = $torrentService->getTorrent($activity->getTorrentId())) - { - throw $this->createNotFoundException(); - } - - return $this->render( - 'default/activity/event/torrent/locales/approve/add' . $extension, - [ - 'id' => $activity->getId(), - 'added' => $activity->getAdded(), - 'user' => - [ - 'id' => $activity->getUserId(), - 'identicon' => $userService->identicon( - $userService->getUser( - $activity->getUserId() - )->getAddress() - ) - ], - 'torrent' => - [ - 'id' => $torrent->getId(), - 'sensitive' => $torrent->isSensitive(), - 'approved' => $torrent->isApproved(), - 'status' => $torrent->isStatus(), - 'name' => $torrentService->readTorrentFileByTorrentId( - $torrent->getId() - )->getName(), - 'locales' => [ - 'id' => $activity->getData()['torrentLocalesId'], - 'exist' => $torrentService->getTorrentLocales( - $activity->getData()['torrentLocalesId'] // could be deleted by moderator, remove links - ) - ] - ], - 'session' => - [ - 'user' => - [ - 'id' => $user->getId(), - 'sensitive' => $user->isSensitive(), - 'moderator' => $user->isModerator(), - 'owner' => $user->getId() === $torrent->getUserId(), - ] - ] - ] - ); - - break; - - case $activity::EVENT_TORRENT_LOCALES_APPROVE_DELETE: - - // Init torrent - if (!$torrent = $torrentService->getTorrent($activity->getTorrentId())) - { - throw $this->createNotFoundException(); - } - - return $this->render( - 'default/activity/event/torrent/locales/approve/delete' . $extension, - [ - 'id' => $activity->getId(), - 'added' => $activity->getAdded(), - 'user' => - [ - 'id' => $activity->getUserId(), - 'identicon' => $userService->identicon( - $userService->getUser( - $activity->getUserId() - )->getAddress() - ) - ], - 'torrent' => - [ - 'id' => $torrent->getId(), - 'sensitive' => $torrent->isSensitive(), - 'approved' => $torrent->isApproved(), - 'status' => $torrent->isStatus(), - 'name' => $torrentService->readTorrentFileByTorrentId( - $torrent->getId() - )->getName(), - 'locales' => [ - 'id' => $activity->getData()['torrentLocalesId'], - 'exist' => $torrentService->getTorrentLocales( - $activity->getData()['torrentLocalesId'] // could be deleted by moderator, remove links - ) - ] - ], - 'session' => - [ - 'user' => - [ - 'id' => $user->getId(), - 'sensitive' => $user->isSensitive(), - 'moderator' => $user->isModerator(), - 'owner' => $user->getId() === $torrent->getUserId(), - ] - ] - ] - ); - - break; - - /// Torrent Categories - case $activity::EVENT_TORRENT_CATEGORIES_ADD: - - // Init torrent - if (!$torrent = $torrentService->getTorrent($activity->getTorrentId())) - { - throw $this->createNotFoundException(); - } - - return $this->render( - 'default/activity/event/torrent/categories/add' . $extension, - [ - 'id' => $activity->getId(), - 'added' => $activity->getAdded(), - 'user' => - [ - 'id' => $activity->getUserId(), - 'identicon' => $userService->identicon( - $userService->getUser( - $activity->getUserId() - )->getAddress() - ) - ], - 'torrent' => - [ - 'id' => $torrent->getId(), - 'sensitive' => $torrent->isSensitive(), - 'approved' => $torrent->isApproved(), - 'status' => $torrent->isStatus(), - 'name' => $torrentService->readTorrentFileByTorrentId( - $torrent->getId() - )->getName(), - 'categories' => [ - 'id' => $activity->getData()['torrentCategoriesId'], - 'exist' => $torrentService->getTorrentCategories( - $activity->getData()['torrentCategoriesId'] // could be deleted by moderator, remove links - ) - ] - ], - 'session' => - [ - 'user' => - [ - 'id' => $user->getId(), - 'sensitive' => $user->isSensitive(), - 'moderator' => $user->isModerator(), - 'owner' => $user->getId() === $torrent->getUserId(), - ] - ] - ] - ); - - break; - - case $activity::EVENT_TORRENT_CATEGORIES_DELETE: - - // Init torrent - if (!$torrent = $torrentService->getTorrent($activity->getTorrentId())) - { - throw $this->createNotFoundException(); - } - - return $this->render( - 'default/activity/event/torrent/categories/delete' . $extension, - [ - 'id' => $activity->getId(), - 'added' => $activity->getAdded(), - 'user' => - [ - 'id' => $activity->getUserId(), - 'identicon' => $userService->identicon( - $userService->getUser( - $activity->getUserId() - )->getAddress() - ) - ], - 'torrent' => - [ - 'id' => $torrent->getId(), - 'sensitive' => $torrent->isSensitive(), - 'approved' => $torrent->isApproved(), - 'status' => $torrent->isStatus(), - 'name' => $torrentService->readTorrentFileByTorrentId( - $torrent->getId() - )->getName(), - 'categories' => [ - 'id' => $activity->getData()['torrentCategoriesId'], - 'exist' => $torrentService->getTorrentCategories( - $activity->getData()['torrentCategoriesId'] // could be deleted by moderator, remove links - ) - ] - ], - 'session' => - [ - 'user' => - [ - 'id' => $user->getId(), - 'sensitive' => $user->isSensitive(), - 'moderator' => $user->isModerator(), - 'owner' => $user->getId() === $torrent->getUserId(), - ] - ] - ] - ); - - break; - - case $activity::EVENT_TORRENT_CATEGORIES_APPROVE_ADD: - - // Init torrent - if (!$torrent = $torrentService->getTorrent($activity->getTorrentId())) - { - throw $this->createNotFoundException(); - } - - return $this->render( - 'default/activity/event/torrent/categories/approve/add' . $extension, - [ - 'id' => $activity->getId(), - 'added' => $activity->getAdded(), - 'user' => - [ - 'id' => $activity->getUserId(), - 'identicon' => $userService->identicon( - $userService->getUser( - $activity->getUserId() - )->getAddress() - ) - ], - 'torrent' => - [ - 'id' => $torrent->getId(), - 'sensitive' => $torrent->isSensitive(), - 'approved' => $torrent->isApproved(), - 'status' => $torrent->isStatus(), - 'name' => $torrentService->readTorrentFileByTorrentId( - $torrent->getId() - )->getName(), - 'categories' => [ - 'id' => $activity->getData()['torrentCategoriesId'], - 'exist' => $torrentService->getTorrentCategories( - $activity->getData()['torrentCategoriesId'] // could be deleted by moderator, remove links - ) - ] - ], - 'session' => - [ - 'user' => - [ - 'id' => $user->getId(), - 'sensitive' => $user->isSensitive(), - 'moderator' => $user->isModerator(), - 'owner' => $user->getId() === $torrent->getUserId(), - ] - ] - ] - ); - - break; - - case $activity::EVENT_TORRENT_CATEGORIES_APPROVE_DELETE: - - // Init torrent - if (!$torrent = $torrentService->getTorrent($activity->getTorrentId())) - { - throw $this->createNotFoundException(); - } - - return $this->render( - 'default/activity/event/torrent/categories/approve/delete' . $extension, - [ - 'id' => $activity->getId(), - 'added' => $activity->getAdded(), - 'user' => - [ - 'id' => $activity->getUserId(), - 'identicon' => $userService->identicon( - $userService->getUser( - $activity->getUserId() - )->getAddress() - ) - ], - 'torrent' => - [ - 'id' => $torrent->getId(), - 'sensitive' => $torrent->isSensitive(), - 'approved' => $torrent->isApproved(), - 'status' => $torrent->isStatus(), - 'name' => $torrentService->readTorrentFileByTorrentId( - $torrent->getId() - )->getName(), - 'categories' => [ - 'id' => $activity->getData()['torrentCategoriesId'], - 'exist' => $torrentService->getTorrentCategories( - $activity->getData()['torrentCategoriesId'] // could be deleted by moderator, remove links - ) - ] - ], - 'session' => - [ - 'user' => - [ - 'id' => $user->getId(), - 'sensitive' => $user->isSensitive(), - 'moderator' => $user->isModerator(), - 'owner' => $user->getId() === $torrent->getUserId(), - ] - ] - ] - ); - - break; - - /// Torrent Sensitive - case $activity::EVENT_TORRENT_SENSITIVE_ADD: - - // Init torrent - if (!$torrent = $torrentService->getTorrent($activity->getTorrentId())) - { - throw $this->createNotFoundException(); - } - - return $this->render( - 'default/activity/event/torrent/sensitive/add' . $extension, - [ - 'id' => $activity->getId(), - 'added' => $activity->getAdded(), - 'user' => - [ - 'id' => $activity->getUserId(), - 'identicon' => $userService->identicon( - $userService->getUser( - $activity->getUserId() - )->getAddress() - ) - ], - 'torrent' => - [ - 'id' => $torrent->getId(), - 'sensitive' => $torrent->isSensitive(), - 'approved' => $torrent->isApproved(), - 'status' => $torrent->isStatus(), - 'name' => $torrentService->readTorrentFileByTorrentId( - $torrent->getId() - )->getName(), - 'sensitive' => [ - 'id' => $activity->getData()['torrentSensitiveId'], - 'exist' => $torrentService->getTorrentSensitive( - $activity->getData()['torrentSensitiveId'] // could be deleted by moderator, remove links - ) - ] - ], - 'session' => - [ - 'user' => - [ - 'id' => $user->getId(), - 'sensitive' => $user->isSensitive(), - 'moderator' => $user->isModerator(), - 'owner' => $user->getId() === $torrent->getUserId(), - ] - ] - ] - ); - - break; - - case $activity::EVENT_TORRENT_SENSITIVE_DELETE: - - // Init torrent - if (!$torrent = $torrentService->getTorrent($activity->getTorrentId())) - { - throw $this->createNotFoundException(); - } - - return $this->render( - 'default/activity/event/torrent/sensitive/delete' . $extension, - [ - 'id' => $activity->getId(), - 'added' => $activity->getAdded(), - 'user' => - [ - 'id' => $activity->getUserId(), - 'identicon' => $userService->identicon( - $userService->getUser( - $activity->getUserId() - )->getAddress() - ) - ], - 'torrent' => - [ - 'id' => $torrent->getId(), - 'sensitive' => $torrent->isSensitive(), - 'approved' => $torrent->isApproved(), - 'status' => $torrent->isStatus(), - 'name' => $torrentService->readTorrentFileByTorrentId( - $torrent->getId() - )->getName(), - 'sensitive' => [ - 'id' => $activity->getData()['torrentSensitiveId'], - 'exist' => $torrentService->getTorrentSensitive( - $activity->getData()['torrentSensitiveId'] // could be deleted by moderator, remove links - ) - ] - ], - 'session' => - [ - 'user' => - [ - 'id' => $user->getId(), - 'sensitive' => $user->isSensitive(), - 'moderator' => $user->isModerator(), - 'owner' => $user->getId() === $torrent->getUserId(), - ] - ] - ] - ); - - break; - - case $activity::EVENT_TORRENT_SENSITIVE_APPROVE_ADD: - - // Init torrent - if (!$torrent = $torrentService->getTorrent($activity->getTorrentId())) - { - throw $this->createNotFoundException(); - } - - return $this->render( - 'default/activity/event/torrent/sensitive/approve/add' . $extension, - [ - 'id' => $activity->getId(), - 'added' => $activity->getAdded(), - 'user' => - [ - 'id' => $activity->getUserId(), - 'identicon' => $userService->identicon( - $userService->getUser( - $activity->getUserId() - )->getAddress() - ) - ], - 'torrent' => - [ - 'id' => $torrent->getId(), - 'sensitive' => $torrent->isSensitive(), - 'approved' => $torrent->isApproved(), - 'status' => $torrent->isStatus(), - 'name' => $torrentService->readTorrentFileByTorrentId( - $torrent->getId() - )->getName(), - 'sensitive' => [ - 'id' => $activity->getData()['torrentSensitiveId'], - 'exist' => $torrentService->getTorrentSensitive( - $activity->getData()['torrentSensitiveId'] // could be deleted by moderator, remove links - ) - ] - ], - 'session' => - [ - 'user' => - [ - 'id' => $user->getId(), - 'sensitive' => $user->isSensitive(), - 'moderator' => $user->isModerator(), - 'owner' => $user->getId() === $torrent->getUserId(), - ] - ] - ] - ); - - break; - - case $activity::EVENT_TORRENT_SENSITIVE_APPROVE_DELETE: - - // Init torrent - if (!$torrent = $torrentService->getTorrent($activity->getTorrentId())) - { - throw $this->createNotFoundException(); - } - - return $this->render( - 'default/activity/event/torrent/sensitive/approve/delete' . $extension, - [ - 'id' => $activity->getId(), - 'added' => $activity->getAdded(), - 'user' => - [ - 'id' => $activity->getUserId(), - 'identicon' => $userService->identicon( - $userService->getUser( - $activity->getUserId() - )->getAddress() - ) - ], - 'torrent' => - [ - 'id' => $torrent->getId(), - 'sensitive' => $torrent->isSensitive(), - 'approved' => $torrent->isApproved(), - 'status' => $torrent->isStatus(), - 'name' => $torrentService->readTorrentFileByTorrentId( - $torrent->getId() - )->getName(), - 'sensitive' => [ - 'id' => $activity->getData()['torrentSensitiveId'], - 'exist' => $torrentService->getTorrentSensitive( - $activity->getData()['torrentSensitiveId'] // could be deleted by moderator, remove links - ) - ] - ], - 'session' => - [ - 'user' => - [ - 'id' => $user->getId(), - 'sensitive' => $user->isSensitive(), - 'moderator' => $user->isModerator(), - 'owner' => $user->getId() === $torrent->getUserId(), - ] - ] - ] - ); - - break; - - /// Torrent Poster - case $activity::EVENT_TORRENT_POSTER_ADD: - - // Init torrent - if (!$torrent = $torrentService->getTorrent($activity->getTorrentId())) - { - throw $this->createNotFoundException(); - } - - return $this->render( - 'default/activity/event/torrent/poster/add' . $extension, - [ - 'id' => $activity->getId(), - 'added' => $activity->getAdded(), - 'user' => - [ - 'id' => $activity->getUserId(), - 'identicon' => $userService->identicon( - $userService->getUser( - $activity->getUserId() - )->getAddress() - ) - ], - 'torrent' => - [ - 'id' => $torrent->getId(), - 'sensitive' => $torrent->isSensitive(), - 'approved' => $torrent->isApproved(), - 'status' => $torrent->isStatus(), - 'name' => $torrentService->readTorrentFileByTorrentId( - $torrent->getId() - )->getName(), - 'poster' => [ - 'id' => $activity->getData()['torrentPosterId'], - 'exist' => $torrentService->getTorrentPoster( - $activity->getData()['torrentPosterId'] // could be deleted by moderator, remove links - ) - ] - ], - 'session' => - [ - 'user' => - [ - 'id' => $user->getId(), - 'sensitive' => $user->isSensitive(), - 'moderator' => $user->isModerator(), - 'owner' => $user->getId() === $torrent->getUserId(), - ] - ] - ] - ); - - break; - - case $activity::EVENT_TORRENT_POSTER_DELETE: - - // Init torrent - if (!$torrent = $torrentService->getTorrent($activity->getTorrentId())) - { - throw $this->createNotFoundException(); - } - - return $this->render( - 'default/activity/event/torrent/poster/delete' . $extension, - [ - 'id' => $activity->getId(), - 'added' => $activity->getAdded(), - 'user' => - [ - 'id' => $activity->getUserId(), - 'identicon' => $userService->identicon( - $userService->getUser( - $activity->getUserId() - )->getAddress() - ) - ], - 'torrent' => - [ - 'id' => $torrent->getId(), - 'sensitive' => $torrent->isSensitive(), - 'approved' => $torrent->isApproved(), - 'status' => $torrent->isStatus(), - 'name' => $torrentService->readTorrentFileByTorrentId( - $torrent->getId() - )->getName(), - 'poster' => [ - 'id' => $activity->getData()['torrentPosterId'], - 'exist' => $torrentService->getTorrentPoster( - $activity->getData()['torrentPosterId'] // could be deleted by moderator, remove links - ) - ] - ], - 'session' => - [ - 'user' => - [ - 'id' => $user->getId(), - 'sensitive' => $user->isSensitive(), - 'moderator' => $user->isModerator(), - 'owner' => $user->getId() === $torrent->getUserId(), - ] - ] - ] - ); - - break; - - case $activity::EVENT_TORRENT_POSTER_APPROVE_ADD: - - // Init torrent - if (!$torrent = $torrentService->getTorrent($activity->getTorrentId())) - { - throw $this->createNotFoundException(); - } - - return $this->render( - 'default/activity/event/torrent/poster/approve/add' . $extension, - [ - 'id' => $activity->getId(), - 'added' => $activity->getAdded(), - 'user' => - [ - 'id' => $activity->getUserId(), - 'identicon' => $userService->identicon( - $userService->getUser( - $activity->getUserId() - )->getAddress() - ) - ], - 'torrent' => - [ - 'id' => $torrent->getId(), - 'sensitive' => $torrent->isSensitive(), - 'approved' => $torrent->isApproved(), - 'status' => $torrent->isStatus(), - 'name' => $torrentService->readTorrentFileByTorrentId( - $torrent->getId() - )->getName(), - 'poster' => [ - 'id' => $activity->getData()['torrentPosterId'], - 'exist' => $torrentService->getTorrentPoster( - $activity->getData()['torrentPosterId'] // could be deleted by moderator, remove links - ) - ] - ], - 'session' => - [ - 'user' => - [ - 'id' => $user->getId(), - 'sensitive' => $user->isSensitive(), - 'moderator' => $user->isModerator(), - 'owner' => $user->getId() === $torrent->getUserId(), - ] - ] - ] - ); - - break; - - case $activity::EVENT_TORRENT_POSTER_APPROVE_DELETE: - - // Init torrent - if (!$torrent = $torrentService->getTorrent($activity->getTorrentId())) - { - throw $this->createNotFoundException(); - } - - return $this->render( - 'default/activity/event/torrent/poster/approve/delete' . $extension, - [ - 'id' => $activity->getId(), - 'added' => $activity->getAdded(), - 'user' => - [ - 'id' => $activity->getUserId(), - 'identicon' => $userService->identicon( - $userService->getUser( - $activity->getUserId() - )->getAddress() - ) - ], - 'torrent' => - [ - 'id' => $torrent->getId(), - 'sensitive' => $torrent->isSensitive(), - 'approved' => $torrent->isApproved(), - 'status' => $torrent->isStatus(), - 'name' => $torrentService->readTorrentFileByTorrentId( - $torrent->getId() - )->getName(), - 'poster' => [ - 'id' => $activity->getData()['torrentPosterId'], - 'exist' => $torrentService->getTorrentPoster( - $activity->getData()['torrentPosterId'] // could be deleted by moderator, remove links - ) - ] - ], - 'session' => - [ - 'user' => - [ - 'id' => $user->getId(), - 'sensitive' => $user->isSensitive(), - 'moderator' => $user->isModerator(), - 'owner' => $user->getId() === $torrent->getUserId(), - ] - ] - ] - ); - - break; - - /// Torrent star - case $activity::EVENT_TORRENT_STAR_ADD: - - // Init torrent - if (!$torrent = $torrentService->getTorrent($activity->getTorrentId())) - { - throw $this->createNotFoundException(); - } - - return $this->render( - 'default/activity/event/torrent/star/add' . $extension, - [ - 'id' => $activity->getId(), - 'added' => $activity->getAdded(), - 'user' => - [ - 'id' => $activity->getUserId(), - 'identicon' => $userService->identicon( - $userService->getUser( - $activity->getUserId() - )->getAddress() - ) - ], - 'torrent' => - [ - 'id' => $torrent->getId(), - 'sensitive' => $torrent->isSensitive(), - 'approved' => $torrent->isApproved(), - 'status' => $torrent->isStatus(), - 'name' => $torrentService->readTorrentFileByTorrentId( - $torrent->getId() - )->getName() - ], - 'session' => - [ - 'user' => - [ - 'id' => $user->getId(), - 'sensitive' => $user->isSensitive(), - 'moderator' => $user->isModerator(), - 'owner' => $user->getId() === $torrent->getUserId(), - ] - ] - ] - ); - - break; - - case $activity::EVENT_TORRENT_STAR_DELETE: - - // Init torrent - if (!$torrent = $torrentService->getTorrent($activity->getTorrentId())) - { - throw $this->createNotFoundException(); - } - - return $this->render( - 'default/activity/event/torrent/star/delete' . $extension, - [ - 'id' => $activity->getId(), - 'added' => $activity->getAdded(), - 'user' => - [ - 'id' => $activity->getUserId(), - 'identicon' => $userService->identicon( - $userService->getUser( - $activity->getUserId() - )->getAddress() - ) - ], - 'torrent' => - [ - 'id' => $torrent->getId(), - 'sensitive' => $torrent->isSensitive(), - 'approved' => $torrent->isApproved(), - 'status' => $torrent->isStatus(), - 'name' => $torrentService->readTorrentFileByTorrentId( - $torrent->getId() - )->getName() - ], - 'session' => - [ - 'user' => - [ - 'id' => $user->getId(), - 'sensitive' => $user->isSensitive(), - 'moderator' => $user->isModerator(), - 'owner' => $user->getId() === $torrent->getUserId(), - ] - ] - ] - ); - - break; - - default: - - return $this->render( - 'default/activity/event/undefined' . $extension, - [ - 'id' => $activity->getId(), - 'added' => $activity->getAdded(), - 'user' => - [ - 'id' => $activity->getUserId(), - 'identicon' => $userService->identicon( - $userService->getUser( - $activity->getUserId() - )->getAddress() - ) - ] - ] - ); - } - } - - private function initUser( - Request $request, - UserService $userService, - ActivityService $activityService - ): ?\App\Entity\User - { - // Init user - if (!$user = $userService->findUserByAddress($request->getClientIp())) - { - $user = $userService->addUser( - $request->getClientIp(), - time(), - $this->getParameter('app.locale'), - explode('|', $this->getParameter('app.locales')), - $activityService->getEventCodes(), - $this->getParameter('app.theme'), - $this->getParameter('app.sensitive'), - $this->getParameter('app.yggdrasil'), - $this->getParameter('app.posters'), - $this->getParameter('app.approved') - ); - - // Add user join event - $activityService->addEventUserAdd( - $user->getId(), - time() - ); - } - - return $user; - } -} \ No newline at end of file diff --git a/src/Controller/SearchController.php b/src/Controller/SearchController.php deleted file mode 100644 index 8cb63bc..0000000 --- a/src/Controller/SearchController.php +++ /dev/null @@ -1,164 +0,0 @@ -get('query') ? urldecode($request->get('query')) : ''; - $filter = $request->get('filter') ? true : false; - - // Extended search - if ($filter) - { - // Init user - $user = $this->initUser( - $request, - $userService, - $activityService - ); - - // Keywords - $keywords = explode(' ', $query); - - // Locales - foreach (explode('|', $this->getParameter('app.locales')) as $locale) - { - - if ($request->get('locales')) - { - $checked = in_array($locale, (array) $request->get('locales')); - } - - else - { - $checked = in_array($locale, $user->getLocales()); - } - - $locales[] = - [ - 'value' => $locale, - 'checked' => $checked, - 'total' => $torrentService->findTorrentsTotal( - 0, - $keywords, - [$locale], - $request->get('categories') ? $request->get('categories') : $user->getCategories(), - $request->get('sensitive') ? null : false, - !$user->isModerator() ? true : null, - !$user->isModerator() ? true : null, - ) - ]; - } - - // Categories - foreach (explode('|', $this->getParameter('app.categories')) as $category) - { - if ($request->get('categories')) - { - $checked = in_array($category, (array) $request->get('categories')); - } - - else - { - $checked = in_array($category, $user->getCategories()); - } - - $categories[] = - [ - 'value' => $category, - 'checked' => $checked, - 'total' => $torrentService->findTorrentsTotal( - 0, - $keywords, - $request->get('locales') ? $request->get('locales') : $user->getLocales(), - [$category], - $request->get('sensitive') ? null : false, - !$user->isModerator() ? true : null, - !$user->isModerator() ? true : null, - ) - ]; - } - - // Sensitive - $sensitive = - [ - 'checked' => $request->get('sensitive'), - 'total' => $torrentService->findTorrentsTotal( - 0, - $keywords, - $request->get('locales') ? $request->get('locales') : $user->getLocales(), - $request->get('categories') ? $request->get('categories') : $user->getCategories(), - true, - !$user->isModerator() ? true : null, - !$user->isModerator() ? true : null, - ) - ]; - } - - return $this->render( - 'default/search/module.html.twig', - [ - 'query' => $query, - 'filter' => $filter, - 'sensitive' => $sensitive, - 'locales' => $locales, - 'categories' => $categories, - ] - ); - } - - private function initUser( - Request $request, - UserService $userService, - ActivityService $activityService - ): ?\App\Entity\User - { - // Init user - if (!$user = $userService->findUserByAddress($request->getClientIp())) - { - $user = $userService->addUser( - $request->getClientIp(), - time(), - $this->getParameter('app.locale'), - explode('|', $this->getParameter('app.locales')), - $activityService->getEventCodes(), - $this->getParameter('app.theme'), - $this->getParameter('app.sensitive'), - $this->getParameter('app.yggdrasil'), - $this->getParameter('app.posters'), - $this->getParameter('app.approved') - ); - - // Add user join event - $activityService->addEventUserAdd( - $user->getId(), - time() - ); - } - - return $user; - } -} \ No newline at end of file diff --git a/src/Controller/TorrentController.php b/src/Controller/TorrentController.php deleted file mode 100644 index 38205db..0000000 --- a/src/Controller/TorrentController.php +++ /dev/null @@ -1,3486 +0,0 @@ - '%app.locales%', - 'torrentId' => '\d+', - ], - methods: - [ - 'GET' - ] - )] - public function info( - Request $request, - TranslatorInterface $translator, - UserService $userService, - TorrentService $torrentService, - ActivityService $activityService - ): Response - { - // Init user - $user = $this->initUser( - $request, - $userService, - $activityService - ); - - // Init torrent - if (!$torrent = $torrentService->getTorrent($request->get('torrentId'))) - { - throw $this->createNotFoundException(); - } - - // Read file - if (!$file = $torrentService->readTorrentFileByTorrentId($torrent->getId())) - { - throw $this->createNotFoundException(); - } - - // Sensitive filter - // @TODO add blur effect or sensitive notice instead of 404 on direct request #37 - /* - if (!$user->isModerator() && $user->isSensitive() && $torrent->isSensitive()) - { - throw $this->createNotFoundException(); - } - */ - - // Access filter - if (!$user->isModerator() && $user->getId() != $torrent->getUserId() && - (!$torrent->isStatus() || !$torrent->isApproved())) - { - throw $this->createNotFoundException(); - } - - // Get contributors - $contributors = []; - foreach ($torrentService->getTorrentContributors($torrent) as $userId) - { - $contributors[$userId] = $userService->identicon( - $userService->getUser( - $userId - )->getAddress() - ); - } - - // Get total activities - $total = $activityService->findActivitiesTotalByTorrentId( - $torrent->getId(), - $user->getEvents() - ); - - // Create trackers list - $appTrackers = explode('|', $this->getParameter('app.trackers')); - $allTrackers = []; - - foreach ($appTrackers as $tracker) - { - $allTrackers[$tracker] = true; - } - - foreach ($file->getAnnounceList() as $announce) - { - foreach ($announce as $tracker) - { - $allTrackers[$tracker] = !($user->isYggdrasil() && !in_array($tracker, $appTrackers)); - } - } - - // Init page - $page = $request->get('page') ? (int) $request->get('page') : 1; - - // Poster - if ($user->isPosters() && $torrent->getTorrentPosterId()) - { - $torrentPoster = $torrentService->getTorrentPoster( - $torrent->getTorrentPosterId() - ); - - $poster = [ - 'position' => $torrentPoster->getPosition(), - 'url' => $request->getScheme() . '://' . - $request->getHttpHost() . - $request->getBasePath() . - $torrentService->getImageUriByTorrentPosterId( - $torrentPoster->getId() - ) - ]; - } - - else - { - $poster = false; - } - - // Render template - return $this->render('default/torrent/info.html.twig', - [ - 'session' => - [ - 'user' => $user, - 'id' => $user->getId(), - 'moderator' => $user->isModerator(), - 'owner' => $user->getId() === $torrent->getUserId(), - ], - 'torrent' => - [ - 'id' => $torrent->getId(), - 'md5file' => $torrent->getMd5File(), - 'added' => $torrent->getAdded(), - 'scrape' => - [ - 'seeders' => (int) $torrent->getSeeders(), - 'peers' => (int) $torrent->getPeers(), - 'leechers' => (int) $torrent->getLeechers(), - ], - 'keywords' => $torrent->getKeywords(), - 'locales' => $torrent->getLocales(), - 'categories' => $torrent->getCategories(), - 'sensitive' => $torrent->isSensitive(), - 'approved' => $torrent->isApproved(), - 'status' => $torrent->isStatus(), - 'download' => - [ - 'file' => - [ - 'exist' => (bool) $torrentService->findTorrentDownloadFile( - $torrent->getId(), - $user->getId() - ), - 'total' => $torrentService->findTorrentDownloadFilesTotalByTorrentId( - $torrent->getId() - ) - ], - 'magnet' => - [ - 'exist' => (bool) $torrentService->findTorrentDownloadMagnet( - $torrent->getId(), - $user->getId() - ), - 'total' => $torrentService->findTorrentDownloadMagnetsTotalByTorrentId( - $torrent->getId() - ) - ] - ], - 'star' => - [ - 'exist' => (bool) $torrentService->findTorrentStar( - $torrent->getId(), - $user->getId() - ), - 'total' => $torrentService->findTorrentStarsTotalByTorrentId( - $torrent->getId() - ) - ], - 'contributors' => $contributors, - 'poster' => $poster - ], - 'file' => - [ - 'name' => $file->getName(), - 'size' => $file->getSize(), - 'count' => $file->getFileCount(), - 'pieces' => $file->getPieceLength(), - 'created' => $file->getCreationDate(), - 'software' => $file->getCreatedBy(), - 'protocol' => $file->getProtocol(), - 'private' => $file->isPrivate(), - 'source' => $file->getSource(), - 'comment' => $file->getComment(), - 'tree' => $file->getFileTree( - \Rhilip\Bencode\TorrentFile::FILETREE_SORT_NATURAL // #34 @TODO cyrillic - ), - //'trackers' => $file->getAnnounceList(), - 'hash' => - [ - 'v1' => $file->getInfoHashV1(false), - 'v2' => $file->getInfoHashV2(false) - ], - ], - 'trackers' => $allTrackers, - 'activities' => $activityService->findLastActivitiesByTorrentId( - $torrent->getId(), - $user->getEvents(), - $this->getParameter('app.pagination'), - ($page - 1) * $this->getParameter('app.pagination') - ), - 'pagination' => - [ - 'page' => $page, - 'pages' => ceil($total / $this->getParameter('app.pagination')), - 'total' => $total - ] - ]); - } - - #[Route( - '/{_locale}/search', - name: 'torrent_search', - requirements: - [ - '_locale' => '%app.locales%' - ], - methods: - [ - 'GET' - ] - )] - public function search( - Request $request, - UserService $userService, - TorrentService $torrentService, - ActivityService $activityService - ): Response - { - // Init user - $user = $this->initUser( - $request, - $userService, - $activityService - ); - - // Init request - $query = $request->get('query') ? explode(' ', urldecode($request->get('query'))) : []; - $page = $request->get('page') ? (int) $request->get('page') : 1; - - // Get total torrents - $total = $torrentService->findTorrentsTotal( - $request->get('filter') ? 0 : $user->getId(), - $query, - $request->get('filter') ? (array) $request->get('locales') : $user->getLocales(), - $request->get('filter') ? (array) $request->get('categories') : $user->getCategories(), - $request->get('filter') ? ($request->get('sensitive') ? null : false) : ($user->isSensitive() ? false : null), - !$user->isModerator() ? true : null, - !$user->isModerator() ? true : null, - ); - - $torrents = []; - foreach ($torrentService->findTorrents( - $request->get('filter') ? 0 : $user->getId(), - $query, - $request->get('filter') ? (array) $request->get('locales') : $user->getLocales(), - $request->get('filter') ? (array) $request->get('categories') : $user->getCategories(), - $request->get('filter') ? ($request->get('sensitive') ? null : false) : ($user->isSensitive() ? false : null), - !$user->isModerator() ? true : null, - !$user->isModerator() ? true : null, - $this->getParameter('app.pagination'), - ($page - 1) * $this->getParameter('app.pagination') - ) as $torrent) - { - // Read file - if (!$file = $torrentService->readTorrentFileByTorrentId($torrent->getId())) - { - throw $this->createNotFoundException(); // @TODO exception - } - - // Generate keywords by extension - $keywords = []; - - foreach ($file->getFileList() as $item) - { - if ($keyword = pathinfo($item['path'], PATHINFO_EXTENSION)) - { - $keyword = mb_strtolower($keyword); - - if (isset($keywords[$keyword])) - { - $keywords[$keyword] = $keywords[$keyword] + (int) $item['size']; - } - - else - { - $keywords[$keyword] = 0; - } - } - } - - arsort($keywords); - - // Poster - if ($user->isPosters() && $torrent->getTorrentPosterId()) - { - $torrentPoster = $torrentService->getTorrentPoster( - $torrent->getTorrentPosterId() - ); - - $poster = [ - 'position' => $torrentPoster->getPosition(), - 'url' => $request->getScheme() . '://' . - $request->getHttpHost() . - $request->getBasePath() . - $torrentService->getImageUriByTorrentPosterId( - $torrentPoster->getId() - ) - ]; - } - - else - { - $poster = false; - } - - // Push torrent - $torrents[] = - [ - 'id' => $torrent->getId(), - 'added' => $torrent->getAdded(), - 'approved' => $torrent->isApproved(), - 'sensitive' => $torrent->isSensitive(), - 'status' => $torrent->isStatus(), - 'file' => - [ - 'name' => $file->getName(), - 'size' => $file->getSize(), - 'hash' => - [ - 'v1' => $file->getInfoHashV1(false), - 'v2' => $file->getInfoHashV2(false) - ], - ], - 'scrape' => - [ - 'seeders' => (int) $torrent->getSeeders(), - 'peers' => (int) $torrent->getPeers(), - 'leechers' => (int) $torrent->getLeechers(), - ], - 'user' => - [ - 'id' => $torrent->getUserId(), - 'identicon' => $userService->identicon( - $userService->getUser( - $torrent->getUserId() - )->getAddress() - ) - ], - 'keywords' => $keywords, - 'download' => - [ - 'file' => - [ - 'exist' => (bool) $torrentService->findTorrentDownloadFile( - $torrent->getId(), - $user->getId() - ), - 'total' => $torrentService->findTorrentDownloadFilesTotalByTorrentId( - $torrent->getId() - ) - ], - 'magnet' => - [ - 'exist' => (bool) $torrentService->findTorrentDownloadMagnet( - $torrent->getId(), - $user->getId() - ), - 'total' => $torrentService->findTorrentDownloadMagnetsTotalByTorrentId( - $torrent->getId() - ) - ] - ], - 'star' => - [ - 'exist' => (bool) $torrentService->findTorrentStar( - $torrent->getId(), - $user->getId() - ), - 'total' => $torrentService->findTorrentStarsTotalByTorrentId( - $torrent->getId() - ) - ], - 'poster' => $poster - ]; - } - - return $this->render('default/torrent/list.html.twig', [ - 'query' => $request->get('query') ? urldecode($request->get('query')) : '', - 'torrents' => $torrents, - 'pagination' => - [ - 'page' => $page, - 'pages' => ceil($total / $this->getParameter('app.pagination')), - 'total' => $total - ] - ]); - } - - #[Route( - '/{_locale}', - name: 'torrent_recent', - requirements: - [ - '_locale' => '%app.locales%' - ], - methods: - [ - 'GET' - ] - )] - public function recent( - Request $request, - UserService $userService, - TorrentService $torrentService, - ActivityService $activityService - ): Response - { - // Init user - $user = $this->initUser( - $request, - $userService, - $activityService - ); - - // Init page - $page = $request->get('page') ? (int) $request->get('page') : 1; - - // Get total torrents - $total = $torrentService->findTorrentsTotal( - $user->getId(), - [], - $user->getLocales(), - $user->getCategories(), - $user->isSensitive() ? false : null, - !$user->isModerator() ? true : null, - !$user->isModerator() ? true : null, - ); - - // Create torrents list - $torrents = []; - foreach ($torrentService->findTorrents( - $user->getId(), - [], - $user->getLocales(), - $user->getCategories(), - $user->isSensitive() ? false : null, - !$user->isModerator() ? true : null, - !$user->isModerator() ? true : null, - $this->getParameter('app.pagination'), - ($page - 1) * $this->getParameter('app.pagination') - ) as $torrent) - { - // Read file - if (!$file = $torrentService->readTorrentFileByTorrentId($torrent->getId())) - { - throw $this->createNotFoundException(); // @TODO exception - } - - // Generate keywords by extension - $keywords = []; - - foreach ($file->getFileList() as $item) - { - if ($keyword = pathinfo($item['path'], PATHINFO_EXTENSION)) - { - $keyword = mb_strtolower($keyword); - - if (isset($keywords[$keyword])) - { - $keywords[$keyword] = $keywords[$keyword] + (int) $item['size']; - } - - else - { - $keywords[$keyword] = 0; - } - } - } - - arsort($keywords); - - // Poster - if ($user->isPosters() && $torrent->getTorrentPosterId()) - { - $torrentPoster = $torrentService->getTorrentPoster( - $torrent->getTorrentPosterId() - ); - - $poster = [ - 'position' => $torrentPoster->getPosition(), - 'url' => $request->getScheme() . '://' . - $request->getHttpHost() . - $request->getBasePath() . - $torrentService->getImageUriByTorrentPosterId( - $torrentPoster->getId() - ) - ]; - } - - else - { - $poster = false; - } - - // Push torrent - $torrents[] = - [ - 'id' => $torrent->getId(), - 'added' => $torrent->getAdded(), - 'approved' => $torrent->isApproved(), - 'sensitive' => $torrent->isSensitive(), - 'status' => $torrent->isStatus(), - 'file' => - [ - 'name' => $file->getName(), - 'size' => $file->getSize(), - 'hash' => - [ - 'v1' => $file->getInfoHashV1(false), - 'v2' => $file->getInfoHashV2(false) - ], - ], - 'scrape' => - [ - 'seeders' => (int) $torrent->getSeeders(), - 'peers' => (int) $torrent->getPeers(), - 'leechers' => (int) $torrent->getLeechers(), - ], - 'keywords' => $keywords, - 'download' => - [ - 'file' => - [ - 'exist' => (bool) $torrentService->findTorrentDownloadFile( - $torrent->getId(), - $user->getId() - ), - 'total' => $torrentService->findTorrentDownloadFilesTotalByTorrentId( - $torrent->getId() - ) - ], - 'magnet' => - [ - 'exist' => (bool) $torrentService->findTorrentDownloadMagnet( - $torrent->getId(), - $user->getId() - ), - 'total' => $torrentService->findTorrentDownloadMagnetsTotalByTorrentId( - $torrent->getId() - ) - ] - ], - 'star' => - [ - 'exist' => (bool) $torrentService->findTorrentStar( - $torrent->getId(), - $user->getId() - ), - 'total' => $torrentService->findTorrentStarsTotalByTorrentId( - $torrent->getId() - ) - ], - 'poster' => $poster - ]; - } - - return $this->render('default/torrent/list.html.twig', [ - 'torrents' => $torrents, - 'pagination' => - [ - 'page' => $page, - 'pages' => ceil($total / $this->getParameter('app.pagination')), - 'total' => $total - ] - ]); - } - - #[Route( - '/{_locale}/rss/torrents', - name: 'rss_torrents_recent', - requirements: [ - '_locale' => '%app.locales%' - ], - methods: - [ - 'GET' - ] - )] - public function rssRecent( - Request $request, - UserService $userService, - TorrentService $torrentService, - ActivityService $activityService - ): Response - { - // Init user - $user = $this->initUser( - $request, - $userService, - $activityService - ); - - // Init request - $query = $request->get('query') ? explode(' ', urldecode($request->get('query'))) : []; - $page = $request->get('page') ? (int) $request->get('page') : 1; - - // Get total torrents - $total = $torrentService->findTorrentsTotal( - $request->get('filter') ? 0 : $user->getId(), - $query, - $request->get('filter') ? (array) $request->get('locales') : $user->getLocales(), - $request->get('filter') ? (array) $request->get('categories') : $user->getCategories(), - $request->get('filter') ? ($request->get('sensitive') ? null : false) : ($user->isSensitive() ? false : null), - !$user->isModerator() ? true : null, - !$user->isModerator() ? true : null, - ); - - // Create torrents list - $torrents = []; - foreach ($torrentService->findTorrents( - $request->get('filter') ? 0 : $user->getId(), - $query, - $request->get('filter') ? (array) $request->get('locales') : $user->getLocales(), - $request->get('filter') ? (array) $request->get('categories') : $user->getCategories(), - $request->get('filter') ? ($request->get('sensitive') ? null : false) : ($user->isSensitive() ? false : null), - !$user->isModerator() ? true : null, - !$user->isModerator() ? true : null, - $this->getParameter('app.pagination'), - ($page - 1) * $this->getParameter('app.pagination') - ) as $torrent) - { - // Read file - if (!$file = $torrentService->readTorrentFileByTorrentId($torrent->getId())) - { - throw $this->createNotFoundException(); // @TODO exception - } - - $torrents[] = - [ - 'id' => $torrent->getId(), - 'added' => $torrent->getAdded(), - 'file' => - [ - 'name' => $file->getName(), - ], - 'user' => - [ - 'id' => $torrent->getUserId(), - ], - ]; - } - - $response = new Response(); - $response->headers->set('Content-Type', 'text/xml'); - - return $this->render( - 'default/torrent/list.rss.twig', - [ - 'torrents' => $torrents - ], - $response - ); - } - - // #25 - // https://github.com/YGGverse/YGGtracker/issues/25 - #[Route( - '/api/torrents', - methods: - [ - 'GET' - ] - )] - public function jsonRecent( - Request $request, - UserService $userService, - TorrentService $torrentService, - ActivityService $activityService - ): Response - { - // Init user - $user = $this->initUser( - $request, - $userService, - $activityService - ); - - // Init request - $query = $request->get('query') ? - explode(' ', urldecode($request->get('query'))) : []; - - $page = $request->get('page') ? - (int) $request->get('page') : 1; - - $filter = $request->get('filter') ? - true : false; - - if ($request->get('locales')) - { - $locales = explode('|', $request->get('locales')); - } - - else - { - $locales = $user->getLocales(); - } - - if ($request->get('categories')) - { - $categories = explode('|', $request->get('categories')); - } - - else - { - $categories = $user->getCategories(); - } - - switch ($request->get('sensitive')) - { - case 'true': - $sensitive = true; - break; - case 'false': - $sensitive = false; - break; - default: - $sensitive = $user->isSensitive() ? false : null; - } - - switch ($request->get('yggdrasil')) - { - case 'true': - $yggdrasil = true; - break; - case 'false': - $yggdrasil = false; - break; - default: - $yggdrasil = $user->isYggdrasil(); - } - - // Init trackers - $trackers = explode('|', $this->getParameter('app.trackers')); - - // Get total torrents - $total = $torrentService->findTorrentsTotal( - $filter ? 0 : $user->getId(), - $query, - $locales, - $categories, - $sensitive, - !$user->isModerator() ? true : null, - !$user->isModerator() ? true : null, - ); - - // Create torrents list - $torrents = []; - foreach ($torrentService->findTorrents( - $filter ? 0 : $user->getId(), - $query, - $locales, - $categories, - $sensitive, - !$user->isModerator() ? true : null, - !$user->isModerator() ? true : null, - $this->getParameter('app.pagination'), - ($page - 1) * $this->getParameter('app.pagination') - ) as $torrent) - { - // Read file - if (!$file = $torrentService->readTorrentFileByTorrentId($torrent->getId())) - { - throw $this->createNotFoundException(); // @TODO exception - } - - // Apply yggdrasil filters - $file = $this->filterYggdrasil($file, $yggdrasil); - - $torrents[] = - [ - 'torrent' => - [ - 'id' => $torrent->getId(), - 'added' => $torrent->getAdded(), - 'locales' => $torrent->getLocales(), - 'categories' => $torrent->getCategories(), - 'sensitive' => $torrent->isSensitive(), - 'file' => - [ - 'name' => $file->getName(), - 'size' => $file->getSize(), - 'url' => $this->generateUrl( - 'torrent_file', - [ - 'torrentId' => $torrent->getId() - ], - false - ) - ], - 'magnet' => - [ - 'url' => $this->generateUrl( - 'torrent_magnet', - [ - 'torrentId' => $torrent->getId() - ], - false - ), - //'urn' => $file->getMagnetLink() - ], - 'scrape' => - [ - 'seeders' => (int) $torrent->getSeeders(), - 'peers' => (int) $torrent->getPeers(), - 'leechers' => (int) $torrent->getLeechers(), - ], - 'url' => $this->generateUrl( - 'torrent_info', - [ - '_locale' => $user->getLocale(), - 'torrentId' => $torrent->getId(), - ], - false - ) - ], - ]; - } - - return $this->json( - [ - 'version' => time(), - 'tracker' => - [ - 'name' => $this->getParameter('app.name'), - 'version' => $this->getParameter('app.version'), - 'url' => $this->generateUrl( - 'torrent_recent', - [ - '_locale' => $user->getLocale() - ], - false - ) - ], - 'torrents' => $torrents - ] - ); - } - - // Forms - #[Route( - '/{_locale}/submit', - name: 'torrent_submit', - requirements: - [ - '_locale' => '%app.locales%' - ], - methods: - [ - 'GET', - 'POST' - ] - )] - public function submit( - Request $request, - TranslatorInterface $translator, - UserService $userService, - TorrentService $torrentService, - ActivityService $activityService - ): Response - { - // Init user - $user = $this->initUser( - $request, - $userService, - $activityService - ); - - if (!$user->isStatus()) - { - // @TODO - throw new \Exception( - $translator->trans('Access denied') - ); - } - - // Init form - $form = - [ - 'locales' => - [ - 'error' => [], - 'attribute' => - [ - 'value' => $request->get('locales') ? $request->get('locales') : [$request->get('_locale')], - ] - ], - 'categories' => - [ - 'error' => [], - 'attribute' => - [ - 'value' => $request->get('categories') ? $request->get('categories') : [], - ] - ], - 'torrent' => - [ - 'error' => [], - ], - 'sensitive' => - [ - 'error' => [], - 'attribute' => - [ - 'value' => $request->get('sensitive'), - ] - ] - ]; - - // Process request - if ($request->isMethod('post')) - { - /// Locales - $locales = []; - if ($request->get('locales')) - { - foreach ((array) $request->get('locales') as $locale) - { - if (in_array($locale, explode('|', $this->getParameter('app.locales')))) - { - $locales[] = $locale; - } - } - } - - //// At least one valid locale required - if (!$locales) - { - $form['locales']['error'][] = $translator->trans('At least one locale required'); - } - - /// Categories - $categories = []; - if ($request->get('categories')) - { - foreach ((array) $request->get('categories') as $locale) - { - if (in_array($locale, explode('|', $this->getParameter('app.categories')))) - { - $categories[] = $locale; - } - } - } - - //// At least one valid locale required - if (!$categories) - { - $form['categories']['error'][] = $translator->trans('At least one category required'); - } - - /// Torrent - if ($file = $request->files->get('torrent')) - { - //// Validate torrent file - if (filesize($file->getPathName()) > $this->getParameter('app.torrent.size.max')) - { - $form['torrent']['error'][] = $translator->trans('Torrent file out of size limit'); - } - - //// Check for duplicates - if ($torrentService->findTorrentByMd5File(md5_file($file->getPathName()))) - { - $form['torrent']['error'][] = $translator->trans('Torrent file already exists'); - } - - //// Validate torrent format - if (!$torrentService->readTorrentFileByFilepath($file->getPathName())) - { - $form['torrent']['error'][] = $translator->trans('Could not parse torrent file'); - } - } - - else - { - $form['torrent']['error'][] = $translator->trans('Torrent file required'); - } - - // Request is valid - if (empty($form['torrent']['error']) && empty($form['locales']['error']) && empty($form['categories']['error'])) - { - // Save data - $torrent = $torrentService->add( - - $file->getPathName(), - - (bool) $this->getParameter('app.index.torrent.name.enabled'), - (bool) $this->getParameter('app.index.torrent.filenames.enabled'), - (bool) $this->getParameter('app.index.torrent.hash.v1.enabled'), - (bool) $this->getParameter('app.index.torrent.hash.v2.enabled'), - (bool) $this->getParameter('app.index.torrent.source.enabled'), - (bool) $this->getParameter('app.index.torrent.comment.enabled'), - (int) $this->getParameter('app.index.word.length.min'), - (int) $this->getParameter('app.index.word.length.max'), - - $user->getId(), - time(), - (array) $locales, - (array) $categories, - (bool) $request->get('sensitive'), - $user->isApproved(), - $user->isStatus() - ); - - // Add activity event - $activityService->addEventTorrentAdd( - $user->getId(), - time(), - $torrent->getId() - ); - - // Redirect to info page - return $this->redirectToRoute( - 'torrent_info', - [ - '_locale' => $request->get('_locale'), - 'torrentId' => $torrent->getId() - ] - ); - } - } - - // Render form template - return $this->render( - 'default/torrent/submit.html.twig', - [ - 'locales' => explode('|', $this->getParameter('app.locales')), - 'categories' => explode('|', $this->getParameter('app.categories')), - 'form' => $form, - ] - ); - } - - // Torrent moderation - #[Route( - '/{_locale}/torrent/{torrentId}/approve/toggle', - name: 'torrent_approve_toggle', - requirements: - [ - '_locale' => '%app.locales%', - 'torrentId' => '\d+', - ], - methods: - [ - 'GET' - ] - )] - public function approve( - Request $request, - UserService $userService, - TorrentService $torrentService, - ActivityService $activityService - ): Response - { - // Init user - $user = $this->initUser( - $request, - $userService, - $activityService - ); - - // Init torrent - if (!$torrent = $torrentService->getTorrent($request->get('torrentId'))) - { - throw $this->createNotFoundException(); - } - - // Check permissions - if (!$user->isModerator()) - { - // @TODO - throw new \Exception( - $translator->trans('Access denied') - ); - } - - // Register activity event - if (!$torrent->isApproved()) - { - $activityService->addEventTorrentApproveAdd( - $user->getId(), - $torrent->getId(), - time() - ); - } - - else - { - $activityService->addEventTorrentApproveDelete( - $user->getId(), - $torrent->getId(), - time() - ); - } - - // Update approved - $torrentService->toggleTorrentApproved( - $torrent->getId() - ); - - // Redirect back to form - return $this->redirectToRoute( - 'torrent_info', - [ - '_locale' => $request->get('_locale'), - 'torrentId' => $torrent->getId() - ] - ); - } - - #[Route( - '/{_locale}/torrent/{torrentId}/status/toggle', - name: 'torrent_status_toggle', - requirements: - [ - '_locale' => '%app.locales%', - 'torrentId' => '\d+', - ], - methods: - [ - 'GET' - ] - )] - public function status( - Request $request, - UserService $userService, - TorrentService $torrentService, - ActivityService $activityService - ): Response - { - // Init user - $user = $this->initUser( - $request, - $userService, - $activityService - ); - - // Init torrent - if (!$torrent = $torrentService->getTorrent($request->get('torrentId'))) - { - throw $this->createNotFoundException(); - } - - // Check permissions - if (!($user->isModerator() || $user->getId() == $torrent->getUserId())) - { - // @TODO - throw new \Exception( - $translator->trans('Access denied') - ); - } - - // Register activity event - if (!$torrent->isStatus()) - { - $activityService->addEventTorrentStatusAdd( - $user->getId(), - $torrent->getId(), - time() - ); - } - - else - { - $activityService->addEventTorrentStatusDelete( - $user->getId(), - $torrent->getId(), - time() - ); - } - - // Update status - $torrentService->toggleTorrentStatus( - $torrent->getId() - ); - - // Redirect back to form - return $this->redirectToRoute( - 'torrent_info', - [ - '_locale' => $request->get('_locale'), - 'torrentId' => $torrent->getId() - ] - ); - } - - // Torrent locales - #[Route( - '/{_locale}/torrent/{torrentId}/edit/locales/{torrentLocalesId}', - name: 'torrent_locales_edit', - requirements: - [ - '_locale' => '%app.locales%', - 'torrentId' => '\d+', - 'torrentLocalesId' => '\d+', - ], - defaults: - [ - 'torrentLocalesId' => null, - ], - methods: - [ - 'GET', - 'POST' - ] - )] - public function editLocales( - Request $request, - TranslatorInterface $translator, - UserService $userService, - TorrentService $torrentService, - ActivityService $activityService - ): Response - { - // Init user - $user = $this->initUser( - $request, - $userService, - $activityService - ); - - if (!$user->isStatus()) - { - // @TODO - throw new \Exception( - $translator->trans('Access denied') - ); - } - - // Init torrent - if (!$torrent = $torrentService->getTorrent($request->get('torrentId'))) - { - throw $this->createNotFoundException(); - } - - // Init torrent locales - $torrentLocalesCurrent = [ - 'userId' => null, - 'value' => [] - ]; - - // Get from edition version requested - if ($request->get('torrentLocalesId')) - { - if ($torrentLocales = $torrentService->getTorrentLocales($request->get('torrentLocalesId'))) - { - $torrentLocalesCurrent['userId'] = $torrentLocales->getUserId(); - - foreach ($torrentLocales->getValue() as $value) - { - $torrentLocalesCurrent['value'][] = $value; - } - } - - else - { - throw $this->createNotFoundException(); - } - } - - // Otherwise, get latest available - else - { - if ($torrentLocales = $torrentService->findLastTorrentLocalesByTorrentId($torrent->getId())) - { - $torrentLocalesCurrent['userId'] = $torrentLocales->getUserId(); - - foreach ($torrentLocales->getValue() as $value) - { - $torrentLocalesCurrent['value'][] = $value; - } - - // Update active locale - $request->attributes->set('torrentLocalesId', $torrentLocales->getId()); - } - - else - { - $torrentLocalesCurrent['value'][] = $request->get('_locale'); - } - } - - // Init edition history - $editions = []; - foreach ($torrentService->findTorrentLocalesByTorrentId($torrent->getId()) as $torrentLocalesEdition) - { - $editions[] = - [ - 'id' => $torrentLocalesEdition->getId(), - 'added' => $torrentLocalesEdition->getAdded(), - 'approved' => $torrentLocalesEdition->isApproved(), - 'active' => $torrentLocalesEdition->getId() == $request->get('torrentLocalesId'), - 'user' => - [ - 'id' => $torrentLocalesEdition->getUserId(), - 'identicon' => $userService->identicon( - $userService->getUser( - $torrentLocalesEdition->getUserId() - )->getAddress() - ), - ] - ]; - } - - // Init form - $form = - [ - 'locales' => - [ - 'error' => [], - 'attribute' => - [ - 'value' => $request->get('locales') ? $request->get('locales') : $torrentLocalesCurrent['value'], - ] - ] - ]; - - // Process request - if ($request->isMethod('post')) - { - /// Locales - $locales = []; - if ($request->get('locales')) - { - foreach ((array) $request->get('locales') as $locale) - { - if (in_array($locale, explode('|', $this->getParameter('app.locales')))) - { - $locales[] = $locale; - } - } - } - - //// At least one valid locale required - if (!$locales) - { - $form['locales']['error'][] = $translator->trans('At least one locale required'); - } - - // Request is valid - if (empty($form['locales']['error'])) - { - // Save data - $torrentLocales = $torrentService->addTorrentLocales( - $torrent->getId(), - $user->getId(), - time(), - $locales, - $user->isApproved() - ); - - // Register activity event - $activityService->addEventTorrentLocalesAdd( - $user->getId(), - $torrent->getId(), - time(), - $torrentLocales->getId() - ); - - // Redirect to info page - return $this->redirectToRoute( - 'torrent_info', - [ - '_locale' => $request->get('_locale'), - 'torrentId' => $torrent->getId() - ] - ); - } - } - - // Render form template - return $this->render( - 'default/torrent/edit/locales.html.twig', - [ - 'torrentId' => $torrent->getId(), - 'locales' => explode('|', $this->getParameter('app.locales')), - 'editions' => $editions, - 'form' => $form, - 'session' => - [ - 'moderator' => $user->isModerator(), - 'owner' => $torrentLocalesCurrent['userId'] === $user->getId(), - ] - ] - ); - } - - #[Route( - '/{_locale}/torrent/{torrentId}/approve/locales/{torrentLocalesId}', - name: 'torrent_locales_approve', - requirements: - [ - '_locale' => '%app.locales%', - 'torrentId' => '\d+', - 'torrentLocalesId' => '\d+', - ], - methods: - [ - 'GET' - ] - )] - public function approveLocales( - Request $request, - TranslatorInterface $translator, - UserService $userService, - TorrentService $torrentService, - ActivityService $activityService - ): Response - { - // Init user - $user = $this->initUser( - $request, - $userService, - $activityService - ); - - // Init torrent - if (!$torrent = $torrentService->getTorrent($request->get('torrentId'))) - { - throw $this->createNotFoundException(); - } - - // Init torrent locales - if (!$torrentLocales = $torrentService->getTorrentLocales($request->get('torrentLocalesId'))) - { - throw $this->createNotFoundException(); - } - - // Check permissions - if (!$user->isModerator()) - { - // @TODO - throw new \Exception( - $translator->trans('Access denied') - ); - } - - // Register activity event - if (!$torrentLocales->isApproved()) - { - $activityService->addEventTorrentLocalesApproveAdd( - $user->getId(), - $torrent->getId(), - time(), - $torrentLocales->getId() - ); - } - - else - { - $activityService->addEventTorrentLocalesApproveDelete( - $user->getId(), - $torrent->getId(), - time(), - $torrentLocales->getId() - ); - } - - // Update approved - $torrentService->toggleTorrentLocalesApproved( - $torrentLocales->getId() - ); - - // Redirect back to form - return $this->redirectToRoute( - 'torrent_locales_edit', - [ - '_locale' => $request->get('_locale'), - 'torrentId' => $torrent->getId(), - 'torrentLocalesId' => $torrentLocales->getId(), - ] - ); - } - - #[Route( - '/{_locale}/torrent/{torrentId}/delete/locales/{torrentLocalesId}', - name: 'torrent_locales_delete', - requirements: - [ - '_locale' => '%app.locales%', - 'torrentId' => '\d+', - 'torrentLocalesId' => '\d+', - ], - methods: - [ - 'GET' - ] - )] - public function deleteLocales( - Request $request, - TranslatorInterface $translator, - UserService $userService, - TorrentService $torrentService, - ActivityService $activityService - ): Response - { - // Init user - $user = $this->initUser( - $request, - $userService, - $activityService - ); - - // Init torrent - if (!$torrent = $torrentService->getTorrent($request->get('torrentId'))) - { - throw $this->createNotFoundException(); - } - - // Init torrent locales - if (!$torrentLocales = $torrentService->getTorrentLocales($request->get('torrentLocalesId'))) - { - throw $this->createNotFoundException(); - } - - // Check permissions - if (!($user->isModerator() || $user->getId() === $torrentLocales->getUserId())) - { - // @TODO - throw new \Exception( - $translator->trans('Access denied') - ); - } - - // Add activity event - $activityService->addEventTorrentLocalesDelete( - $user->getId(), - $torrent->getId(), - time(), - $torrentLocales->getId() - ); - - // Update approved - $torrentService->deleteTorrentLocales( - $torrentLocales->getId() - ); - - // Redirect back to form - return $this->redirectToRoute( - 'torrent_locales_edit', - [ - '_locale' => $request->get('_locale'), - 'torrentId' => $torrent->getId(), - 'torrentLocalesId' => $torrentLocales->getId(), - ] - ); - } - - // Torrent categories - #[Route( - '/{_locale}/torrent/{torrentId}/edit/categories/{torrentCategoriesId}', - name: 'torrent_categories_edit', - requirements: - [ - '_locale' => '%app.locales%', - 'torrentId' => '\d+', - 'torrentCategoriesId' => '\d+', - ], - defaults: - [ - 'torrentCategoriesId' => null, - ], - methods: - [ - 'GET', - 'POST' - ] - )] - public function editCategories( - Request $request, - TranslatorInterface $translator, - UserService $userService, - TorrentService $torrentService, - ActivityService $activityService - ): Response - { - // Init user - $user = $this->initUser( - $request, - $userService, - $activityService - ); - - if (!$user->isStatus()) - { - // @TODO - throw new \Exception( - $translator->trans('Access denied') - ); - } - - // Init torrent - if (!$torrent = $torrentService->getTorrent($request->get('torrentId'))) - { - throw $this->createNotFoundException(); - } - - // Init torrent categories - $torrentCategoriesCurrent = [ - 'userId' => null, - 'value' => [] - ]; - - // Get from edition version requested - if ($request->get('torrentCategoriesId')) - { - if ($torrentCategories = $torrentService->getTorrentCategories($request->get('torrentCategoriesId'))) - { - $torrentCategoriesCurrent['userId'] = $torrentCategories->getUserId(); - - foreach ($torrentCategories->getValue() as $value) - { - $torrentCategoriesCurrent['value'][] = $value; - } - } - - else - { - throw $this->createNotFoundException(); - } - } - - // Otherwise, get latest available - else - { - if ($torrentCategories = $torrentService->findLastTorrentCategoriesByTorrentId($torrent->getId())) - { - $torrentCategoriesCurrent['userId'] = $torrentCategories->getUserId(); - - foreach ($torrentCategories->getValue() as $value) - { - $torrentCategoriesCurrent['value'][] = $value; - } - - // Update active categories - $request->attributes->set('torrentCategoriesId', $torrentCategories->getId()); - } - } - - // Init edition history - $editions = []; - foreach ($torrentService->findTorrentCategoriesByTorrentId($torrent->getId()) as $torrentCategoriesEdition) - { - $editions[] = - [ - 'id' => $torrentCategoriesEdition->getId(), - 'added' => $torrentCategoriesEdition->getAdded(), - 'approved' => $torrentCategoriesEdition->isApproved(), - 'active' => $torrentCategoriesEdition->getId() == $request->get('torrentCategoriesId'), - 'user' => - [ - 'id' => $torrentCategoriesEdition->getUserId(), - 'identicon' => $userService->identicon( - $userService->getUser( - $torrentCategoriesEdition->getUserId() - )->getAddress() - ), - ] - ]; - } - - // Init form - $form = - [ - 'categories' => - [ - 'error' => [], - 'attribute' => - [ - 'value' => $request->get('categories') ? $request->get('categories') : $torrentCategoriesCurrent['value'], - ] - ] - ]; - - // Process request - if ($request->isMethod('post')) - { - /// Categories - $categories = []; - if ($request->get('categories')) - { - foreach ((array) $request->get('categories') as $category) - { - if (in_array($category, explode('|', $this->getParameter('app.categories')))) - { - $categories[] = $category; - } - } - } - - //// At least one valid category required - if (!$categories) - { - $form['categories']['error'][] = $translator->trans('At least one category required'); - } - - // Request is valid - if (empty($form['categories']['error'])) - { - // Save data - $torrentCategories = $torrentService->addTorrentCategories( - $torrent->getId(), - $user->getId(), - time(), - $categories, - $user->isApproved() - ); - - // Register activity event - $activityService->addEventTorrentCategoriesAdd( - $user->getId(), - $torrent->getId(), - time(), - $torrentCategories->getId() - ); - - // Redirect to info page - return $this->redirectToRoute( - 'torrent_info', - [ - '_locale' => $request->get('_locale'), - 'torrentId' => $torrent->getId() - ] - ); - } - } - - // Render form template - return $this->render( - 'default/torrent/edit/categories.html.twig', - [ - 'torrentId' => $torrent->getId(), - 'categories' => explode('|', $this->getParameter('app.categories')), - 'editions' => $editions, - 'form' => $form, - 'session' => - [ - 'moderator' => $user->isModerator(), - 'owner' => $torrentCategoriesCurrent['userId'] === $user->getId(), - ] - ] - ); - } - - #[Route( - '/{_locale}/torrent/{torrentId}/approve/categories/{torrentCategoriesId}', - name: 'torrent_categories_approve', - requirements: - [ - '_locale' => '%app.locales%', - 'torrentId' => '\d+', - 'torrentCategoriesId' => '\d+', - ], - methods: - [ - 'GET' - ] - )] - public function approveCategories( - Request $request, - TranslatorInterface $translator, - UserService $userService, - TorrentService $torrentService, - ActivityService $activityService - ): Response - { - // Init user - $user = $this->initUser( - $request, - $userService, - $activityService - ); - - // Init torrent - if (!$torrent = $torrentService->getTorrent($request->get('torrentId'))) - { - throw $this->createNotFoundException(); - } - - // Init torrent categories - if (!$torrentCategories = $torrentService->getTorrentCategories($request->get('torrentCategoriesId'))) - { - throw $this->createNotFoundException(); - } - - // Check permissions - if (!$user->isModerator()) - { - // @TODO - throw new \Exception( - $translator->trans('Access denied') - ); - } - - // Register activity event - if (!$torrentCategories->isApproved()) - { - $activityService->addEventTorrentCategoriesApproveAdd( - $user->getId(), - $torrent->getId(), - time(), - $torrentCategories->getId() - ); - } - - else - { - $activityService->addEventTorrentCategoriesApproveDelete( - $user->getId(), - $torrent->getId(), - time(), - $torrentCategories->getId() - ); - } - - // Update approved - $torrentService->toggleTorrentCategoriesApproved( - $torrentCategories->getId() - ); - - // Redirect back to form - return $this->redirectToRoute( - 'torrent_categories_edit', - [ - '_locale' => $request->get('_locale'), - 'torrentId' => $torrent->getId(), - 'torrentCategoriesId' => $torrentCategories->getId(), - ] - ); - } - - #[Route( - '/{_locale}/torrent/{torrentId}/delete/categories/{torrentCategoriesId}', - name: 'torrent_categories_delete', - requirements: - [ - '_locale' => '%app.locales%', - 'torrentId' => '\d+', - 'torrentCategoriesId' => '\d+', - ], - methods: - [ - 'GET' - ] - )] - public function deleteCategories( - Request $request, - TranslatorInterface $translator, - UserService $userService, - TorrentService $torrentService, - ActivityService $activityService - ): Response - { - // Init user - $user = $this->initUser( - $request, - $userService, - $activityService - ); - - // Init torrent - if (!$torrent = $torrentService->getTorrent($request->get('torrentId'))) - { - throw $this->createNotFoundException(); - } - - // Init torrent categories - if (!$torrentCategories = $torrentService->getTorrentCategories($request->get('torrentCategoriesId'))) - { - throw $this->createNotFoundException(); - } - - // Check permissions - if (!($user->isModerator() || $user->getId() === $torrentCategories->getUserId())) - { - // @TODO - throw new \Exception( - $translator->trans('Access denied') - ); - } - - // Add activity event - $activityService->addEventTorrentCategoriesDelete( - $user->getId(), - $torrent->getId(), - time(), - $torrentCategories->getId() - ); - - // Update approved - $torrentService->deleteTorrentCategories( - $torrentCategories->getId() - ); - - // Redirect back to form - return $this->redirectToRoute( - 'torrent_categories_edit', - [ - '_locale' => $request->get('_locale'), - 'torrentId' => $torrent->getId(), - 'torrentCategoriesId' => $torrentCategories->getId(), - ] - ); - } - - // Torrent sensitive - #[Route( - '/{_locale}/torrent/{torrentId}/edit/sensitive/{torrentSensitiveId}', - name: 'torrent_sensitive_edit', - requirements: - [ - '_locale' => '%app.locales%', - 'torrentId' => '\d+', - 'torrentSensitiveId' => '\d+', - ], - defaults: - [ - 'torrentSensitiveId' => null, - ], - methods: - [ - 'GET', - 'POST' - ] - )] - public function editSensitive( - Request $request, - TranslatorInterface $translator, - UserService $userService, - TorrentService $torrentService, - ActivityService $activityService - ): Response - { - // Init user - $user = $this->initUser( - $request, - $userService, - $activityService - ); - - if (!$user->isStatus()) - { - // @TODO - throw new \Exception( - $translator->trans('Access denied') - ); - } - - // Init torrent - if (!$torrent = $torrentService->getTorrent($request->get('torrentId'))) - { - throw $this->createNotFoundException(); - } - - // Init sensitive value - if ($request->get('torrentSensitiveId')) - { - if ($torrentSensitive = $torrentService->getTorrentSensitive($request->get('torrentSensitiveId'))) - { - $torrentSensitiveCurrent = - [ - 'id' => $torrentSensitive->getId(), - 'userId' => $torrentSensitive->getUserId(), - 'value' => $torrentSensitive->isValue(), - ]; - } - - else - { - throw $this->createNotFoundException(); - } - } - else - { - if ($torrentSensitive = $torrentService->findLastTorrentSensitiveByTorrentId($torrent->getId())) - { - $torrentSensitiveCurrent = - [ - 'id' => $torrentSensitive->getId(), - 'userId' => $torrentSensitive->getUserId(), - 'value' => $torrentSensitive->isValue(), - ]; - } - - else - { - $torrentSensitiveCurrent = - [ - 'id' => null, - 'userId' => null, - 'value' => false, - ]; - } - } - - // Init edition history - $editions = []; - foreach ($torrentService->findTorrentSensitiveByTorrentId($torrent->getId()) as $torrentSensitiveEdition) - { - $editions[] = - [ - 'id' => $torrentSensitiveEdition->getId(), - 'added' => $torrentSensitiveEdition->getAdded(), - 'approved' => $torrentSensitiveEdition->isApproved(), - 'active' => $torrentSensitiveEdition->getId() == $torrentSensitiveCurrent['id'], - 'user' => - [ - 'id' => $torrentSensitiveEdition->getUserId(), - 'identicon' => $userService->identicon( - $userService->getUser( - $torrentSensitiveEdition->getUserId() - )->getAddress() - ), - ] - ]; - } - - // Init form - $form = - [ - 'sensitive' => - [ - 'error' => [], - 'attribute' => - [ - 'value' => $torrentSensitiveCurrent['value'], - ] - ] - ]; - - // Process request - if ($request->isMethod('post')) - { - // Save data - $torrentSensitive = $torrentService->addTorrentSensitive( - $torrent->getId(), - $user->getId(), - time(), - $request->get('sensitive') === 'true', - $user->isApproved() - ); - - // Add activity event - $activityService->addEventTorrentSensitiveAdd( - $user->getId(), - $torrent->getId(), - time(), - $torrentSensitive->getId() - ); - - // Redirect to info page created - return $this->redirectToRoute( - 'torrent_info', - [ - '_locale' => $request->get('_locale'), - 'torrentId' => $torrent->getId() - ] - ); - } - - // Render form template - return $this->render( - 'default/torrent/edit/sensitive.html.twig', - [ - 'torrentId' => $torrent->getId(), - 'editions' => $editions, - 'form' => $form, - 'session' => - [ - 'moderator' => $user->isModerator(), - 'owner' => $torrentSensitiveCurrent['userId'] === $user->getId(), - ] - ] - ); - } - - #[Route( - '/{_locale}/torrent/{torrentId}/approve/sensitive/{torrentSensitiveId}', - name: 'torrent_sensitive_approve', - requirements: - [ - '_locale' => '%app.locales%', - 'torrentId' => '\d+', - 'torrentSensitiveId' => '\d+', - ], - methods: - [ - 'GET' - ] - )] - public function approveSensitive( - Request $request, - TranslatorInterface $translator, - UserService $userService, - TorrentService $torrentService, - ActivityService $activityService - ): Response - { - // Init user - $user = $this->initUser( - $request, - $userService, - $activityService - ); - - // Init torrent - if (!$torrent = $torrentService->getTorrent($request->get('torrentId'))) - { - throw $this->createNotFoundException(); - } - - // Init torrent sensitive - if (!$torrentSensitive = $torrentService->getTorrentSensitive($request->get('torrentSensitiveId'))) - { - throw $this->createNotFoundException(); - } - - // Check permissions - if (!$user->isModerator()) - { - // @TODO - throw new \Exception( - $translator->trans('Access denied') - ); - } - - // Add activity event - if (!$torrentSensitive->isApproved()) - { - $activityService->addEventTorrentSensitiveApproveAdd( - $user->getId(), - $torrent->getId(), - time(), - $torrentSensitive->getId() - ); - } - - else - { - $activityService->addEventTorrentSensitiveApproveDelete( - $user->getId(), - $torrent->getId(), - time(), - $torrentSensitive->getId() - ); - } - - // Update approved - $torrentService->toggleTorrentSensitiveApproved( - $torrentSensitive->getId() - ); - - // Redirect - return $this->redirectToRoute( - 'torrent_sensitive_edit', - [ - '_locale' => $request->get('_locale'), - 'torrentId' => $torrent->getId(), - 'torrentSensitiveId' => $torrentSensitive->getId(), - ] - ); - } - - #[Route( - '/{_locale}/torrent/{torrentId}/delete/sensitive/{torrentSensitiveId}', - name: 'torrent_sensitive_delete', - requirements: - [ - '_locale' => '%app.locales%', - 'torrentId' => '\d+', - 'torrentSensitiveId' => '\d+', - ], - methods: - [ - 'GET' - ] - )] - public function deleteSensitive( - Request $request, - TranslatorInterface $translator, - UserService $userService, - TorrentService $torrentService, - ActivityService $activityService - ): Response - { - // Init user - $user = $this->initUser( - $request, - $userService, - $activityService - ); - - // Init torrent - if (!$torrent = $torrentService->getTorrent($request->get('torrentId'))) - { - throw $this->createNotFoundException(); - } - - // Init torrent sensitive - if (!$torrentSensitive = $torrentService->getTorrentSensitive($request->get('torrentSensitiveId'))) - { - throw $this->createNotFoundException(); - } - - // Check permissions - if (!($user->isModerator() || $user->getId() === $torrentSensitive->getUserId())) - { - // @TODO - throw new \Exception( - $translator->trans('Access denied') - ); - } - - // Add activity event - $activityService->addEventTorrentSensitiveDelete( - $user->getId(), - $torrent->getId(), - time(), - $torrentSensitive->getId() - ); - - // Update approved - $torrentService->deleteTorrentSensitive( - $torrentSensitive->getId() - ); - - // Redirect - return $this->redirectToRoute( - 'torrent_sensitive_edit', - [ - '_locale' => $request->get('_locale'), - 'torrentId' => $torrent->getId(), - 'torrentSensitiveId' => $torrentSensitive->getId(), - ] - ); - } - - // Torrent poster - #[Route( - '/{_locale}/torrent/{torrentId}/edit/poster/{torrentPosterId}', - name: 'torrent_poster_edit', - requirements: - [ - '_locale' => '%app.locales%', - 'torrentId' => '\d+', - 'torrentPosterId' => '\d+', - ], - defaults: - [ - 'torrentPosterId' => null, - ], - methods: - [ - 'GET', - 'POST' - ] - )] - public function editPoster( - Request $request, - TranslatorInterface $translator, - UserService $userService, - TorrentService $torrentService, - ActivityService $activityService - ): Response - { - // Init user - $user = $this->initUser( - $request, - $userService, - $activityService - ); - - if (!$user->isStatus()) - { - // @TODO - throw new \Exception( - $translator->trans('Access denied') - ); - } - - // Init torrent - if (!$torrent = $torrentService->getTorrent($request->get('torrentId'))) - { - throw $this->createNotFoundException(); - } - - // Init poster value - if ($request->get('torrentPosterId')) - { - if ($torrentPoster = $torrentService->getTorrentPoster($request->get('torrentPosterId'))) - { - $torrentPosterCurrent = - [ - 'id' => $torrentPoster->getId(), - 'userId' => $torrentPoster->getUserId(), - 'value' => 'src' // @TODO - ]; - } - - else - { - throw $this->createNotFoundException(); - } - } - else - { - if ($torrentPoster = $torrentService->findLastTorrentPosterByTorrentId($torrent->getId())) - { - $torrentPosterCurrent = - [ - 'id' => $torrentPoster->getId(), - 'userId' => $torrentPoster->getUserId(), - 'value' => 'src' // @TODO - ]; - } - - else - { - $torrentPosterCurrent = - [ - 'id' => null, - 'userId' => null, - 'value' => false, - ]; - } - } - - // Init position - $position = in_array( - $request->get('position'), - [ - 'center', - 'top', - 'bottom' - ] - ) ? $request->get('position') : 'center'; - - // Init edition history - $editions = []; - foreach ($torrentService->findTorrentPosterByTorrentId($torrent->getId()) as $torrentPosterEdition) - { - $editions[] = - [ - 'id' => $torrentPosterEdition->getId(), - 'added' => $torrentPosterEdition->getAdded(), - 'position' => $torrentPosterEdition->getPosition(), - 'approved' => $torrentPosterEdition->isApproved(), - 'active' => $torrentPosterEdition->getId() == $torrentPosterCurrent['id'], - 'user' => - [ - 'id' => $torrentPosterEdition->getUserId(), - 'identicon' => $userService->identicon( - $userService->getUser( - $torrentPosterEdition->getUserId() - )->getAddress() - ), - ], - 'poster' => - $request->getScheme() . '://' . - $request->getHttpHost() . - $request->getBasePath() . - $torrentService->getImageUriByTorrentPosterId( - $torrentPosterEdition->getId() - ) - ]; - } - - // Init form - $form = - [ - 'poster' => - [ - 'error' => [] - ], - 'position' => - [ - 'error' => [], - 'attribute' => - [ - 'value' => $position - ] - ] - ]; - - // Process request - if ($request->isMethod('post')) - { - if ($request->get('id') && $torrentService->getTorrentPoster($request->get('id'))) - { - $filename = $torrentService->getStorageFilepathByTorrentPosterId( - $request->get('id') - ); - } - - else if ($file = $request->files->get('poster')) - { - //// Validate poster file - if (filesize($file->getPathName()) > $this->getParameter('app.torrent.poster.size.max')) - { - $form['poster']['error'][] = $translator->trans('Poster file out of size limit'); - } - - //// Validate image format - if (!@getimagesize($file->getPathName())) - { - $form['poster']['error'][] = $translator->trans('Image file not supported'); - } - - $filename = $file->getPathName(); - } - - else - { - $form['poster']['error'][] = $translator->trans('Poster file required'); - - $filename = false; - } - - // Request is valid - if (empty($form['poster']['error'])) - { - // Save data - $torrentPoster = $torrentService->addTorrentPoster( - $filename, - $position, - $torrent->getId(), - $user->getId(), - time(), - $user->isApproved() - ); - - // Add activity event - $activityService->addEventTorrentPosterAdd( - $user->getId(), - $torrent->getId(), - time(), - $torrentPoster->getId() - ); - - // Redirect to info page created - return $this->redirectToRoute( - 'torrent_info', - [ - '_locale' => $request->get('_locale'), - 'torrentId' => $torrent->getId() - ] - ); - } - } - - // Render form template - return $this->render( - 'default/torrent/edit/poster.html.twig', - [ - 'torrentId' => $torrent->getId(), - 'editions' => $editions, - 'form' => $form, - 'session' => - [ - 'moderator' => $user->isModerator(), - 'owner' => $torrentPosterCurrent['userId'] === $user->getId(), - ] - ] - ); - } - - #[Route( - '/{_locale}/torrent/{torrentId}/approve/poster/{torrentPosterId}', - name: 'torrent_poster_approve', - requirements: - [ - '_locale' => '%app.locales%', - 'torrentId' => '\d+', - 'torrentPosterId' => '\d+', - ], - methods: - [ - 'GET' - ] - )] - public function approvePoster( - Request $request, - TranslatorInterface $translator, - UserService $userService, - TorrentService $torrentService, - ActivityService $activityService - ): Response - { - // Init user - $user = $this->initUser( - $request, - $userService, - $activityService - ); - - // Init torrent - if (!$torrent = $torrentService->getTorrent($request->get('torrentId'))) - { - throw $this->createNotFoundException(); - } - - // Init torrent poster - if (!$torrentPoster = $torrentService->getTorrentPoster($request->get('torrentPosterId'))) - { - throw $this->createNotFoundException(); - } - - // Check permissions - if (!$user->isModerator()) - { - // @TODO - throw new \Exception( - $translator->trans('Access denied') - ); - } - - // Add activity event - if (!$torrentPoster->isApproved()) - { - $activityService->addEventTorrentPosterApproveAdd( - $user->getId(), - $torrent->getId(), - time(), - $torrentPoster->getId() - ); - } - - else - { - $activityService->addEventTorrentPosterApproveDelete( - $user->getId(), - $torrent->getId(), - time(), - $torrentPoster->getId() - ); - } - - // Update approved - $torrentService->toggleTorrentPosterApproved( - $torrentPoster->getId() - ); - - // Redirect - return $this->redirectToRoute( - 'torrent_poster_edit', - [ - '_locale' => $request->get('_locale'), - 'torrentId' => $torrent->getId(), - 'torrentPosterId' => $torrentPoster->getId(), - ] - ); - } - - #[Route( - '/{_locale}/torrent/{torrentId}/delete/poster/{torrentPosterId}', - name: 'torrent_poster_delete', - requirements: - [ - '_locale' => '%app.locales%', - 'torrentId' => '\d+', - 'torrentPosterId' => '\d+', - ], - methods: - [ - 'GET' - ] - )] - public function deletePoster( - Request $request, - TranslatorInterface $translator, - UserService $userService, - TorrentService $torrentService, - ActivityService $activityService - ): Response - { - // Init user - $user = $this->initUser( - $request, - $userService, - $activityService - ); - - // Init torrent - if (!$torrent = $torrentService->getTorrent($request->get('torrentId'))) - { - throw $this->createNotFoundException(); - } - - // Init torrent poster - if (!$torrentPoster = $torrentService->getTorrentPoster($request->get('torrentPosterId'))) - { - throw $this->createNotFoundException(); - } - - // Check permissions - if (!($user->isModerator() || $user->getId() === $torrentPoster->getUserId())) - { - // @TODO - throw new \Exception( - $translator->trans('Access denied') - ); - } - - // Add activity event - $activityService->addEventTorrentPosterDelete( - $user->getId(), - $torrent->getId(), - time(), - $torrentPoster->getId() - ); - - // Update approved - $torrentService->deleteTorrentPoster( - $torrentPoster->getId() - ); - - // Redirect - return $this->redirectToRoute( - 'torrent_poster_edit', - [ - '_locale' => $request->get('_locale'), - 'torrentId' => $torrent->getId(), - 'torrentPosterId' => $torrentPoster->getId(), - ] - ); - } - - // Torrent star - #[Route( - '/{_locale}/torrent/{torrentId}/star/toggle', - name: 'torrent_star_toggle', - requirements: - [ - '_locale' => '%app.locales%', - 'torrentId' => '\d+', - ], - methods: - [ - 'GET' - ] - )] - public function toggleStar( - Request $request, - TranslatorInterface $translator, - UserService $userService, - TorrentService $torrentService, - ActivityService $activityService - ): Response - { - // Init user - $user = $this->initUser( - $request, - $userService, - $activityService - ); - - if (!$user->isStatus()) - { - // @TODO - throw new \Exception( - $translator->trans('Access denied') - ); - } - - // Block crawler requests - if (in_array($request->getClientIp(), explode('|', $this->getParameter('app.crawlers')))) - { - throw $this->createNotFoundException(); - } - - // Init torrent - if (!$torrent = $torrentService->getTorrent($request->get('torrentId'))) - { - throw $this->createNotFoundException(); - } - - // Update - $value = $torrentService->toggleTorrentStar( - $torrent->getId(), - $user->getId(), - time() - ); - - // Register activity event - if ($value) - { - $activityService->addEventTorrentStarAdd( - $user->getId(), - time(), - $torrent->getId() - ); - } - - else - { - $activityService->addEventTorrentStarDelete( - $user->getId(), - time(), - $torrent->getId() - ); - } - - // Redirect - return $this->redirectToRoute( - 'torrent_info', - [ - '_locale' => $request->get('_locale'), - 'torrentId' => $torrent->getId() - ] - ); - } - - // Torrent download file - #[Route( - '/torrent/{torrentId}/file', - name: 'torrent_file', - requirements: - [ - 'torrentId' => '\d+' - ], - methods: - [ - 'GET' - ] - )] - public function downloadFile( - Request $request, - TranslatorInterface $translator, - UserService $userService, - TorrentService $torrentService, - ActivityService $activityService - ): Response - { - // Init user - $user = $this->initUser( - $request, - $userService, - $activityService - ); - - if (!$user->isStatus()) - { - // @TODO - throw new \Exception( - $translator->trans('Access denied') - ); - } - - // Block crawler requests - if (in_array($request->getClientIp(), explode('|', $this->getParameter('app.crawlers')))) - { - throw $this->createNotFoundException(); - } - - // Init torrent - if (!$torrent = $torrentService->getTorrent($request->get('torrentId'))) - { - throw $this->createNotFoundException(); - } - - if (!$file = $torrentService->readTorrentFileByTorrentId($torrent->getId())) - { - throw $this->createNotFoundException(); - } - - // Access filter - if (!$user->isModerator() && $user->getId() != $torrent->getUserId() && - (!$torrent->isStatus() || !$torrent->isApproved())) - { - throw $this->createNotFoundException(); - } - - // Register download - $torrentService->addTorrentDownloadFile( - $torrent->getId(), - $user->getId(), - time() - ); - - // Request scrape - $torrentService->updateTorrentScraped( - $torrent->getId(), - 0 - ); - - // Register download event - $activityService->addEventTorrentDownloadFileAdd( - $user->getId(), - time(), - $torrent->getId() - ); - - // Apply filters - $file = $this->filterYggdrasil( - $file, - $user->isYggdrasil() - ); - - // Get data - $data = $file->dumpToString(); - - // Set headers - $response = new Response(); - - $response->headers->set( - 'Content-type', - 'application/x-bittorrent' - ); - - $response->headers->set( - 'Content-length', - strlen($data) - ); - - $response->headers->set( - 'Content-Disposition', - sprintf( - 'attachment; filename="%s [%s#%s].torrent";', - $file->getName(), - $this->getParameter('app.name'), - $torrent->getId() - ) - ); - - $response->sendHeaders(); - - // Return file content - return $response->setContent($data); - } - - // Torrent download wanted file - #[Route( - '/torrent/{torrentId}/file/wanted', - name: 'torrent_file_wanted', - requirements: - [ - 'torrentId' => '\d+' - ], - methods: - [ - 'GET' - ] - )] - public function downloadFileWanted( - Request $request, - TranslatorInterface $translator, - UserService $userService, - TorrentService $torrentService, - ActivityService $activityService - ): Response - { - // Init user - $user = $this->initUser( - $request, - $userService, - $activityService - ); - - if (!$user->isStatus()) - { - // @TODO - throw new \Exception( - $translator->trans('Access denied') - ); - } - - // Block crawler requests - if (in_array($request->getClientIp(), explode('|', $this->getParameter('app.crawlers')))) - { - throw $this->createNotFoundException(); - } - - // Init torrent - if (!$torrent = $torrentService->getTorrent($request->get('torrentId'))) - { - throw $this->createNotFoundException(); - } - - if (!$file = $torrentService->readTorrentFileByTorrentId($torrent->getId())) - { - throw $this->createNotFoundException(); - } - - // Access filter - if (!$user->isModerator() && $user->getId() != $torrent->getUserId() && - (!$torrent->isStatus() || !$torrent->isApproved())) - { - throw $this->createNotFoundException(); - } - - // Register download - $torrentService->addTorrentDownloadFile( - $torrent->getId(), - $user->getId(), - time() - ); - - // Request scrape - $torrentService->updateTorrentScraped( - $torrent->getId(), - 0 - ); - - // Register download event - $activityService->addEventTorrentDownloadFileAdd( - $user->getId(), - time(), - $torrent->getId() - ); - - // Apply filters - $file = $this->filterYggdrasil( - $file, - false // wanted file downloading with original trackers - ); - - // Get data - $data = $file->dumpToString(); - - // Set headers - $response = new Response(); - - $response->headers->set( - 'Content-type', - 'application/x-bittorrent' - ); - - $response->headers->set( - 'Content-length', - strlen($data) - ); - - $response->headers->set( - 'Content-Disposition', - sprintf( - 'attachment; filename="%s [wanted#%s].torrent";', - $file->getName(), - $torrent->getId() - ) - ); - - $response->sendHeaders(); - - // Return file content - return $response->setContent($data); - } - - // Torrent download magnet - #[Route( - '/torrent/{torrentId}/magnet', - name: 'torrent_magnet', - requirements: - [ - 'torrentId' => '\d+' - ], - methods: - [ - 'GET' - ] - )] - public function getMagnet( - Request $request, - TranslatorInterface $translator, - UserService $userService, - TorrentService $torrentService, - ActivityService $activityService - ): Response - { - // Init user - $user = $this->initUser( - $request, - $userService, - $activityService - ); - - if (!$user->isStatus()) - { - // @TODO - throw new \Exception( - $translator->trans('Access denied') - ); - } - - // Block crawler requests - if (in_array($request->getClientIp(), explode('|', $this->getParameter('app.crawlers')))) - { - throw $this->createNotFoundException(); - } - - // Init torrent - if (!$torrent = $torrentService->getTorrent($request->get('torrentId'))) - { - throw $this->createNotFoundException(); - } - - if (!$file = $torrentService->readTorrentFileByTorrentId($torrent->getId())) - { - throw $this->createNotFoundException(); - } - - // Access filter - if (!$user->isModerator() && $user->getId() != $torrent->getUserId() && - (!$torrent->isStatus() || !$torrent->isApproved())) - { - throw $this->createNotFoundException(); - } - - // Register download - $torrentService->addTorrentDownloadMagnet( - $torrent->getId(), - $user->getId(), - time() - ); - - // Request scrape - $torrentService->updateTorrentScraped( - $torrent->getId(), - 0 - ); - - // Register download event - $activityService->addEventTorrentDownloadMagnetAdd( - $user->getId(), - time(), - $torrent->getId() - ); - - // Apply filters - $file = $this->filterYggdrasil( - $file, - $user->isYggdrasil() - ); - - // Return magnet link - return $this->redirect( - $file->getMagnetLink() - ); - } - - // Tools - #[Route( - '/crontab/torrent/scrape/{key}', - requirements: [ - 'key' => '%app.key%' - ], - methods: - [ - 'GET' - ] - )] - public function scrape( - Request $request, - TranslatorInterface $translator, - TorrentService $torrentService, - ActivityService $activityService - ): Response - { - // Init Scraper - $scraper = new \Yggverse\Scrapeer\Scraper(); - - // Get next torrent in scrape queue - if (!$torrent = $torrentService->getTorrentScrapeQueue()) - { - throw $this->createNotFoundException(); - } - - // Get file - if (!$file = $torrentService->readTorrentFileByTorrentId($torrent->getId())) - { - throw $this->createNotFoundException(); - } - - // Filter yggdrasil trackers - $file = $this->filterYggdrasil($file, true); - - // Get trackers list - $trackers = []; - - if ($announce = $file->getAnnounce()) - { - $trackers[] = $announce; - } - - if ($announceList = $file->getAnnounceList()) - { - if (isset($announceList[0])) - { - foreach ($announceList[0] as $value) - { - $trackers[] = $value; - } - } - - if (isset($announceList[1])) - { - foreach ($announceList[1] as $value) - { - $trackers[] = $value; - } - } - } - - $trackers = array_unique($trackers); - - // Get info hashes - $hashes = []; - - if ($hash = $file->getInfoHashV1(false)) - { - $hashes[] = $hash; - } - - if ($hash = $file->getInfoHashV2(false)) - { - $hashes[] = $hash; - } - - // Get scrape - $seeders = 0; - $peers = 0; - $leechers = 0; - - if ($hashes && $trackers) - { - // Update scrape info - if ($results = $scraper->scrape($hashes, $trackers, null, 1)) - { - foreach ($results as $result) - { - if (isset($result['seeders'])) - { - $seeders = $seeders + (int) $result['seeders']; - } - - if (isset($result['completed'])) - { - $peers = $peers + (int) $result['completed']; - } - - if (isset($result['leechers'])) - { - $leechers = $leechers + (int) $result['leechers']; - } - } - } - } - - // Register activity event only on previous status changed - if ($leechers && !$seeders && - $leechers != (int) $torrent->getLeechers() && $seeders != (int) $torrent->getSeeders()) - { - $activityService->addEventTorrentWantedAdd( - $torrent->getUserId(), // just required field, let's relate with author, because we don't know which exactly user requires for seeders from crontab @TODO - time(), - $torrent->getId() - ); - } - - // Update DB - $torrentService->updateTorrentScrape( - $torrent->getId(), - $seeders, - $peers, - $leechers - ); - - // Update torrent wanted storage if enabled - if ($this->getParameter('app.torrent.wanted.ftp.enabled') === '1') - { - // Add wanted file - if ($leechers && !$seeders) - { - if ($this->getParameter('app.torrent.wanted.ftp.approved') === '0' || - ($this->getParameter('app.torrent.wanted.ftp.approved') === '1' && $torrent->isApproved())) - { - /// All - $torrentService->copyToFtpStorage( - $torrent->getId(), - sprintf( - '%s/torrents/wanted/all/wanted#%s.torrent', - $this->getParameter('app.torrent.wanted.ftp.folder'), - $torrent->getId() - ) - ); - - /// Sensitive - if ($torrent->isSensitive()) - { - $torrentService->copyToFtpStorage( - $torrent->getId(), - sprintf( - '%s/torrents/wanted/sensitive/yes/wanted#%s.torrent', - $this->getParameter('app.torrent.wanted.ftp.folder'), - $torrent->getId() - ) - ); - } - - else - { - $torrentService->copyToFtpStorage( - $torrent->getId(), - sprintf( - '%s/torrents/wanted/sensitive/no/wanted#%s.torrent', - $this->getParameter('app.torrent.wanted.ftp.folder'), - $torrent->getId() - ) - ); - } - - /// Locals - foreach ($torrent->getLocales() as $locale) - { - $torrentService->copyToFtpStorage( - $torrent->getId(), - sprintf( - '%s/torrents/wanted/locale/%s/wanted#%s.torrent', - $this->getParameter('app.torrent.wanted.ftp.folder'), - $locale, - $torrent->getId() - ) - ); - } - } - } - - // Remove not wanted files - else - { - /// All - $torrentService->removeFromFtpStorage( - sprintf( - '%s/torrents/wanted/all/wanted#%s.torrent', - $this->getParameter('app.torrent.wanted.ftp.folder'), - $torrent->getId() - ) - ); - - /// Sensitive - $torrentService->removeFromFtpStorage( - sprintf( - '%s/torrents/wanted/sensitive/yes/wanted#%s.torrent', - $this->getParameter('app.torrent.wanted.ftp.folder'), - $torrent->getId() - ) - ); - - $torrentService->removeFromFtpStorage( - sprintf( - '%s/torrents/wanted/sensitive/no/wanted#%s.torrent', - $this->getParameter('app.torrent.wanted.ftp.folder'), - $torrent->getId() - ) - ); - - /// Locals - foreach (explode('|', $this->getParameter('app.locales')) as $locale) - { - $torrentService->removeFromFtpStorage( - sprintf( - '%s/torrents/wanted/locale/%s/wanted#%s.torrent', - $this->getParameter('app.torrent.wanted.ftp.folder'), - $locale, - $torrent->getId() - ) - ); - } - } - } - - // Render response - return new Response(); // @TODO - } - - #[Route( - '/tool/torrent/reindex/{key}', - requirements: [ - 'key' => '%app.key%' - ], - methods: - [ - 'GET' - ] - )] - public function reindex( - TorrentService $torrentService - ): Response - { - // Reindex keywords - $torrentService->reindexTorrentKeywordsAll( - (bool) $this->getParameter('app.index.torrent.name.enabled'), - (bool) $this->getParameter('app.index.torrent.filenames.enabled'), - (bool) $this->getParameter('app.index.torrent.hash.v1.enabled'), - (bool) $this->getParameter('app.index.torrent.hash.v2.enabled'), - (bool) $this->getParameter('app.index.torrent.source.enabled'), - (bool) $this->getParameter('app.index.torrent.comment.enabled'), - (int) $this->getParameter('app.index.word.length.min'), - (int) $this->getParameter('app.index.word.length.max') - ); - - // Render response - return new Response(); // @TODO - } - - #[Route( - '/sitemap.xml', - methods: - [ - 'GET' - ] - )] - public function sitemap( - TorrentService $torrentService - ): Response - { - $locale = $this->getParameter('app.locale'); - $locales = explode('|', $this->getParameter('app.locales')); - - $response = new Response(); - $response->headers->set('Content-Type', 'text/xml'); - - return $this->render( - 'default/torrent/sitemap.xml.twig', - [ - 'locale' => $locale, - 'locales' => $locales, - 'torrents' => $torrentService->findTorrents( - 0, // no user session init, pass 0 - [], // without keywords filter - $locales, // all system locales - $categories, // all system locales - null, // all sensitive levels - true, // approved only - true, // enabled only - 1000, // @TODO limit - 0 // offset - ) - ], - $response - ); - } - - private function initUser( - Request $request, - UserService $userService, - ActivityService $activityService - ): ?\App\Entity\User - { - // Init user - if (!$user = $userService->findUserByAddress($request->getClientIp())) - { - $user = $userService->addUser( - $request->getClientIp(), - time(), - $this->getParameter('app.locale'), - explode('|', $this->getParameter('app.locales')), - $activityService->getEventCodes(), - $this->getParameter('app.theme'), - $this->getParameter('app.sensitive'), - $this->getParameter('app.yggdrasil'), - $this->getParameter('app.posters'), - $this->getParameter('app.approved') - ); - - // Add user join event - $activityService->addEventUserAdd( - $user->getId(), - time() - ); - } - - return $user; - } - - private function filterYggdrasil( - ?\Rhilip\Bencode\TorrentFile $file, bool $yggdrasil, string $regex = '/^0{0,1}[2-3][a-f0-9]{0,2}:/' - ): ?\Rhilip\Bencode\TorrentFile - { - // Init trackers registry - $allTrackers = []; - - // Get app trackers - $appTrackers = explode('|', $this->getParameter('app.trackers')); - - // Append app trackers - foreach ($appTrackers as $appTracker) - { - $allTrackers[] = $appTracker; - } - - // Get original file announcements - $announceList = $file->getAnnounceList(); - - // Append original file announcements - foreach ($announceList as $announce) - { - if (is_array($announce)) - { - foreach ($announce as $value) - { - $allTrackers[] = $value; - } - } - - else - { - $allTrackers[] = $value; - } - } - - // Remove duplicates - $allTrackers = array_unique($allTrackers); - - // Yggdrasil-only mode - if ($yggdrasil) - { - // Replace announce URL with first application tracker if original does not match Yggdrasil condition - if (!preg_match($regex, str_replace(['[',']'], false, parse_url($value, PHP_URL_HOST)))) - { - $file->setAnnounce( - $appTrackers[0] - ); - } - - // Remove non-Yggdrasil trackers from announcement list - foreach ($allTrackers as $key => $value) - { - // trackers - if (!preg_match($regex, str_replace(['[',']'], false, parse_url($value, PHP_URL_HOST)))) - { - unset($allTrackers[$key]); - } - } - } - - // Format announce list - $trackers = []; - - foreach ($allTrackers as $value) - { - $trackers[] = [$value]; - } - - // Update announce list - $file->setAnnounceList( - $trackers - ); - - // Return filtered file - return $file; - } -} diff --git a/src/Controller/UserController.php b/src/Controller/UserController.php deleted file mode 100644 index 538af56..0000000 --- a/src/Controller/UserController.php +++ /dev/null @@ -1,672 +0,0 @@ -initUser( - $request, - $userService, - $activityService - ); - - return $this->redirectToRoute( - 'torrent_recent', - [ - '_locale' => $user->getLocale() - ] - ); - } - - #[Route( - '/{_locale}/settings', - name: 'user_settings', - requirements: [ - '_locale' => '%app.locales%', - ], - )] - public function settings( - Request $request, - UserService $userService, - ActivityService $activityService - ): Response - { - // Init user - $user = $this->initUser( - $request, - $userService, - $activityService - ); - - // Process post request - if ($request->isMethod('post')) - { - // Update locale - if (in_array($request->get('locale'), explode('|', $this->getParameter('app.locales')))) - { - $user->setLocale( - $request->get('locale') - ); - } - - // Update locales - if ($request->get('locales')) - { - $locales = []; - foreach ((array) $request->get('locales') as $locale) - { - if (in_array($locale, explode('|', $this->getParameter('app.locales')))) - { - $locales[] = $locale; - } - } - - $user->setLocales( - $locales - ); - } - - // Update categories - if ($request->get('categories')) - { - $categories = []; - foreach ((array) $request->get('categories') as $category) - { - if (in_array($category, explode('|', $this->getParameter('app.categories')))) - { - $categories[] = $category; - } - } - - $user->setCategories( - $categories - ); - } - - // Update theme - if (in_array($request->get('theme'), explode('|', $this->getParameter('app.themes')))) - { - $user->setTheme( - $request->get('theme') - ); - } - - // Update events - $events = []; - foreach ((array) $request->get('events') as $event) - { - if (in_array($event, $activityService->getEventCodes())) - { - $events[] = $event; - } - } - - $user->setEvents( - $events - ); - - // Update sensitive - $user->setSensitive( - $request->get('sensitive') === 'true' - ); - - // Update yggdrasil - $user->setYggdrasil( - $request->get('yggdrasil') === 'true' - ); - - // Update posters - $user->setPosters( - $request->get('posters') === 'true' - ); - - // Save changes to DB - $userService->save($user); - - // Redirect user to new locale - return $this->redirectToRoute( - 'user_settings', - [ - '_locale' => $user->getLocale() - ] - ); - } - - // Render template - return $this->render( - 'default/user/settings.html.twig', - [ - 'user' => [ - 'id' => $user->getId(), - 'sensitive' => $user->isSensitive(), - 'yggdrasil' => $user->isYggdrasil(), - 'posters' => $user->isPosters(), - 'locale' => $user->getLocale(), - 'locales' => $user->getLocales(), - 'categories' => $user->getCategories(), - 'events' => $user->getEvents(), - 'theme' => $user->getTheme(), - 'added' => $user->getAdded() - ], - 'locales' => explode('|', $this->getParameter('app.locales')), - 'categories' => explode('|', $this->getParameter('app.categories')), - 'themes' => explode('|', $this->getParameter('app.themes')), - 'events' => $activityService->getEventsTree() - ] - ); - } - - #[Route( - '/{_locale}/profile/{userId}', - name: 'user_info', - defaults: [ - 'userId' => 0, - ], - requirements: [ - '_locale' => '%app.locales%', - 'userId' => '\d+', - ], - )] - public function info( - Request $request, - TranslatorInterface $translator, - UserService $userService, - ActivityService $activityService - ): Response - { - // Init user - $user = $this->initUser( - $request, - $userService, - $activityService - ); - - if (!$user->isStatus()) - { - // @TODO - throw new \Exception( - $translator->trans('Access denied') - ); - } - - // Init target user - if (!$userTarget = $userService->getUser( - $request->get('userId') ? $request->get('userId') : $user->getId() - )) - { - throw $this->createNotFoundException(); - } - - // Get total activities - $total = $activityService->findActivitiesTotalByUserId( - $userTarget->getId(), - $user->getEvents() - ); - - // Init page - $page = $request->get('page') ? (int) $request->get('page') : 1; - - // Render template - return $this->render( - 'default/user/info.html.twig', - [ - 'session' => - [ - 'user' => $user, - 'owner' => $user->getId() === $userTarget->getId(), - 'moderator' => $user->isModerator() - ], - 'user' => [ - 'id' => $userTarget->getId(), - 'address' => $userTarget->getAddress(), - 'moderator' => $userTarget->isModerator(), - 'approved' => $userTarget->isApproved(), - 'status' => $userTarget->isStatus(), - 'posters' => $userTarget->isPosters(), - 'sensitive' => $userTarget->isSensitive(), - 'yggdrasil' => $userTarget->isYggdrasil(), - 'locale' => $userTarget->getLocale(), - 'locales' => $userTarget->getLocales(), - 'categories' => $user->getCategories(), - 'events' => $userTarget->getEvents(), - 'theme' => $userTarget->getTheme(), - 'added' => $userTarget->getAdded(), - 'identicon' => $userService->identicon( - $userTarget->getAddress(), - 48 - ), - 'owner' => $user->getId() === $userTarget->getId(), - 'star' => - [ - 'exist' => (bool) $userService->findUserStar( - $user->getId(), - $userTarget->getId() - ), - 'total' => $userService->findUserStarsTotalByUserIdTarget( - $userTarget->getId() - ) - ], - 'activities' => $activityService->findLastActivitiesByUserId( - $userTarget->getId(), - $userTarget->getEvents(), - $this->getParameter('app.pagination'), - ($page - 1) * $this->getParameter('app.pagination') - ) - ], - 'events' => $activityService->getEventsTree(), - 'pagination' => - [ - 'page' => $page, - 'pages' => ceil($total / $this->getParameter('app.pagination')), - 'total' => $total - ] - ] - ); - } - - #[Route( - '/{_locale}/user/star/toggle/{userId}', - name: 'user_star_toggle', - requirements: - [ - '_locale' => '%app.locales%', - 'userId' => '\d+', - ], - methods: - [ - 'GET' - ] - )] - public function toggleStar( - Request $request, - TranslatorInterface $translator, - UserService $userService, - ActivityService $activityService - ): Response - { - // Init user - $user = $this->initUser( - $request, - $userService, - $activityService - ); - - if (!$user->isStatus()) - { - // @TODO - throw new \Exception( - $translator->trans('Access denied') - ); - } - - // Block crawler requests - if (in_array($request->getClientIp(), explode('|', $this->getParameter('app.crawlers')))) - { - throw $this->createNotFoundException(); - } - - // Init target user - if (!$userTarget = $userService->getUser($request->get('userId'))) - { - throw $this->createNotFoundException(); - } - - // Update - $value = $userService->toggleUserStar( - $user->getId(), - $userTarget->getId(), - time() - ); - - // Add activity event - if ($value) - { - $activityService->addEventUserStarAdd( - $user->getId(), - time(), - $userTarget->getId() - ); - } - - else - { - $activityService->addEventUserStarDelete( - $user->getId(), - time(), - $userTarget->getId() - ); - } - - // Redirect - return $this->redirectToRoute( - 'user_info', - [ - '_locale' => $request->get('_locale'), - 'userId' => $userTarget->getId() - ] - ); - } - - #[Route( - '/{_locale}/user/{userId}/moderator/toggle', - name: 'user_moderator_toggle', - requirements: - [ - '_locale' => '%app.locales%', - 'userId' => '\d+', - ], - methods: - [ - 'GET' - ] - )] - public function toggleModerator( - Request $request, - TranslatorInterface $translator, - UserService $userService, - ActivityService $activityService - ): Response - { - // Init user - $user = $this->initUser( - $request, - $userService, - $activityService - ); - - if (!$user->isModerator()) - { - // @TODO - throw new \Exception( - $translator->trans('Access denied') - ); - } - - // Init target user - if (!$userTarget = $userService->getUser($request->get('userId'))) - { - throw $this->createNotFoundException(); - } - - // Update user moderator - $value = $userService->toggleUserModerator( - $userTarget->getId() - )->isModerator(); - - // Add activity event - if ($value) - { - $activityService->addEventUserModeratorAdd( - $user->getId(), - time(), - $userTarget->getId() - ); - } - - else - { - $activityService->addEventUserModeratorDelete( - $user->getId(), - time(), - $userTarget->getId() - ); - } - - // Redirect - return $this->redirectToRoute( - 'user_info', - [ - '_locale' => $request->get('_locale'), - 'userId' => $userTarget->getId() - ] - ); - } - - #[Route( - '/{_locale}/user/{userId}/status/toggle', - name: 'user_status_toggle', - requirements: - [ - '_locale' => '%app.locales%', - 'userId' => '\d+', - ], - methods: - [ - 'GET' - ] - )] - public function toggleStatus( - Request $request, - TranslatorInterface $translator, - UserService $userService, - ActivityService $activityService - ): Response - { - // Init user - $user = $this->initUser( - $request, - $userService, - $activityService - ); - - if (!$user->isModerator()) - { - // @TODO - throw new \Exception( - $translator->trans('Access denied') - ); - } - - // Init target user - if (!$userTarget = $userService->getUser($request->get('userId'))) - { - throw $this->createNotFoundException(); - } - - // Update user status - $value = $userService->toggleUserStatus( - $userTarget->getId() - )->isStatus(); - - // Add activity event - if ($value) - { - $activityService->addEventUserStatusAdd( - $user->getId(), - time(), - $userTarget->getId() - ); - } - - else - { - $activityService->addEventUserStatusDelete( - $user->getId(), - time(), - $userTarget->getId() - ); - } - - // Redirect - return $this->redirectToRoute( - 'user_info', - [ - '_locale' => $request->get('_locale'), - 'userId' => $userTarget->getId() - ] - ); - } - - #[Route( - '/{_locale}/user/{userId}/approved/toggle', - name: 'user_approved_toggle', - requirements: - [ - '_locale' => '%app.locales%', - 'userId' => '\d+', - ], - methods: - [ - 'GET' - ] - )] - public function toggleApproved( - Request $request, - TranslatorInterface $translator, - UserService $userService, - TorrentService $torrentService, - ActivityService $activityService - ): Response - { - // Init user - $user = $this->initUser( - $request, - $userService, - $activityService - ); - - if (!$user->isModerator()) - { - // @TODO - throw new \Exception( - $translator->trans('Access denied') - ); - } - - // Init target user - if (!$userTarget = $userService->getUser($request->get('userId'))) - { - throw $this->createNotFoundException(); - } - - // Auto-approve all related content on user approve - if (!$userTarget->isApproved()) - { - $torrentService->setTorrentsApprovedByUserId( - $userTarget->getId(), - true - ); - - $torrentService->setTorrentLocalesApprovedByUserId( - $userTarget->getId(), - true - ); - - $torrentService->setTorrentCategoriesApprovedByUserId( - $userTarget->getId(), - true - ); - - $torrentService->setTorrentSensitivesApprovedByUserId( - $userTarget->getId(), - true - ); - - $torrentService->setTorrentPostersApprovedByUserId( - $userTarget->getId(), - true - ); - - // @TODO make event for each item - } - - // Update user approved - $value = $userService->toggleUserApproved( - $userTarget->getId() - )->isApproved(); - - // Add activity event - if ($value) - { - $activityService->addEventUserApproveAdd( - $user->getId(), - time(), - $userTarget->getId() - ); - } - - else - { - $activityService->addEventUserApproveDelete( - $user->getId(), - time(), - $userTarget->getId() - ); - } - - // Redirect - return $this->redirectToRoute( - 'user_info', - [ - '_locale' => $request->get('_locale'), - 'userId' => $userTarget->getId() - ] - ); - } - - public function module(?string $route): Response - { - return $this->render( - 'default/user/module.html.twig', - [ - 'route' => $route, - 'stars' => 0, - 'views' => 0, - 'comments' => 0, - 'downloads' => 0, - 'editions' => 0, - ] - ); - } - - private function initUser( - Request $request, - UserService $userService, - ActivityService $activityService - ): ?\App\Entity\User - { - // Init user - if (!$user = $userService->findUserByAddress($request->getClientIp())) - { - $user = $userService->addUser( - $request->getClientIp(), - time(), - $this->getParameter('app.locale'), - explode('|', $this->getParameter('app.locales')), - $activityService->getEventCodes(), - $this->getParameter('app.theme'), - $this->getParameter('app.sensitive'), - $this->getParameter('app.yggdrasil'), - $this->getParameter('app.posters'), - $this->getParameter('app.approved') - ); - - // Add user join event - $activityService->addEventUserAdd( - $user->getId(), - time() - ); - } - - return $user; - } -} \ No newline at end of file diff --git a/src/Entity/.gitignore b/src/Entity/.gitignore deleted file mode 100644 index e69de29..0000000 diff --git a/src/Entity/Activity.php b/src/Entity/Activity.php deleted file mode 100644 index 1be1097..0000000 --- a/src/Entity/Activity.php +++ /dev/null @@ -1,160 +0,0 @@ -id; - } - - public function setId(string $id): static - { - $this->id = $id; - - return $this; - } - - public function getEvent(): ?int - { - return $this->event; - } - - public function setEvent(int $event): static - { - $this->event = $event; - - return $this; - } - - public function getUserId(): ?int - { - return $this->userId; - } - - public function setUserId(?int $userId): static - { - $this->userId = $userId; - - return $this; - } - - public function getTorrentId(): ?int - { - return $this->torrentId; - } - - public function setTorrentId(?int $torrentId): static - { - $this->torrentId = $torrentId; - - return $this; - } - - public function getAdded(): ?int - { - return $this->added; - } - - public function setAdded(int $added): static - { - $this->added = $added; - - return $this; - } - - public function getData(): array - { - return $this->data; - } - - public function setData(array $data): static - { - $this->data = $data; - - return $this; - } -} diff --git a/src/Entity/Torrent.php b/src/Entity/Torrent.php deleted file mode 100644 index 515a62e..0000000 --- a/src/Entity/Torrent.php +++ /dev/null @@ -1,239 +0,0 @@ -id; - } - - public function setId(string $id): static - { - $this->id = $id; - - return $this; - } - - public function getUserId(): ?int - { - return $this->userId; - } - - public function setUserId(int $userId): static - { - $this->userId = $userId; - - return $this; - } - - public function getAdded(): ?int - { - return $this->added; - } - - public function setAdded(int $added): static - { - $this->added = $added; - - return $this; - } - - public function getScraped(): ?int - { - return $this->scraped; - } - - public function setScraped(int $scraped): static - { - $this->scraped = $scraped; - - return $this; - } - - public function getMd5file(): ?string - { - return $this->md5file; - } - - public function setMd5file(string $md5file): static - { - $this->md5file = $md5file; - - return $this; - } - - public function getKeywords(): ?array - { - return $this->keywords; - } - - public function setKeywords(?array $keywords): static - { - $this->keywords = $keywords; - - return $this; - } - - public function getLocales(): array - { - return $this->locales; - } - - public function setLocales(array $locales): static - { - $this->locales = $locales; - - return $this; - } - - public function isSensitive(): ?bool - { - return $this->sensitive; - } - - public function setSensitive(bool $sensitive): static - { - $this->sensitive = $sensitive; - - return $this; - } - - public function isApproved(): ?bool - { - return $this->approved; - } - - public function setApproved(bool $approved): static - { - $this->approved = $approved; - - return $this; - } - - public function isStatus(): ?bool - { - return $this->status; - } - - public function setStatus(bool $status): static - { - $this->status = $status; - - return $this; - } - - public function getSeeders(): ?int - { - return $this->seeders; - } - - public function setSeeders(?int $seeders): static - { - $this->seeders = $seeders; - - return $this; - } - - public function getPeers(): ?int - { - return $this->peers; - } - - public function setPeers(?int $peers): static - { - $this->peers = $peers; - - return $this; - } - - public function getLeechers(): ?int - { - return $this->leechers; - } - - public function setLeechers(?int $leechers): static - { - $this->leechers = $leechers; - - return $this; - } - - public function getTorrentPosterId(): ?int - { - return $this->torrentPosterId; - } - - public function setTorrentPosterId(?int $torrentPosterId): static - { - $this->torrentPosterId = $torrentPosterId; - - return $this; - } - - public function getCategories(): ?array - { - return $this->categories; - } - - public function setCategories(?array $categories): static - { - $this->categories = $categories; - - return $this; - } -} diff --git a/src/Entity/TorrentCategories.php b/src/Entity/TorrentCategories.php deleted file mode 100644 index 9d73809..0000000 --- a/src/Entity/TorrentCategories.php +++ /dev/null @@ -1,103 +0,0 @@ -id; - } - - public function setId(string $id): static - { - $this->id = $id; - - return $this; - } - - public function getTorrentId(): ?int - { - return $this->torrentId; - } - - public function setTorrentId(int $torrentId): static - { - $this->torrentId = $torrentId; - - return $this; - } - - public function getUserId(): ?int - { - return $this->userId; - } - - public function setUserId(int $userId): static - { - $this->userId = $userId; - - return $this; - } - - public function getAdded(): ?int - { - return $this->added; - } - - public function setAdded(int $added): static - { - $this->added = $added; - - return $this; - } - - public function getValue(): array - { - return $this->value; - } - - public function setValue(array $value): static - { - $this->value = $value; - - return $this; - } - - public function isApproved(): ?bool - { - return $this->approved; - } - - public function setApproved(bool $approved): static - { - $this->approved = $approved; - - return $this; - } -} diff --git a/src/Entity/TorrentDownloadFile.php b/src/Entity/TorrentDownloadFile.php deleted file mode 100644 index f05b416..0000000 --- a/src/Entity/TorrentDownloadFile.php +++ /dev/null @@ -1,72 +0,0 @@ -id; - } - - public function setId(string $id): static - { - $this->id = $id; - - return $this; - } - - public function getTorrentId(): ?int - { - return $this->torrentId; - } - - public function setTorrentId(int $torrentId): static - { - $this->torrentId = $torrentId; - - return $this; - } - - public function getUserId(): ?int - { - return $this->userId; - } - - public function setUserId(int $userId): static - { - $this->userId = $userId; - - return $this; - } - - public function getAdded(): ?int - { - return $this->added; - } - - public function setAdded(int $added): static - { - $this->added = $added; - - return $this; - } -} diff --git a/src/Entity/TorrentDownloadMagnet.php b/src/Entity/TorrentDownloadMagnet.php deleted file mode 100644 index 1b56cad..0000000 --- a/src/Entity/TorrentDownloadMagnet.php +++ /dev/null @@ -1,72 +0,0 @@ -id; - } - - public function setId(string $id): static - { - $this->id = $id; - - return $this; - } - - public function getTorrentId(): ?int - { - return $this->torrentId; - } - - public function setTorrentId(int $torrentId): static - { - $this->torrentId = $torrentId; - - return $this; - } - - public function getUserId(): ?int - { - return $this->userId; - } - - public function setUserId(int $userId): static - { - $this->userId = $userId; - - return $this; - } - - public function getAdded(): ?int - { - return $this->added; - } - - public function setAdded(int $added): static - { - $this->added = $added; - - return $this; - } -} diff --git a/src/Entity/TorrentLocales.php b/src/Entity/TorrentLocales.php deleted file mode 100644 index f5322d9..0000000 --- a/src/Entity/TorrentLocales.php +++ /dev/null @@ -1,103 +0,0 @@ -id; - } - - public function setId(string $id): static - { - $this->id = $id; - - return $this; - } - - public function getTorrentId(): ?int - { - return $this->torrentId; - } - - public function setTorrentId(int $torrentId): static - { - $this->torrentId = $torrentId; - - return $this; - } - - public function getUserId(): ?int - { - return $this->userId; - } - - public function setUserId(int $userId): static - { - $this->userId = $userId; - - return $this; - } - - public function getAdded(): ?int - { - return $this->added; - } - - public function setAdded(int $added): static - { - $this->added = $added; - - return $this; - } - - public function getValue(): array - { - return $this->value; - } - - public function setValue(array $value): static - { - $this->value = $value; - - return $this; - } - - public function isApproved(): ?bool - { - return $this->approved; - } - - public function setApproved(bool $approved): static - { - $this->approved = $approved; - - return $this; - } -} diff --git a/src/Entity/TorrentPoster.php b/src/Entity/TorrentPoster.php deleted file mode 100644 index b25c481..0000000 --- a/src/Entity/TorrentPoster.php +++ /dev/null @@ -1,117 +0,0 @@ -id; - } - - public function setId(string $id): static - { - $this->id = $id; - - return $this; - } - - public function getTorrentId(): ?int - { - return $this->torrentId; - } - - public function setTorrentId(int $torrentId): static - { - $this->torrentId = $torrentId; - - return $this; - } - - public function getUserId(): ?int - { - return $this->userId; - } - - public function setUserId(int $userId): static - { - $this->userId = $userId; - - return $this; - } - - public function getAdded(): ?int - { - return $this->added; - } - - public function setAdded(int $added): static - { - $this->added = $added; - - return $this; - } - - public function isApproved(): ?bool - { - return $this->approved; - } - - public function setApproved(bool $approved): static - { - $this->approved = $approved; - - return $this; - } - - public function getMd5file(): ?string - { - return $this->md5file; - } - - public function setMd5file(string $md5file): static - { - $this->md5file = $md5file; - - return $this; - } - - public function getPosition(): ?string - { - return $this->position; - } - - public function setPosition(string $position): static - { - $this->position = $position; - - return $this; - } -} diff --git a/src/Entity/TorrentSensitive.php b/src/Entity/TorrentSensitive.php deleted file mode 100644 index 9c1560f..0000000 --- a/src/Entity/TorrentSensitive.php +++ /dev/null @@ -1,103 +0,0 @@ -id; - } - - public function setId(string $id): static - { - $this->id = $id; - - return $this; - } - - public function getTorrentId(): ?int - { - return $this->torrentId; - } - - public function setTorrentId(int $torrentId): static - { - $this->torrentId = $torrentId; - - return $this; - } - - public function getUserId(): ?int - { - return $this->userId; - } - - public function setUserId(int $userId): static - { - $this->userId = $userId; - - return $this; - } - - public function getAdded(): ?int - { - return $this->added; - } - - public function setAdded(int $added): static - { - $this->added = $added; - - return $this; - } - - public function isValue(): ?bool - { - return $this->value; - } - - public function setValue(bool $value): static - { - $this->value = $value; - - return $this; - } - - public function isApproved(): ?bool - { - return $this->approved; - } - - public function setApproved(bool $approved): static - { - $this->approved = $approved; - - return $this; - } -} diff --git a/src/Entity/TorrentStar.php b/src/Entity/TorrentStar.php deleted file mode 100644 index e5fd435..0000000 --- a/src/Entity/TorrentStar.php +++ /dev/null @@ -1,65 +0,0 @@ -id; - } - - public function getTorrentId(): ?int - { - return $this->torrentId; - } - - public function setTorrentId(int $torrentId): static - { - $this->torrentId = $torrentId; - - return $this; - } - - public function getUserId(): ?int - { - return $this->userId; - } - - public function setUserId(int $userId): static - { - $this->userId = $userId; - - return $this; - } - - public function getAdded(): ?int - { - return $this->added; - } - - public function setAdded(int $added): static - { - $this->added = $added; - - return $this; - } -} diff --git a/src/Entity/User.php b/src/Entity/User.php deleted file mode 100644 index 330a97a..0000000 --- a/src/Entity/User.php +++ /dev/null @@ -1,223 +0,0 @@ -id; - } - - public function setId(string $id): static - { - $this->id = $id; - - return $this; - } - - public function getAddress(): ?string - { - return $this->address; - } - - public function setAddress(string $address): static - { - $this->address = $address; - - return $this; - } - - public function getAdded(): ?int - { - return $this->added; - } - - public function setAdded(int $added): static - { - $this->added = $added; - - return $this; - } - - public function isModerator(): ?bool - { - return $this->moderator; - } - - public function setModerator(bool $moderator): static - { - $this->moderator = $moderator; - - return $this; - } - - public function isApproved(): ?bool - { - return $this->approved; - } - - public function setApproved(bool $approved): static - { - $this->approved = $approved; - - return $this; - } - - public function isStatus(): ?bool - { - return $this->status; - } - - public function setStatus(bool $status): static - { - $this->status = $status; - - return $this; - } - - public function getLocale(): ?string - { - return $this->locale; - } - - public function setLocale(string $locale): static - { - $this->locale = $locale; - - return $this; - } - - public function getLocales(): array - { - return $this->locales; - } - - public function setLocales(array $locales): static - { - $this->locales = $locales; - - return $this; - } - - public function getEvents(): array - { - return $this->events; - } - - public function setEvents(array $events): static - { - $this->events = $events; - - return $this; - } - - public function getTheme(): ?string - { - return $this->theme; - } - - public function setTheme(string $theme): static - { - $this->theme = $theme; - - return $this; - } - - public function isSensitive(): ?bool - { - return $this->sensitive; - } - - public function setSensitive(bool $sensitive): static - { - $this->sensitive = $sensitive; - - return $this; - } - - public function isYggdrasil(): ?bool - { - return $this->yggdrasil; - } - - public function setYggdrasil(bool $yggdrasil): static - { - $this->yggdrasil = $yggdrasil; - - return $this; - } - - public function isPosters(): ?bool - { - return $this->posters; - } - - public function setPosters(bool $posters): static - { - $this->posters = $posters; - - return $this; - } - - public function getCategories(): ?array - { - return $this->categories; - } - - public function setCategories(?array $categories): static - { - $this->categories = $categories; - - return $this; - } -} diff --git a/src/Entity/UserStar.php b/src/Entity/UserStar.php deleted file mode 100644 index 2fd755e..0000000 --- a/src/Entity/UserStar.php +++ /dev/null @@ -1,65 +0,0 @@ -id; - } - - public function getUserId(): ?int - { - return $this->userId; - } - - public function setUserId(int $userId): static - { - $this->userId = $userId; - - return $this; - } - - public function getUserIdTarget(): ?int - { - return $this->userIdTarget; - } - - public function setUserIdTarget(int $userIdTarget): static - { - $this->userIdTarget = $userIdTarget; - - return $this; - } - - public function getAdded(): ?int - { - return $this->added; - } - - public function setAdded(int $added): static - { - $this->added = $added; - - return $this; - } -} diff --git a/src/Kernel.php b/src/Kernel.php deleted file mode 100644 index 779cd1f..0000000 --- a/src/Kernel.php +++ /dev/null @@ -1,11 +0,0 @@ - - * - * @method Activity|null find($id, $lockMode = null, $lockVersion = null) - * @method Activity|null findOneBy(array $criteria, array $orderBy = null) - * @method Activity[] findAll() - * @method Activity[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null) - */ -class ActivityRepository extends ServiceEntityRepository -{ - public function __construct(ManagerRegistry $registry) - { - parent::__construct($registry, Activity::class); - } - - public function findActivitiesTotal( - array $whitelist - ): int - { - return $this->createQueryBuilder('a') - ->select('count(a.id)') - ->where('a.event IN (:event)') - ->setParameter(':event', $whitelist) - ->getQuery() - ->getSingleScalarResult() - ; - } - - public function findActivitiesTotalByUserId( - int $userId, - array $whitelist - ): int - { - return $this->createQueryBuilder('a') - ->select('count(a.id)') - ->where('a.userId = :userId') - ->andWhere('a.event IN (:event)') - ->setParameter(':userId', $userId) - ->setParameter(':event', $whitelist) - ->getQuery() - ->getSingleScalarResult() - ; - } - - public function findActivitiesTotalByTorrentId( - int $torrentId, - array $whitelist - ): int - { - return $this->createQueryBuilder('a') - ->select('count(a.id)') - ->where('a.torrentId = :torrentId') - ->andWhere('a.event IN (:event)') - ->setParameter(':torrentId', $torrentId) - ->setParameter(':event', $whitelist) - ->getQuery() - ->getSingleScalarResult() - ; - } -} diff --git a/src/Repository/TorrentCategoriesRepository.php b/src/Repository/TorrentCategoriesRepository.php deleted file mode 100644 index 030f69c..0000000 --- a/src/Repository/TorrentCategoriesRepository.php +++ /dev/null @@ -1,23 +0,0 @@ - - * - * @method TorrentCategories|null find($id, $lockMode = null, $lockVersion = null) - * @method TorrentCategories|null findOneBy(array $criteria, array $orderBy = null) - * @method TorrentCategories[] findAll() - * @method TorrentCategories[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null) - */ -class TorrentCategoriesRepository extends ServiceEntityRepository -{ - public function __construct(ManagerRegistry $registry) - { - parent::__construct($registry, TorrentCategories::class); - } -} diff --git a/src/Repository/TorrentDownloadFileRepository.php b/src/Repository/TorrentDownloadFileRepository.php deleted file mode 100644 index 4052176..0000000 --- a/src/Repository/TorrentDownloadFileRepository.php +++ /dev/null @@ -1,36 +0,0 @@ - - * - * @method TorrentDownloadFile|null find($id, $lockMode = null, $lockVersion = null) - * @method TorrentDownloadFile|null findOneBy(array $criteria, array $orderBy = null) - * @method TorrentDownloadFile[] findAll() - * @method TorrentDownloadFile[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null) - */ -class TorrentDownloadFileRepository extends ServiceEntityRepository -{ - public function __construct(ManagerRegistry $registry) - { - parent::__construct($registry, TorrentDownloadFile::class); - } - - public function findTorrentDownloadFilesTotalByTorrentId( - int $torrentId - ): int - { - return $this->createQueryBuilder('tdf') - ->select('count(tdf.id)') - ->where('tdf.torrentId = :torrentId') - ->setParameter('torrentId', $torrentId) - ->getQuery() - ->getSingleScalarResult() - ; - } -} diff --git a/src/Repository/TorrentDownloadMagnetRepository.php b/src/Repository/TorrentDownloadMagnetRepository.php deleted file mode 100644 index ef4e706..0000000 --- a/src/Repository/TorrentDownloadMagnetRepository.php +++ /dev/null @@ -1,36 +0,0 @@ - - * - * @method TorrentDownloadMagnet|null find($id, $lockMode = null, $lockVersion = null) - * @method TorrentDownloadMagnet|null findOneBy(array $criteria, array $orderBy = null) - * @method TorrentDownloadMagnet[] findAll() - * @method TorrentDownloadMagnet[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null) - */ -class TorrentDownloadMagnetRepository extends ServiceEntityRepository -{ - public function __construct(ManagerRegistry $registry) - { - parent::__construct($registry, TorrentDownloadMagnet::class); - } - - public function findTorrentDownloadMagnetsTotalByTorrentId( - int $torrentId - ): int - { - return $this->createQueryBuilder('tdm') - ->select('count(tdm.id)') - ->where('tdm.torrentId = :torrentId') - ->setParameter('torrentId', $torrentId) - ->getQuery() - ->getSingleScalarResult() - ; - } -} diff --git a/src/Repository/TorrentLocalesRepository.php b/src/Repository/TorrentLocalesRepository.php deleted file mode 100644 index 8ba7b73..0000000 --- a/src/Repository/TorrentLocalesRepository.php +++ /dev/null @@ -1,23 +0,0 @@ - - * - * @method TorrentLocales|null find($id, $lockMode = null, $lockVersion = null) - * @method TorrentLocales|null findOneBy(array $criteria, array $orderBy = null) - * @method TorrentLocales[] findAll() - * @method TorrentLocales[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null) - */ -class TorrentLocalesRepository extends ServiceEntityRepository -{ - public function __construct(ManagerRegistry $registry) - { - parent::__construct($registry, TorrentLocales::class); - } -} diff --git a/src/Repository/TorrentPosterRepository.php b/src/Repository/TorrentPosterRepository.php deleted file mode 100644 index 235231c..0000000 --- a/src/Repository/TorrentPosterRepository.php +++ /dev/null @@ -1,23 +0,0 @@ - - * - * @method TorrentPoster|null find($id, $lockMode = null, $lockVersion = null) - * @method TorrentPoster|null findOneBy(array $criteria, array $orderBy = null) - * @method TorrentPoster[] findAll() - * @method TorrentPoster[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null) - */ -class TorrentPosterRepository extends ServiceEntityRepository -{ - public function __construct(ManagerRegistry $registry) - { - parent::__construct($registry, TorrentPoster::class); - } -} diff --git a/src/Repository/TorrentRepository.php b/src/Repository/TorrentRepository.php deleted file mode 100644 index 536a72f..0000000 --- a/src/Repository/TorrentRepository.php +++ /dev/null @@ -1,241 +0,0 @@ - - * - * @method Torrent|null find($id, $lockMode = null, $lockVersion = null) - * @method Torrent|null findOneBy(array $criteria, array $orderBy = null) - * @method Torrent[] findAll() - * @method Torrent[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null) - */ -class TorrentRepository extends ServiceEntityRepository -{ - public function __construct(ManagerRegistry $registry) - { - parent::__construct($registry, Torrent::class); - } - - public function findTorrentsTotal( - int $userId, - array $keywords, - ?array $locales, - ?array $categories, - ?bool $sensitive = null, - ?bool $approved = null, - ?bool $status = null, - int $limit = 10, - int $offset = 0 - ): int - { - return $this->getTorrentsQueryByFilter( - $userId, - $keywords, - $locales, - $categories, - $sensitive, - $approved, - $status, - )->select('count(t.id)') - ->getQuery() - ->getSingleScalarResult(); - } - - public function findTorrents( - int $userId, - array $keywords, - ?array $locales, - ?array $categories, - ?bool $sensitive = null, - ?bool $approved = null, - ?bool $status = null, - int $limit = 10, - int $offset = 0 - ): array - { - return $this->getTorrentsQueryByFilter( - $userId, - $keywords, - $locales, - $categories, - $sensitive, - $approved, - $status, - )->setMaxResults($limit) - ->setFirstResult($offset) - ->orderBy('t.id', 'DESC') // same as t.added - ->getQuery() - ->getResult(); - } - - private function getTorrentsQueryByFilter( - int $userId, - ?array $keywords, - ?array $locales, - ?array $categories, - ?bool $sensitive = null, - ?bool $approved = null, - ?bool $status = null - ): \Doctrine\ORM\QueryBuilder - { - $query = $this->createQueryBuilder('t'); - - if (is_array($keywords)) - { - foreach ($keywords as $i => $keyword) - { - // Make query to the index case insensitive - $keyword = mb_strtolower($keyword); - - // Init OR condition for each word form - $orKeywords = $query->expr()->orX(); - - $orKeywords->add("t.keywords LIKE :keyword{$i}"); - $query->setParameter(":keyword{$i}", "%{$keyword}%"); - - // Generate word forms for each transliteration locale #33 - foreach ($this->generateWordForms($keyword) as $j => $wordForm) - { - $orKeywords->add("t.keywords LIKE :keyword{$i}{$j}"); - $query->setParameter(":keyword{$i}{$j}", "%{$wordForm}%"); - } - - // Append AND condition - $query->andWhere($orKeywords); - } - } - - if (is_array($locales)) - { - $orLocales = $query->expr()->orX(); - - foreach ($locales as $i => $locale) - { - $orLocales->add("t.locales LIKE :locale{$i}"); - $orLocales->add("t.userId = :userId"); - - $query->setParameter(":locale{$i}", "%{$locale}%"); - $query->setParameter('userId', $userId); - } - - $query->andWhere($orLocales); - } - - if (is_array($categories)) - { - $orCategories = $query->expr()->orX(); - - foreach ($categories as $i => $category) - { - $orCategories->add("t.categories LIKE :category{$i}"); - $orCategories->add("t.userId = :userId"); - - $query->setParameter(":category{$i}", "%{$category}%"); - $query->setParameter('userId', $userId); - } - - $query->andWhere($orCategories); - } - - if (is_bool($sensitive)) - { - $orSensitive = $query->expr()->orX(); - - $orSensitive->add("t.sensitive = :sensitive"); - $orSensitive->add("t.userId = :userId"); - - $query->setParameter('sensitive', $sensitive); - $query->setParameter('userId', $userId); - - $query->andWhere($orSensitive); - } - - if (is_bool($approved)) - { - $orApproved = $query->expr()->orX(); - - $orApproved->add("t.approved = :approved"); - $orApproved->add("t.userId = :userId"); - - $query->setParameter('approved', $approved); - $query->setParameter('userId', $userId); - - $query->andWhere($orApproved); - } - - if (is_bool($status)) - { - $orStatus = $query->expr()->orX(); - - $orStatus->add("t.status = :status"); - $orStatus->add("t.userId = :userId"); - - $query->setParameter('status', $status); - $query->setParameter('userId', $userId); - - $query->andWhere($orStatus); - } - - return $query; - } - - // Word forms generator to improve search results - // e.g. transliteration rules for latin filenames - private function generateWordForms( - string $keyword, - // #33 supported locales: - // https://github.com/ashtokalo/php-translit - array $transliteration = [ - 'be', - 'bg', - 'el', - 'hy', - 'kk', - 'mk', - 'ru', - 'ka', - 'uk' - ], - // Additional char forms - array $charForms = - [ - 'c' => 'k', - 'k' => 'c', - ] - ): array - { - $wordForms = []; - - // Apply transliteration - foreach ($transliteration as $locale) - { - $wordForms[] = \ashtokalo\translit\Translit::object()->convert( - $keyword, - $locale - ); - } - - // Apply char forms - foreach ($wordForms as $wordForm) - { - foreach ($charForms as $from => $to) - { - $wordForms[] = str_replace( - $from, - $to, - $wordForm - ); - } - } - - // Remove duplicates - return array_unique( - $wordForms - ); - } -} diff --git a/src/Repository/TorrentSensitiveRepository.php b/src/Repository/TorrentSensitiveRepository.php deleted file mode 100644 index e21c7e6..0000000 --- a/src/Repository/TorrentSensitiveRepository.php +++ /dev/null @@ -1,23 +0,0 @@ - - * - * @method TorrentSensitive|null find($id, $lockMode = null, $lockVersion = null) - * @method TorrentSensitive|null findOneBy(array $criteria, array $orderBy = null) - * @method TorrentSensitive[] findAll() - * @method TorrentSensitive[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null) - */ -class TorrentSensitiveRepository extends ServiceEntityRepository -{ - public function __construct(ManagerRegistry $registry) - { - parent::__construct($registry, TorrentSensitive::class); - } -} diff --git a/src/Repository/TorrentStarRepository.php b/src/Repository/TorrentStarRepository.php deleted file mode 100644 index 978aa95..0000000 --- a/src/Repository/TorrentStarRepository.php +++ /dev/null @@ -1,36 +0,0 @@ - - * - * @method TorrentStar|null find($id, $lockMode = null, $lockVersion = null) - * @method TorrentStar|null findOneBy(array $criteria, array $orderBy = null) - * @method TorrentStar[] findAll() - * @method TorrentStar[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null) - */ -class TorrentStarRepository extends ServiceEntityRepository -{ - public function __construct(ManagerRegistry $registry) - { - parent::__construct($registry, TorrentStar::class); - } - - public function findTorrentStarsTotalByTorrentId( - int $torrentId - ): int - { - return $this->createQueryBuilder('ts') - ->select('count(ts.id)') - ->where('ts.torrentId = :torrentId') - ->setParameter('torrentId', $torrentId) - ->getQuery() - ->getSingleScalarResult() - ; - } -} diff --git a/src/Repository/UserRepository.php b/src/Repository/UserRepository.php deleted file mode 100644 index 86a987a..0000000 --- a/src/Repository/UserRepository.php +++ /dev/null @@ -1,23 +0,0 @@ - - * - * @method User|null find($id, $lockMode = null, $lockVersion = null) - * @method User|null findOneBy(array $criteria, array $orderBy = null) - * @method User[] findAll() - * @method User[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null) - */ -class UserRepository extends ServiceEntityRepository -{ - public function __construct(ManagerRegistry $registry) - { - parent::__construct($registry, User::class); - } -} diff --git a/src/Repository/UserStarRepository.php b/src/Repository/UserStarRepository.php deleted file mode 100644 index 2a4f295..0000000 --- a/src/Repository/UserStarRepository.php +++ /dev/null @@ -1,36 +0,0 @@ - - * - * @method UserStar|null find($id, $lockMode = null, $lockVersion = null) - * @method UserStar|null findOneBy(array $criteria, array $orderBy = null) - * @method UserStar[] findAll() - * @method UserStar[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null) - */ -class UserStarRepository extends ServiceEntityRepository -{ - public function __construct(ManagerRegistry $registry) - { - parent::__construct($registry, UserStar::class); - } - - public function findUserStarsTotalByUserIdTarget( - int $userIdTarget - ): int - { - return $this->createQueryBuilder('us') - ->select('count(us.userId)') - ->where('us.userIdTarget = :userIdTarget') - ->setParameter('userIdTarget', $userIdTarget) - ->getQuery() - ->getSingleScalarResult() - ; - } -} diff --git a/src/Service/ActivityService.php b/src/Service/ActivityService.php deleted file mode 100644 index dd785d1..0000000 --- a/src/Service/ActivityService.php +++ /dev/null @@ -1,1806 +0,0 @@ -entityManagerInterface = $entityManagerInterface; - $this->translatorInterface = $translatorInterface; - } - - public function getEventCodes(): array - { - return - [ - // User - Activity::EVENT_USER_ADD, - - Activity::EVENT_USER_APPROVE_ADD, - Activity::EVENT_USER_APPROVE_DELETE, - - Activity::EVENT_USER_MODERATOR_ADD, - Activity::EVENT_USER_MODERATOR_DELETE, - - Activity::EVENT_USER_STATUS_ADD, - Activity::EVENT_USER_STATUS_DELETE, - - Activity::EVENT_USER_STAR_ADD, - Activity::EVENT_USER_STAR_DELETE, - - // Torrents - Activity::EVENT_TORRENT_ADD, - - Activity::EVENT_TORRENT_APPROVE_ADD, - Activity::EVENT_TORRENT_APPROVE_DELETE, - - Activity::EVENT_TORRENT_LOCALES_ADD, - Activity::EVENT_TORRENT_LOCALES_DELETE, - Activity::EVENT_TORRENT_LOCALES_APPROVE_ADD, - Activity::EVENT_TORRENT_LOCALES_APPROVE_DELETE, - - Activity::EVENT_TORRENT_CATEGORIES_ADD, - Activity::EVENT_TORRENT_CATEGORIES_DELETE, - Activity::EVENT_TORRENT_CATEGORIES_APPROVE_ADD, - Activity::EVENT_TORRENT_CATEGORIES_APPROVE_DELETE, - - Activity::EVENT_TORRENT_SENSITIVE_ADD, - Activity::EVENT_TORRENT_SENSITIVE_DELETE, - Activity::EVENT_TORRENT_SENSITIVE_APPROVE_ADD, - Activity::EVENT_TORRENT_SENSITIVE_APPROVE_DELETE, - - Activity::EVENT_TORRENT_POSTER_ADD, - Activity::EVENT_TORRENT_POSTER_DELETE, - Activity::EVENT_TORRENT_POSTER_APPROVE_ADD, - Activity::EVENT_TORRENT_POSTER_APPROVE_DELETE, - - Activity::EVENT_TORRENT_STAR_ADD, - Activity::EVENT_TORRENT_STAR_DELETE, - - Activity::EVENT_TORRENT_DOWNLOAD_FILE_ADD, - Activity::EVENT_TORRENT_DOWNLOAD_MAGNET_ADD, - - Activity::EVENT_TORRENT_STATUS_ADD, - Activity::EVENT_TORRENT_STATUS_DELETE, - - Activity::EVENT_TORRENT_WANTED_ADD, - ]; - } - - public function getEventsTree(): array - { - $events = []; - - foreach ($this->getEventCodes() as $code) - { - switch ($code) - { - // User - case Activity::EVENT_USER_ADD: - - $events - [ - $this->translatorInterface->trans('Users') - ] - [ - $this->translatorInterface->trans('Joined') - ] = $code; - - break; - - /// User approve - case Activity::EVENT_USER_APPROVE_ADD: - - $events - [ - $this->translatorInterface->trans('Users') - ] - [ - $this->translatorInterface->trans('Approved') - ] = $code; - - break; - - case Activity::EVENT_USER_APPROVE_DELETE: - - $events - [ - $this->translatorInterface->trans('Users') - ] - [ - $this->translatorInterface->trans('Disapproved') - ] = $code; - break; - - /// User status - case Activity::EVENT_USER_STATUS_ADD: - - $events - [ - $this->translatorInterface->trans('User statuses') - ] - [ - $this->translatorInterface->trans('Enabled') - ] = $code; - - break; - - case Activity::EVENT_USER_STATUS_DELETE: - - $events - [ - $this->translatorInterface->trans('User statuses') - ] - [ - $this->translatorInterface->trans('Disabled') - ] = $code; - break; - - /// User moderator - case Activity::EVENT_USER_MODERATOR_ADD: - - $events - [ - $this->translatorInterface->trans('User moderators') - ] - [ - $this->translatorInterface->trans('Added') - ] = $code; - - break; - - case Activity::EVENT_USER_MODERATOR_DELETE: - - $events - [ - $this->translatorInterface->trans('User moderators') - ] - [ - $this->translatorInterface->trans('Removed') - ] = $code; - break; - - /// User star - case Activity::EVENT_USER_STAR_ADD: - - $events - [ - $this->translatorInterface->trans('User stars') - ] - [ - $this->translatorInterface->trans('Added') - ] = $code; - - break; - - case Activity::EVENT_USER_STAR_DELETE: - - $events - [ - $this->translatorInterface->trans('User stars') - ] - [ - $this->translatorInterface->trans('Removed') - ] = $code; - break; - - // Torrent - case Activity::EVENT_TORRENT_ADD: - - $events - [ - $this->translatorInterface->trans('Torrents') - ] - [ - $this->translatorInterface->trans('Added') - ] = $code; - - break; - - case Activity::EVENT_TORRENT_APPROVE_ADD: - - $events - [ - $this->translatorInterface->trans('Torrents') - ] - [ - $this->translatorInterface->trans('Approved') - ] = $code; - - break; - - case Activity::EVENT_TORRENT_APPROVE_DELETE: - - $events - [ - $this->translatorInterface->trans('Torrents') - ] - [ - $this->translatorInterface->trans('Disapproved') - ] = $code; - - break; - - /// Torrent locales - case Activity::EVENT_TORRENT_LOCALES_ADD: - - $events - [ - $this->translatorInterface->trans('Torrent locales') - ] - [ - $this->translatorInterface->trans('Added') - ] = $code; - - break; - - case Activity::EVENT_TORRENT_LOCALES_DELETE: - - $events - [ - $this->translatorInterface->trans('Torrent locales') - ] - [ - $this->translatorInterface->trans('Deleted') - ] = $code; - - break; - - case Activity::EVENT_TORRENT_LOCALES_APPROVE_ADD: - - $events - [ - $this->translatorInterface->trans('Torrent locales') - ] - [ - $this->translatorInterface->trans('Approved') - ] = $code; - - break; - - case Activity::EVENT_TORRENT_LOCALES_APPROVE_DELETE: - - $events - [ - $this->translatorInterface->trans('Torrent locales') - ] - [ - $this->translatorInterface->trans('Disapproved') - ] = $code; - - break; - - /// Torrent categories - case Activity::EVENT_TORRENT_CATEGORIES_ADD: - - $events - [ - $this->translatorInterface->trans('Torrent categories') - ] - [ - $this->translatorInterface->trans('Added') - ] = $code; - - break; - - case Activity::EVENT_TORRENT_CATEGORIES_DELETE: - - $events - [ - $this->translatorInterface->trans('Torrent categories') - ] - [ - $this->translatorInterface->trans('Deleted') - ] = $code; - - break; - - case Activity::EVENT_TORRENT_CATEGORIES_APPROVE_ADD: - - $events - [ - $this->translatorInterface->trans('Torrent categories') - ] - [ - $this->translatorInterface->trans('Approved') - ] = $code; - - break; - - case Activity::EVENT_TORRENT_CATEGORIES_APPROVE_DELETE: - - $events - [ - $this->translatorInterface->trans('Torrent categories') - ] - [ - $this->translatorInterface->trans('Disapproved') - ] = $code; - - break; - - /// Torrent sensitive - case Activity::EVENT_TORRENT_SENSITIVE_ADD: - - $events - [ - $this->translatorInterface->trans('Torrent sensitive') - ] - [ - $this->translatorInterface->trans('Added') - ] = $code; - - break; - - case Activity::EVENT_TORRENT_SENSITIVE_DELETE: - - $events - [ - $this->translatorInterface->trans('Torrent sensitive') - ] - [ - $this->translatorInterface->trans('Deleted') - ] = $code; - - break; - - case Activity::EVENT_TORRENT_SENSITIVE_APPROVE_ADD: - - $events - [ - $this->translatorInterface->trans('Torrent sensitive') - ] - [ - $this->translatorInterface->trans('Approved') - ] = $code; - - break; - - case Activity::EVENT_TORRENT_SENSITIVE_APPROVE_DELETE: - - $events - [ - $this->translatorInterface->trans('Torrent sensitive') - ] - [ - $this->translatorInterface->trans('Disapproved') - ] = $code; - - break; - - /// Torrent poster - case Activity::EVENT_TORRENT_POSTER_ADD: - - $events - [ - $this->translatorInterface->trans('Torrent posters') - ] - [ - $this->translatorInterface->trans('Added') - ] = $code; - - break; - - case Activity::EVENT_TORRENT_POSTER_DELETE: - - $events - [ - $this->translatorInterface->trans('Torrent posters') - ] - [ - $this->translatorInterface->trans('Deleted') - ] = $code; - - break; - - case Activity::EVENT_TORRENT_POSTER_APPROVE_ADD: - - $events - [ - $this->translatorInterface->trans('Torrent posters') - ] - [ - $this->translatorInterface->trans('Approved') - ] = $code; - - break; - - case Activity::EVENT_TORRENT_POSTER_APPROVE_DELETE: - - $events - [ - $this->translatorInterface->trans('Torrent posters') - ] - [ - $this->translatorInterface->trans('Disapproved') - ] = $code; - - break; - - /// Torrent stars - case Activity::EVENT_TORRENT_STAR_ADD: - - $events - [ - $this->translatorInterface->trans('Torrent stars') - ] - [ - $this->translatorInterface->trans('Added') - ] = $code; - - break; - - case Activity::EVENT_TORRENT_STAR_DELETE: - - $events - [ - $this->translatorInterface->trans('Torrent stars') - ] - [ - $this->translatorInterface->trans('Removed') - ] = $code; - - break; - - /// Torrent downloads - case Activity::EVENT_TORRENT_DOWNLOAD_FILE_ADD: - - $events - [ - $this->translatorInterface->trans('Torrent downloads') - ] - [ - $this->translatorInterface->trans('Files') - ] = $code; - - break; - - case Activity::EVENT_TORRENT_DOWNLOAD_MAGNET_ADD: - - $events - [ - $this->translatorInterface->trans('Torrent downloads') - ] - [ - $this->translatorInterface->trans('Magnet links') - ] = $code; - - break; - - case Activity::EVENT_TORRENT_WANTED_ADD: - - $events - [ - $this->translatorInterface->trans('Torrents') - ] - [ - $this->translatorInterface->trans('Wanted') - ] = $code; - - break; - - case Activity::EVENT_TORRENT_STATUS_ADD: - - $events - [ - $this->translatorInterface->trans('Torrents') - ] - [ - $this->translatorInterface->trans('Enabled') - ] = $code; - - break; - - case Activity::EVENT_TORRENT_STATUS_DELETE: - - $events - [ - $this->translatorInterface->trans('Torrents') - ] - [ - $this->translatorInterface->trans('Disabled') - ] = $code; - - break; - } - } - - return $events; - } - - public function findLastActivities( - array $whitelist, - int $limit = 10, - int $offset = 0 - ): array - { - return $this->entityManagerInterface - ->getRepository(Activity::class) - ->findBy( - [ - 'event' => $whitelist - ], - [ - 'id' => 'DESC' - ], - $limit, - $offset - ); - } - - public function findLastActivitiesByUserId( - int $userId, - array $whitelist, - int $limit = 10, - int $offset = 0 - ): array - { - return $this->entityManagerInterface - ->getRepository(Activity::class) - ->findBy( - [ - 'userId' => $userId, - 'event' => $whitelist, - ], - [ - 'id' => 'DESC' - ], - $limit, - $offset - ); - } - - public function findLastActivitiesByTorrentId( - int $torrentId, - array $whitelist, - int $limit = 10, - int $offset = 0 - ): array - { - return $this->entityManagerInterface - ->getRepository(Activity::class) - ->findBy( - [ - 'torrentId' => $torrentId, - 'event' => $whitelist, - ], - [ - 'id' => 'DESC' - ], - $limit, - $offset - ); - } - - public function findActivitiesTotal( - array $whitelist - ): int - { - return $this->entityManagerInterface - ->getRepository(Activity::class) - ->findActivitiesTotal($whitelist); - } - - public function findActivitiesTotalByUserId( - int $userId, - array $whitelist - ): int - { - return $this->entityManagerInterface - ->getRepository(Activity::class) - ->findActivitiesTotalByUserId( - $userId, - $whitelist - ); - } - - public function findActivitiesTotalByTorrentId( - int $torrentId, - array $whitelist - ): int - { - return $this->entityManagerInterface - ->getRepository(Activity::class) - ->findActivitiesTotalByTorrentId( - $torrentId, - $whitelist - ); - } - - // User - public function addEventUserAdd( - int $userId, - int $added - ): ?Activity - { - $activity = new Activity(); - - $activity->setEvent( - Activity::EVENT_USER_ADD - ); - - $activity->setUserId( - $userId - ); - - $activity->setAdded( - $added - ); - - $this->entityManagerInterface->persist($activity); - $this->entityManagerInterface->flush(); - - return $activity; - } - - /// User approved - public function addEventUserApproveAdd( - int $userId, - int $added, - int $userIdTarget, - ): ?Activity - { - $activity = new Activity(); - - $activity->setEvent( - Activity::EVENT_USER_APPROVE_ADD - ); - - $activity->setUserId( - $userId - ); - - $activity->setAdded( - $added - ); - - $activity->setData( - [ - 'userId' => $userIdTarget - ] - ); - - $this->entityManagerInterface->persist($activity); - $this->entityManagerInterface->flush(); - - return $activity; - } - - public function addEventUserApproveDelete( - int $userId, - int $added, - int $userIdTarget, - ): ?Activity - { - $activity = new Activity(); - - $activity->setEvent( - Activity::EVENT_USER_APPROVE_DELETE - ); - - $activity->setUserId( - $userId - ); - - $activity->setAdded( - $added - ); - - $activity->setData( - [ - 'userId' => $userIdTarget - ] - ); - - $this->entityManagerInterface->persist($activity); - $this->entityManagerInterface->flush(); - - return $activity; - } - - /// User status - public function addEventUserStatusAdd( - int $userId, - int $added, - int $userIdTarget, - ): ?Activity - { - $activity = new Activity(); - - $activity->setEvent( - Activity::EVENT_USER_STATUS_ADD - ); - - $activity->setUserId( - $userId - ); - - $activity->setAdded( - $added - ); - - $activity->setData( - [ - 'userId' => $userIdTarget - ] - ); - - $this->entityManagerInterface->persist($activity); - $this->entityManagerInterface->flush(); - - return $activity; - } - - public function addEventUserStatusDelete( - int $userId, - int $added, - int $userIdTarget, - ): ?Activity - { - $activity = new Activity(); - - $activity->setEvent( - Activity::EVENT_USER_STATUS_DELETE - ); - - $activity->setUserId( - $userId - ); - - $activity->setAdded( - $added - ); - - $activity->setData( - [ - 'userId' => $userIdTarget - ] - ); - - $this->entityManagerInterface->persist($activity); - $this->entityManagerInterface->flush(); - - return $activity; - } - - /// User moderator - public function addEventUserModeratorAdd( - int $userId, - int $added, - int $userIdTarget, - ): ?Activity - { - $activity = new Activity(); - - $activity->setEvent( - Activity::EVENT_USER_MODERATOR_ADD - ); - - $activity->setUserId( - $userId - ); - - $activity->setAdded( - $added - ); - - $activity->setData( - [ - 'userId' => $userIdTarget - ] - ); - - $this->entityManagerInterface->persist($activity); - $this->entityManagerInterface->flush(); - - return $activity; - } - - public function addEventUserModeratorDelete( - int $userId, - int $added, - int $userIdTarget, - ): ?Activity - { - $activity = new Activity(); - - $activity->setEvent( - Activity::EVENT_USER_MODERATOR_DELETE - ); - - $activity->setUserId( - $userId - ); - - $activity->setAdded( - $added - ); - - $activity->setData( - [ - 'userId' => $userIdTarget - ] - ); - - $this->entityManagerInterface->persist($activity); - $this->entityManagerInterface->flush(); - - return $activity; - } - - /// User star - public function addEventUserStarAdd( - int $userId, - int $added, - int $userIdTarget - ): ?Activity - { - $activity = new Activity(); - - $activity->setEvent( - Activity::EVENT_USER_STAR_ADD - ); - - $activity->setUserId( - $userId - ); - - $activity->setAdded( - $added - ); - - $activity->setData( - [ - 'userId' => $userIdTarget - ] - ); - - $this->entityManagerInterface->persist($activity); - $this->entityManagerInterface->flush(); - - return $activity; - } - - public function addEventUserStarDelete( - int $userId, - int $added, - int $userIdTarget - ): ?Activity - { - $activity = new Activity(); - - $activity->setEvent( - Activity::EVENT_USER_STAR_DELETE - ); - - $activity->setUserId( - $userId - ); - - $activity->setAdded( - $added - ); - - $activity->setData( - [ - 'userId' => $userIdTarget - ] - ); - - $this->entityManagerInterface->persist($activity); - $this->entityManagerInterface->flush(); - - return $activity; - } - - // Torrent - public function addEventTorrentAdd( - int $userId, - int $added, - int $torrentId - ): ?Activity - { - $activity = new Activity(); - - $activity->setEvent( - Activity::EVENT_TORRENT_ADD - ); - - $activity->setUserId( - $userId - ); - - $activity->setAdded( - $added - ); - - $activity->setTorrentId( - $torrentId - ); - - $this->entityManagerInterface->persist($activity); - $this->entityManagerInterface->flush(); - - return $activity; - } - - public function addEventTorrentApproveAdd( - int $userId, - int $torrentId, - int $added - ): ?Activity - { - $activity = new Activity(); - - $activity->setEvent( - Activity::EVENT_TORRENT_APPROVE_ADD - ); - - $activity->setUserId( - $userId - ); - - $activity->setTorrentId( - $torrentId - ); - - $activity->setAdded( - $added - ); - - $this->entityManagerInterface->persist($activity); - $this->entityManagerInterface->flush(); - - return $activity; - } - - public function addEventTorrentApproveDelete( - int $userId, - int $torrentId, - int $added - ): ?Activity - { - $activity = new Activity(); - - $activity->setEvent( - Activity::EVENT_TORRENT_APPROVE_DELETE - ); - - $activity->setUserId( - $userId - ); - - $activity->setTorrentId( - $torrentId - ); - - $activity->setAdded( - $added - ); - - $this->entityManagerInterface->persist($activity); - $this->entityManagerInterface->flush(); - - return $activity; - } - - public function addEventTorrentStatusAdd( - int $userId, - int $torrentId, - int $added - ): ?Activity - { - $activity = new Activity(); - - $activity->setEvent( - Activity::EVENT_TORRENT_STATUS_ADD - ); - - $activity->setUserId( - $userId - ); - - $activity->setTorrentId( - $torrentId - ); - - $activity->setAdded( - $added - ); - - $this->entityManagerInterface->persist($activity); - $this->entityManagerInterface->flush(); - - return $activity; - } - - public function addEventTorrentStatusDelete( - int $userId, - int $torrentId, - int $added - ): ?Activity - { - $activity = new Activity(); - - $activity->setEvent( - Activity::EVENT_TORRENT_STATUS_DELETE - ); - - $activity->setUserId( - $userId - ); - - $activity->setTorrentId( - $torrentId - ); - - $activity->setAdded( - $added - ); - - $this->entityManagerInterface->persist($activity); - $this->entityManagerInterface->flush(); - - return $activity; - } - - public function addEventTorrentWantedAdd( - int $userId, - int $added, - int $torrentId - ): ?Activity - { - $activity = new Activity(); - - $activity->setEvent( - Activity::EVENT_TORRENT_WANTED_ADD - ); - - $activity->setUserId( - $userId - ); - - $activity->setAdded( - $added - ); - - $activity->setTorrentId( - $torrentId - ); - - $this->entityManagerInterface->persist($activity); - $this->entityManagerInterface->flush(); - - return $activity; - } - - /// Torrent Download - public function addEventTorrentDownloadFileAdd( - int $userId, - int $added, - int $torrentId - ): ?Activity - { - $activity = new Activity(); - - $activity->setEvent( - Activity::EVENT_TORRENT_DOWNLOAD_FILE_ADD - ); - - $activity->setUserId( - $userId - ); - - $activity->setAdded( - $added - ); - - $activity->setTorrentId( - $torrentId - ); - - $this->entityManagerInterface->persist($activity); - $this->entityManagerInterface->flush(); - - return $activity; - } - - public function addEventTorrentDownloadMagnetAdd( - int $userId, - int $added, - int $torrentId - ): ?Activity - { - $activity = new Activity(); - - $activity->setEvent( - Activity::EVENT_TORRENT_DOWNLOAD_MAGNET_ADD - ); - - $activity->setUserId( - $userId - ); - - $activity->setAdded( - $added - ); - - $activity->setTorrentId( - $torrentId - ); - - $this->entityManagerInterface->persist($activity); - $this->entityManagerInterface->flush(); - - return $activity; - } - - /// Torrent star - public function addEventTorrentStarAdd( - int $userId, - int $added, - int $torrentId - ): ?Activity - { - $activity = new Activity(); - - $activity->setEvent( - Activity::EVENT_TORRENT_STAR_ADD - ); - - $activity->setUserId( - $userId - ); - - $activity->setTorrentId( - $torrentId - ); - - $activity->setAdded( - $added - ); - - $this->entityManagerInterface->persist($activity); - $this->entityManagerInterface->flush(); - - return $activity; - } - - public function addEventTorrentStarDelete( - int $userId, - int $added, - int $torrentId - ): ?Activity - { - $activity = new Activity(); - - $activity->setEvent( - Activity::EVENT_TORRENT_STAR_DELETE - ); - - $activity->setUserId( - $userId - ); - - $activity->setTorrentId( - $torrentId - ); - - $activity->setAdded( - $added - ); - - $this->entityManagerInterface->persist($activity); - $this->entityManagerInterface->flush(); - - return $activity; - } - - /// Torrent locales - public function addEventTorrentLocalesAdd( - int $userId, - int $torrentId, - int $added, - int $torrentLocalesId, - ): ?Activity - { - $activity = new Activity(); - - $activity->setEvent( - Activity::EVENT_TORRENT_LOCALES_ADD - ); - - $activity->setUserId( - $userId - ); - - $activity->setTorrentId( - $torrentId - ); - - $activity->setAdded( - $added - ); - - $activity->setData( - [ - 'torrentLocalesId' => $torrentLocalesId - ] - ); - - $this->entityManagerInterface->persist($activity); - $this->entityManagerInterface->flush(); - - return $activity; - } - - public function addEventTorrentLocalesDelete( - int $userId, - int $torrentId, - int $added, - int $torrentLocalesId, - ): ?Activity - { - $activity = new Activity(); - - $activity->setEvent( - Activity::EVENT_TORRENT_LOCALES_DELETE - ); - - $activity->setUserId( - $userId - ); - - $activity->setTorrentId( - $torrentId - ); - - $activity->setAdded( - $added - ); - - $activity->setData( - [ - 'torrentLocalesId' => $torrentLocalesId - ] - ); - - $this->entityManagerInterface->persist($activity); - $this->entityManagerInterface->flush(); - - return $activity; - } - - public function addEventTorrentLocalesApproveAdd( - int $userId, - int $torrentId, - int $added, - int $torrentLocalesId, - ): ?Activity - { - $activity = new Activity(); - - $activity->setEvent( - Activity::EVENT_TORRENT_LOCALES_APPROVE_ADD - ); - - $activity->setUserId( - $userId - ); - - $activity->setTorrentId( - $torrentId - ); - - $activity->setAdded( - $added - ); - - $activity->setData( - [ - 'torrentLocalesId' => $torrentLocalesId - ] - ); - - $this->entityManagerInterface->persist($activity); - $this->entityManagerInterface->flush(); - - return $activity; - } - - public function addEventTorrentLocalesApproveDelete( - int $userId, - int $torrentId, - int $added, - int $torrentLocalesId, - ): ?Activity - { - $activity = new Activity(); - - $activity->setEvent( - Activity::EVENT_TORRENT_LOCALES_APPROVE_DELETE - ); - - $activity->setUserId( - $userId - ); - - $activity->setTorrentId( - $torrentId - ); - - $activity->setAdded( - $added - ); - - $activity->setData( - [ - 'torrentLocalesId' => $torrentLocalesId - ] - ); - - $this->entityManagerInterface->persist($activity); - $this->entityManagerInterface->flush(); - - return $activity; - } - - /// Torrent categories - public function addEventTorrentCategoriesAdd( - int $userId, - int $torrentId, - int $added, - int $torrentCategoriesId, - ): ?Activity - { - $activity = new Activity(); - - $activity->setEvent( - Activity::EVENT_TORRENT_CATEGORIES_ADD - ); - - $activity->setUserId( - $userId - ); - - $activity->setTorrentId( - $torrentId - ); - - $activity->setAdded( - $added - ); - - $activity->setData( - [ - 'torrentCategoriesId' => $torrentCategoriesId - ] - ); - - $this->entityManagerInterface->persist($activity); - $this->entityManagerInterface->flush(); - - return $activity; - } - - public function addEventTorrentCategoriesDelete( - int $userId, - int $torrentId, - int $added, - int $torrentCategoriesId, - ): ?Activity - { - $activity = new Activity(); - - $activity->setEvent( - Activity::EVENT_TORRENT_CATEGORIES_DELETE - ); - - $activity->setUserId( - $userId - ); - - $activity->setTorrentId( - $torrentId - ); - - $activity->setAdded( - $added - ); - - $activity->setData( - [ - 'torrentCategoriesId' => $torrentCategoriesId - ] - ); - - $this->entityManagerInterface->persist($activity); - $this->entityManagerInterface->flush(); - - return $activity; - } - - public function addEventTorrentCategoriesApproveAdd( - int $userId, - int $torrentId, - int $added, - int $torrentCategoriesId, - ): ?Activity - { - $activity = new Activity(); - - $activity->setEvent( - Activity::EVENT_TORRENT_CATEGORIES_APPROVE_ADD - ); - - $activity->setUserId( - $userId - ); - - $activity->setTorrentId( - $torrentId - ); - - $activity->setAdded( - $added - ); - - $activity->setData( - [ - 'torrentCategoriesId' => $torrentCategoriesId - ] - ); - - $this->entityManagerInterface->persist($activity); - $this->entityManagerInterface->flush(); - - return $activity; - } - - public function addEventTorrentCategoriesApproveDelete( - int $userId, - int $torrentId, - int $added, - int $torrentCategoriesId, - ): ?Activity - { - $activity = new Activity(); - - $activity->setEvent( - Activity::EVENT_TORRENT_CATEGORIES_APPROVE_DELETE - ); - - $activity->setUserId( - $userId - ); - - $activity->setTorrentId( - $torrentId - ); - - $activity->setAdded( - $added - ); - - $activity->setData( - [ - 'torrentCategoriesId' => $torrentCategoriesId - ] - ); - - $this->entityManagerInterface->persist($activity); - $this->entityManagerInterface->flush(); - - return $activity; - } - - /// Torrent sensitive - public function addEventTorrentSensitiveAdd( - int $userId, - int $torrentId, - int $added, - int $torrentSensitiveId, - ): ?Activity - { - $activity = new Activity(); - - $activity->setEvent( - Activity::EVENT_TORRENT_SENSITIVE_ADD - ); - - $activity->setUserId( - $userId - ); - - $activity->setTorrentId( - $torrentId - ); - - $activity->setAdded( - $added - ); - - $activity->setData( - [ - 'torrentSensitiveId' => $torrentSensitiveId - ] - ); - - $this->entityManagerInterface->persist($activity); - $this->entityManagerInterface->flush(); - - return $activity; - } - - public function addEventTorrentSensitiveDelete( - int $userId, - int $torrentId, - int $added, - int $torrentSensitiveId, - ): ?Activity - { - $activity = new Activity(); - - $activity->setEvent( - Activity::EVENT_TORRENT_SENSITIVE_DELETE - ); - - $activity->setUserId( - $userId - ); - - $activity->setTorrentId( - $torrentId - ); - - $activity->setAdded( - $added - ); - - $activity->setData( - [ - 'torrentSensitiveId' => $torrentSensitiveId - ] - ); - - $this->entityManagerInterface->persist($activity); - $this->entityManagerInterface->flush(); - - return $activity; - } - - public function addEventTorrentSensitiveApproveAdd( - int $userId, - int $torrentId, - int $added, - int $torrentSensitiveId, - ): ?Activity - { - $activity = new Activity(); - - $activity->setEvent( - Activity::EVENT_TORRENT_SENSITIVE_APPROVE_ADD - ); - - $activity->setUserId( - $userId - ); - - $activity->setTorrentId( - $torrentId - ); - - $activity->setAdded( - $added - ); - - $activity->setData( - [ - 'torrentSensitiveId' => $torrentSensitiveId - ] - ); - - $this->entityManagerInterface->persist($activity); - $this->entityManagerInterface->flush(); - - return $activity; - } - - public function addEventTorrentSensitiveApproveDelete( - int $userId, - int $torrentId, - int $added, - int $torrentSensitiveId, - ): ?Activity - { - $activity = new Activity(); - - $activity->setEvent( - Activity::EVENT_TORRENT_SENSITIVE_APPROVE_DELETE - ); - - $activity->setUserId( - $userId - ); - - $activity->setTorrentId( - $torrentId - ); - - $activity->setAdded( - $added - ); - - $activity->setData( - [ - 'torrentSensitiveId' => $torrentSensitiveId - ] - ); - - $this->entityManagerInterface->persist($activity); - $this->entityManagerInterface->flush(); - - return $activity; - } - - /// Torrent poster - public function addEventTorrentPosterAdd( - int $userId, - int $torrentId, - int $added, - int $torrentPosterId, - ): ?Activity - { - $activity = new Activity(); - - $activity->setEvent( - Activity::EVENT_TORRENT_POSTER_ADD - ); - - $activity->setUserId( - $userId - ); - - $activity->setTorrentId( - $torrentId - ); - - $activity->setAdded( - $added - ); - - $activity->setData( - [ - 'torrentPosterId' => $torrentPosterId - ] - ); - - $this->entityManagerInterface->persist($activity); - $this->entityManagerInterface->flush(); - - return $activity; - } - - public function addEventTorrentPosterDelete( - int $userId, - int $torrentId, - int $added, - int $torrentPosterId, - ): ?Activity - { - $activity = new Activity(); - - $activity->setEvent( - Activity::EVENT_TORRENT_POSTER_DELETE - ); - - $activity->setUserId( - $userId - ); - - $activity->setTorrentId( - $torrentId - ); - - $activity->setAdded( - $added - ); - - $activity->setData( - [ - 'torrentPosterId' => $torrentPosterId - ] - ); - - $this->entityManagerInterface->persist($activity); - $this->entityManagerInterface->flush(); - - return $activity; - } - - public function addEventTorrentPosterApproveAdd( - int $userId, - int $torrentId, - int $added, - int $torrentPosterId, - ): ?Activity - { - $activity = new Activity(); - - $activity->setEvent( - Activity::EVENT_TORRENT_POSTER_APPROVE_ADD - ); - - $activity->setUserId( - $userId - ); - - $activity->setTorrentId( - $torrentId - ); - - $activity->setAdded( - $added - ); - - $activity->setData( - [ - 'torrentPosterId' => $torrentPosterId - ] - ); - - $this->entityManagerInterface->persist($activity); - $this->entityManagerInterface->flush(); - - return $activity; - } - - public function addEventTorrentPosterApproveDelete( - int $userId, - int $torrentId, - int $added, - int $torrentPosterId, - ): ?Activity - { - $activity = new Activity(); - - $activity->setEvent( - Activity::EVENT_TORRENT_POSTER_APPROVE_DELETE - ); - - $activity->setUserId( - $userId - ); - - $activity->setTorrentId( - $torrentId - ); - - $activity->setAdded( - $added - ); - - $activity->setData( - [ - 'torrentPosterId' => $torrentPosterId - ] - ); - - $this->entityManagerInterface->persist($activity); - $this->entityManagerInterface->flush(); - - return $activity; - } -} \ No newline at end of file diff --git a/src/Service/TorrentService.php b/src/Service/TorrentService.php deleted file mode 100644 index c0c3d52..0000000 --- a/src/Service/TorrentService.php +++ /dev/null @@ -1,1548 +0,0 @@ -kernelInterface = $kernelInterface; - $this->entityManagerInterface = $entityManagerInterface; - } - - // Tools - public function readTorrentFileByFilepath( - string $filepath - ): ?\Rhilip\Bencode\TorrentFile - { - try - { - return \Rhilip\Bencode\TorrentFile::load( - $filepath - ); - } - - catch (\Rhilip\Bencode\ParseException $error) - { - return null; - } - } - - public function readTorrentFileByTorrentId( - int $torrentId - ): ?\Rhilip\Bencode\TorrentFile - { - return $this->readTorrentFileByFilepath( - $this->getStorageFilepathByTorrentId($torrentId) - ); - } - - public function generateTorrentKeywordsByString( - string $string, - int $wordLengthMin, - int $wordLengthMax, - ): array - { - $words = explode( - ' ', - preg_replace( - '/[\s]+/', - ' ', - preg_replace( - '/[\W_]+/u', - ' ', - $string - ) - ) - ); - - // Apply words filter - foreach ((array) $words as $key => $value) - { - // Apply word length filter - $length = mb_strlen($value); - - if ($length < $wordLengthMin || $length > $wordLengthMax) - { - unset($words[$key]); - } - - else - { - // Apply case insensitive search conversion - $words[$key] = mb_strtolower($value); - } - } - - // Build simple array - $keywords = []; - foreach ((array) $words as $word) - { - $keywords[] = $word; - } - - // Return unique keywords - return array_unique( - $keywords - ); - } - - public function generateTorrentKeywordsByTorrentFilepath( - - string $filepath, - - bool $extractName, - bool $extractFilenames, - bool $extractInfoHashV1, - bool $extractInfoHashV2, - bool $extractSource, - bool $extractComment, - - int $wordLengthMin, - int $wordLengthMax - - ): array - { - $keywords = []; - - if ($file = $this->readTorrentFileByFilepath($filepath)) - { - if ($extractName) - { - if ($name = $file->getName(false)) - { - $keywords = array_merge( - $keywords, - $this->generateTorrentKeywordsByString( - $name, - $wordLengthMin, - $wordLengthMax - ) - ); - } - } - - if ($extractFilenames) - { - foreach ($file->getFileList() as $list) - { - $keywords = array_merge( - $keywords, - $this->generateTorrentKeywordsByString( - $list['path'], - $wordLengthMin, - $wordLengthMax - ) - ); - } - } - - if ($extractSource) - { - if ($source = $file->getSource(false)) - { - $keywords = array_merge( - $keywords, - $this->generateTorrentKeywordsByString( - $source, - $wordLengthMin, - $wordLengthMax - ) - ); - } - } - - if ($extractComment) - { - if ($comment = $file->getComment(false)) - { - $keywords = array_merge( - $keywords, - $this->generateTorrentKeywordsByString( - $comment, - $wordLengthMin, - $wordLengthMax - ) - ); - } - } - - if ($extractInfoHashV1) - { - if ($hash = $file->getInfoHashV1(false)) - { - $keywords[] = $hash; - } - } - - if ($extractInfoHashV2) - { - if ($hash = $file->getInfoHashV2(false)) - { - $keywords[] = $hash; - } - } - } - - return array_unique( - $keywords - ); - } - - public function getImageUriByTorrentPosterId( - int $torrentPosterId, - int $quality = 100, - int $width = 748, - int $height = 0, - float $opacity = 1, - bool $grayscale = false, - string $format = 'webp' - ): string - { - $uri = sprintf( - '/posters/%s.%s', - implode('/', str_split($torrentPosterId)), - $format - ); - - $filename = sprintf( - '%s/public/posters/%s.%s', - $this->kernelInterface->getProjectDir(), - implode('/', str_split($torrentPosterId)), - $format - ); - - if (file_exists($filename)) - { - return $uri; - } - - $path = explode('/', $filename); - - array_pop($path); - - @mkdir(implode('/', $path), 0755, true); - - $image = new \Imagick(); - - $image->readImage( - $this->getStorageFilepathByTorrentPosterId( - $torrentPosterId - ) - ); - - $image->setImageFormat($format); - $image->setImageCompressionQuality($quality); - - if ($width || $height) - { - $image->adaptiveResizeImage( - $width, - $height - ); - } - - if ($grayscale) - { - $image->setImageType( - \Imagick::IMGTYPE_GRAYSCALE - ); - } - - if ($opacity) - { - $image->setImageOpacity( - $opacity - ); - } - - $image->writeImage( - $filename - ); - - return $uri; - } - - public function getStorageFilepathByTorrentPosterId(int $torrentPosterId): string - { - return sprintf( - '%s/var/posters/%s.original', - $this->kernelInterface->getProjectDir(), - implode('/', str_split($torrentPosterId)) - ); - } - - public function getStorageFilepathByTorrentId(int $torrentId): string - { - return sprintf( - '%s/var/torrents/%s.torrent', - $this->kernelInterface->getProjectDir(), - implode('/', str_split($torrentId)) - ); - } - - public function getFtpFilepathByFilename(string $filename): string - { - return sprintf( - '%s/var/ftp/%s', - $this->kernelInterface->getProjectDir(), - $filename - ); - } - - public function getTorrentContributors(Torrent $torrent): array - { - $contributors = []; - - foreach ($this->findTorrentCategoriesByTorrentId($torrent->getId()) as $torrentCategory) - { - $contributors[] = $torrentCategory->getUserId(); - } - - foreach ($this->findTorrentLocalesByTorrentId($torrent->getId()) as $torrentLocale) - { - $contributors[] = $torrentLocale->getUserId(); - } - - foreach ($this->findTorrentSensitiveByTorrentId($torrent->getId()) as $torrentSensitive) - { - $contributors[] = $torrentSensitive->getUserId(); - } - - foreach ($this->findTorrentPosterByTorrentId($torrent->getId()) as $torrentPoster) - { - $contributors[] = $torrentPoster->getUserId(); - } - - $contributors[] = $torrent->getUserId(); - - return array_unique($contributors); - } - - public function copyToFtpStorage( - int $torrentId, - string $filename - ): void - { - $filesystem = new Filesystem(); - $filesystem->copy( - $this->getStorageFilepathByTorrentId( - $torrentId - ), - $this->getFtpFilepathByFilename( - $filename - ) - ); - } - - public function removeFromFtpStorage( - string $filename - ): void - { - $filesystem = new Filesystem(); - $filesystem->remove( - $this->getFtpFilepathByFilename( - $filename - ) - ); - } - - public function add( - - string $filepath, - - bool $extractName, - bool $extractFilenames, - bool $extractInfoHashV1, - bool $extractInfoHashV2, - bool $extractSource, - bool $extractComment, - - int $wordLengthMin, - int $wordLengthMax, - - int $userId, - int $added, - array $locales, - array $categories, - bool $sensitive, - bool $approved, - bool $status - - ): ?Torrent - { - $torrent = $this->addTorrent( - $userId, - $added, - md5_file($filepath), - $this->generateTorrentKeywordsByTorrentFilepath( - $filepath, - $extractName, - $extractFilenames, - $extractInfoHashV1, - $extractInfoHashV2, - $extractSource, - $extractComment, - $wordLengthMin, - $wordLengthMax - ), - $locales, - $categories, - $sensitive, - $approved, - $status - ); - - $filesystem = new Filesystem(); - $filesystem->copy( - $filepath, - $this->getStorageFilepathByTorrentId( - $torrent->getId() - ) - ); - - $this->addTorrentLocales( - $torrent->getId(), - $userId, - $added, - $locales, - $approved - ); - - $this->addTorrentCategories( - $torrent->getId(), - $userId, - $added, - $categories, - $approved - ); - - $this->addTorrentSensitive( - $torrent->getId(), - $userId, - $added, - $sensitive, - $approved - ); - - return $torrent; - } - - // Torrent - public function getTorrent(int $torrentId): ?Torrent - { - return $this->entityManagerInterface - ->getRepository(Torrent::class) - ->find($torrentId); - } - - public function addTorrent( - int $userId, - int $added, - string $md5file, - array $keywords, - array $locales, - array $categories, - bool $sensitive, - bool $approved, - bool $status - ): ?Torrent - { - $torrent = new Torrent(); - - $torrent->setUserId($userId); - $torrent->setAdded($added); - $torrent->setMd5File($md5file); - $torrent->setKeywords($keywords); - $torrent->setLocales($locales); - $torrent->setCategories($categories); - $torrent->setSensitive($sensitive); - $torrent->setApproved($approved); - $torrent->setStatus($status); - - $this->entityManagerInterface->persist($torrent); - $this->entityManagerInterface->flush(); - - return $torrent; - } - - public function toggleTorrentApproved( - int $torrentId - ): ?Torrent - { - $torrent = $this->getTorrent($torrentId); - - $torrent->setApproved( - !$torrent->isApproved() // toggle current value - ); - - $this->entityManagerInterface->persist($torrent); - $this->entityManagerInterface->flush(); - - $this->updateTorrentLocales( - $torrent->getId() - ); - - $this->updateTorrentSensitive( - $torrent->getId() - ); - - return $torrent; - } - - public function toggleTorrentStatus( - int $torrentId - ): ?Torrent - { - $torrent = $this->getTorrent($torrentId); - - $torrent->setStatus( - !$torrent->isStatus() // toggle current value - ); - - $this->entityManagerInterface->persist($torrent); - $this->entityManagerInterface->flush(); - - $this->updateTorrentLocales( - $torrent->getId() - ); - - $this->updateTorrentSensitive( - $torrent->getId() - ); - - return $torrent; - } - - public function getTorrentScrapeQueue(): ?Torrent - { - return $this->entityManagerInterface - ->getRepository(Torrent::class) - ->findOneBy( - [], - [ - 'scraped' => 'ASC' - ] - ); - } - - public function findTorrents( - int $userId, - array $keywords, - ?array $locales, - ?array $categories, - ?bool $sensitive, - ?bool $approved, - ?bool $status, - int $limit, - int $offset - ) : array - { - return $this->entityManagerInterface - ->getRepository(Torrent::class) - ->findTorrents( - $userId, - $keywords, - $locales, - $categories, - $sensitive, - $approved, - $status, - $limit, - $offset - ); - } - - public function findTorrentsTotal( - int $userId, - array $keywords, - ?array $locales, - ?array $categories, - ?bool $sensitive, - ?bool $approved, - ?bool $status - ) : int - { - return $this->entityManagerInterface - ->getRepository(Torrent::class) - ->findTorrentsTotal( - $userId, - $keywords, - $locales, - $categories, - $sensitive, - $approved, - $status - ); - } - - public function findTorrentByMd5File(string $md5file) : ?Torrent - { - return $this->entityManagerInterface - ->getRepository(Torrent::class) - ->findOneBy( - [ - 'md5file' => $md5file - ] - ); - } - - public function updateTorrentSensitive( - int $torrentId, - ): void - { - if ($torrent = $this->getTorrent($torrentId)) - { - if ($torrentSensitive = $this->entityManagerInterface - ->getRepository(TorrentSensitive::class) - ->findOneBy( - [ - 'torrentId' => $torrentId, - 'approved' => true, - ], - [ - 'id' => 'DESC' - ] - )) - { - $torrent->setSensitive( - $torrentSensitive->isValue() - ); - - $this->entityManagerInterface->persist($torrent); - $this->entityManagerInterface->flush(); - } - } - } - - public function updateTorrentLocales( - int $torrentId - ): void - { - if ($torrent = $this->getTorrent($torrentId)) - { - if ($torrentLocales = $this->entityManagerInterface - ->getRepository(TorrentLocales::class) - ->findOneBy( - [ - 'torrentId' => $torrentId, - 'approved' => true, - ], - [ - 'id' => 'DESC' - ] - )) - { - $torrent->setLocales($torrentLocales->getValue()); - - $this->entityManagerInterface->persist($torrent); - $this->entityManagerInterface->flush(); - } - } - } - - public function updateTorrentCategories( - int $torrentId - ): void - { - if ($torrent = $this->getTorrent($torrentId)) - { - if ($torrentCategories = $this->entityManagerInterface - ->getRepository(TorrentCategories::class) - ->findOneBy( - [ - 'torrentId' => $torrentId, - 'approved' => true, - ], - [ - 'id' => 'DESC' - ] - )) - { - $torrent->setCategories($torrentCategories->getValue()); - - $this->entityManagerInterface->persist($torrent); - $this->entityManagerInterface->flush(); - } - } - } - - public function updateTorrentScraped( - int $torrentId, - int $time - ): void - { - if ($torrent = $this->getTorrent($torrentId)) - { - $torrent->setScraped( - $time - ); - - $this->entityManagerInterface->persist($torrent); - $this->entityManagerInterface->flush(); - } - } - - public function updateTorrentScrape( - int $torrentId, - int $seeders, - int $peers, - int $leechers - ): void - { - if ($torrent = $this->getTorrent($torrentId)) - { - $torrent->setSeeders( - $seeders - ); - - $torrent->setPeers( - $peers - ); - - $torrent->setLeechers( - $leechers - ); - - $torrent->setScraped( - time() - ); - - $this->entityManagerInterface->persist($torrent); - $this->entityManagerInterface->flush(); - } - } - - public function reindexTorrentKeywordsAll( - bool $extractName, - bool $extractFilenames, - bool $extractInfoHashV1, - bool $extractInfoHashV2, - bool $extractSource, - bool $extractComment, - int $wordLengthMin, - int $wordLengthMax - ): void - { - foreach ($this->entityManagerInterface - ->getRepository(Torrent::class) - ->findAll() as $torrent) - { - $torrent->setKeywords( - $this->generateTorrentKeywordsByTorrentFilepath( - $this->getStorageFilepathByTorrentId( - $torrent->getId() - ), - $extractName, - $extractFilenames, - $extractInfoHashV1, - $extractInfoHashV2, - $extractSource, - $extractComment, - $wordLengthMin, - $wordLengthMax - ) - ); - - $this->entityManagerInterface->persist($torrent); - $this->entityManagerInterface->flush(); - } - } - - public function setTorrentApprovedByTorrentId( - int $torrentId, - bool $value - ): void - { - if ($torrent = $this->getTorrent($torrentId)) - { - $torrent->setApproved($value); - - $this->entityManagerInterface->persist($torrent); - $this->entityManagerInterface->flush(); - } - } - - public function setTorrentsApprovedByUserId( - int $userId, - bool $value - ): void - { - foreach ($this->entityManagerInterface - ->getRepository(Torrent::class) - ->findBy( - [ - 'userId' => $userId - ]) as $torrent) - { - $torrent->setApproved( - $value - ); - - $this->entityManagerInterface->persist($torrent); - $this->entityManagerInterface->flush(); - } - } - - // Torrent locale - public function getTorrentLocales( - int $torrentLocaleId - ): ?TorrentLocales - { - return $this->entityManagerInterface - ->getRepository(TorrentLocales::class) - ->find($torrentLocaleId); - } - - public function findLastTorrentLocalesByTorrentId( - int $torrentId - ): ?TorrentLocales - { - return $this->entityManagerInterface - ->getRepository(TorrentLocales::class) - ->findOneBy( - [ - 'torrentId' => $torrentId - ], - [ - 'id' => 'DESC' - ] - ); - } - - public function findTorrentLocalesByTorrentId(int $torrentId): array - { - return $this->entityManagerInterface - ->getRepository(TorrentLocales::class) - ->findBy( - [ - 'torrentId' => $torrentId, - ], - [ - 'id' => 'DESC' - ] - ); - } - - public function toggleTorrentLocalesApproved( - int $torrentLocalesId - ): ?TorrentLocales - { - $torrentLocales = $this->getTorrentLocales($torrentLocalesId); - - $torrentLocales->setApproved( - !$torrentLocales->isApproved() // toggle current value - ); - - $this->entityManagerInterface->persist($torrentLocales); - $this->entityManagerInterface->flush(); - - $this->updateTorrentLocales( - $torrentLocales->getTorrentId() - ); - - return $torrentLocales; - } - - public function deleteTorrentLocales( - int $torrentLocalesId - ): ?TorrentLocales - { - $torrentLocales = $this->getTorrentLocales($torrentLocalesId); - - $this->entityManagerInterface->remove($torrentLocales); - $this->entityManagerInterface->flush(); - - $this->updateTorrentLocales( - $torrentLocales->getTorrentId() - ); - - return $torrentLocales; - } - - public function addTorrentLocales( - int $torrentId, - int $userId, - int $added, - array $value, - bool $approved - ): ?TorrentLocales - { - $torrentLocales = new TorrentLocales(); - - $torrentLocales->setTorrentId($torrentId); - $torrentLocales->setUserId($userId); - $torrentLocales->setAdded($added); - $torrentLocales->setValue($value); - $torrentLocales->setApproved($approved); - - $this->entityManagerInterface->persist($torrentLocales); - $this->entityManagerInterface->flush(); - - $this->updateTorrentLocales( - $torrentId - ); - - return $torrentLocales; - } - - public function setTorrentLocalesApprovedByUserId( - int $userId, - bool $value - ): void - { - foreach ($this->entityManagerInterface - ->getRepository(TorrentLocales::class) - ->findBy( - [ - 'userId' => $userId - ]) as $torrentLocales) - { - $torrentLocales->setApproved( - $value - ); - - $this->entityManagerInterface->persist($torrentLocales); - $this->entityManagerInterface->flush(); - - $this->updateTorrentLocales( - $torrentLocales->getTorrentId(), - ); - } - } - - // Torrent category - public function getTorrentCategories( - int $torrentCategoryId - ): ?TorrentCategories - { - return $this->entityManagerInterface - ->getRepository(TorrentCategories::class) - ->find($torrentCategoryId); - } - - public function findLastTorrentCategoriesByTorrentId( - int $torrentId - ): ?TorrentCategories - { - return $this->entityManagerInterface - ->getRepository(TorrentCategories::class) - ->findOneBy( - [ - 'torrentId' => $torrentId - ], - [ - 'id' => 'DESC' - ] - ); - } - - public function findTorrentCategoriesByTorrentId(int $torrentId): array - { - return $this->entityManagerInterface - ->getRepository(TorrentCategories::class) - ->findBy( - [ - 'torrentId' => $torrentId, - ], - [ - 'id' => 'DESC' - ] - ); - } - - public function toggleTorrentCategoriesApproved( - int $torrentCategoriesId - ): ?TorrentCategories - { - $torrentCategories = $this->getTorrentCategories($torrentCategoriesId); - - $torrentCategories->setApproved( - !$torrentCategories->isApproved() // toggle current value - ); - - $this->entityManagerInterface->persist($torrentCategories); - $this->entityManagerInterface->flush(); - - $this->updateTorrentCategories( - $torrentCategories->getTorrentId() - ); - - return $torrentCategories; - } - - public function deleteTorrentCategories( - int $torrentCategoriesId - ): ?TorrentCategories - { - $torrentCategories = $this->getTorrentCategories($torrentCategoriesId); - - $this->entityManagerInterface->remove($torrentCategories); - $this->entityManagerInterface->flush(); - - $this->updateTorrentCategories( - $torrentCategories->getTorrentId() - ); - - return $torrentCategories; - } - - public function addTorrentCategories( - int $torrentId, - int $userId, - int $added, - array $value, - bool $approved - ): ?TorrentCategories - { - $torrentCategories = new TorrentCategories(); - - $torrentCategories->setTorrentId($torrentId); - $torrentCategories->setUserId($userId); - $torrentCategories->setAdded($added); - $torrentCategories->setValue($value); - $torrentCategories->setApproved($approved); - - $this->entityManagerInterface->persist($torrentCategories); - $this->entityManagerInterface->flush(); - - $this->updateTorrentCategories( - $torrentId - ); - - return $torrentCategories; - } - - public function setTorrentCategoriesApprovedByUserId( - int $userId, - bool $value - ): void - { - foreach ($this->entityManagerInterface - ->getRepository(TorrentCategories::class) - ->findBy( - [ - 'userId' => $userId - ]) as $torrentCategories) - { - $torrentCategories->setApproved( - $value - ); - - $this->entityManagerInterface->persist($torrentCategories); - $this->entityManagerInterface->flush(); - - $this->updateTorrentCategories( - $torrentCategories->getTorrentId(), - ); - } - } - - // Torrent sensitive - public function getTorrentSensitive( - int $torrentSensitiveId - ): ?TorrentSensitive - { - return $this->entityManagerInterface - ->getRepository(TorrentSensitive::class) - ->find( - $torrentSensitiveId - ); - } - - public function findLastTorrentSensitiveByTorrentId(int $torrentId): ?TorrentSensitive - { - return $this->entityManagerInterface - ->getRepository(TorrentSensitive::class) - ->findOneBy( - [ - 'torrentId' => $torrentId - ], - [ - 'id' => 'DESC' - ] - ); - } - - public function findTorrentSensitiveByTorrentId(int $torrentId): array - { - return $this->entityManagerInterface - ->getRepository(TorrentSensitive::class) - ->findBy( - [ - 'torrentId' => $torrentId - ], - [ - 'id' => 'DESC' - ] - ); - } - - public function toggleTorrentSensitiveApproved( - int $torrentSensitiveId - ): ?TorrentSensitive - { - $torrentSensitive = $this->entityManagerInterface - ->getRepository(TorrentSensitive::class) - ->find($torrentSensitiveId); - - $torrentSensitive->setApproved( - !$torrentSensitive->isApproved() // toggle current value - ); - - $this->entityManagerInterface->persist($torrentSensitive); - $this->entityManagerInterface->flush(); - - $this->updateTorrentSensitive( - $torrentSensitive->getTorrentId() - ); - - return $torrentSensitive; - } - - public function deleteTorrentSensitive( - int $torrentSensitiveId - ): ?TorrentSensitive - { - $torrentSensitive = $this->getTorrentSensitive( - $torrentSensitiveId - ); - - $this->entityManagerInterface->remove($torrentSensitive); - $this->entityManagerInterface->flush(); - - $this->updateTorrentSensitive( - $torrentSensitive->getTorrentId() - ); - - return $torrentSensitive; - } - - public function addTorrentSensitive( - int $torrentId, - int $userId, - int $added, - bool $value, - bool $approved - ): ?TorrentSensitive - { - $torrentSensitive = new TorrentSensitive(); - - $torrentSensitive->setTorrentId($torrentId); - $torrentSensitive->setUserId($userId); - $torrentSensitive->setAdded($added); - $torrentSensitive->setValue($value); - $torrentSensitive->setApproved($approved); - - $this->entityManagerInterface->persist($torrentSensitive); - $this->entityManagerInterface->flush(); - - $this->updateTorrentSensitive( - $torrentId - ); - - return $torrentSensitive; - } - - public function setTorrentSensitivesApprovedByUserId( - int $userId, - bool $value - ): void - { - foreach ($this->entityManagerInterface - ->getRepository(TorrentSensitive::class) - ->findBy( - [ - 'userId' => $userId - ]) as $torrentSensitive) - { - $torrentSensitive->setApproved( - $value - ); - - $this->entityManagerInterface->persist($torrentSensitive); - $this->entityManagerInterface->flush(); - - $this->updateTorrentSensitive( - $torrentSensitive->getTorrentId(), - ); - } - } - - // Torrent poster - public function getTorrentPoster( - int $torrentPosterId - ): ?TorrentPoster - { - return $this->entityManagerInterface - ->getRepository(TorrentPoster::class) - ->find( - $torrentPosterId - ); - } - - public function findTorrentPosterByMd5File( - string $md5file - ): ?Torrent - { - return $this->entityManagerInterface - ->getRepository(TorrentPoster::class) - ->findOneBy( - [ - 'md5file' => $md5file - ] - ); - } - - public function findLastTorrentPosterByTorrentId( - int $torrentId - ): ?TorrentPoster - { - return $this->entityManagerInterface - ->getRepository(TorrentPoster::class) - ->findOneBy( - [ - 'torrentId' => $torrentId - ], - [ - 'id' => 'DESC' - ] - ); - } - - public function findTorrentPosterByTorrentId( - int $torrentId - ): array - { - return $this->entityManagerInterface - ->getRepository(TorrentPoster::class) - ->findBy( - [ - 'torrentId' => $torrentId - ], - [ - 'id' => 'DESC' - ] - ); - } - - public function toggleTorrentPosterApproved( - int $torrentPosterId - ): ?TorrentPoster - { - $torrentPoster = $this->entityManagerInterface - ->getRepository(TorrentPoster::class) - ->find($torrentPosterId); - - $torrentPoster->setApproved( - !$torrentPoster->isApproved() // toggle current value - ); - - $this->entityManagerInterface->persist($torrentPoster); - $this->entityManagerInterface->flush(); - - $this->updateTorrentPoster( - $torrentPoster->getTorrentId() - ); - - return $torrentSensitive; - } - - public function deleteTorrentPoster( - int $torrentPosterId - ): ?TorrentPoster - { - // Remove torrent file from permanent storage - $filesystem = new Filesystem(); - $filesystem->remove( - $this->getStorageFilepathByTorrentPosterId( - $torrentPosterId - ) - ); - - // Remove from DB - $torrentPoster = $this->getTorrentPoster( - $torrentPosterId - ); - - $this->entityManagerInterface->remove($torrentPoster); - $this->entityManagerInterface->flush(); - - // Update torrent - $this->updateTorrentPoster( - $torrentPoster->getTorrentId() - ); - - return $torrentSensitive; - } - - public function addTorrentPoster( - string $filename, - string $position, - int $torrentId, - int $userId, - int $added, - bool $approved - ): ?TorrentPoster - { - // Add new DB record - $torrentPoster = new TorrentPoster(); - - $torrentPoster->setTorrentId($torrentId); - $torrentPoster->setUserId($userId); - $torrentPoster->setAdded($added); - $torrentPoster->setApproved($approved); - $torrentPoster->setPosition($position); - $torrentPoster->setMd5file( - md5_file($filename) - ); - - $this->entityManagerInterface->persist($torrentPoster); - $this->entityManagerInterface->flush(); - - // Save file in permanent storage - $filesystem = new Filesystem(); - $filesystem->copy( - $filename, - $this->getStorageFilepathByTorrentPosterId( - $torrentPoster->getId() - ) - ); - - // Update torrent info - $this->updateTorrentPoster( - $torrentId - ); - - return $torrentPoster; - } - - public function setTorrentPostersApprovedByUserId( - int $userId, - bool $value - ): void - { - foreach ($this->entityManagerInterface - ->getRepository(TorrentPoster::class) - ->findBy( - [ - 'userId' => $userId - ]) as $torrentPoster) - { - $torrentPoster->setApproved( - $value - ); - - $this->entityManagerInterface->persist($torrentPoster); - $this->entityManagerInterface->flush(); - - $this->updateTorrentPoster( - $torrentPoster->getTorrentId(), - ); - } - } - - public function updateTorrentPoster( - int $torrentId, - ): void - { - if ($torrent = $this->getTorrent($torrentId)) - { - if ($torrentPoster = $this->entityManagerInterface - ->getRepository(TorrentPoster::class) - ->findOneBy( - [ - 'torrentId' => $torrentId, - 'approved' => true, - ], - [ - 'id' => 'DESC' - ] - )) - { - $torrent->setTorrentPosterId( - $torrentPoster->getId() - ); - } - - else - { - $torrent->setTorrentPosterId( - null - ); - } - - $this->entityManagerInterface->persist($torrent); - $this->entityManagerInterface->flush(); - } - } - - - - - - // Torrent star - public function findTorrentStar( - int $torrentId, - int $userId - ): ?TorrentStar - { - return $this->entityManagerInterface - ->getRepository(TorrentStar::class) - ->findOneBy( - [ - 'torrentId' => $torrentId, - 'userId' => $userId, - ] - ); - } - - public function findTorrentStarsTotalByTorrentId(int $torrentId): int - { - return $this->entityManagerInterface - ->getRepository(TorrentStar::class) - ->findTorrentStarsTotalByTorrentId($torrentId); - } - - public function toggleTorrentStar( - int $torrentId, - int $userId, - int $added - ): bool - { - if ($torrentStar = $this->findTorrentStar($torrentId, $userId)) - { - $this->entityManagerInterface->remove($torrentStar); - $this->entityManagerInterface->flush(); - - return false; - } - - else - { - $torrentStar = new TorrentStar(); - - $torrentStar->setTorrentId($torrentId); - $torrentStar->setUserId($userId); - $torrentStar->setAdded($added); - - $this->entityManagerInterface->persist($torrentStar); - $this->entityManagerInterface->flush(); - - return true; - } - } - - // Torrent download file - public function findTorrentDownloadFile( - int $torrentId, - int $userId - ): ?TorrentDownloadFile - { - return $this->entityManagerInterface - ->getRepository(TorrentDownloadFile::class) - ->findOneBy( - [ - 'torrentId' => $torrentId, - 'userId' => $userId - ] - ); - } - - public function findTorrentDownloadFilesTotalByTorrentId(int $torrentId): int - { - return $this->entityManagerInterface - ->getRepository(TorrentDownloadFile::class) - ->findTorrentDownloadFilesTotalByTorrentId($torrentId); - } - - public function addTorrentDownloadFile( - int $torrentId, - int $userId, - int $added - ): void - { - if (!$this->findTorrentDownloadFile($torrentId, $userId)) - { - $torrentDownloadFile = new TorrentDownloadFile(); - - $torrentDownloadFile->setTorrentId($torrentId); - $torrentDownloadFile->setUserId($userId); - $torrentDownloadFile->setAdded($added); - - $this->entityManagerInterface->persist($torrentDownloadFile); - $this->entityManagerInterface->flush(); - } - } - - // Torrent download magnet - public function findTorrentDownloadMagnet( - int $torrentId, - int $userId - ): ?TorrentDownloadMagnet - { - return $this->entityManagerInterface - ->getRepository(TorrentDownloadMagnet::class) - ->findOneBy( - [ - 'torrentId' => $torrentId, - 'userId' => $userId - ] - ); - } - - public function findTorrentDownloadMagnetsTotalByTorrentId(int $torrentId): int - { - return $this->entityManagerInterface - ->getRepository(TorrentDownloadMagnet::class) - ->findTorrentDownloadMagnetsTotalByTorrentId($torrentId); - } - - public function addTorrentDownloadMagnet( - int $torrentId, - int $userId, - int $added - ): void - { - if (!$this->findTorrentDownloadMagnet($torrentId, $userId)) - { - $torrentDownloadMagnet = new TorrentDownloadMagnet(); - - $torrentDownloadMagnet->setTorrentId($torrentId); - $torrentDownloadMagnet->setUserId($userId); - $torrentDownloadMagnet->setAdded($added); - - $this->entityManagerInterface->persist($torrentDownloadMagnet); - $this->entityManagerInterface->flush(); - } - } -} \ No newline at end of file diff --git a/src/Service/UserService.php b/src/Service/UserService.php deleted file mode 100644 index eeba420..0000000 --- a/src/Service/UserService.php +++ /dev/null @@ -1,256 +0,0 @@ -entityManagerInterface = $entityManagerInterface; - $this->parameterBagInterface = $parameterBagInterface; - } - - public function addUser( - string $address, - string $added, - string $locale, - array $locales, - array $events, - string $theme, - bool $sensitive = true, - bool $yggdrasil = true, - bool $posters = true, - bool $approved = false, - bool $moderator = false, - bool $status = true - ): ?User - { - // Create new user - $user = new User(); - - $user->setAddress( - $address - ); - - $user->setAdded( - $added - ); - - $user->setApproved( - $approved - ); - - $user->setModerator( - $moderator - ); - - $user->setStatus( - $status - ); - - $user->setLocale( - $locale - ); - - $user->setLocales( - $locales - ); - - $user->setTheme( - $theme - ); - - $user->setEvents( - $events - ); - - $user->setSensitive( - $sensitive - ); - - $user->setYggdrasil( - $yggdrasil - ); - - $user->setPosters( - $posters - ); - - $this->entityManagerInterface->persist($user); - $this->entityManagerInterface->flush(); - - // Set initial user as approved & moderator - if (1 === $user->getId()) - { - $user->setApproved(true); - $user->setModerator(true); - $user->setSensitive(false); - - $this->entityManagerInterface->persist($user); - $this->entityManagerInterface->flush(); - } - - // Return user data - return $user; - } - - public function getUser(int $userId): ?User - { - return $this->entityManagerInterface - ->getRepository(User::class) - ->find($userId); - } - - public function findUserByAddress(string $address): ?User - { - return $this->entityManagerInterface - ->getRepository(User::class) - ->findOneBy( - [ - 'address' => $address - ] - ); - } - - public function identicon( - mixed $value, - int $size = 16, - array $style = - [ - 'backgroundColor' => 'rgba(255, 255, 255, 0)', - 'padding' => 0 - ], - string $format = 'webp' - ): string - { - $identicon = new \Jdenticon\Identicon(); - - $identicon->setValue($value); - $identicon->setSize($size); - $identicon->setStyle($style); - - return $identicon->getImageDataUri($format); - } - - public function save(User $user) : void // @TODO delete - { - $this->entityManagerInterface->persist($user); - $this->entityManagerInterface->flush(); - } - - // User star - public function findUserStar( - int $userId, - int $userIdTarget - ): ?UserStar - { - return $this->entityManagerInterface - ->getRepository(UserStar::class) - ->findOneBy( - [ - 'userId' => $userId, - 'userIdTarget' => $userIdTarget - ] - ); - } - - public function findUserStarsTotalByUserIdTarget(int $torrentId): int - { - return $this->entityManagerInterface - ->getRepository(UserStar::class) - ->findUserStarsTotalByUserIdTarget($torrentId); - } - - public function toggleUserStar( - int $userId, - int $userIdTarget, - int $added - ): bool - { - if ($userStar = $this->findUserStar($userId, $userIdTarget)) - { - $this->entityManagerInterface->remove($userStar); - $this->entityManagerInterface->flush(); - - return false; - } - - else - { - $userStar = new UserStar(); - - $userStar->setUserId($userId); - $userStar->setUserIdTarget($userIdTarget); - $userStar->setAdded($added); - - $this->entityManagerInterface->persist($userStar); - $this->entityManagerInterface->flush(); - - return true; - } - } - - public function toggleUserModerator( - int $userId - ): ?User - { - if ($user = $this->getUser($userId)) - { - $user->setModerator( - !$user->isModerator() - ); - - $this->entityManagerInterface->persist($user); - $this->entityManagerInterface->flush(); - } - - return $user; - } - - public function toggleUserStatus( - int $userId - ): ?User - { - if ($user = $this->getUser($userId)) - { - $user->setStatus( - !$user->isStatus() - ); - - $this->entityManagerInterface->persist($user); - $this->entityManagerInterface->flush(); - } - - return $user; - } - - public function toggleUserApproved( - int $userId - ): ?User - { - if ($user = $this->getUser($userId)) - { - $user->setApproved( - !$user->isApproved() - ); - - $this->entityManagerInterface->persist($user); - $this->entityManagerInterface->flush(); - } - - return $user; - } -} \ No newline at end of file diff --git a/src/Twig/AppExtension.php b/src/Twig/AppExtension.php deleted file mode 100644 index 440ca6c..0000000 --- a/src/Twig/AppExtension.php +++ /dev/null @@ -1,192 +0,0 @@ -container = $container; - $this->translator = $translator; - } - - public function getFilters() - { - return - [ - new TwigFilter( - 'format_bytes', - [ - $this, - 'formatBytes' - ] - ), - new TwigFilter( - 'format_ago', - [ - $this, - 'formatAgo' - ] - ), - new TwigFilter( - 'url_to_markdown', - [ - $this, - 'urlToMarkdown' - ] - ), - new TwigFilter( - 'trans_category', - [ - $this, - 'transCategory' - ] - ), - ]; - } - - public function formatBytes( - int $bytes, - int $precision = 2 - ): string - { - $size = [ - $this->translator->trans('B'), - $this->translator->trans('Kb'), - $this->translator->trans('Mb'), - $this->translator->trans('Gb'), - $this->translator->trans('Tb'), - $this->translator->trans('Pb'), - $this->translator->trans('Eb'), - $this->translator->trans('Zb'), - $this->translator->trans('Yb') - ]; - - $factor = floor((strlen($bytes) - 1) / 3); - - return sprintf("%.{$precision}f", $bytes / pow(1024, $factor)) . ' ' . @$size[$factor]; - } - - public function formatAgo( - int $time, - ): string - { - $diff = time() - $time; - - if ($diff < 1) - { - return $this->translator->trans('now'); - } - - $values = - [ - 365 * 24 * 60 * 60 => - [ - $this->translator->trans('year ago'), - $this->translator->trans('years ago'), - $this->translator->trans(' years ago') - ], - 30 * 24 * 60 * 60 => - [ - $this->translator->trans('month ago'), - $this->translator->trans('months ago'), - $this->translator->trans(' months ago') - ], - 24 * 60 * 60 => - [ - $this->translator->trans('day ago'), - $this->translator->trans('days ago'), - $this->translator->trans(' days ago') - ], - 60 * 60 => - [ - $this->translator->trans('hour ago'), - $this->translator->trans('hours ago'), - $this->translator->trans(' hours ago') - ], - 60 => - [ - $this->translator->trans('minute ago'), - $this->translator->trans('minutes ago'), - $this->translator->trans(' minutes ago') - ], - 1 => - [ - $this->translator->trans('second ago'), - $this->translator->trans('seconds ago'), - $this->translator->trans(' seconds ago') - ] - ]; - - foreach ($values as $key => $value) - { - $result = $diff / $key; - - if ($result >= 1) - { - $round = round($result); - - return sprintf( - '%s %s', - $round, - $this->plural( - $round, - $value - ) - ); - } - } - } - - public function urlToMarkdown( - string $text - ): string - { - return preg_replace( - '~(https?://(?:www\.)?[^\(\s\)]+)~i', - '[$1]($1)', - $text - ); - } - - public function transCategory( - string $name - ): string - { - switch ($name) - { - case 'movie': return $this->translator->trans('movie'); - case 'series': return $this->translator->trans('series'); - case 'tv': return $this->translator->trans('tv'); - case 'animation': return $this->translator->trans('animation'); - case 'music': return $this->translator->trans('music'); - case 'game': return $this->translator->trans('game'); - case 'audiobook': return $this->translator->trans('audiobook'); - case 'podcast': return $this->translator->trans('podcast'); - case 'book': return $this->translator->trans('book'); - case 'archive': return $this->translator->trans('archive'); - case 'picture': return $this->translator->trans('picture'); - case 'software': return $this->translator->trans('software'); - case 'other': return $this->translator->trans('other'); - default: return $name; - } - } - - private function plural(int $number, array $texts) - { - $cases = [2, 0, 1, 1, 1, 2]; - - return $texts[(($number % 100) > 4 && ($number % 100) < 20) ? 2 : $cases[min($number % 10, 5)]]; - } -} \ No newline at end of file diff --git a/src/config/bootstrap.php b/src/config/bootstrap.php new file mode 100644 index 0000000..906adf0 --- /dev/null +++ b/src/config/bootstrap.php @@ -0,0 +1,83 @@ + [], + 'time' => [ + 'ISO8601' => date('c'), + 'total' => microtime(true), + ], + 'http' => + [ + 'total' => 0, + ], + 'memory' => + [ + 'start' => memory_get_usage(), + 'total' => 0, + 'peaks' => 0 + ], +]; + +// Define public registry +$public = [ + 'user' => [], + 'magnet' => [], +]; + +// Begin export +try +{ + // Init API folder if not exists + @mkdir(__DIR__ . '/../public/api'); + + // Delete cached feeds + @unlink(__DIR__ . '/../public/api/manifest.json'); + + @unlink(__DIR__ . '/../public/api/users.json'); + @unlink(__DIR__ . '/../public/api/magnets.json'); + @unlink(__DIR__ . '/../public/api/magnetComments.json'); + @unlink(__DIR__ . '/../public/api/magnetDownloads.json'); + @unlink(__DIR__ . '/../public/api/magnetStars.json'); + @unlink(__DIR__ . '/../public/api/magnetViews.json'); + + if (API_EXPORT_ENABLED) + { + // Manifest + $manifest = + [ + 'updated' => time(), + + 'settings' => (object) + [ + 'YGGDRASIL_HOST_REGEX' => (string) YGGDRASIL_HOST_REGEX, + + 'NODE_RULE_SUBJECT' => (string) NODE_RULE_SUBJECT, + 'NODE_RULE_LANGUAGES' => (string) NODE_RULE_LANGUAGES, + + 'USER_DEFAULT_APPROVED' => (bool) USER_DEFAULT_APPROVED, + 'USER_AUTO_APPROVE_ON_MAGNET_APPROVE' => (bool) USER_AUTO_APPROVE_ON_MAGNET_APPROVE, + 'USER_AUTO_APPROVE_ON_COMMENT_APPROVE' => (bool) USER_AUTO_APPROVE_ON_COMMENT_APPROVE, + 'USER_DEFAULT_IDENTICON' => (string) USER_DEFAULT_IDENTICON, + 'USER_IDENTICON_FIELD' => (string) USER_IDENTICON_FIELD, + + 'MAGNET_DEFAULT_APPROVED' => (bool) MAGNET_DEFAULT_APPROVED, + 'MAGNET_DEFAULT_PUBLIC' => (bool) MAGNET_DEFAULT_PUBLIC, + 'MAGNET_DEFAULT_COMMENTS' => (bool) MAGNET_DEFAULT_COMMENTS, + 'MAGNET_DEFAULT_SENSITIVE' => (bool) MAGNET_DEFAULT_SENSITIVE, + + 'MAGNET_EDITOR_LOCK_TIMEOUT' => (int) MAGNET_EDITOR_LOCK_TIMEOUT, + + 'MAGNET_TITLE_MIN_LENGTH' => (int) MAGNET_TITLE_MIN_LENGTH, + 'MAGNET_TITLE_MAX_LENGTH' => (int) MAGNET_TITLE_MAX_LENGTH, + 'MAGNET_TITLE_REGEX' => (string) MAGNET_TITLE_REGEX, + + 'MAGNET_PREVIEW_MIN_LENGTH' => (int) MAGNET_PREVIEW_MIN_LENGTH, + 'MAGNET_PREVIEW_MAX_LENGTH' => (int) MAGNET_PREVIEW_MAX_LENGTH, + 'MAGNET_PREVIEW_REGEX' => (string) MAGNET_PREVIEW_REGEX, + + 'MAGNET_DESCRIPTION_MIN_LENGTH' => (int) MAGNET_DESCRIPTION_MIN_LENGTH, + 'MAGNET_DESCRIPTION_MAX_LENGTH' => (int) MAGNET_DESCRIPTION_MAX_LENGTH, + 'MAGNET_DESCRIPTION_REGEX' => (string) MAGNET_DESCRIPTION_REGEX, + + 'MAGNET_DN_MIN_LENGTH' => (int) MAGNET_DN_MIN_LENGTH, + 'MAGNET_DN_MAX_LENGTH' => (int) MAGNET_DN_MAX_LENGTH, + 'MAGNET_DN_REGEX' => (string) MAGNET_DN_REGEX, + + 'MAGNET_KT_MIN_LENGTH' => (int) MAGNET_KT_MIN_LENGTH, + 'MAGNET_KT_MAX_LENGTH' => (int) MAGNET_KT_MAX_LENGTH, + 'MAGNET_KT_MIN_QUANTITY' => (int) MAGNET_KT_MIN_QUANTITY, + 'MAGNET_KT_MAX_QUANTITY' => (int) MAGNET_KT_MAX_QUANTITY, + 'MAGNET_KT_REGEX' => (string) MAGNET_KT_REGEX, + + 'MAGNET_TR_MIN_QUANTITY' => (int) MAGNET_TR_MIN_QUANTITY, + 'MAGNET_TR_MAX_QUANTITY' => (int) MAGNET_TR_MAX_QUANTITY, + + 'MAGNET_AS_MIN_QUANTITY' => (int) MAGNET_AS_MIN_QUANTITY, + 'MAGNET_AS_MAX_QUANTITY' => (int) MAGNET_AS_MAX_QUANTITY, + + 'MAGNET_WS_MIN_QUANTITY' => (int) MAGNET_WS_MIN_QUANTITY, + 'MAGNET_WS_MAX_QUANTITY' => (int) MAGNET_WS_MAX_QUANTITY, + + 'MAGNET_COMMENT_DEFAULT_APPROVED' => (bool) MAGNET_COMMENT_DEFAULT_APPROVED, + 'MAGNET_COMMENT_DEFAULT_PUBLIC' => (bool) MAGNET_COMMENT_DEFAULT_PUBLIC, + 'MAGNET_COMMENT_DEFAULT_PUBLIC' => (bool) MAGNET_COMMENT_DEFAULT_PUBLIC, + 'MAGNET_COMMENT_MIN_LENGTH' => (int) MAGNET_COMMENT_MIN_LENGTH, + 'MAGNET_COMMENT_MAX_LENGTH' => (int) MAGNET_COMMENT_MAX_LENGTH, + + 'MAGNET_STOP_WORDS_SIMILAR' => (object) MAGNET_STOP_WORDS_SIMILAR, + + 'API_VERSION' => (string) API_VERSION, + 'API_USER_AGENT' => (string) API_USER_AGENT, + + 'API_EXPORT_ENABLED' => (bool) API_EXPORT_ENABLED, + 'API_EXPORT_PUSH_ENABLED' => (bool) API_EXPORT_PUSH_ENABLED, + 'API_EXPORT_USERS_ENABLED' => (bool) API_EXPORT_USERS_ENABLED, + 'API_EXPORT_MAGNETS_ENABLED' => (bool) API_EXPORT_MAGNETS_ENABLED, + 'API_EXPORT_MAGNET_DOWNLOADS_ENABLED' => (bool) API_EXPORT_MAGNET_DOWNLOADS_ENABLED, + 'API_EXPORT_MAGNET_COMMENTS_ENABLED' => (bool) API_EXPORT_MAGNET_COMMENTS_ENABLED, + 'API_EXPORT_MAGNET_STARS_ENABLED' => (bool) API_EXPORT_MAGNET_STARS_ENABLED, + 'API_EXPORT_MAGNET_STARS_ENABLED' => (bool) API_EXPORT_MAGNET_STARS_ENABLED, + 'API_EXPORT_MAGNET_VIEWS_ENABLED' => (bool) API_EXPORT_MAGNET_VIEWS_ENABLED, + + 'API_IMPORT_ENABLED' => (bool) API_IMPORT_ENABLED, + 'API_IMPORT_PUSH_ENABLED' => (bool) API_IMPORT_PUSH_ENABLED, + 'API_IMPORT_USERS_ENABLED' => (bool) API_IMPORT_USERS_ENABLED, + + 'API_IMPORT_USERS_APPROVED_ONLY' => (bool) API_IMPORT_USERS_APPROVED_ONLY, + 'API_IMPORT_MAGNETS_ENABLED' => (bool) API_IMPORT_MAGNETS_ENABLED, + 'API_IMPORT_MAGNETS_APPROVED_ONLY' => (bool) API_IMPORT_MAGNETS_APPROVED_ONLY, + 'API_IMPORT_MAGNET_DOWNLOADS_ENABLED' => (bool) API_IMPORT_MAGNET_DOWNLOADS_ENABLED, + 'API_IMPORT_MAGNET_COMMENTS_ENABLED' => (bool) API_IMPORT_MAGNET_COMMENTS_ENABLED, + 'API_IMPORT_MAGNET_COMMENTS_APPROVED_ONLY' => (bool) API_IMPORT_MAGNET_COMMENTS_APPROVED_ONLY, + 'API_IMPORT_MAGNET_STARS_ENABLED' => (bool) API_IMPORT_MAGNET_STARS_ENABLED, + 'API_IMPORT_MAGNET_VIEWS_ENABLED' => (bool) API_IMPORT_MAGNET_VIEWS_ENABLED, + ], + 'totals' => (object) + [ + 'magnets' => (object) + [ + 'total' => $db->getMagnetsTotal(), + 'distributed' => $db->getMagnetsTotalByUsersPublic(true), + 'local' => $db->getMagnetsTotalByUsersPublic(false), + ], + 'downloads' => (object) + [ + 'total' => $db->getMagnetDownloadsTotal(), + 'distributed' => $db->findMagnetDownloadsTotalByUsersPublic(true), + 'local' => $db->findMagnetDownloadsTotalByUsersPublic(false), + ], + 'comments' => (object) + [ + 'total' => $db->getMagnetCommentsTotal(), + 'distributed' => $db->findMagnetCommentsTotalByUsersPublic(true), + 'local' => $db->findMagnetCommentsTotalByUsersPublic(false), + ], + 'stars' => (object) + [ + 'total' => $db->getMagnetStarsTotal(), + 'distributed' => $db->findMagnetStarsTotalByUsersPublic(true), + 'local' => $db->findMagnetStarsTotalByUsersPublic(false), + ], + 'views' => (object) + [ + 'total' => $db->getMagnetViewsTotal(), + 'distributed' => $db->findMagnetViewsTotalByUsersPublic(true), + 'local' => $db->findMagnetViewsTotalByUsersPublic(false), + ], + ], + 'import' => (object) + [ + 'push' => API_IMPORT_PUSH_ENABLED ? sprintf('%s/api/push.php', WEBSITE_URL) : false, + ], + 'export' => (object) + [ + 'users' => API_EXPORT_USERS_ENABLED ? sprintf('%s/api/users.json', WEBSITE_URL) : false, + 'magnets' => API_EXPORT_MAGNETS_ENABLED ? sprintf('%s/api/magnets.json', WEBSITE_URL) : false, + 'magnetDownloads' => API_EXPORT_MAGNET_DOWNLOADS_ENABLED ? sprintf('%s/api/magnetDownloads.json', WEBSITE_URL) : false, + 'magnetComments' => API_EXPORT_MAGNET_COMMENTS_ENABLED ? sprintf('%s/api/magnetComments.json', WEBSITE_URL) : false, + 'magnetStars' => API_EXPORT_MAGNET_STARS_ENABLED ? sprintf('%s/api/magnetStars.json', WEBSITE_URL) : false, + 'magnetViews' => API_EXPORT_MAGNET_VIEWS_ENABLED ? sprintf('%s/api/magnetViews.json', WEBSITE_URL) : false, + ], + 'trackers' => (object) json_decode(file_get_contents(__DIR__ . '/../../config/trackers.json')), + 'nodes' => (object) json_decode(file_get_contents(__DIR__ . '/../../config/nodes.json')), + 'peers' => (object) json_decode(file_get_contents(__DIR__ . '/../../config/peers.json')), + ]; + + /// Dump feed + if ($handle = fopen(__DIR__ . '/../../public/api/manifest.json', 'w+')) + { + fwrite($handle, json_encode($manifest)); + fclose($handle); + + chmod(__DIR__ . '/../../public/api/manifest.json', 0774); + } + + // Users + if (API_EXPORT_USERS_ENABLED) + { + $users = []; + + foreach ($db->getUsers() as $user) + { + // Dump public data only + if ($user->public) + { + $users[] = (object) + [ + 'userId' => (int) $user->userId, + 'address' => (string) $user->address, + 'timeAdded' => (int) $user->timeAdded, + 'timeUpdated' => (int) $user->timeUpdated, + 'approved' => (bool) $user->approved, + 'magnets' => (int) $db->findMagnetsTotalByUserId($user->userId), + 'downloads' => (int) $db->findMagnetDownloadsTotalByUserId($user->userId), + 'comments' => (int) $db->findMagnetCommentsTotalByUserId($user->userId), + 'stars' => (int) $db->findMagnetStarsTotalByUserId($user->userId), + 'views' => (int) $db->findMagnetViewsTotalByUserId($user->userId), + ]; + } + + // Cache public status + $public['user'][$user->userId] = (bool) $user->public; + } + + /// Dump users feed + if ($handle = fopen(__DIR__ . '/../../public/api/users.json', 'w+')) + { + fwrite($handle, json_encode($users)); + fclose($handle); + + chmod(__DIR__ . '/../../public/api/users.json', 0774); + } + } + + // Magnets + if (API_EXPORT_MAGNETS_ENABLED) + { + $magnets = []; + + foreach ($db->getMagnets($user->userId) as $magnet) + { + // Dump public data only + if ($magnet->public && + $public['user'][$magnet->userId]) // After upgrade, some users have not updated their public status. + // Remote node have warning on import, because user info still hidden to init new profile there. + // Stop magnets export without public profile available, even magnet is public. + { + // Info Hash + $xt = []; + foreach ($db->findMagnetToInfoHashByMagnetId($magnet->magnetId) as $result) + { + if ($infoHash = $db->getInfoHash($result->infoHashId)) + { + $xt[] = (object) [ + 'version' => (float) $infoHash->version, + 'value' => (string) $infoHash->value, + ]; + } + } + + // Keyword Topic + $kt = []; + + foreach ($db->findKeywordTopicByMagnetId($magnet->magnetId) as $result) + { + $kt[] = $db->getKeywordTopic($result->keywordTopicId)->value; + } + + // Address Tracker + $tr = []; + foreach ($db->findAddressTrackerByMagnetId($magnet->magnetId) as $result) + { + $addressTracker = $db->getAddressTracker($result->addressTrackerId); + + $scheme = $db->getScheme($addressTracker->schemeId); + $host = $db->getHost($addressTracker->hostId); + $port = $db->getPort($addressTracker->portId); + $uri = $db->getUri($addressTracker->uriId); + + // Yggdrasil host only + if (!Valid::host($host->value)) + { + continue; + } + + $tr[] = $port->value ? sprintf('%s://%s:%s%s', $scheme->value, + $host->value, + $port->value, + $uri->value) : sprintf('%s://%s%s', $scheme->value, + $host->value, + $uri->value); + } + + // Acceptable Source + $as = []; + + foreach ($db->findAcceptableSourceByMagnetId($magnet->magnetId) as $result) + { + $acceptableSource = $db->getAcceptableSource($result->acceptableSourceId); + + $scheme = $db->getScheme($acceptableSource->schemeId); + $host = $db->getHost($acceptableSource->hostId); + $port = $db->getPort($acceptableSource->portId); + $uri = $db->getUri($acceptableSource->uriId); + + // Yggdrasil host only + if (!Valid::host($host->value)) + { + continue; + } + + $as[] = $port->value ? sprintf('%s://%s:%s%s', $scheme->value, + $host->value, + $port->value, + $uri->value) : sprintf('%s://%s%s', $scheme->value, + $host->value, + $uri->value); + } + + // Exact Source + $xs = []; + + foreach ($db->findExactSourceByMagnetId($magnet->magnetId) as $result) + { + $eXactSource = $db->getExactSource($result->eXactSourceId); + + $scheme = $db->getScheme($eXactSource->schemeId); + $host = $db->getHost($eXactSource->hostId); + $port = $db->getPort($eXactSource->portId); + $uri = $db->getUri($eXactSource->uriId); + + // Yggdrasil host only + if (!Valid::host($host->value)) + { + continue; + } + + $xs[] = $port->value ? sprintf('%s://%s:%s%s', $scheme->value, + $host->value, + $port->value, + $uri->value) : sprintf('%s://%s%s', $scheme->value, + $host->value, + $uri->value); + } + + $magnets[] = (object) + [ + 'magnetId' => (int) $magnet->magnetId, + 'userId' => (int) $magnet->userId, + 'title' => (string) $magnet->title, + 'preview' => (string) $magnet->preview, + 'description' => (string) $magnet->description, + 'comments' => (bool) $magnet->comments, + 'sensitive' => (bool) $magnet->sensitive, + 'approved' => (bool) $magnet->approved, + 'timeAdded' => (int) $magnet->timeAdded, + 'timeUpdated' => (int) $magnet->timeUpdated, + 'dn' => (string) $magnet->dn, + 'xl' => (float) $magnet->xl, + 'xt' => (object) $xt, + 'kt' => (object) $kt, + 'tr' => (object) $tr, + 'as' => (object) $as, + 'xs' => (object) $xs, + ]; + } + + // Cache public status + if (!empty($public['user'][$magnet->userId])) + { + $public['magnet'][$magnet->magnetId] = (bool) $magnet->public; + } else { + $public['magnet'][$magnet->magnetId] = false; + } + } + + /// Dump magnets feed + if ($handle = fopen(__DIR__ . '/../../public/api/magnets.json', 'w+')) + { + fwrite($handle, json_encode($magnets)); + fclose($handle); + + chmod(__DIR__ . '/../../public/api/magnets.json', 0774); + } + } + + // Magnet downloads + if (API_EXPORT_MAGNET_DOWNLOADS_ENABLED) + { + $magnetDownloads = []; + + foreach ($db->getMagnetDownloads() as $magnetDownload) + { + // Dump public data only + if (!empty($public['magnet'][$magnetDownload->magnetId]) && + !empty($public['user'][$magnetDownload->userId])) + { + $magnetDownloads[] = (object) + [ + 'magnetDownloadId' => (int) $magnetDownload->magnetDownloadId, + 'userId' => (int) $magnetDownload->userId, + 'magnetId' => (int) $magnetDownload->magnetId, + 'timeAdded' => (int) $magnetDownload->timeAdded, + ]; + } + } + + /// Dump feed + if ($handle = fopen(__DIR__ . '/../../public/api/magnetDownloads.json', 'w+')) + { + fwrite($handle, json_encode($magnetDownloads)); + fclose($handle); + + chmod(__DIR__ . '/../../public/api/magnetDownloads.json', 0774); + } + } + + // Magnet comments + if (API_EXPORT_MAGNET_COMMENTS_ENABLED) + { + $magnetComments = []; + + foreach ($db->getMagnetComments() as $magnetComment) + { + // Dump public data only + if (!empty($public['magnet'][$magnetComment->magnetId]) && + !empty($public['user'][$magnetComment->userId])) + { + $magnetComments[] = (object) + [ + 'magnetCommentId' => (int) $magnetComment->magnetCommentId, + 'magnetCommentIdParent' => $magnetComment->magnetCommentIdParent, + 'userId' => (int) $magnetComment->userId, + 'magnetId' => (int) $magnetComment->magnetId, + 'timeAdded' => (int) $magnetComment->timeAdded, + 'approved' => (bool) $magnetComment->approved, + 'value' => (string) $magnetComment->value + ]; + } + } + + /// Dump feed + if ($handle = fopen(__DIR__ . '/../../public/api/magnetComments.json', 'w+')) + { + fwrite($handle, json_encode($magnetComments)); + fclose($handle); + + chmod(__DIR__ . '/../../public/api/magnetComments.json', 0774); + } + } + + // Magnet stars + if (API_EXPORT_MAGNET_STARS_ENABLED) + { + $magnetStars = []; + + foreach ($db->getMagnetStars() as $magnetStar) + { + // Dump public data only + if (!empty($public['magnet'][$magnetStar->magnetId]) && + !empty($public['user'][$magnetStar->userId])) + { + $magnetStars[] = (object) + [ + 'magnetStarId' => (int) $magnetStar->magnetStarId, + 'userId' => (int) $magnetStar->userId, + 'magnetId' => (int) $magnetStar->magnetId, + 'value' => (bool) $magnetStar->value, + 'timeAdded' => (int) $magnetStar->timeAdded, + ]; + } + } + + /// Dump feed + if ($handle = fopen(__DIR__ . '/../../public/api/magnetStars.json', 'w+')) + { + fwrite($handle, json_encode($magnetStars)); + fclose($handle); + + chmod(__DIR__ . '/../../public/api/magnetStars.json', 0774); + } + } + + // Magnet views + if (API_EXPORT_MAGNET_VIEWS_ENABLED) + { + $magnetViews = []; + + foreach ($db->getMagnetViews() as $magnetView) + { + // Dump public data only + if (!empty($public['magnet'][$magnetView->magnetId]) && + !empty($public['user'][$magnetView->userId])) + { + $magnetViews[] = (object) + [ + 'magnetViewId' => (int) $magnetView->magnetViewId, + 'userId' => (int) $magnetView->userId, + 'magnetId' => (int) $magnetView->magnetId, + 'timeAdded' => (int) $magnetView->timeAdded, + ]; + } + } + + /// Dump feed + if ($handle = fopen(__DIR__ . '/../../public/api/magnetViews.json', 'w+')) + { + fwrite($handle, json_encode($magnetViews)); + fclose($handle); + + chmod(__DIR__ . '/../../public/api/magnetViews.json', 0774); + } + } + } + +} catch (EXception $e) { + + var_dump($e); +} + +// Debug output +$debug['time']['total'] = microtime(true) - $debug['time']['total']; + +$debug['memory']['total'] = memory_get_usage() - $debug['memory']['start']; +$debug['memory']['peaks'] = memory_get_peak_usage(); + +$debug['db']['total']['select'] = $db->getDebug()->query->select->total; +$debug['db']['total']['insert'] = $db->getDebug()->query->insert->total; +$debug['db']['total']['update'] = $db->getDebug()->query->update->total; +$debug['db']['total']['delete'] = $db->getDebug()->query->delete->total; + +print_r($debug); + +// Debug log +if (LOG_CRONTAB_EXPORT_FEED_ENABLED) +{ + @mkdir(LOG_DIRECTORY, 0774, true); + + if ($handle = fopen(LOG_DIRECTORY . '/' . LOG_CRONTAB_EXPORT_FEED_FILENAME, 'a+')) + { + fwrite($handle, print_r($debug, true)); + fclose($handle); + + chmod(LOG_DIRECTORY . '/' . LOG_CRONTAB_EXPORT_FEED_FILENAME, 0774); + } +} \ No newline at end of file diff --git a/src/crontab/export/push.php b/src/crontab/export/push.php new file mode 100644 index 0000000..18ae4e2 --- /dev/null +++ b/src/crontab/export/push.php @@ -0,0 +1,506 @@ + [], + 'time' => [ + 'ISO8601' => date('c'), + 'total' => microtime(true), + ], + 'http' => + [ + 'total' => 0, + ], + 'memory' => + [ + 'start' => memory_get_usage(), + 'total' => 0, + 'peaks' => 0 + ], +]; + +// Define public registry +$public = [ + 'user' => [], + 'magnet' => [], +]; + +// Push export enabled +if (API_EXPORT_PUSH_ENABLED) +{ + // Get push queue from memory pool + foreach((array) $memoryApiExportPush = $memory->get('api.export.push') as $id => $push) + { + // Init request + $request = []; + + // User request + if (!empty($push->userId) && API_EXPORT_USERS_ENABLED) + { + // Get user info + if ($user = $db->getUser($push->userId)) + { + // Dump public data only + if ($user->public) + { + $request['user'] = (object) + [ + 'userId' => (int) $user->userId, + 'address' => (string) $user->address, + 'timeAdded' => (int) $user->timeAdded, + 'timeUpdated' => (int) $user->timeUpdated, + 'approved' => (bool) $user->approved, + ]; + + // Cache public status + $public['user'][$user->userId] = (bool) $user->public; + } + } + } + + // Magnet request + if (!empty($push->magnetId) && API_EXPORT_MAGNETS_ENABLED) + { + // Get magnet info + if ($magnet = $db->getMagnet($push->magnetId)) + { + if ($magnet->public && + $public['user'][$magnet->userId]) // After upgrade, some users have not updated their public status. + // Remote node have warning on import, because user info still hidden to init new profile there. + // Stop magnets export without public profile available, even magnet is public. + { + // Info Hash + $xt = []; + foreach ($db->findMagnetToInfoHashByMagnetId($magnet->magnetId) as $result) + { + if ($infoHash = $db->getInfoHash($result->infoHashId)) + { + $xt[] = (object) [ + 'version' => (float) $infoHash->version, + 'value' => (string) $infoHash->value, + ]; + } + } + + // Keyword Topic + $kt = []; + + foreach ($db->findKeywordTopicByMagnetId($magnet->magnetId) as $result) + { + $kt[] = $db->getKeywordTopic($result->keywordTopicId)->value; + } + + // Address Tracker + $tr = []; + foreach ($db->findAddressTrackerByMagnetId($magnet->magnetId) as $result) + { + $addressTracker = $db->getAddressTracker($result->addressTrackerId); + + $scheme = $db->getScheme($addressTracker->schemeId); + $host = $db->getHost($addressTracker->hostId); + $port = $db->getPort($addressTracker->portId); + $uri = $db->getUri($addressTracker->uriId); + + // Yggdrasil host only + if (!Valid::host($host->value)) + { + continue; + } + + $tr[] = $port->value ? sprintf('%s://%s:%s%s', $scheme->value, + $host->value, + $port->value, + $uri->value) : sprintf('%s://%s%s', $scheme->value, + $host->value, + $uri->value); + } + + // Acceptable Source + $as = []; + + foreach ($db->findAcceptableSourceByMagnetId($magnet->magnetId) as $result) + { + $acceptableSource = $db->getAcceptableSource($result->acceptableSourceId); + + $scheme = $db->getScheme($acceptableSource->schemeId); + $host = $db->getHost($acceptableSource->hostId); + $port = $db->getPort($acceptableSource->portId); + $uri = $db->getUri($acceptableSource->uriId); + + // Yggdrasil host only + if (!Valid::host($host->value)) + { + continue; + } + + $as[] = $port->value ? sprintf('%s://%s:%s%s', $scheme->value, + $host->value, + $port->value, + $uri->value) : sprintf('%s://%s%s', $scheme->value, + $host->value, + $uri->value); + } + + // Exact Source + $xs = []; + + foreach ($db->findExactSourceByMagnetId($magnet->magnetId) as $result) + { + $eXactSource = $db->getExactSource($result->eXactSourceId); + + $scheme = $db->getScheme($eXactSource->schemeId); + $host = $db->getHost($eXactSource->hostId); + $port = $db->getPort($eXactSource->portId); + $uri = $db->getUri($eXactSource->uriId); + + // Yggdrasil host only + if (!Valid::host($host->value)) + { + continue; + } + + $xs[] = $port->value ? sprintf('%s://%s:%s%s', $scheme->value, + $host->value, + $port->value, + $uri->value) : sprintf('%s://%s%s', $scheme->value, + $host->value, + $uri->value); + } + + $request['magnet'] = (object) + [ + 'magnetId' => (int) $magnet->magnetId, + 'userId' => (int) $magnet->userId, + 'title' => (string) $magnet->title, + 'preview' => (string) $magnet->preview, + 'description' => (string) $magnet->description, + 'comments' => (bool) $magnet->comments, + 'sensitive' => (bool) $magnet->sensitive, + 'approved' => (bool) $magnet->approved, + 'timeAdded' => (int) $magnet->timeAdded, + 'timeUpdated' => (int) $magnet->timeUpdated, + 'dn' => (string) $magnet->dn, + 'xl' => (float) $magnet->xl, + 'xt' => (object) $xt, + 'kt' => (object) $kt, + 'tr' => (object) $tr, + 'as' => (object) $as, + 'xs' => (object) $xs, + ]; + } + + // Cache public status + if (!empty($public['user'][$magnet->userId])) + { + $public['magnet'][$magnet->magnetId] = (bool) $magnet->public; + } else { + $public['magnet'][$magnet->magnetId] = false; + } + } + } + + // Magnet download request + if (!empty($push->magnetDownloadId) && API_EXPORT_MAGNET_DOWNLOADS_ENABLED) + { + // Get magnet download info + if ($magnetDownload = $db->getMagnetDownload($push->magnetDownloadId)) + { + // Dump public data only + if (!empty($public['magnet'][$magnetDownload->magnetId]) && + !empty($public['user'][$magnetDownload->userId])) + { + $request['magnetDownload'] = (object) + [ + 'magnetDownloadId' => (int) $magnetDownload->magnetDownloadId, + 'userId' => (int) $magnetDownload->userId, + 'magnetId' => (int) $magnetDownload->magnetId, + 'timeAdded' => (int) $magnetDownload->timeAdded, + ]; + } + } + } + + // Magnet comment request + if (!empty($push->magnetCommentId) && API_EXPORT_MAGNET_COMMENTS_ENABLED) + { + // Get magnet comment info + if ($magnetComment = $db->getMagnetComment($push->magnetCommentId)) + { + // Dump public data only + if (!empty($public['magnet'][$magnetComment->magnetId]) && + !empty($public['user'][$magnetComment->userId])) + { + $request['magnetComment'] = (object) + [ + 'magnetCommentId' => (int) $magnetComment->magnetCommentId, + 'magnetCommentIdParent' => (int) $magnetComment->magnetCommentIdParent, + 'userId' => (int) $magnetComment->userId, + 'magnetId' => (int) $magnetComment->magnetId, + 'timeAdded' => (int) $magnetComment->timeAdded, + 'approved' => (bool) $magnetComment->approved, + 'value' => (string) $magnetComment->value + ]; + } + } + } + + // Magnet star request + if (!empty($push->magnetStarId) && API_EXPORT_MAGNET_STARS_ENABLED) + { + // Get magnet star info + if ($magnetStar = $db->getMagnetStar($push->magnetStarId)) + { + // Dump public data only + if (!empty($public['magnet'][$magnetStar->magnetId]) && + !empty($public['user'][$magnetStar->userId])) + { + $request['magnetStar'] = (object) + [ + 'magnetStarId' => (int) $magnetStar->magnetStarId, + 'userId' => (int) $magnetStar->userId, + 'magnetId' => (int) $magnetStar->magnetId, + 'value' => (bool) $magnetStar->value, + 'timeAdded' => (int) $magnetStar->timeAdded, + ]; + } + } + } + + // Magnet view request + if (!empty($push->magnetViewId) && API_EXPORT_MAGNET_VIEWS_ENABLED) + { + // Get magnet view info + if ($magnetView = $db->getMagnetView($push->magnetViewId)) + { + // Dump public data only + if (!empty($public['magnet'][$magnetView->magnetId]) && + !empty($public['user'][$magnetView->userId])) + { + $request['magnetView'] = (object) + [ + 'magnetViewId' => (int) $magnetView->magnetViewId, + 'userId' => (int) $magnetView->userId, + 'magnetId' => (int) $magnetView->magnetId, + 'timeAdded' => (int) $magnetView->timeAdded, + ]; + } + } + } + + // Check request + if (empty($request)) + { + // Amy request data match conditions, skip + + continue; + } + + // Send push data + foreach (json_decode( + file_get_contents(__DIR__ . '/../../config/nodes.json') + ) as $node) + { + // Manifest exists + if (empty($node->manifest)) + { + $debug['dump']['warning'][] = sprintf( + _('Manifest URL not provided: %s'), + $node + ); + + continue; + } + + // Skip non-condition addresses + $error = []; + + if (!Valid::url($node->manifest, $error)) + { + $debug['dump'][$node->manifest]['warning'][] = sprintf( + _('Manifest URL invalid: %s'), + print_r( + $error, + true + ) + ); + + continue; + } + + // Skip current host + $thisUrl = Yggverse\Parser\Url::parse(WEBSITE_URL); + $manifestUrl = Yggverse\Parser\Url::parse($node->manifest); + + if (empty($thisUrl->host->name) || + empty($manifestUrl->host->name) || + $manifestUrl->host->name == $thisUrl->host->name) // @TODO some mirrors could be available, improve condition + { + // No debug warnings in this case, continue next item + + continue; + } + + // Get node manifest + // @TODO cache to prevent extra-queries as usually this script running every minute + $curl = new Curl($node->manifest, API_USER_AGENT); + + $debug['http']['total']++; + + if (200 != $code = $curl->getCode()) + { + $debug['dump'][$node->manifest]['warning'][] = sprintf( + _('Manifest unreachable with code: "%s"'), + $code + ); + + continue; + } + + if (!$manifest = $curl->getResponse()) + { + $debug['dump'][$node->manifest]['warning'][] = sprintf( + _('Manifest URL "%s" has broken response'), + $node->manifest + ); + + continue; + } + + // API channel not exists + if (empty($manifest->import)) + { + $debug['dump'][$node->manifest]['warning'][] = sprintf( + _('Manifest import URL not provided: %s'), + $node + ); + + continue; + } + + // Push API channel not exists + if (empty($manifest->import->push)) + { + $debug['dump'][$manifest->import->push]['warning'][] = sprintf( + _('Manifest import push URL not provided: %s'), + $node + ); + + continue; + } + + // Skip sending to non-condition addresses + $error = []; + + if (!Valid::url($manifest->import->push, $error)) + { + $debug['dump'][$manifest->import->push]['warning'][] = sprintf( + _('Manifest import push URL invalid: %s'), + print_r( + $error, + true + ) + ); + + continue; + } + + // Skip current host + $thisUrl = Yggverse\Parser\Url::parse(WEBSITE_URL); + $pushUrl = Yggverse\Parser\Url::parse($manifest->import->push); + + if (empty($thisUrl->host->name) || + empty($pushUrl->host->name) || + $pushUrl->host->name == $thisUrl->host->name) // @TODO some mirrors could be available, improve condition + { + // No debug warnings in this case, continue next item + + continue; + } + + // @TODO add recipient manifest conditions check to not disturb it API without needs + + // Send push request + $debug['dump'][$manifest->import->push]['request'][] = $request; + + $curl = new Curl( + $manifest->import->push, + API_USER_AGENT, + [ + 'data' => json_encode($request) + ] + ); + + $debug['http']['total']++; + + if (200 != $code = $curl->getCode()) + { + $debug['dump'][$manifest->import->push]['warning'][] = sprintf( + _('Server returned code "%s"'), + $code + ); + + continue; + } + + if (!$response = $curl->getResponse()) + { + $debug['dump'][$manifest->import->push]['warning'][] = _('Could not receive server response'); + + continue; + } + + $debug['dump'][$manifest->import->push]['response'][] = $response; + } + + // Drop processed item from queue + unset($memoryApiExportPush[$id]); + } + + // Update memory pool + $memory->set('api.export.push', $memoryApiExportPush, 3600); +} + +// Export push disabled, free api.export.push pool +else +{ + $memory->delete('api.export.push'); +} + +// Debug output +$debug['time']['total'] = microtime(true) - $debug['time']['total']; + +$debug['memory']['total'] = memory_get_usage() - $debug['memory']['start']; +$debug['memory']['peaks'] = memory_get_peak_usage(); + +$debug['db']['total']['select'] = $db->getDebug()->query->select->total; +$debug['db']['total']['insert'] = $db->getDebug()->query->insert->total; +$debug['db']['total']['update'] = $db->getDebug()->query->update->total; +$debug['db']['total']['delete'] = $db->getDebug()->query->delete->total; + +print_r($debug); + +// Debug log +if (LOG_CRONTAB_EXPORT_PUSH_ENABLED) +{ + @mkdir(LOG_DIRECTORY, 0770, true); + + if ($handle = fopen(LOG_DIRECTORY . '/' . LOG_CRONTAB_EXPORT_PUSH_FILENAME, 'a+')) + { + fwrite($handle, print_r($debug, true)); + fclose($handle); + + chmod(LOG_DIRECTORY . '/' . LOG_CRONTAB_EXPORT_PUSH_FILENAME, 0770); + } +} \ No newline at end of file diff --git a/src/crontab/import/feed.php b/src/crontab/import/feed.php new file mode 100644 index 0000000..a1c657e --- /dev/null +++ b/src/crontab/import/feed.php @@ -0,0 +1,1180 @@ + [], + 'time' => + [ + 'ISO8601' => date('c'), + 'total' => microtime(true), + ], + 'http' => + [ + 'total' => 0, + ], + 'memory' => + [ + 'start' => memory_get_usage(), + 'total' => 0, + 'peaks' => 0 + ], + 'db' => + [ + 'total' => [ + 'select' => 0, + 'insert' => 0, + 'update' => 0, + 'delete' => 0, + ] + ], +]; + +// Begin import +try +{ + // Transaction begin + $db->beginTransaction(); + + foreach (json_decode( + file_get_contents(__DIR__ . '/../../config/nodes.json') + ) as $node) + { + // Manifest exists + if (empty($node->manifest)) + { + array_push( + $debug['dump'], + sprintf( + _('Manifest URL not provided for this node: %s'), + $node + ) + ); + + continue; + } + + // Skip non-condition addresses + $error = []; + + if (!Valid::url($node->manifest, $error)) + { + array_push( + $debug['dump'], + sprintf( + _('Manifest URL "%s" invalid: %s'), + $node->manifest, + print_r( + $error, + true + ) + ) + ); + + continue; + } + + // Skip current host + $thisUrl = Yggverse\Parser\Url::parse(WEBSITE_URL); + $manifestUrl = Yggverse\Parser\Url::parse($node->manifest); + + if (empty($thisUrl->host->name) || + empty($manifestUrl->host->name) || + $manifestUrl->host->name == $thisUrl->host->name) // @TODO some mirrors could be available, improve condition + { + // No debug warnings in this case, continue next item + + continue; + } + + // Get node manifest + $curl = new Curl($node->manifest, API_USER_AGENT); + + $debug['http']['total']++; + + if (200 != $code = $curl->getCode()) + { + array_push( + $debug['dump'], + sprintf( + _('Manifest URL "%s" unreachable with code: "%s"'), + $node->manifest, + $code + ) + ); + + continue; + } + + if (!$manifest = $curl->getResponse()) + { + array_push( + $debug['dump'], + sprintf( + _('Manifest URL "%s" has broken response'), + $node->manifest + ) + ); + + continue; + } + + if (empty($manifest->export)) + { + array_push( + $debug['dump'], + sprintf( + _('Manifest URL "%s" has broken protocol'), + $node->manifest + ) + ); + + continue; + } + + // Users + if (API_IMPORT_USERS_ENABLED) + { + $error = []; + + if (!Valid::url($manifest->export->users, $error)) + { + array_push( + $debug['dump'], + sprintf( + _('Users feed URL "%s" invalid: %s'), + $manifest->export->users, + print_r( + $error, + true + ) + ) + ); + + continue; + } + + // Call feed + $curl = new Curl($manifest->export->users, API_USER_AGENT); + + $debug['http']['total']++; + + if (200 != $code = $curl->getCode()) + { + array_push( + $debug['dump'], + sprintf( + _('Users feed URL "%s" unreachable with code: "%s"'), + $manifest->export->users, + $code + ) + ); + + continue; + } + + if (!$remoteUsers = $curl->getResponse()) + { + array_push( + $debug['dump'], + sprintf( + _('Users feed URL "%s" has broken response'), + $manifest->export->users + ) + ); + + continue; + } + + // Init alias registry for this host + $aliasUserId = []; + + foreach ((object) $remoteUsers as $remoteUser) + { + // Validate required fields + $error = []; + + if (!Valid::user($remoteUser, $error)) + { + array_push( + $debug['dump'], + sprintf( + _('Users feed URL "%s" has invalid protocol: "%s" error: "%s"'), + $manifest->export->users, + print_r( + $remoteUser, + true + ), + print_r( + $error, + true + ) + ) + ); + + continue; + } + + // Skip import on user approved required + if (API_IMPORT_USERS_APPROVED_ONLY && !$remoteUser->approved) + { + // No debug warnings in this case, continue next item + + continue; + } + + // Init session + else if (!$localUser = $db->getUser( + $db->initUserId( + $remoteUser->address, + USER_AUTO_APPROVE_ON_IMPORT_APPROVED ? $remoteUser->approved : USER_DEFAULT_APPROVED, + $remoteUser->timeAdded + ) + )) + { + array_push( + $debug['dump'], + sprintf( + _('Could not init user with address "%s" using feed URL "%s"'), + $remoteUser->address, + $manifest->export->users + ) + ); + + continue; + } + + // Update time added if newer + if ($localUser->timeAdded < $remoteUser->timeAdded) + { + $db->updateUserTimeAdded( + $localUser->userId, + $remoteUser->timeAdded + ); + } + + // Update user info if newer + if ($localUser->timeUpdated < $remoteUser->timeUpdated) + { + // Update time updated + $db->updateUserTimeUpdated( + $localUser->userId, + $remoteUser->timeUpdated + ); + + // Update approved for existing user + if (USER_AUTO_APPROVE_ON_IMPORT_APPROVED && $localUser->approved !== $remoteUser->approved && $remoteUser->approved) + { + $db->updateUserApproved( + $localUser->userId, + $remoteUser->approved, + $remoteUser->timeUpdated + ); + } + + // Set public as received remotely + if (!$localUser->public) + { + $db->updateUserPublic( + $localUser->userId, + true, + $remoteUser->timeUpdated + ); + } + } + + // Register userId alias + $aliasUserId[$remoteUser->userId] = $localUser->userId; + } + + // Magnets + if (API_IMPORT_MAGNETS_ENABLED) + { + $error = []; + + if (!Valid::url($manifest->export->magnets, $error)) + { + array_push( + $debug['dump'], + sprintf( + _('Magnets feed URL "%s" invalid: %s'), + $manifest->export->magnets, + print_r( + $error, + true + ) + ) + ); + + continue; + } + + // Call feed + $curl = new Curl($manifest->export->magnets, API_USER_AGENT); + + $debug['http']['total']++; + + if (200 != $code = $curl->getCode()) + { + array_push( + $debug['dump'], + sprintf( + _('Magnets feed URL "%s" unreachable with code: "%s"'), + $manifest->export->magnets, + $code + ) + ); + + continue; + } + + if (!$remoteMagnets = $curl->getResponse()) + { + array_push( + $debug['dump'], + sprintf( + _('Magnets feed URL "%s" has broken response'), + $manifest->export->magnets + ) + ); + + continue; + } + + // Init alias registry for this host + $aliasMagnetId = []; + + foreach ((object) $remoteMagnets as $remoteMagnet) + { + // Validate required fields by protocol + $error = []; + + if (!Valid::magnet($remoteMagnet, $error)) + { + array_push( + $debug['dump'], + sprintf( + _('Magnets feed URL "%s" has invalid protocol: "%s" error: "%s"'), + $manifest->export->magnets, + print_r( + $remoteMagnet, + true + ), + print_r( + $error, + true + ) + ) + ); + + continue; + } + + // Aliases check + if (!isset($aliasUserId[$remoteMagnet->userId])) + { + array_push( + $debug['dump'], + sprintf( + _('Local alias for remote userId "%s" not found in URL "%s" %s'), + $remoteMagnet->userId, + $manifest->export->magnets, + print_r( + $remoteMagnet, + true + ), + ) + ); + + continue; + } + + // Skip import on magnet approved required + if (API_IMPORT_MAGNETS_APPROVED_ONLY && !$remoteMagnet->approved) + { + // No debug warnings in this case, continue next item + + continue; + } + + // Add new magnet if not exist by timestamp added for this user + if (!$localMagnet = $db->findMagnet($aliasUserId[$remoteMagnet->userId], $remoteMagnet->timeAdded)) + { + $localMagnet = $db->getMagnet( + $db->addMagnet( + $aliasUserId[$remoteMagnet->userId], + $remoteMagnet->xl, + $remoteMagnet->dn, + '', // @TODO linkSource used for debug only, will be deleted later + true, + $remoteMagnet->comments, + $remoteMagnet->sensitive, + MAGNET_AUTO_APPROVE_ON_IMPORT_APPROVED ? $remoteMagnet->approved : MAGNET_DEFAULT_APPROVED, + $remoteMagnet->timeAdded + ) + ); + } + + // Update time added if newer + if ($localMagnet->timeAdded < $remoteMagnet->timeAdded) + { + $db->updateMagnetTimeAdded( + $localMagnet->magnetId, + $remoteMagnet->timeAdded + ); + } + + // Update info if remote newer + if ($localMagnet->timeUpdated < $remoteMagnet->timeUpdated) + { + // Magnet fields + $db->updateMagnetXl($localMagnet->magnetId, $remoteMagnet->xl, $remoteMagnet->timeUpdated); + $db->updateMagnetDn($localMagnet->magnetId, $remoteMagnet->dn, $remoteMagnet->timeUpdated); + $db->updateMagnetTitle($localMagnet->magnetId, $remoteMagnet->title, $remoteMagnet->timeUpdated); + $db->updateMagnetPreview($localMagnet->magnetId, $remoteMagnet->preview, $remoteMagnet->timeUpdated); + $db->updateMagnetDescription($localMagnet->magnetId, $remoteMagnet->description, $remoteMagnet->timeUpdated); + $db->updateMagnetComments($localMagnet->magnetId, $remoteMagnet->comments, $remoteMagnet->timeUpdated); + $db->updateMagnetSensitive($localMagnet->magnetId, $remoteMagnet->sensitive, $remoteMagnet->timeUpdated); + + if (MAGNET_AUTO_APPROVE_ON_IMPORT_APPROVED && $localMagnet->approved !== $remoteMagnet->approved && $remoteMagnet->approved) + { + $db->updateMagnetApproved($localMagnet->magnetId, $remoteMagnet->approved, $remoteMagnet->timeUpdated); + } + + // xt + foreach ((array) $remoteMagnet->xt as $xt) + { + switch ($xt->version) + { + case 1: + + $exist = false; + + foreach ($db->findMagnetToInfoHashByMagnetId($localMagnet->magnetId) as $result) + { + if ($infoHash = $db->getInfoHash($result->infoHashId)) + { + if ($infoHash->version == 1) + { + $exist = true; + } + } + } + + if (!$exist) + { + $db->addMagnetToInfoHash( + $localMagnet->magnetId, + $db->initInfoHashId( + $xt->value, 1 + ) + ); + } + + break; + + case 2: + + $exist = false; + + foreach ($db->findMagnetToInfoHashByMagnetId($localMagnet->magnetId) as $result) + { + if ($infoHash = $db->getInfoHash($result->infoHashId)) + { + if ($infoHash->version == 2) + { + $exist = true; + } + } + } + + if (!$exist) + { + $db->addMagnetToInfoHash( + $localMagnet->magnetId, + $db->initInfoHashId( + $xt->value, 2 + ) + ); + } + + break; + } + } + + // kt + $db->deleteMagnetToKeywordTopicByMagnetId($localMagnet->magnetId); + + foreach ($remoteMagnet->kt as $kt) + { + $db->initMagnetToKeywordTopicId( + $localMagnet->magnetId, + $db->initKeywordTopicId(trim(mb_strtolower($kt))) // @TODO + ); + } + + // tr + $db->deleteMagnetToAddressTrackerByMagnetId($localMagnet->magnetId); + + foreach ($remoteMagnet->tr as $tr) + { + if ($url = Yggverse\Parser\Url::parse($tr)) + { + $db->initMagnetToAddressTrackerId( + $localMagnet->magnetId, + $db->initAddressTrackerId( + $db->initSchemeId($url->host->scheme), + $db->initHostId($url->host->name), + $db->initPortId($url->host->port), + $db->initUriId($url->page->uri) + ) + ); + } + } + + // as + $db->deleteMagnetToAcceptableSourceByMagnetId($localMagnet->magnetId); + + foreach ($remoteMagnet->as as $as) + { + if ($url = Yggverse\Parser\Url::parse($as)) + { + $db->initMagnetToAcceptableSourceId( + $localMagnet->magnetId, + $db->initAcceptableSourceId( + $db->initSchemeId($url->host->scheme), + $db->initHostId($url->host->name), + $db->initPortId($url->host->port), + $db->initUriId($url->page->uri) + ) + ); + } + } + + // xs + $db->deleteMagnetToExactSourceByMagnetId($localMagnet->magnetId); + + foreach ($remoteMagnet->xs as $xs) + { + if ($url = Yggverse\Parser\Url::parse($xs)) + { + $db->initMagnetToExactSourceId( + $localMagnet->magnetId, + $db->initExactSourceId( + $db->initSchemeId($url->host->scheme), + $db->initHostId($url->host->name), + $db->initPortId($url->host->port), + $db->initUriId($url->page->uri) + ) + ); + } + } + } + + // Add magnet alias for this host + $aliasMagnetId[$remoteMagnet->magnetId] = $localMagnet->magnetId; + } + + // Magnet comments + if (API_IMPORT_MAGNET_COMMENTS_ENABLED) + { + $error = []; + + if (!Valid::url($manifest->export->magnetComments, $error)) + { + array_push( + $debug['dump'], + sprintf( + _('Magnet comments feed URL "%s" invalid: %s'), + $manifest->export->magnetComments, + print_r( + $error, + true + ) + ) + ); + + continue; + } + + // Call feed + $curl = new Curl($manifest->export->magnetComments, API_USER_AGENT); + + $debug['http']['total']++; + + if (200 != $code = $curl->getCode()) + { + array_push( + $debug['dump'], + sprintf( + _('Magnet comments feed URL "%s" unreachable with code: "%s"'), + $manifest->export->magnetComments, + $code + ) + ); + + continue; + } + + if (!$remoteMagnetComments = $curl->getResponse()) + { + array_push( + $debug['dump'], + sprintf( + _('Magnet comments feed URL "%s" has broken response'), + $manifest->export->magnetComments + ) + ); + + continue; + } + + foreach ((object) $remoteMagnetComments as $remoteMagnetComment) + { + // Validate + $error = []; + + if (!Valid::magnetComment($remoteMagnetComment, $error)) + { + array_push( + $debug['dump'], + sprintf( + _('Magnet comments feed URL "%s" has invalid protocol: "%s" error: "%s"'), + $manifest->export->magnetComments, + print_r( + $remoteMagnetComment, + true + ), + print_r( + $error, + true + ) + ) + ); + + continue; + } + + // Aliases check + if (!isset($aliasUserId[$remoteMagnetComment->userId])) + { + array_push( + $debug['dump'], + sprintf( + _('Local alias for remote userId "%s" not found in URL "%s" %s'), + $remoteMagnetComment->userId, + $manifest->export->magnetComments, + print_r( + $remoteMagnetComment, + true + ), + ) + ); + + continue; + } + + if (!isset($aliasMagnetId[$remoteMagnetComment->magnetId])) + { + array_push( + $debug['dump'], + sprintf( + _('Local alias for remote magnetId "%s" not found in URL "%s" %s'), + $remoteMagnetComment->magnetId, + $manifest->export->magnetComments, + print_r( + $remoteMagnetComment, + true + ), + ) + ); + + continue; + } + + // Skip import on magnet comment approved required + if (API_IMPORT_MAGNET_COMMENTS_APPROVED_ONLY && !$remoteMagnetComment->approved) + { + // No debug warnings in this case, continue next item + + continue; + } + + // Add new magnet comment if not exist by timestamp added for this user + if (!$db->findMagnetComment($aliasMagnetId[$remoteMagnetComment->magnetId], + $aliasUserId[$remoteMagnetComment->userId], + $remoteMagnetComment->timeAdded)) + { + // Parent comment provided + if (is_int($remoteMagnetComment->magnetCommentIdParent)) + { + $localMagnetCommentIdParent = null; // @TODO feature not in use yet + } + + else + { + $localMagnetCommentIdParent = null; + } + + $db->addMagnetComment( + $aliasMagnetId[$remoteMagnetComment->magnetId], + $aliasUserId[$remoteMagnetComment->userId], + $localMagnetCommentIdParent, + $remoteMagnetComment->value, + $remoteMagnetComment->approved, + true, + $remoteMagnetComment->timeAdded + ); + } + } + } + + // Magnet downloads + if (API_IMPORT_MAGNET_DOWNLOADS_ENABLED) + { + // Skip non-condition addresses + $error = []; + + if (!Valid::url($manifest->export->magnetDownloads, $error)) + { + array_push( + $debug['dump'], + sprintf( + _('Magnet downloads feed URL "%s" invalid: %s'), + $manifest->export->magnetDownloads, + print_r( + $error, + true + ) + ) + ); + + continue; + } + + // Call feed + $curl = new Curl($manifest->export->magnetDownloads, API_USER_AGENT); + + $debug['http']['total']++; + + if (200 != $code = $curl->getCode()) + { + array_push( + $debug['dump'], + sprintf( + _('Magnet downloads feed URL "%s" unreachable with code: "%s"'), + $manifest->export->magnetDownloads, + $code + ) + ); + + continue; + } + + if (!$remoteMagnetDownloads = $curl->getResponse()) + { + array_push( + $debug['dump'], + sprintf( + _('Magnet downloads feed URL "%s" has broken response'), + $manifest->export->magnetDownloads + ) + ); + + continue; + } + + foreach ((object) $remoteMagnetDownloads as $remoteMagnetDownload) + { + // Validate + $error = []; + + if (!Valid::magnetDownload($remoteMagnetDownload, $error)) + { + array_push( + $debug['dump'], + sprintf( + _('Magnet downloads feed URL "%s" has invalid protocol: "%s" error: "%s"'), + $manifest->export->magnetDownloads, + print_r( + $remoteMagnetDownload, + true + ), + print_r( + $error, + true + ) + ) + ); + + continue; + } + + // Aliases check + if (!isset($aliasUserId[$remoteMagnetDownload->userId])) + { + array_push( + $debug['dump'], + sprintf( + _('Local alias for remote userId "%s" not found in URL "%s" %s'), + $remoteMagnetDownload->userId, + $manifest->export->magnetDownloads, + print_r( + $remoteMagnetDownload, + true + ), + ) + ); + + continue; + } + + if (!isset($aliasMagnetId[$remoteMagnetDownload->magnetId])) + { + array_push( + $debug['dump'], + sprintf( + _('Local alias for remote magnetId "%s" not found in URL "%s" %s'), + $remoteMagnetDownload->magnetId, + $manifest->export->magnetDownloads, + print_r( + $remoteMagnetDownload, + true + ), + ) + ); + + continue; + } + + // Add new magnet download if not exist by timestamp added for this user + if (!$db->findMagnetDownload($aliasMagnetId[$remoteMagnetDownload->magnetId], + $aliasUserId[$remoteMagnetDownload->userId], + $remoteMagnetDownload->timeAdded)) + { + $db->addMagnetDownload( + $aliasMagnetId[$remoteMagnetDownload->magnetId], + $aliasUserId[$remoteMagnetDownload->userId], + $remoteMagnetDownload->timeAdded + ); + } + } + } + + // Magnet views + if (API_IMPORT_MAGNET_VIEWS_ENABLED) + { + $error = []; + + if (!Valid::url($manifest->export->magnetViews, $error)) + { + array_push( + $debug['dump'], + sprintf( + _('Magnet views feed URL "%s" invalid: %s'), + $manifest->export->magnetViews, + print_r( + $error, + true + ) + ) + ); + + continue; + } + + // Call feed + $curl = new Curl($manifest->export->magnetViews, API_USER_AGENT); + + $debug['http']['total']++; + + if (200 != $code = $curl->getCode()) + { + array_push( + $debug['dump'], + sprintf( + _('Magnet views feed URL "%s" unreachable with code: "%s"'), + $manifest->export->magnetViews, + $code + ) + ); + + continue; + } + + if (!$remoteMagnetViews = $curl->getResponse()) + { + array_push( + $debug['dump'], + sprintf( + _('Magnet views feed URL "%s" has broken response'), + $manifest->export->magnetViews + ) + ); + + continue; + } + + foreach ((object) $remoteMagnetViews as $remoteMagnetView) + { + // Validate + $error = []; + + if (!Valid::magnetView($remoteMagnetView, $error)) + { + array_push( + $debug['dump'], + sprintf( + _('Magnet views feed URL "%s" has invalid protocol: "%s" error: "%s"'), + $manifest->export->magnetViews, + print_r( + $remoteMagnetView, + true + ), + print_r( + $error, + true + ) + ) + ); + + continue; + } + + // Aliases check + if (!isset($aliasUserId[$remoteMagnetView->userId])) + { + array_push( + $debug['dump'], + sprintf( + _('Local alias for remote userId "%s" not found in URL "%s" %s'), + $remoteMagnetView->userId, + $manifest->export->magnetViews, + print_r( + $remoteMagnetView, + true + ), + ) + ); + + continue; + } + + if (!isset($aliasMagnetId[$remoteMagnetView->magnetId])) + { + array_push( + $debug['dump'], + sprintf( + _('Local alias for remote magnetId "%s" not found in URL "%s" %s'), + $remoteMagnetView->magnetId, + $manifest->export->magnetViews, + print_r( + $remoteMagnetView, + true + ), + ) + ); + + continue; + } + + // Add new magnet view if not exist by timestamp added for this user + if (!$db->findMagnetView($aliasMagnetId[$remoteMagnetView->magnetId], + $aliasUserId[$remoteMagnetView->userId], + $remoteMagnetView->timeAdded)) + { + $db->addMagnetView( + $aliasMagnetId[$remoteMagnetView->magnetId], + $aliasUserId[$remoteMagnetView->userId], + $remoteMagnetView->timeAdded + ); + } + } + } + + // Magnet stars + if (API_IMPORT_MAGNET_STARS_ENABLED) + { + $error = []; + + if (!Valid::url($manifest->export->magnetStars, $error)) + { + array_push( + $debug['dump'], + sprintf( + _('Magnet stars feed URL "%s" invalid: %s'), + $manifest->export->magnetStars, + print_r( + $error, + true + ) + ) + ); + + continue; + } + + // Call feed + $curl = new Curl($manifest->export->magnetStars, API_USER_AGENT); + + $debug['http']['total']++; + + if (200 != $code = $curl->getCode()) + { + array_push( + $debug['dump'], + sprintf( + _('Magnet stars feed URL "%s" unreachable with code: "%s"'), + $manifest->export->magnetStars, + $code + ) + ); + + continue; + } + + if (!$remoteMagnetStars = $curl->getResponse()) + { + array_push( + $debug['dump'], + sprintf( + _('Magnet stars feed URL "%s" has broken response'), + $manifest->export->magnetStars + ) + ); + + continue; + } + + foreach ((object) $remoteMagnetStars as $remoteMagnetStar) + { + // Validate + $error = []; + + if (!Valid::magnetStar($remoteMagnetStar, $error)) + { + array_push( + $debug['dump'], + sprintf( + _('Magnet stars feed URL "%s" has invalid protocol: "%s" error: "%s"'), + $manifest->export->magnetStars, + print_r( + $remoteMagnetStar, + true + ), + print_r( + $error, + true + ) + ) + ); + + continue; + } + + // Aliases check + if (!isset($aliasUserId[$remoteMagnetStar->userId])) + { + array_push( + $debug['dump'], + sprintf( + _('Local alias for remote userId "%s" not found in URL "%s" %s'), + $remoteMagnetStar->userId, + $manifest->export->magnetStars, + print_r( + $remoteMagnetStar, + true + ), + ) + ); + + continue; + } + + if (!isset($aliasMagnetId[$remoteMagnetStar->magnetId])) + { + array_push( + $debug['dump'], + sprintf( + _('Local alias for remote magnetId "%s" not found in URL "%s" %s'), + $remoteMagnetStar->magnetId, + $manifest->export->magnetStars, + print_r( + $remoteMagnetStar, + true + ), + ) + ); + + continue; + } + + // Add new magnet star if not exist by timestamp added for this user + if (!$db->findMagnetStar($aliasMagnetId[$remoteMagnetStar->magnetId], + $aliasUserId[$remoteMagnetStar->userId], + $remoteMagnetStar->timeAdded)) + { + $db->addMagnetStar( + $aliasMagnetId[$remoteMagnetStar->magnetId], + $aliasUserId[$remoteMagnetStar->userId], + $remoteMagnetStar->value, + $remoteMagnetStar->timeAdded + ); + } + } + } + } + } + } + + $db->commit(); + +} catch (EXception $e) { + + $db->rollBack(); + + var_dump($e); +} + +// Debug output +$debug['time']['total'] = microtime(true) - $debug['time']['total']; + +$debug['memory']['total'] = memory_get_usage() - $debug['memory']['start']; +$debug['memory']['peaks'] = memory_get_peak_usage(); + +$debug['db']['total']['select'] = $db->getDebug()->query->select->total; +$debug['db']['total']['insert'] = $db->getDebug()->query->insert->total; +$debug['db']['total']['update'] = $db->getDebug()->query->update->total; +$debug['db']['total']['delete'] = $db->getDebug()->query->delete->total; + +print_r($debug); + +// Debug log +if (LOG_CRONTAB_IMPORT_FEED_ENABLED) +{ + @mkdir(LOG_DIRECTORY, 0770, true); + + if ($handle = fopen(LOG_DIRECTORY . '/' . LOG_CRONTAB_IMPORT_FEED_FILENAME, 'a+')) + { + fwrite($handle, print_r($debug, true)); + fclose($handle); + + chmod(LOG_DIRECTORY . '/' . LOG_CRONTAB_IMPORT_FEED_FILENAME, 0770); + } +} \ No newline at end of file diff --git a/src/crontab/scrape.php b/src/crontab/scrape.php new file mode 100644 index 0000000..f974165 --- /dev/null +++ b/src/crontab/scrape.php @@ -0,0 +1,158 @@ + [ + 'ISO8601' => date('c'), + 'total' => microtime(true), + ], + 'http' => + [ + 'total' => 0, + ], + 'memory' => + [ + 'start' => memory_get_usage(), + 'total' => 0, + 'peaks' => 0 + ], +]; + +// Init Scraper +try { + + $scraper = new Scrapeer\Scraper(); + +} catch(Exception $e) { + + var_dump($e); + + exit; +} + +// Begin +try { + + $db->beginTransaction(); + + // Reset time offline by timeout + $db->resetMagnetToAddressTrackerTimeOfflineByTimeout( + CRAWLER_SCRAPE_TIME_OFFLINE_TIMEOUT + ); + + foreach ($db->getMagnetToAddressTrackerScrapeQueue(CRAWLER_SCRAPE_QUEUE_LIMIT) as $queue) + { + $hashes = []; + foreach ($db->findMagnetToInfoHashByMagnetId($queue->magnetId) as $result) + { + $hashes[] = $db->getInfoHash($result->infoHashId)->value; + } + + if ($addressTracker = $db->getAddressTracker($queue->addressTrackerId)) + { + // Build url + $scheme = $db->getScheme($addressTracker->schemeId); + $host = $db->getHost($addressTracker->hostId); + $port = $db->getPort($addressTracker->portId); + $uri = $db->getUri($addressTracker->uriId); + + $url = $port->value ? sprintf('%s://%s:%s%s', $scheme->value, + $host->value, + $port->value, + $uri->value) : sprintf('%s://%s%s', $scheme->value, + $host->value, + $uri->value); + + foreach ($hashes as $hash) + { + if ($scrape = $scraper->scrape([$hash], [$url], null, 1)) + { + $db->updateMagnetToAddressTrackerTimeOffline( + $queue->magnetToAddressTrackerId, + null + ); + + if (isset($scrape[$hash]['seeders'])) + { + $db->updateMagnetToAddressTrackerSeeders( + $queue->magnetToAddressTrackerId, + (int) $scrape[$hash]['seeders'], + time() + ); + } + + if (isset($scrape[$hash]['completed'])) + { + $db->updateMagnetToAddressTrackerCompleted( + $queue->magnetToAddressTrackerId, + (int) $scrape[$hash]['completed'], + time() + ); + } + + if (isset($scrape[$hash]['leechers'])) + { + $db->updateMagnetToAddressTrackerLeechers( + $queue->magnetToAddressTrackerId, + (int) $scrape[$hash]['leechers'], + time() + ); + } + } + else + { + $db->updateMagnetToAddressTrackerTimeOffline( + $queue->magnetToAddressTrackerId, + time() + ); + } + } + } + } + + $db->commit(); + +} catch (EXception $e) { + + $db->rollback(); + + var_dump($e); +} + +// Debug output +$debug['time']['total'] = microtime(true) - $debug['time']['total']; + +$debug['memory']['total'] = memory_get_usage() - $debug['memory']['start']; +$debug['memory']['peaks'] = memory_get_peak_usage(); + +$debug['db']['total']['select'] = $db->getDebug()->query->select->total; +$debug['db']['total']['insert'] = $db->getDebug()->query->insert->total; +$debug['db']['total']['update'] = $db->getDebug()->query->update->total; +$debug['db']['total']['delete'] = $db->getDebug()->query->delete->total; + +print_r($debug); + +// Debug log +if (LOG_CRONTAB_SCRAPE_ENABLED) +{ + @mkdir(LOG_DIRECTORY, 0774, true); + + if ($handle = fopen(LOG_DIRECTORY . '/' . LOG_CRONTAB_SCRAPE_FILENAME, 'a+')) + { + fwrite($handle, print_r($debug, true)); + fclose($handle); + + chmod(LOG_DIRECTORY . '/' . LOG_CRONTAB_SCRAPE_FILENAME, 0774); + } +} \ No newline at end of file diff --git a/src/crontab/sitemap.php b/src/crontab/sitemap.php new file mode 100644 index 0000000..1c65e87 --- /dev/null +++ b/src/crontab/sitemap.php @@ -0,0 +1,86 @@ + [ + 'ISO8601' => date('c'), + 'total' => microtime(true), + ], + 'http' => + [ + 'total' => 0, + ], + 'memory' => + [ + 'start' => memory_get_usage(), + 'total' => 0, + 'peaks' => 0 + ], +]; + +// Begin +try { + + // Delete cache + @unlink(__DIR__ . '/../public/sitemap.xml'); + + if ($handle = fopen(__DIR__ . '/../public/sitemap.xml', 'w+')) + { + + fwrite($handle, ''); + fwrite($handle, ''); + + foreach ($db->getMagnets() as $magnet) + { + if ($magnet->public && $magnet->approved) + { + fwrite($handle, sprintf('%s/magnet.php?magnetId=%s', WEBSITE_URL, $magnet->magnetId)); + } + } + + fwrite($handle, ''); + fclose($handle); + } + +} catch (EXception $e) { + + var_dump($e); +} + +// Debug output +$debug['time']['total'] = microtime(true) - $debug['time']['total']; + +$debug['memory']['total'] = memory_get_usage() - $debug['memory']['start']; +$debug['memory']['peaks'] = memory_get_peak_usage(); + +$debug['db']['total']['select'] = $db->getDebug()->query->select->total; +$debug['db']['total']['insert'] = $db->getDebug()->query->insert->total; +$debug['db']['total']['update'] = $db->getDebug()->query->update->total; +$debug['db']['total']['delete'] = $db->getDebug()->query->delete->total; + +print_r($debug); + +// Debug log +if (LOG_CRONTAB_SITEMAP_ENABLED) +{ + @mkdir(LOG_DIRECTORY, 0774, true); + + if ($handle = fopen(LOG_DIRECTORY . '/' . LOG_CRONTAB_SITEMAP_FILENAME, 'a+')) + { + fwrite($handle, print_r($debug, true)); + fclose($handle); + + chmod(LOG_DIRECTORY . '/' . LOG_CRONTAB_SITEMAP_FILENAME, 0774); + } +} \ No newline at end of file diff --git a/src/library/curl.php b/src/library/curl.php new file mode 100644 index 0000000..24c4021 --- /dev/null +++ b/src/library/curl.php @@ -0,0 +1,97 @@ +_connection = curl_init($url); + + if ($userAgent) + { + curl_setopt($this->_connection, CURLOPT_USERAGENT, $userAgent); + } + + if (!empty($post)) + { + curl_setopt($this->_connection, CURLOPT_POST, true); + curl_setopt($this->_connection, CURLOPT_POSTFIELDS, http_build_query($post)); + } + + if ($header) { + curl_setopt($this->_connection, CURLOPT_HEADER, true); + } + + if ($followLocation) { + curl_setopt($this->_connection, CURLOPT_FOLLOWLOCATION, true); + curl_setopt($this->_connection, CURLOPT_MAXREDIRS, $maxRedirects); + } + + curl_setopt($this->_connection, CURLOPT_FRESH_CONNECT, true); + curl_setopt($this->_connection, CURLOPT_RETURNTRANSFER, true); + curl_setopt($this->_connection, CURLOPT_CONNECTTIMEOUT, $connectTimeout); + curl_setopt($this->_connection, CURLOPT_TIMEOUT, $connectTimeout); + curl_setopt($this->_connection, CURLOPT_SSL_VERIFYHOST, $sslVerifyHost); + curl_setopt($this->_connection, CURLOPT_SSL_VERIFYPEER, $sslVerifyPeer); + + $this->_response = curl_exec($this->_connection); + } + + public function __destruct() + { + curl_close($this->_connection); + } + + public function getError() + { + if (curl_errno($this->_connection)) + { + return curl_errno($this->_connection); + } + + else + { + return false; + } + } + + public function getCode() + { + return curl_getinfo($this->_connection, CURLINFO_HTTP_CODE); + } + + public function getContentType() + { + return curl_getinfo($this->_connection, CURLINFO_CONTENT_TYPE); + } + + public function getSizeDownload() + { + return curl_getinfo($this->_connection, CURLINFO_SIZE_DOWNLOAD); + } + + public function getSizeRequest() + { + return curl_getinfo($this->_connection, CURLINFO_REQUEST_SIZE); + } + + public function getTotalTime() + { + return curl_getinfo($this->_connection, CURLINFO_TOTAL_TIME_T); + } + + public function getResponse(bool $json = true) + { + return $json ? json_decode($this->_response) : $this->_response; + } +} \ No newline at end of file diff --git a/src/library/database.php b/src/library/database.php new file mode 100644 index 0000000..ccb6c0e --- /dev/null +++ b/src/library/database.php @@ -0,0 +1,1708 @@ +_db = new PDO('mysql:dbname=' . $database . ';host=' . $host . ';port=' . $port . ';charset=utf8', $username, $password, [PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES utf8']); + $this->_db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); + $this->_db->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_OBJ); + $this->_db->setAttribute(PDO::ATTR_TIMEOUT, 600); + + $this->_debug = (object) + [ + 'query' => (object) + [ + 'select' => (object) + [ + 'total' => 0 + ], + 'insert' => (object) + [ + 'total' => 0 + ], + 'update' => (object) + [ + 'total' => 0 + ], + 'delete' => (object) + [ + 'total' => 0 + ], + ] + ]; + } + + // Tools + public function beginTransaction() { + + $this->_db->beginTransaction(); + } + + public function commit() { + + $this->_db->commit(); + } + + public function rollBack() { + + $this->_db->rollBack(); + } + + public function getDebug() { + + return $this->_debug; + } + + // Scheme + public function addScheme(string $value) : int { + + $this->_debug->query->insert->total++; + + $query = $this->_db->prepare('INSERT INTO `scheme` SET `value` = ?'); + + $query->execute([$value]); + + return $this->_db->lastInsertId(); + } + + public function getScheme(int $schemeId) { + + $this->_debug->query->select->total++; + + $query = $this->_db->prepare('SELECT * FROM `scheme` WHERE `schemeId` = ?'); + + $query->execute([$schemeId]); + + return $query->fetch(); + } + + public function findScheme(string $value) { + + $this->_debug->query->select->total++; + + $query = $this->_db->prepare('SELECT * FROM `scheme` WHERE `value` = ?'); + + $query->execute([$value]); + + return $query->fetch(); + } + + public function initSchemeId(string $value) : int { + + if ($result = $this->findScheme($value)) { + + return $result->schemeId; + } + + return $this->addScheme($value); + } + + // Host + public function addHost(string $value) : int { + + $this->_debug->query->insert->total++; + + $query = $this->_db->prepare('INSERT INTO `host` SET `value` = ?'); + + $query->execute([$value]); + + return $this->_db->lastInsertId(); + } + + public function getHost(int $hostId) { + + $this->_debug->query->select->total++; + + $query = $this->_db->prepare('SELECT * FROM `host` WHERE `hostId` = ?'); + + $query->execute([$hostId]); + + return $query->fetch(); + } + + public function findHost(string $value) { + + $this->_debug->query->select->total++; + + $query = $this->_db->prepare('SELECT * FROM `host` WHERE `value` = ?'); + + $query->execute([$value]); + + return $query->fetch(); + } + + public function initHostId(string $value) : int { + + if ($result = $this->findHost($value)) { + + return $result->hostId; + } + + return $this->addHost($value); + } + + // Port + public function addPort(mixed $value) : int { + + $this->_debug->query->insert->total++; + + $query = $this->_db->prepare('INSERT INTO `port` SET `value` = ?'); + + $query->execute([$value]); + + return $this->_db->lastInsertId(); + } + + public function getPort(int $portId) { + + $this->_debug->query->select->total++; + + $query = $this->_db->prepare('SELECT * FROM `port` WHERE `portId` = ?'); + + $query->execute([$portId]); + + return $query->fetch(); + } + + public function findPort(mixed $value) { + + $this->_debug->query->select->total++; + + if ($value) { + + $query = $this->_db->prepare('SELECT * FROM `port` WHERE `value` = ?'); + + $query->execute([$value]); + + } else { + + $query = $this->_db->query('SELECT * FROM `port` WHERE `value` IS NULL'); + } + + return $query->fetch(); + } + + public function initPortId(mixed $value) : int { + + if ($result = $this->findPort($value)) { + + return $result->portId; + } + + return $this->addPort($value); + } + + // URI + public function addUri(mixed $value) : int { + + $this->_debug->query->insert->total++; + + $query = $this->_db->prepare('INSERT INTO `uri` SET `value` = ?'); + + $query->execute([$value]); + + return $this->_db->lastInsertId(); + } + + public function getUri(int $uriId) { + + $this->_debug->query->select->total++; + + $query = $this->_db->prepare('SELECT * FROM `uri` WHERE `uriId` = ?'); + + $query->execute([$uriId]); + + return $query->fetch(); + } + + public function findUri(mixed $value) { + + $this->_debug->query->select->total++; + + if ($value) { + + $query = $this->_db->prepare('SELECT * FROM `uri` WHERE `value` = ?'); + + $query->execute([$value]); + + } else { + + $query = $this->_db->query('SELECT * FROM `uri` WHERE `value` IS NULL'); + } + + return $query->fetch(); + } + + public function initUriId(mixed $value) : int { + + if ($result = $this->findUri($value)) { + + return $result->uriId; + } + + return $this->addUri($value); + } + + // Info Hash + public function addInfoHash(mixed $value, int $version) : int { + + $this->_debug->query->insert->total++; + + $query = $this->_db->prepare('INSERT INTO `infoHash` SET `value` = ?, `version` = ?'); + + $query->execute([$value, $version]); + + return $this->_db->lastInsertId(); + } + + public function getInfoHash(int $infoHashId) { + + $this->_debug->query->select->total++; + + $query = $this->_db->prepare('SELECT * FROM `infoHash` WHERE `infoHashId` = ?'); + + $query->execute([$infoHashId]); + + return $query->fetch(); + } + + public function findInfoHash(string $value, int $version) { + + $this->_debug->query->select->total++; + + $query = $this->_db->prepare('SELECT * FROM `infoHash` WHERE `value` = ? AND `version` = ?'); + + $query->execute([$value, $version]); + + return $query->fetch(); + } + + public function initInfoHashId(mixed $value, int $version) : int { + + if ($result = $this->findInfoHash($value, $version)) { + + return $result->infoHashId; + } + + return $this->addInfoHash($value, $version); + } + + // Address Tracker + public function addAddressTracker(int $schemeId, int $hostId, mixed $portId, mixed $uriId) : int { + + $this->_debug->query->insert->total++; + + $query = $this->_db->prepare('INSERT INTO `addressTracker` SET `schemeId` = ?, `hostId` = ?, `portId` = ?, `uriId` = ?'); + + $query->execute([$schemeId, $hostId, $portId, $uriId]); + + return $this->_db->lastInsertId(); + } + + public function getAddressTracker(int $addressTrackerId) { + + $this->_debug->query->select->total++; + + $query = $this->_db->prepare('SELECT * FROM `addressTracker` WHERE `addressTrackerId` = ?'); + + $query->execute([$addressTrackerId]); + + return $query->fetch(); + } + + public function findAddressTracker(int $schemeId, int $hostId, mixed $portId, mixed $uriId) { + + $this->_debug->query->select->total++; + + $query = $this->_db->query('SELECT * FROM `addressTracker` WHERE `schemeId` = ' . (int) $schemeId . ' + AND `hostId` = ' . (int) $hostId . ' + AND `portId` ' . ($portId ? ' = ' . (int) $portId : ' IS NULL ') . ' + AND `uriId` ' . ($uriId ? ' = ' . (int) $uriId : ' IS NULL ')); + + return $query->fetch(); + } + + public function initAddressTrackerId(int $schemeId, int $hostId, mixed $portId, mixed $uriId) : int { + + if ($result = $this->findAddressTracker($schemeId, $hostId, $portId, $uriId)) { + + return $result->addressTrackerId; + } + + return $this->addAddressTracker($schemeId, $hostId, $portId, $uriId); + } + + // Acceptable Source + public function addAcceptableSource(int $schemeId, int $hostId, mixed $portId, mixed $uriId) : int { + + $this->_debug->query->insert->total++; + + $query = $this->_db->prepare('INSERT INTO `acceptableSource` SET `schemeId` = ?, `hostId` = ?, `portId` = ?, `uriId` = ?'); + + $query->execute([$schemeId, $hostId, $portId, $uriId]); + + return $this->_db->lastInsertId(); + } + + public function getAcceptableSource(int $acceptableSourceId) { + + $this->_debug->query->select->total++; + + $query = $this->_db->prepare('SELECT * FROM `acceptableSource` WHERE `acceptableSourceId` = ?'); + + $query->execute([$acceptableSourceId]); + + return $query->fetch(); + } + + public function findAcceptableSource(int $schemeId, int $hostId, mixed $portId, mixed $uriId) { + + $this->_debug->query->select->total++; + + $query = $this->_db->query('SELECT * FROM `acceptableSource` WHERE `schemeId` = ' . (int) $schemeId . ' + AND `hostId` = ' . (int) $hostId . ' + AND `portId` ' . ($portId ? ' = ' . (int) $portId : ' IS NULL ') . ' + AND `uriId` ' . ($uriId ? ' = ' . (int) $uriId : ' IS NULL ')); + + return $query->fetch(); + } + + public function initAcceptableSourceId(int $schemeId, int $hostId, mixed $portId, mixed $uriId) : int { + + if ($result = $this->findAcceptableSource($schemeId, $hostId, $portId, $uriId)) { + + return $result->acceptableSourceId; + } + + return $this->addAcceptableSource($schemeId, $hostId, $portId, $uriId); + } + + // eXact Source + public function addExactSource(int $schemeId, int $hostId, mixed $portId, mixed $uriId) : int { + + $this->_debug->query->insert->total++; + + $query = $this->_db->prepare('INSERT INTO `eXactSource` SET `schemeId` = ?, `hostId` = ?, `portId` = ?, `uriId` = ?'); + + $query->execute([$schemeId, $hostId, $portId, $uriId]); + + return $this->_db->lastInsertId(); + } + + public function getExactSource(int $eXactSourceId) { + + $this->_debug->query->select->total++; + + $query = $this->_db->prepare('SELECT * FROM `eXactSource` WHERE `eXactSourceId` = ?'); + + $query->execute([$eXactSourceId]); + + return $query->fetch(); + } + + public function findExactSource(int $schemeId, int $hostId, mixed $portId, mixed $uriId) { + + $this->_debug->query->select->total++; + + $query = $this->_db->query('SELECT * FROM `eXactSource` WHERE `schemeId` = ' . (int) $schemeId . ' + AND `hostId` = ' . (int) $hostId . ' + AND `portId` ' . ($portId ? ' = ' . (int) $portId : ' IS NULL ') . ' + AND `uriId` ' . ($uriId ? ' = ' . (int) $uriId : ' IS NULL ')); + + return $query->fetch(); + } + + public function initExactSourceId(int $schemeId, int $hostId, mixed $portId, mixed $uriId) : int { + + if ($result = $this->findExactSource($schemeId, $hostId, $portId, $uriId)) { + + return $result->eXactSourceId; + } + + return $this->addExactSource($schemeId, $hostId, $portId, $uriId); + } + + // Keyword Topic + public function addKeywordTopic(string $value) : int { + + $this->_debug->query->insert->total++; + + $query = $this->_db->prepare('INSERT INTO `keywordTopic` SET `value` = ?'); + + $query->execute([$value]); + + return $this->_db->lastInsertId(); + } + + public function findKeywordTopic(string $value) { + + $this->_debug->query->select->total++; + + $query = $this->_db->prepare('SELECT * FROM `keywordTopic` WHERE `value` = ?'); + + $query->execute([$value]); + + return $query->fetch(); + } + + public function getKeywordTopic(int $keywordTopicId) { + + $this->_debug->query->select->total++; + + $query = $this->_db->prepare('SELECT * FROM `keywordTopic` WHERE `keywordTopicId` = ?'); + + $query->execute([$keywordTopicId]); + + return $query->fetch(); + } + + public function initKeywordTopicId(string $value) : int { + + if ($result = $this->findKeywordTopic($value)) { + + return $result->keywordTopicId; + } + + return $this->addKeywordTopic($value); + } + + // User + public function addUser(string $address, bool $approved, $timeAdded) : int { + + $this->_debug->query->insert->total++; + + $query = $this->_db->prepare('INSERT INTO `user` SET `address` = ?, `approved` = ?, `timeAdded` = ?'); + + $query->execute([$address, (int) $approved, $timeAdded]); + + return $this->_db->lastInsertId(); + } + + public function getUser(int $userId) { + + $this->_debug->query->select->total++; + + $query = $this->_db->prepare('SELECT * FROM `user` WHERE `userId` = ?'); + + $query->execute([$userId]); + + return $query->fetch(); + } + + public function getUsers() { + + $this->_debug->query->select->total++; + + $query = $this->_db->query('SELECT * FROM `user`'); + + return $query->fetchAll(); + } + + public function getUsersTotal() : int { + + $this->_debug->query->select->total++; + + $query = $this->_db->prepare('SELECT COUNT(*) AS `result` FROM `user`'); + + $query->execute(); + + return $query->fetch()->result; + } + + public function getUsersTotalByPublic(mixed $public) : int { + + $this->_debug->query->select->total++; + + if (is_null($public)) + { + $query = $this->_db->prepare('SELECT COUNT(*) AS `result` FROM `user` WHERE `public` IS NULL'); + $query->execute(); + } + else + { + $query = $this->_db->prepare('SELECT COUNT(*) AS `result` FROM `user` WHERE `public` = ?'); + $query->execute([(int) $public]); + } + + return $query->fetch()->result; + } + + public function findUserByAddress(string $address) { + + $this->_debug->query->select->total++; + + $query = $this->_db->prepare('SELECT * FROM `user` WHERE `address` = ?'); + + $query->execute([$address]); + + return $query->fetch(); + } + + public function initUserId(string $address, bool $approved, int $timeAdded) : int { + + if ($result = $this->findUserByAddress($address)) { + + return $result->userId; + } + + return $this->addUser($address, $approved, $timeAdded); + } + + public function updateUserApproved(int $userId, mixed $approved, int $timeUpdated) : int { + + $this->_debug->query->update->total++; + + $query = $this->_db->prepare('UPDATE `user` SET `approved` = ?, `timeUpdated` = ? WHERE `userId` = ?'); + + $query->execute([(int) $approved, $timeUpdated, $userId]); + + return $query->rowCount(); + } + + public function updateUserPublic(int $userId, bool $public, int $timeUpdated) : int { + + $this->_debug->query->update->total++; + + $query = $this->_db->prepare('UPDATE `user` SET `public` = ?, `timeUpdated` = ? WHERE `userId` = ?'); + + $query->execute([(int) $public, $timeUpdated, $userId]); + + return $query->rowCount(); + } + + public function updateUserTimeAdded(int $userId, int $timeAdded) : int { + + $this->_debug->query->update->total++; + + $query = $this->_db->prepare('UPDATE `user` SET `timeAdded` = ? WHERE `userId` = ?'); + + $query->execute([$timeAdded, $userId]); + + return $query->rowCount(); + } + + public function updateUserTimeUpdated(int $userId, int $timeUpdated) : int { + + $this->_debug->query->update->total++; + + $query = $this->_db->prepare('UPDATE `user` SET `timeUpdated` = ? WHERE `userId` = ?'); + + $query->execute([$timeUpdated, $userId]); + + return $query->rowCount(); + } + + // Magnet + public function addMagnet(int $userId, + int $xl, + string $dn, + string $linkSource, + bool $public, + bool $comments, + bool $sensitive, + bool $approved, + int $timeAdded, + mixed $timeUpdated = null) : int { + + $this->_debug->query->insert->total++; + + $query = $this->_db->prepare('INSERT INTO `magnet` SET `userId` = ?, + `xl` = ?, + `dn` = ?, + `linkSource` = ?, + `public` = ?, + `comments` = ?, + `sensitive` = ?, + `approved` = ?, + `timeAdded` = ?, + `timeUpdated` = ?'); + + $query->execute( + [ + $userId, + $xl, + $dn, + $linkSource, + $public ? 1 : 0, + $comments ? 1 : 0, + $sensitive ? 1 : 0, + $approved ? 1 : 0, + $timeAdded, + $timeUpdated + ] + ); + + return $this->_db->lastInsertId(); + } + + public function getMagnet(int $magnetId) { + + $this->_debug->query->select->total++; + + $query = $this->_db->prepare('SELECT * FROM `magnet` WHERE `magnetId` = ?'); + + $query->execute([$magnetId]); + + return $query->fetch(); + } + + public function getMagnets() { + + $this->_debug->query->select->total++; + + $query = $this->_db->prepare('SELECT * FROM `magnet`'); + + $query->execute(); + + return $query->fetchAll(); + } + + public function getMagnetsTotal() : int { + + $this->_debug->query->select->total++; + + $query = $this->_db->prepare('SELECT COUNT(*) AS `result` FROM `magnet`'); + + $query->execute(); + + return $query->fetch()->result; + } + + public function findMagnet(int $userId, int $timeAdded) { + + $this->_debug->query->select->total++; + + $query = $this->_db->prepare('SELECT * FROM `magnet` WHERE `userId` = ? AND `timeAdded` = ?'); + + $query->execute([$userId, $timeAdded]); + + return $query->fetch(); + } + + public function findMagnetsByUserId(int $userId) { + + $this->_debug->query->select->total++; + + $query = $this->_db->prepare('SELECT * FROM `magnet` WHERE `userId` = ?'); + + $query->execute([$userId]); + + return $query->fetchAll(); + } + + public function findMagnetsTotalByUserId(int $userId) : int { + + $this->_debug->query->select->total++; + + $query = $this->_db->prepare('SELECT COUNT(*) AS `result` FROM `magnet` WHERE `userId` = ?'); + + $query->execute([$userId]); + + return $query->fetch()->result; + } + + public function getMagnetsTotalByUsersPublic(bool $public) : int { + + $this->_debug->query->select->total++; + + $query = $this->_db->prepare('SELECT COUNT(*) AS `result` FROM `magnet` + JOIN `user` ON (`user`.`userId` = `magnet`.`userId`) + WHERE `user`.`public` = ?'); + + $query->execute([(int) $public]); + + return $query->fetch()->result; + } + + public function updateMagnetXl(int $magnetId, int $xl, int $timeUpdated) : int { + + $this->_debug->query->update->total++; + + $query = $this->_db->prepare('UPDATE `magnet` SET `xl` = ?, `timeUpdated` = ? WHERE `magnetId` = ?'); + + $query->execute([$xl, $timeUpdated, $magnetId]); + + return $query->rowCount(); + } + + public function updateMagnetDn(int $magnetId, string $dn, int $timeUpdated) : int { + + $this->_debug->query->update->total++; + + $query = $this->_db->prepare('UPDATE `magnet` SET `dn` = ?, `timeUpdated` = ? WHERE `magnetId` = ?'); + + $query->execute([$dn, $timeUpdated, $magnetId]); + + return $query->rowCount(); + } + + public function updateMagnetTitle(int $magnetId, string $title, int $timeUpdated) : int { + + $this->_debug->query->update->total++; + + $query = $this->_db->prepare('UPDATE `magnet` SET `title` = ?, `timeUpdated` = ? WHERE `magnetId` = ?'); + + $query->execute([$title, $timeUpdated, $magnetId]); + + return $query->rowCount(); + } + + public function updateMagnetPreview(int $magnetId, string $preview, int $timeUpdated) : int { + + $this->_debug->query->update->total++; + + $query = $this->_db->prepare('UPDATE `magnet` SET `preview` = ?, `timeUpdated` = ? WHERE `magnetId` = ?'); + + $query->execute([$preview, $timeUpdated, $magnetId]); + + return $query->rowCount(); + } + + public function updateMagnetDescription(int $magnetId, string $description, int $timeUpdated) : int { + + $this->_debug->query->update->total++; + + $query = $this->_db->prepare('UPDATE `magnet` SET `description` = ?, `timeUpdated` = ? WHERE `magnetId` = ?'); + + $query->execute([$description, $timeUpdated, $magnetId]); + + return $query->rowCount(); + } + + public function updateMagnetPublic(int $magnetId, bool $public, int $timeUpdated) : int { + + $this->_debug->query->update->total++; + + $query = $this->_db->prepare('UPDATE `magnet` SET `public` = ?, `timeUpdated` = ? WHERE `magnetId` = ?'); + + $query->execute([(int) $public, $timeUpdated, $magnetId]); + + return $query->rowCount(); + } + + public function updateMagnetComments(int $magnetId, bool $comments, int $timeUpdated) : int { + + $this->_debug->query->update->total++; + + $query = $this->_db->prepare('UPDATE `magnet` SET `comments` = ?, `timeUpdated` = ? WHERE `magnetId` = ?'); + + $query->execute([(int) $comments, $timeUpdated, $magnetId]); + + return $query->rowCount(); + } + + public function updateMagnetSensitive(int $magnetId, bool $sensitive, int $timeUpdated) : int { + + $this->_debug->query->update->total++; + + $query = $this->_db->prepare('UPDATE `magnet` SET `sensitive` = ?, `timeUpdated` = ? WHERE `magnetId` = ?'); + + $query->execute([(int) $sensitive, $timeUpdated, $magnetId]); + + return $query->rowCount(); + } + + public function updateMagnetApproved(int $magnetId, bool $approved, int $timeUpdated) : int { + + $this->_debug->query->update->total++; + + $query = $this->_db->prepare('UPDATE `magnet` SET `approved` = ?, `timeUpdated` = ? WHERE `magnetId` = ?'); + + $query->execute([(int) $approved, $timeUpdated, $magnetId]); + + return $query->rowCount(); + } + + public function updateMagnetTimeUpdated(int $magnetId, int $timeUpdated) : int { + + $this->_debug->query->update->total++; + + $query = $this->_db->prepare('UPDATE `magnet` SET `timeUpdated` = ? WHERE `magnetId` = ?'); + + $query->execute([$timeUpdated, $magnetId]); + + return $query->rowCount(); + } + + public function updateMagnetTimeAdded(int $magnetId, int $timeAdded) : int { + + $this->_debug->query->update->total++; + + $query = $this->_db->prepare('UPDATE `magnet` SET `timeAdded` = ? WHERE `magnetId` = ?'); + + $query->execute([$timeAdded, $magnetId]); + + return $query->rowCount(); + } + + // Magnet to Info Hash + public function addMagnetToInfoHash(int $magnetId, int $infoHashId) : int { + + $this->_debug->query->insert->total++; + + $query = $this->_db->prepare('INSERT INTO `magnetToInfoHash` SET `magnetId` = ?, `infoHashId` = ?'); + + $query->execute([$magnetId, $infoHashId]); + + return $this->_db->lastInsertId(); + } + + public function findMagnetToInfoHashByMagnetId(int $magnetId) + { + $this->_debug->query->select->total++; + + $query = $this->_db->prepare('SELECT * FROM `magnetToInfoHash` WHERE `magnetId` = ?'); + + $query->execute([$magnetId]); + + return $query->fetchAll(); + } + + // Magnet to AddressTracker + public function addMagnetToAddressTracker(int $magnetId, int $addressTrackerId) : int { + + $this->_debug->query->insert->total++; + + $query = $this->_db->prepare('INSERT INTO `magnetToAddressTracker` SET `magnetId` = ?, `addressTrackerId` = ?'); + + $query->execute([$magnetId, $addressTrackerId]); + + return $this->_db->lastInsertId(); + } + + public function updateMagnetToAddressTrackerSeeders(int $magnetToAddressTrackerId, int $seeders, int $timeUpdated) : int { + + $this->_debug->query->update->total++; + + $query = $this->_db->prepare('UPDATE `magnetToAddressTracker` SET `seeders` = ?, `timeUpdated` = ? WHERE `magnetToAddressTrackerId` = ?'); + + $query->execute([$seeders, $timeUpdated, $magnetToAddressTrackerId]); + + return $query->rowCount(); + } + + public function updateMagnetToAddressTrackerCompleted(int $magnetToAddressTrackerId, int $completed, int $timeUpdated) : int { + + $this->_debug->query->update->total++; + + $query = $this->_db->prepare('UPDATE `magnetToAddressTracker` SET `completed` = ?, `timeUpdated` = ? WHERE `magnetToAddressTrackerId` = ?'); + + $query->execute([$completed, $timeUpdated, $magnetToAddressTrackerId]); + + return $query->rowCount(); + } + + public function updateMagnetToAddressTrackerLeechers(int $magnetToAddressTrackerId, int $leechers, int $timeUpdated) : int { + + $this->_debug->query->update->total++; + + $query = $this->_db->prepare('UPDATE `magnetToAddressTracker` SET `leechers` = ?, `timeUpdated` = ? WHERE `magnetToAddressTrackerId` = ?'); + + $query->execute([$leechers, $timeUpdated, $magnetToAddressTrackerId]); + + return $query->rowCount(); + } + + public function updateMagnetToAddressTrackerTimeOffline(int $magnetToAddressTrackerId, mixed $timeOffline) : int { + + $this->_debug->query->update->total++; + + $query = $this->_db->prepare('UPDATE `magnetToAddressTracker` SET `timeOffline` = ? WHERE `magnetToAddressTrackerId` = ?'); + + $query->execute([$timeOffline, $magnetToAddressTrackerId]); + + return $query->rowCount(); + } + + public function deleteMagnetToAddressTrackerByMagnetId(int $magnetId) : int { + + $this->_debug->query->delete->total++; + + $query = $this->_db->prepare('DELETE FROM `magnetToAddressTracker` WHERE `magnetId` = ?'); + + $query->execute([$magnetId]); + + return $query->rowCount(); + } + + public function findMagnetToAddressTracker(int $magnetId, int $addressTrackerId) { + + $this->_debug->query->select->total++; + + $query = $this->_db->prepare('SELECT * FROM `magnetToAddressTracker` WHERE `magnetId` = ? AND `addressTrackerId` = ?'); + + $query->execute([$magnetId, $addressTrackerId]); + + return $query->fetch(); + } + + public function findAddressTrackerByMagnetId(int $magnetId) { + + $this->_debug->query->select->total++; + + $query = $this->_db->prepare('SELECT * FROM `magnetToAddressTracker` WHERE `magnetId` = ?'); + + $query->execute([$magnetId]); + + return $query->fetchAll(); + } + + public function getMagnetToAddressTrackerScrapeQueue(int $limit) { + + $this->_debug->query->select->total++; + + $query = $this->_db->prepare('SELECT * FROM `magnetToAddressTracker` + + WHERE `timeOffline` IS NULL + + ORDER BY `timeUpdated` ASC, RAND() + + LIMIT ' . (int) $limit); + + $query->execute(); + + return $query->fetchAll(); + } + + public function resetMagnetToAddressTrackerTimeOfflineByTimeout(int $timeOffline) : int { + + $this->_debug->query->update->total++; + + $query = $this->_db->prepare('UPDATE `magnetToAddressTracker` SET `timeOffline` = NULL WHERE `timeOffline` < ?'); + + $query->execute( + [ + time() - $timeOffline + ] + ); + + return $query->rowCount(); + } + + public function initMagnetToAddressTrackerId(int $magnetId, int $addressTrackerId) : int { + + if ($result = $this->findMagnetToAddressTracker($magnetId, $addressTrackerId)) { + + return $result->magnetToAddressTrackerId; + } + + return $this->addMagnetToAddressTracker($magnetId, $addressTrackerId); + } + + public function getMagnetToAddressTrackerSeedersSumByMagnetId(int $magnetId) : int { + + $this->_debug->query->select->total++; + + $query = $this->_db->prepare('SELECT SUM(`seeders`) AS `result` FROM `magnetToAddressTracker` WHERE `magnetId` = ?'); + + $query->execute([$magnetId]); + + return (int) $query->fetch()->result; + } + + public function getMagnetToAddressTrackerCompletedSumByMagnetId(int $magnetId) : int { + + $this->_debug->query->select->total++; + + $query = $this->_db->prepare('SELECT SUM(`completed`) AS `result` FROM `magnetToAddressTracker` WHERE `magnetId` = ?'); + + $query->execute([$magnetId]); + + return (int) $query->fetch()->result; + } + + public function getMagnetToAddressTrackerLeechersSumByMagnetId(int $magnetId) : int { + + $this->_debug->query->select->total++; + + $query = $this->_db->prepare('SELECT SUM(`leechers`) AS `result` FROM `magnetToAddressTracker` WHERE `magnetId` = ?'); + + $query->execute([$magnetId]); + + return (int) $query->fetch()->result; + } + + public function getMagnetToAcceptableSourceTotalByMagnetId(int $magnetId) : int { + + $this->_debug->query->select->total++; + + $query = $this->_db->prepare('SELECT COUNT(*) AS `result` FROM `magnetToAcceptableSource` WHERE `magnetId` = ?'); + + $query->execute([$magnetId]); + + return (int) $query->fetch()->result; + } + + public function getMagnetToAddressTrackerSeedersSum() : int { + + $this->_debug->query->select->total++; + + $query = $this->_db->prepare('SELECT SUM(`seeders`) AS `result` FROM `magnetToAddressTracker`'); + + $query->execute(); + + return (int) $query->fetch()->result; + } + + public function getMagnetToAddressTrackerCompletedSum() : int { + + $this->_debug->query->select->total++; + + $query = $this->_db->prepare('SELECT SUM(`completed`) AS `result` FROM `magnetToAddressTracker`'); + + $query->execute(); + + return (int) $query->fetch()->result; + } + + public function getMagnetToAddressTrackerLeechersSum() : int { + + $this->_debug->query->select->total++; + + $query = $this->_db->prepare('SELECT SUM(`leechers`) AS `result` FROM `magnetToAddressTracker`'); + + $query->execute(); + + return (int) $query->fetch()->result; + } + + // Magnet to AcceptableSource + public function addMagnetToAcceptableSource(int $magnetId, int $acceptableSourceId) : int { + + $this->_debug->query->insert->total++; + + $query = $this->_db->prepare('INSERT INTO `magnetToAcceptableSource` SET `magnetId` = ?, `acceptableSourceId` = ?'); + + $query->execute([$magnetId, $acceptableSourceId]); + + return $this->_db->lastInsertId(); + } + + public function deleteMagnetToAcceptableSourceByMagnetId(int $magnetId) : int { + + $this->_debug->query->delete->total++; + + $query = $this->_db->prepare('DELETE FROM `magnetToAcceptableSource` WHERE `magnetId` = ?'); + + $query->execute([$magnetId]); + + return $query->rowCount(); + } + + public function findMagnetToAcceptableSource(int $magnetId, int $acceptableSourceId) { + + $this->_debug->query->select->total++; + + $query = $this->_db->prepare('SELECT * FROM `magnetToAcceptableSource` WHERE `magnetId` = ? AND `acceptableSourceId` = ?'); + + $query->execute([$magnetId, $acceptableSourceId]); + + return $query->fetch(); + } + + public function findAcceptableSourceByMagnetId(int $magnetId) { + + $this->_debug->query->select->total++; + + $query = $this->_db->prepare('SELECT * FROM `magnetToAcceptableSource` WHERE `magnetId` = ?'); + + $query->execute([$magnetId]); + + return $query->fetchAll(); + } + + public function initMagnetToAcceptableSourceId(int $magnetId, int $acceptableSourceId) : int { + + if ($result = $this->findMagnetToAcceptableSource($magnetId, $acceptableSourceId)) { + + return $result->magnetToAcceptableSourceId; + } + + return $this->addMagnetToAcceptableSource($magnetId, $acceptableSourceId); + } + + // Magnet to eXactSource + public function addMagnetToExactSource(int $magnetId, int $eXactSourceId) : int { + + $this->_debug->query->insert->total++; + + $query = $this->_db->prepare('INSERT INTO `magnetToExactSource` SET `magnetId` = ?, `eXactSourceId` = ?'); + + $query->execute([$magnetId, $eXactSourceId]); + + return $this->_db->lastInsertId(); + } + + public function deleteMagnetToExactSourceByMagnetId(int $magnetId) : int { + + $this->_debug->query->delete->total++; + + $query = $this->_db->prepare('DELETE FROM `magnetToExactSource` WHERE `magnetId` = ?'); + + $query->execute([$magnetId]); + + return $this->_db->lastInsertId(); + } + + public function findMagnetToExactSource(int $magnetId, int $eXactSourceId) { + + $this->_debug->query->select->total++; + + $query = $this->_db->prepare('SELECT * FROM `magnetToExactSource` WHERE `magnetId` = ? AND `eXactSourceId` = ?'); + + $query->execute([$magnetId, $eXactSourceId]); + + return $query->fetch(); + } + + public function findExactSourceByMagnetId(int $magnetId) { + + $this->_debug->query->select->total++; + + $query = $this->_db->prepare('SELECT * FROM `magnetToExactSource` WHERE `magnetId` = ?'); + + $query->execute([$magnetId]); + + return $query->fetchAll(); + } + + public function initMagnetToExactSourceId(int $magnetId, int $eXactSourceId) : int { + + if ($result = $this->findMagnetToEXactSource($magnetId, $eXactSourceId)) { + + return $result->magnetToExactSourceId; + } + + return $this->addMagnetToEXactSource($magnetId, $eXactSourceId); + } + + // Magnet to KeywordTopic + public function addMagnetToKeywordTopic(int $magnetId, int $keywordTopicId) : int { + + $this->_debug->query->insert->total++; + + $query = $this->_db->prepare('INSERT INTO `magnetToKeywordTopic` SET `magnetId` = ?, `keywordTopicId` = ?'); + + $query->execute([$magnetId, $keywordTopicId]); + + return $this->_db->lastInsertId(); + } + + public function deleteMagnetToKeywordTopicByMagnetId(int $magnetId) : int { + + $this->_debug->query->delete->total++; + + $query = $this->_db->prepare('DELETE FROM `magnetToKeywordTopic` WHERE `magnetId` = ?'); + + $query->execute([$magnetId]); + + return $query->rowCount(); + } + + public function findMagnetToKeywordTopic(int $magnetId, int $keywordTopicId) { + + $this->_debug->query->select->total++; + + $query = $this->_db->prepare('SELECT * FROM `magnetToKeywordTopic` WHERE `magnetId` = ? AND `keywordTopicId` = ?'); + + $query->execute([$magnetId, $keywordTopicId]); + + return $query->fetch(); + } + + public function findKeywordTopicByMagnetId(int $magnetId) { + + $this->_debug->query->select->total++; + + $query = $this->_db->prepare('SELECT * FROM `magnetToKeywordTopic` WHERE `magnetId` = ?'); + + $query->execute([$magnetId]); + + return $query->fetchAll(); + } + + public function initMagnetToKeywordTopicId(int $magnetId, int $keywordTopicId) : int { + + if ($result = $this->findMagnetToKeywordTopic($magnetId, $keywordTopicId)) { + + return $result->magnetToKeywordTopicId; + } + + return $this->addMagnetToKeywordTopic($magnetId, $keywordTopicId); + } + + // Magnet lock + public function addMagnetLock(int $magnetId, int $userId, int $timeAdded) : int { + + $this->_debug->query->insert->total++; + + $query = $this->_db->prepare('INSERT INTO `magnetLock` SET `magnetId` = ?, `userId` = ?, `timeAdded` = ?'); + + $query->execute([$magnetId, $userId, $timeAdded]); + + return $this->_db->lastInsertId(); + } + + public function flushMagnetLock(int $magnetId) : int { + + $this->_debug->query->update->total++; + + $query = $this->_db->prepare('DELETE FROM `magnetLock` WHERE `magnetId` = ?'); + + $query->execute([$magnetId]); + + return $query->rowCount(); + } + + public function findLastMagnetLock(int $magnetId) { + + $this->_debug->query->select->total++; + + $query = $this->_db->prepare('SELECT * FROM `magnetLock` WHERE `magnetId` = ? ORDER BY `magnetLockId` DESC LIMIT 1'); + + $query->execute([$magnetId]); + + return $query->fetch(); + } + + // Magnet comment + public function addMagnetComment( int $magnetId, + int $userId, + mixed $magnetCommentIdParent, + string $value, + bool $approved, + bool $public, + int $timeAdded) : int { + + $this->_debug->query->insert->total++; + + $query = $this->_db->prepare('INSERT INTO `magnetComment` SET `magnetId` = ?, + `userId` = ?, + `magnetCommentIdParent` = ?, + `value` = ?, + `approved` = ?, + `public` = ?, + `timeAdded` = ?'); + + $query->execute( + [ + $magnetId, + $userId, + $magnetCommentIdParent, + $value, + $approved, + $public, + $timeAdded + ] + ); + + return $this->_db->lastInsertId(); + } + + public function updateMagnetCommentPublic(int $magnetCommentId, mixed $public) : int { + + $this->_debug->query->update->total++; + + $query = $this->_db->prepare('UPDATE `magnetComment` SET `public` = ? WHERE `magnetCommentId` = ?'); + + $query->execute([(int) $public, $magnetCommentId]); + + return $query->rowCount(); + } + + public function updateMagnetCommentApproved(int $magnetCommentId, mixed $approved) : int { + + $this->_debug->query->update->total++; + + $query = $this->_db->prepare('UPDATE `magnetComment` SET `approved` = ? WHERE `magnetCommentId` = ?'); + + $query->execute([(int) $approved, $magnetCommentId]); + + return $query->rowCount(); + } + + public function getMagnetCommentsTotal() : int { + + $this->_debug->query->select->total++; + + $query = $this->_db->query('SELECT COUNT(*) AS `result` FROM `magnetComment`'); + + return $query->fetch()->result; + } + + public function getMagnetComments() { + + $this->_debug->query->select->total++; + + $query = $this->_db->query('SELECT * FROM `magnetComment`'); + + return $query->fetchAll(); + } + + public function findMagnetCommentsTotalByMagnetId(int $magnetId) : int { + + $this->_debug->query->select->total++; + + $query = $this->_db->prepare('SELECT COUNT(DISTINCT `userId`) AS `result` FROM `magnetComment` WHERE `magnetId` = ?'); + + $query->execute([$magnetId]); + + return $query->fetch()->result; + } + + public function findMagnetCommentsTotalByUserId(int $userId) : int { + + $this->_debug->query->select->total++; + + $query = $this->_db->prepare('SELECT COUNT(DISTINCT `magnetId`) AS `result` FROM `magnetComment` WHERE `userId` = ?'); + + $query->execute([$userId]); + + return $query->fetch()->result; + } + + public function findMagnetCommentsTotal(int $magnetId, int $userId) : int { + + $this->_debug->query->select->total++; + + $query = $this->_db->prepare('SELECT COUNT(*) AS `result` FROM `magnetComment` WHERE `magnetId` = ? AND `userId` = ?'); + + $query->execute([$magnetId, $userId]); + + return $query->fetch()->result; + } + + public function findMagnetCommentsTotalByUsersPublic(bool $public) : int { + + $this->_debug->query->select->total++; + + $query = $this->_db->prepare('SELECT COUNT(*) AS `result` FROM `magnetComment` + JOIN `user` ON (`user`.`userId` = `magnetComment`.`userId`) + WHERE `user`.`public` = ?'); + + $query->execute([(int) $public]); + + return $query->fetch()->result; + } + + public function findMagnetComments(int $magnetId, mixed $magnetCommentIdParent = null) { + + $this->_debug->query->select->total++; + + if ($magnetCommentIdParent) + { + $query = $this->_db->prepare('SELECT * FROM `magnetComment` WHERE `magnetId` = ? AND `magnetCommentIdParent` = ?'); + + $query->execute([$magnetId, $magnetCommentIdParent]); + } + else + { + $query = $this->_db->prepare('SELECT * FROM `magnetComment` WHERE `magnetId` = ? AND `magnetCommentIdParent` IS NULL'); + + $query->execute([$magnetId]); + } + + return $query->fetchAll(); + } + + public function findMagnetComment(int $magnetId, int $userId, int $timeAdded) { + + $this->_debug->query->select->total++; + + $query = $this->_db->prepare('SELECT * FROM `magnetComment` WHERE `magnetId` = ? AND `userId` = ? AND `timeAdded` = ?'); + + $query->execute([$magnetId, $userId, $timeAdded]); + + return $query->fetch(); + } + + public function getMagnetComment(int $magnetCommentId) { + + $this->_debug->query->select->total++; + + $query = $this->_db->prepare('SELECT * FROM `magnetComment` WHERE `magnetCommentId` = ?'); + + $query->execute([$magnetCommentId]); + + return $query->fetch(); + } + + // Magnet star + public function addMagnetStar(int $magnetId, int $userId, bool $value, int $timeAdded) : int { + + $this->_debug->query->insert->total++; + + $query = $this->_db->prepare('INSERT INTO `magnetStar` SET `magnetId` = ?, `userId` = ?, `value` = ?, `timeAdded` = ?'); + + $query->execute([$magnetId, $userId, (int) $value, $timeAdded]); + + return $this->_db->lastInsertId(); + } + + public function getMagnetStar(int $magnetStarId) { + + $this->_debug->query->select->total++; + + $query = $this->_db->prepare('SELECT * FROM `magnetStar` WHERE `magnetStarId` = ?'); + + $query->execute([$magnetStarId]); + + return $query->fetch(); + } + + public function getMagnetStars() { + + $this->_debug->query->select->total++; + + $query = $this->_db->query('SELECT * FROM `magnetStar`'); + + return $query->fetchAll(); + } + + public function getMagnetStarsTotal() : int { + + $this->_debug->query->select->total++; + + $query = $this->_db->query('SELECT COUNT(*) AS `result` FROM `magnetStar`'); + + return $query->fetch()->result; + } + + public function findMagnetStarsTotalByMagnetId(int $magnetId, bool $value) : int { + + $this->_debug->query->select->total++; + + $total = 0; + + $query = $this->_db->prepare('SELECT COUNT(DISTINCT `userId`) AS `result` FROM `magnetStar` WHERE `magnetId` = ? AND `value` = ?'); + + $query->execute([$magnetId, (int) $value]); + + return $query->fetch()->result; + } + + public function findMagnetStarsTotalByUserId(int $userId) : int { + + $this->_debug->query->select->total++; + + $query = $this->_db->prepare('SELECT COUNT(DISTINCT `magnetId`) AS `result` FROM `magnetStar` WHERE `userId` = ?'); + + $query->execute([$userId]); + + return $query->fetch()->result; + } + + public function findLastMagnetStarValue(int $magnetId, int $userId) : bool { + + $this->_debug->query->select->total++; + + $query = $this->_db->prepare('SELECT * FROM `magnetStar` WHERE `magnetId` = ? AND `userId` = ? ORDER BY `magnetStarId` DESC'); + + $query->execute([$magnetId, $userId]); + + return $query->rowCount() ? (bool) $query->fetch()->value : false; + } + + public function findMagnetStarsTotalByUsersPublic(bool $public) : int { + + $this->_debug->query->select->total++; + + $query = $this->_db->prepare('SELECT COUNT(*) AS `result` FROM `magnetStar` + JOIN `user` ON (`user`.`userId` = `magnetStar`.`userId`) + WHERE `user`.`public` = ?'); + + $query->execute([(int) $public]); + + return $query->fetch()->result; + } + + public function findMagnetStar(int $magnetId, int $userId, int $timeAdded) { + + $this->_debug->query->select->total++; + + $query = $this->_db->prepare('SELECT * FROM `magnetStar` WHERE `magnetId` = ? AND `userId` = ? AND `timeAdded` = ?'); + + $query->execute([$magnetId, $userId, $timeAdded]); + + return $query->fetch(); + } + + // Magnet download + public function addMagnetDownload(int $magnetId, int $userId, int $timeAdded) : int { + + $this->_debug->query->insert->total++; + + $query = $this->_db->prepare('INSERT INTO `magnetDownload` SET `magnetId` = ?, `userId` = ?, `timeAdded` = ?'); + + $query->execute([$magnetId, $userId, $timeAdded]); + + return $this->_db->lastInsertId(); + } + + public function getMagnetDownload(int $magnetDownloadId) { + + $this->_debug->query->select->total++; + + $query = $this->_db->prepare('SELECT * FROM `magnetDownload` WHERE `magnetDownloadId` = ?'); + + $query->execute([$magnetDownloadId]); + + return $query->fetch(); + } + + public function getMagnetDownloads() { + + $this->_debug->query->select->total++; + + $query = $this->_db->query('SELECT * FROM `magnetDownload`'); + + return $query->fetchAll(); + } + + public function getMagnetDownloadsTotal() : int { + + $this->_debug->query->select->total++; + + $query = $this->_db->query('SELECT COUNT(*) AS `result` FROM `magnetDownload`'); + + return $query->fetch()->result; + } + + public function findMagnetDownloadsTotal(int $magnetId, int $userId) : int { + + $this->_debug->query->select->total++; + + $query = $this->_db->prepare('SELECT COUNT(*) AS `result` FROM `magnetDownload` WHERE `magnetId` = ? AND `userId` = ?'); + + $query->execute([$magnetId, $userId]); + + return $query->fetch()->result; + } + + public function findMagnetDownload(int $magnetId, int $userId, int $timeAdded) { + + $this->_debug->query->select->total++; + + $query = $this->_db->prepare('SELECT * FROM `magnetDownload` WHERE `magnetId` = ? AND `userId` = ? AND `timeAdded` = ?'); + + $query->execute([$magnetId, $userId, $timeAdded]); + + return $query->fetch(); + } + + public function findMagnetDownloadsTotalByMagnetId(int $magnetId) : int { + + $this->_debug->query->select->total++; + + $query = $this->_db->prepare('SELECT COUNT(DISTINCT `userId`) AS `result` FROM `magnetDownload` WHERE `magnetId` = ?'); + + $query->execute([$magnetId]); + + return $query->fetch()->result; + } + + public function findMagnetDownloadsTotalByUserId(int $userId) : int { + + $this->_debug->query->select->total++; + + $query = $this->_db->prepare('SELECT COUNT(DISTINCT `magnetId`) AS `result` FROM `magnetDownload` WHERE `userId` = ?'); + + $query->execute([$userId]); + + return $query->fetch()->result; + } + + public function findMagnetDownloadsTotalByUsersPublic(bool $public) : int { + + $this->_debug->query->select->total++; + + $query = $this->_db->prepare('SELECT COUNT(*) AS `result` FROM `magnetDownload` + JOIN `user` ON (`user`.`userId` = `magnetDownload`.`userId`) + WHERE `user`.`public` = ?'); + + $query->execute([(int) $public]); + + return $query->fetch()->result; + } + + // Magnet view + public function addMagnetView(int $magnetId, int $userId, int $timeAdded) : int { + + $this->_debug->query->insert->total++; + + $query = $this->_db->prepare('INSERT INTO `magnetView` SET `magnetId` = ?, `userId` = ?, `timeAdded` = ?'); + + $query->execute([$magnetId, $userId, $timeAdded]); + + return $this->_db->lastInsertId(); + } + + public function getMagnetViews() { + + $this->_debug->query->select->total++; + + $query = $this->_db->query('SELECT * FROM `magnetView`'); + + return $query->fetchAll(); + } + + public function getMagnetView(int $magnetViewId) { + + $this->_debug->query->select->total++; + + $query = $this->_db->prepare('SELECT * FROM `magnetView` WHERE `magnetViewId` = ?'); + + $query->execute([$magnetViewId]); + + return $query->fetch(); + } + + public function getMagnetViewsTotal() : int { + + $this->_debug->query->select->total++; + + $query = $this->_db->query('SELECT COUNT(*) AS `result` FROM `magnetView`'); + + return $query->fetch()->result; + } + + public function findMagnetViewsTotalByUserId(int $userId) : int { + + $this->_debug->query->select->total++; + + $query = $this->_db->prepare('SELECT COUNT(*) AS `result` FROM `magnetView` WHERE `userId` = ?'); + + $query->execute([$userId]); + + return $query->fetch()->result; + } + + public function findMagnetViewsTotalByUsersPublic(bool $public) : int { + + $this->_debug->query->select->total++; + + $query = $this->_db->prepare('SELECT COUNT(*) AS `result` FROM `magnetView` + JOIN `user` ON (`user`.`userId` = `magnetView`.`userId`) + WHERE `user`.`public` = ?'); + + $query->execute([(int) $public]); + + return $query->fetch()->result; + } + + public function findMagnetView(int $magnetId, int $userId, int $timeAdded) { + + $this->_debug->query->select->total++; + + $query = $this->_db->prepare('SELECT * FROM `magnetView` WHERE `magnetId` = ? AND `userId` = ? AND `timeAdded` = ?'); + + $query->execute([$magnetId, $userId, $timeAdded]); + + return $query->fetch(); + } +} \ No newline at end of file diff --git a/src/library/filter.php b/src/library/filter.php new file mode 100644 index 0000000..72d9e28 --- /dev/null +++ b/src/library/filter.php @@ -0,0 +1,48 @@ +1) or string of infohash(es). + * @param array|string $trackers List (>1) or string of tracker(s). + * @param int|null $max_trackers Optional. Maximum number of trackers to be scraped, Default all. + * @param int $timeout Optional. Maximum time for each tracker scrape in seconds, Default 2. + * @param bool $announce Optional. Use announce instead of scrape, Default false. + * @return array List of results. + */ + public function scrape( $hashes, $trackers, $max_trackers = null, $timeout = 2, $announce = false ) { + $final_result = array(); + + if ( empty( $trackers ) ) { + $this->errors[] = 'No tracker specified, aborting.'; + return $final_result; + } else if ( ! is_array( $trackers ) ) { + $trackers = array( $trackers ); + } + + if ( is_int( $timeout ) ) { + $this->timeout = $timeout; + } else { + $this->timeout = 2; + $this->errors[] = 'Timeout must be an integer. Using default value.'; + } + + try { + $this->infohashes = $this->normalize_infohashes( $hashes ); + } catch ( \RangeException $e ) { + $this->errors[] = $e->getMessage(); + return $final_result; + } + + $max_iterations = is_int( $max_trackers ) ? $max_trackers : count( $trackers ); + foreach ( $trackers as $index => $tracker ) { + if ( ! empty( $this->infohashes ) && $index < $max_iterations ) { + $info = parse_url( $tracker ); + $protocol = $info['scheme']; + $host = $info['host']; + if ( empty( $protocol ) || empty( $host ) ) { + $this->errors[] = 'Skipping invalid tracker (' . $tracker . ').'; + continue; + } + + $port = isset( $info['port'] ) ? $info['port'] : null; + $path = isset( $info['path'] ) ? $info['path'] : null; + $passkey = $this->get_passkey( $path ); + $result = $this->try_scrape( $protocol, $host, $port, $passkey, $announce ); + $final_result = array_merge( $final_result, $result ); + continue; + } + break; + } + return $final_result; + } + + /** + * Normalizes the given hashes + * + * @throws \RangeException If amount of valid infohashes > 64 or < 1. + * + * @param array $infohashes List of infohash(es). + * @return array Normalized infohash(es). + */ + private function normalize_infohashes( $infohashes ) { + if ( ! is_array( $infohashes ) ) { + $infohashes = array( $infohashes ); + } + + foreach ( $infohashes as $index => $infohash ) { + if ( ! preg_match( '/^[a-f0-9]{40}$/i', $infohash ) ) { + $this->errors[] = 'Invalid infohash skipped (' . $infohash . ').'; + unset( $infohashes[ $index ] ); + } + } + + $total_infohashes = count( $infohashes ); + if ( $total_infohashes > 64 || $total_infohashes < 1 ) { + throw new \RangeException( 'Invalid amount of valid infohashes (' . $total_infohashes . ').' ); + } + + $infohashes = array_values( $infohashes ); + + return $infohashes; + } + + /** + * Returns the passkey found in the scrape request. + * + * @param string $path Path from the scrape request. + * @return string Passkey or empty string. + */ + private function get_passkey( $path ) { + if ( ! is_null( $path ) && preg_match( '/[a-z0-9]{32}/i', $path, $matches ) ) { + return '/' . $matches[0]; + } + + return ''; + } + + /** + * Tries to scrape with a single tracker. + * + * @throws \Exception In case of unsupported protocol. + * + * @param string $protocol Protocol of the tracker. + * @param string $host Domain or address of the tracker. + * @param int $port Optional. Port number of the tracker. + * @param string $passkey Optional. Passkey provided in the scrape request. + * @param bool $announce Optional. Use announce instead of scrape, Default false. + * @return array List of results. + */ + private function try_scrape( $protocol, $host, $port, $passkey, $announce ) { + $infohashes = $this->infohashes; + $this->infohashes = array(); + $results = array(); + try { + switch ( $protocol ) { + case 'udp': + $port = isset( $port ) ? $port : 80; + $results = $this->scrape_udp( $infohashes, $host, $port, $announce ); + break; + case 'http': + $port = isset( $port ) ? $port : 80; + $results = $this->scrape_http( $infohashes, $protocol, $host, $port, $passkey, $announce ); + break; + case 'https': + $port = isset( $port ) ? $port : 443; + $results = $this->scrape_http( $infohashes, $protocol, $host, $port, $passkey, $announce ); + break; + default: + throw new \Exception( 'Unsupported protocol (' . $protocol . '://' . $host . ').' ); + } + } catch ( \Exception $e ) { + $this->infohashes = $infohashes; + $this->errors[] = $e->getMessage(); + } + return $results; + } + + /** + * Initiates the HTTP(S) scraping + * + * @param array|string $infohashes List (>1) or string of infohash(es). + * @param string $protocol Protocol to use for the scraping. + * @param string $host Domain or IP address of the tracker. + * @param int $port Optional. Port number of the tracker, Default 80 (HTTP) or 443 (HTTPS). + * @param string $passkey Optional. Passkey provided in the scrape request. + * @param bool $announce Optional. Use announce instead of scrape, Default false. + * @return array List of results. + */ + private function scrape_http( $infohashes, $protocol, $host, $port, $passkey, $announce ) { + if ( true === $announce ) { + $response = $this->http_announce( $infohashes, $protocol, $host, $port, $passkey ); + } else { + $query = $this->http_query( $infohashes, $protocol, $host, $port, $passkey ); + $response = $this->http_request( $query, $host, $port ); + } + $results = $this->http_data( $response, $infohashes, $host ); + + return $results; + } + + /** + * Builds the HTTP(S) query + * + * @param array|string $infohashes List (>1) or string of infohash(es). + * @param string $protocol Protocol to use for the scraping. + * @param string $host Domain or IP address of the tracker. + * @param int $port Port number of the tracker, Default 80 (HTTP) or 443 (HTTPS). + * @param string $passkey Optional. Passkey provided in the scrape request. + * @return string Request query. + */ + private function http_query( $infohashes, $protocol, $host, $port, $passkey ) { + $tracker_url = $protocol . '://' . $host . ':' . $port . $passkey; + $scrape_query = ''; + + foreach ( $infohashes as $index => $infohash ) { + if ( $index > 0 ) { + $scrape_query .= '&info_hash=' . urlencode( pack( 'H*', $infohash ) ); + } else { + $scrape_query .= '/scrape?info_hash=' . urlencode( pack( 'H*', $infohash ) ); + } + } + $request_query = $tracker_url . $scrape_query; + + return $request_query; + } + + /** + * Executes the query and returns the result + * + * @throws \Exception If the connection can't be established. + * @throws \Exception If the response isn't valid. + * + * @param string $query The query that will be executed. + * @param string $host Domain or IP address of the tracker. + * @param int $port Port number of the tracker, Default 80 (HTTP) or 443 (HTTPS). + * @return string Request response. + */ + private function http_request( $query, $host, $port ) { + $context = stream_context_create( array( + 'http' => array( + 'timeout' => $this->timeout, + ), + )); + + if ( false === ( $response = @file_get_contents( $query, false, $context ) ) ) { + throw new \Exception( 'Invalid scrape connection (' . $host . ':' . $port . ').' ); + } + + if ( substr( $response, 0, 12 ) !== 'd5:filesd20:' ) { + throw new \Exception( 'Invalid scrape response (' . $host . ':' . $port . ').' ); + } + + return $response; + } + + /** + * Builds the query, sends the announce request and returns the data + * + * @throws \Exception If the connection can't be established. + * + * @param array|string $infohashes List (>1) or string of infohash(es). + * @param string $protocol Protocol to use for the scraping. + * @param string $host Domain or IP address of the tracker. + * @param int $port Port number of the tracker, Default 80 (HTTP) or 443 (HTTPS). + * @param string $passkey Optional. Passkey provided in the scrape request. + * @return string Request response. + */ + private function http_announce( $infohashes, $protocol, $host, $port, $passkey ) { + $tracker_url = $protocol . '://' . $host . ':' . $port . $passkey; + $context = stream_context_create( array( + 'http' => array( + 'timeout' => $this->timeout, + ), + )); + + $response_data = ''; + foreach ( $infohashes as $infohash ) { + $query = $tracker_url . '/announce?info_hash=' . urlencode( pack( 'H*', $infohash ) ); + if ( false === ( $response = @file_get_contents( $query, false, $context ) ) ) { + throw new \Exception( 'Invalid announce connection (' . $host . ':' . $port . ').' ); + } + + if ( substr( $response, 0, 12 ) !== 'd8:completei' || + substr( $response, 0, 46 ) === 'd8:completei0e10:downloadedi0e10:incompletei1e' ) { + continue; + } + + $ben_hash = '20:' . pack( 'H*', $infohash ) . 'd'; + $response_data .= $ben_hash . $response; + } + + return $response_data; + } + + /** + * Parses the response and returns the data + * + * @param string $response The response that will be parsed. + * @param array $infohashes List of infohash(es). + * @param string $host Domain or IP address of the tracker. + * @return array Parsed data. + */ + private function http_data( $response, $infohashes, $host ) { + $torrents_data = array(); + + foreach ( $infohashes as $infohash ) { + $ben_hash = '20:' . pack( 'H*', $infohash ) . 'd'; + $start_pos = strpos( $response, $ben_hash ); + if ( false !== $start_pos ) { + $start = $start_pos + 24; + $head = substr( $response, $start ); + $end = strpos( $head, 'ee' ) + 1; + $data = substr( $response, $start, $end ); + + $seeders = '8:completei'; + $torrent_info['seeders'] = $this->get_information( $data, $seeders, 'e' ); + + $completed = '10:downloadedi'; + $torrent_info['completed'] = $this->get_information( $data, $completed, 'e' ); + + $leechers = '10:incompletei'; + $torrent_info['leechers'] = $this->get_information( $data, $leechers, 'e' ); + + $torrents_data[ $infohash ] = $torrent_info; + } else { + $this->collect_infohash( $infohash ); + $this->errors[] = 'Invalid infohash (' . $infohash . ') for tracker: ' . $host . '.'; + } + } + + return $torrents_data; + } + + /** + * Parses a string and returns the data between $start and $end. + * + * @param string $data The data that will be parsed. + * @param string $start Beginning part of the data. + * @param string $end Ending part of the data. + * @return int Parsed information or 0. + */ + private function get_information( $data, $start, $end ) { + $start_pos = strpos( $data, $start ); + if ( false !== $start_pos ) { + $start = $start_pos + strlen( $start ); + $head = substr( $data, $start ); + $end = strpos( $head, $end ); + $information = substr( $data, $start, $end ); + + return (int) $information; + } + + return 0; + } + + /** + * Initiates the UDP scraping + * + * @param array|string $infohashes List (>1) or string of infohash(es). + * @param string $host Domain or IP address of the tracker. + * @param int $port Optional. Port number of the tracker, Default 80. + * @param bool $announce Optional. Use announce instead of scrape, Default false. + * @return array List of results. + */ + private function scrape_udp( $infohashes, $host, $port, $announce ) { + list( $socket, $transaction_id, $connection_id ) = $this->prepare_udp( $host, $port ); + + if ( true === $announce ) { + $response = $this->udp_announce( $socket, $infohashes, $connection_id ); + $keys = 'Nleechers/Nseeders'; + $start = 12; + $end = 16; + $offset = 20; + } else { + $response = $this->udp_scrape( $socket, $infohashes, $connection_id, $transaction_id, $host, $port ); + $keys = 'Nseeders/Ncompleted/Nleechers'; + $start = 8; + $end = $offset = 12; + } + $results = $this->udp_scrape_data( $response, $infohashes, $host, $keys, $start, $end, $offset ); + + return $results; + } + + /** + * Prepares the UDP connection + * + * @param string $host Domain or IP address of the tracker. + * @param int $port Optional. Port number of the tracker, Default 80. + * @return array Created socket, transaction ID and connection ID. + */ + private function prepare_udp( $host, $port ) { + $socket = $this->udp_create_connection( $host, $port ); + $transaction_id = $this->udp_connection_request( $socket ); + $connection_id = $this->udp_connection_response( $socket, $transaction_id, $host, $port ); + + return array( $socket, $transaction_id, $connection_id ); + } + + /** + * Creates the UDP socket and establishes the connection + * + * @throws \Exception If the socket couldn't be created or connected to. + * + * @param string $host Domain or IP address of the tracker. + * @param int $port Port number of the tracker, Default 80. + * @return resource $socket Created and connected socket. + */ + private function udp_create_connection( $host, $port ) { + if ( false === ( $socket = @socket_create( AF_INET, SOCK_DGRAM, SOL_UDP ) ) ) { + throw new \Exception( "Couldn't create socket." ); + } + + $timeout = $this->timeout; + socket_set_option( $socket, SOL_SOCKET, SO_RCVTIMEO, array( 'sec' => $timeout, 'usec' => 0 ) ); + socket_set_option( $socket, SOL_SOCKET, SO_SNDTIMEO, array( 'sec' => $timeout, 'usec' => 0 ) ); + if ( false === @socket_connect( $socket, $host, $port ) ) { + throw new \Exception( "Couldn't connect to socket." ); + } + + return $socket; + } + + /** + * Writes to the connected socket and returns the transaction ID + * + * @throws \Exception If the socket couldn't be written to. + * + * @param resource $socket The socket resource. + * @return int The transaction ID. + */ + private function udp_connection_request( $socket ) { + $connection_id = "\x00\x00\x04\x17\x27\x10\x19\x80"; + $action = pack( 'N', 0 ); + $transaction_id = mt_rand( 0, 2147483647 ); + $buffer = $connection_id . $action . pack( 'N', $transaction_id ); + if ( false === @socket_write( $socket, $buffer, strlen( $buffer ) ) ) { + socket_close( $socket ); + throw new \Exception( "Couldn't write to socket." ); + } + + return $transaction_id; + } + + /** + * Reads the connection response and returns the connection ID + * + * @throws \Exception If anything fails with the scraping. + * + * @param resource $socket The socket resource. + * @param int $transaction_id The transaction ID. + * @param string $host Domain or IP address of the tracker. + * @param int $port Port number of the tracker, Default 80. + * @return string The connection ID. + */ + private function udp_connection_response( $socket, $transaction_id, $host, $port ) { + if ( false === ( $response = @socket_read( $socket, 16 ) ) ) { + socket_close( $socket ); + throw new \Exception( 'Invalid scrape connection! (' . $host . ':' . $port . ').' ); + } + + if ( strlen( $response ) < 16 ) { + socket_close( $socket ); + throw new \Exception( 'Invalid scrape response (' . $host . ':' . $port . ').' ); + } + + $result = unpack( 'Naction/Ntransaction_id', $response ); + if ( 0 !== $result['action'] || $result['transaction_id'] !== $transaction_id ) { + socket_close( $socket ); + throw new \Exception( 'Invalid scrape result (' . $host . ':' . $port . ').' ); + } + + $connection_id = substr( $response, 8, 8 ); + + return $connection_id; + } + + /** + * Reads the socket response and returns the torrent data + * + * @throws \Exception If anything fails while reading the response. + * + * @param resource $socket The socket resource. + * @param array $hashes List (>1) or string of infohash(es). + * @param string $connection_id The connection ID. + * @param int $transaction_id The transaction ID. + * @param string $host Domain or IP address of the tracker. + * @param int $port Port number of the tracker, Default 80. + * @return string Response data. + */ + private function udp_scrape( $socket, $hashes, $connection_id, $transaction_id, $host, $port ) { + $this->udp_scrape_request( $socket, $hashes, $connection_id, $transaction_id ); + + $read_length = 8 + ( 12 * count( $hashes ) ); + if ( false === ( $response = @socket_read( $socket, $read_length ) ) ) { + socket_close( $socket ); + throw new \Exception( 'Invalid scrape connection (' . $host . ':' . $port . ').' ); + } + socket_close( $socket ); + + if ( strlen( $response ) < $read_length ) { + throw new \Exception( 'Invalid scrape response (' . $host . ':' . $port . ').' ); + } + + $result = unpack( 'Naction/Ntransaction_id', $response ); + if ( 2 !== $result['action'] || $result['transaction_id'] !== $transaction_id ) { + throw new \Exception( 'Invalid scrape result (' . $host . ':' . $port . ').' ); + } + + return $response; + } + + /** + * Writes to the connected socket + * + * @throws \Exception If the socket couldn't be written to. + * + * @param resource $socket The socket resource. + * @param array $hashes List (>1) or string of infohash(es). + * @param string $connection_id The connection ID. + * @param int $transaction_id The transaction ID. + */ + private function udp_scrape_request( $socket, $hashes, $connection_id, $transaction_id ) { + $action = pack( 'N', 2 ); + + $infohashes = ''; + foreach ( $hashes as $infohash ) { + $infohashes .= pack( 'H*', $infohash ); + } + + $buffer = $connection_id . $action . pack( 'N', $transaction_id ) . $infohashes; + if ( false === @socket_write( $socket, $buffer, strlen( $buffer ) ) ) { + socket_close( $socket ); + throw new \Exception( "Couldn't write to socket." ); + } + } + + /** + * Writes the announce to the connected socket + * + * @throws \Exception If the socket couldn't be written to. + * + * @param resource $socket The socket resource. + * @param array $hashes List (>1) or string of infohash(es). + * @param string $connection_id The connection ID. + * @return string Torrent(s) data. + */ + private function udp_announce( $socket, $hashes, $connection_id ) { + $action = pack( 'N', 1 ); + $downloaded = $left = $uploaded = "\x30\x30\x30\x30\x30\x30\x30\x30"; + $peer_id = $this->random_peer_id(); + $event = pack( 'N', 3 ); + $ip_addr = pack( 'N', 0 ); + $key = pack( 'N', mt_rand( 0, 2147483647 ) ); + $num_want = -1; + $ann_port = pack( 'N', mt_rand( 0, 255 ) ); + + $response_data = ''; + foreach ( $hashes as $infohash ) { + $transaction_id = mt_rand( 0, 2147483647 ); + $buffer = $connection_id . $action . pack( 'N', $transaction_id ) . pack( 'H*', $infohash ) . + $peer_id . $downloaded . $left . $uploaded . $event . $ip_addr . $key . $num_want . $ann_port; + + if ( false === @socket_write( $socket, $buffer, strlen( $buffer ) ) ) { + socket_close( $socket ); + throw new \Exception( "Couldn't write announce to socket." ); + } + + $response = $this->udp_verify_announce( $socket, $transaction_id ); + if ( false === $response ) { + continue; + } + + $response_data .= $response; + } + socket_close( $socket ); + + return $response_data; + } + + /** + * Generates a random peer ID + * + * @return string Generated peer ID. + */ + private function random_peer_id() { + $identifier = '-SP0054-'; + $chars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'; + $peer_id = $identifier . substr( str_shuffle( $chars ), 0, 12 ); + + return $peer_id; + } + + /** + * Verifies the correctness of the announce response + * + * @param resource $socket The socket resource. + * @param int $transaction_id The transaction ID. + * @return string Response data. + */ + private function udp_verify_announce( $socket, $transaction_id ) { + if ( false === ( $response = @socket_read( $socket, 20 ) ) ) { + return false; + } + + if ( strlen( $response ) < 20 ) { + return false; + } + + $result = unpack( 'Naction/Ntransaction_id', $response ); + if ( 1 !== $result['action'] || $result['transaction_id'] !== $transaction_id ) { + return false; + } + + return $response; + } + + /** + * Reads the socket response and returns the torrent data + * + * @param string $response Data from the request response. + * @param array $hashes List (>1) or string of infohash(es). + * @param string $host Domain or IP address of the tracker. + * @param string $keys Keys for the unpacked information. + * @param int $start Start of the content we want to unpack. + * @param int $end End of the content we want to unpack. + * @param int $offset Offset to the next content part. + * @return array Scraped torrent data. + */ + private function udp_scrape_data( $response, $hashes, $host, $keys, $start, $end, $offset ) { + $torrents_data = array(); + + foreach ( $hashes as $infohash ) { + $byte_string = substr( $response, $start, $end ); + $data = unpack( 'N', $byte_string ); + $content = $data[1]; + if ( ! empty( $content ) ) { + $results = unpack( $keys, $byte_string ); + $torrents_data[ $infohash ] = $results; + } else { + $this->collect_infohash( $infohash ); + $this->errors[] = 'Invalid infohash (' . $infohash . ') for tracker: ' . $host . '.'; + } + $start += $offset; + } + + return $torrents_data; + } + + /** + * Collects info-hashes that couldn't be scraped. + * + * @param string $infohash Infohash that wasn't scraped. + */ + private function collect_infohash( $infohash ) { + $this->infohashes[] = $infohash; + } + + /** + * Checks if there are any errors + * + * @return bool True or false, depending if errors are present or not. + */ + public function has_errors() { + return ! empty( $this->errors ); + } + + /** + * Returns all the errors that were logged + * + * @return array All the logged errors. + */ + public function get_errors() { + return $this->errors; + } +} diff --git a/src/library/sphinx.php b/src/library/sphinx.php new file mode 100644 index 0000000..6cb15ae --- /dev/null +++ b/src/library/sphinx.php @@ -0,0 +1,111 @@ +_sphinx = new PDO('mysql:host=' . $host . ';port=' . $port . ';charset=utf8', false, false, [PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES utf8']); + $this->_sphinx->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); + $this->_sphinx->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_OBJ); + } + + public function searchMagnetsTotal(string $keyword, string $mode = 'default', array $stopWords = []) : int + { + $query = $this->_sphinx->prepare('SELECT COUNT(*) AS `total` FROM `magnet` WHERE MATCH(?)'); + + $query->execute( + [ + self::_match($keyword, $mode, $stopWords) + ] + ); + + return $query->fetch()->total; + } + + public function searchMagnets(string $keyword, int $start, int $limit, int $maxMatches, string $mode = 'default', array $stopWords = []) + { + $query = $this->_sphinx->prepare("SELECT * + + FROM `magnet` + + WHERE MATCH(?) + + ORDER BY `magnetId` DESC, WEIGHT() DESC + + LIMIT " . (int) ($start >= $maxMatches ? ($maxMatches > 0 ? $maxMatches - 1 : 0) : $start) . "," . (int) $limit . " + + OPTION `max_matches`=" . (int) ($maxMatches >= 1 ? $maxMatches : 1)); + + $query->execute( + [ + self::_match($keyword, $mode, $stopWords) + ] + ); + + return $query->fetchAll(); + } + + private static function _match(string $keyword, string $mode = 'default', array $stopWords = []) : string + { + $keyword = trim($keyword); + + if (empty($keyword)) + { + return $keyword; + } + + $keyword = str_replace(['"'], ' ', $keyword); + $keyword = preg_replace('/[\W]/ui', ' ', $keyword); + $keyword = preg_replace('/[\s]+/ui', ' ', $keyword); + $keyword = trim($keyword); + + switch ($mode) + { + case 'similar': + + $result = []; + + $keyword = preg_replace('/[\d]/ui', ' ', $keyword); + $keyword = preg_replace('/[\s]+/ui', ' ', $keyword); + $keyword = trim($keyword); + + foreach ((array) explode(' ', $keyword) as $value) + { + if (mb_strlen($value) > 5) + { + if (!in_array(mb_strtolower($value), array_map('strtolower', $stopWords))) + { + $result[] = sprintf('@title "%s" | @dn "%s"', $value, $value); + } + } + } + + if (empty($result)) + { + return '*'; + } + else + { + return implode(' | ', $result); + } + + break; + + default: + + $result = []; + + foreach ((array) explode(' ', $keyword) as $value) + { + if (!in_array(mb_strtolower($value), $stopWords)) + { + $result[] = sprintf('@"*%s*"', $value); + } + } + + return implode(' | ', $result); + } + } +} diff --git a/src/library/time.php b/src/library/time.php new file mode 100644 index 0000000..9199d3c --- /dev/null +++ b/src/library/time.php @@ -0,0 +1,45 @@ + _('year'), + 30 * 24 * 60 * 60 => _('month'), + 24 * 60 * 60 => _('day'), + 60 * 60 => _('hour'), + 60 => _('minute'), + 1 => _('second') + ]; + + $plural = [ + _('year') => _('years'), + _('month') => _('months'), + _('day') => _('days'), + _('hour') => _('hours'), + _('minute') => _('minutes'), + _('second') => _('seconds') + ]; + + foreach ($values as $key => $value) + { + $result = $diff / $key; + + if ($result >= 1) + { + $round = round($result); + + return sprintf('%s %s ago', $round, $round > 1 ? $plural[$value] : $value); + } + } + } +} diff --git a/src/library/valid.php b/src/library/valid.php new file mode 100644 index 0000000..0c3b843 --- /dev/null +++ b/src/library/valid.php @@ -0,0 +1,1898 @@ +userId) || !self::userId($value->userId, $error) || + !isset($value->address) || !self::userAddress($value->address, $error) || + !isset($value->timeAdded) || !self::userTimeAdded($value->timeAdded, $error) || + !isset($value->timeUpdated) || !self::userTimeUpdated($value->timeUpdated, $error) || + !isset($value->approved) || !self::userApproved($value->approved, $error) || + + (isset($value->public) && !self::userPublic($value->public, $error))) + { + array_push( + $error, + _('Invalid user data protocol') + ); + + return false; + } + + return true; + } + + public static function userId(mixed $value, array &$error = []) : bool + { + if (!is_int($value)) + { + array_push( + $error, + _('Invalid userId data type') + ); + + return false; + } + + return true; + } + + public static function userAddress(mixed $value, array &$error = []) : bool + { + if (!is_string($value)) + { + array_push( + $error, + _('Invalid user address data type') + ); + + return false; + } + + if (!self::host($value, $error)) + { + array_push( + $error, + sprintf( + _('User address "%s" not supported'), + $value + ) + ); + + return false; + } + + return true; + } + + public static function userTimeAdded(mixed $value, array &$error = []) : bool + { + if (!is_int($value)) + { + array_push( + $error, + _('Invalid user timeAdded data type') + ); + + return false; + } + + if ($value > time() || $value < 0) + { + array_push( + $error, + _('User timeAdded out of range') + ); + + return false; + } + + return true; + } + + public static function userTimeUpdated(mixed $value, array &$error = []) : bool + { + if (!(is_int($value) || is_bool($value))) + { + array_push( + $error, + _('Invalid user timeUpdated data type') + ); + + return false; + } + + if (is_int($value) && ($value > time() || $value < 0)) + { + array_push( + $error, + _('User timeUpdated out of range') + ); + + return false; + } + + return true; + } + + public static function userApproved(mixed $value, array &$error = []) : bool + { + if (!is_bool($value)) + { + array_push( + $error, + _('Invalid user approved data type') + ); + + return false; + } + + return true; + } + + public static function userPublic(mixed $value, array &$error = []) : bool + { + if (!is_bool($value)) + { + array_push( + $error, + _('Invalid user public data type') + ); + + return false; + } + + return true; + } + + // Magnet + public static function magnet(mixed $value, array &$error = []) : bool + { + if (!is_object($value)) + { + array_push( + $error, + _('Invalid magnet data type') + ); + + return false; + } + + // Validate required fields by protocol + if (!isset($value->userId) || !self::userId($value->userId, $error) || + + !isset($value->magnetId) || !self::magnetId($value->magnetId, $error) || + + + !isset($value->title) || !self::magnetTitle($value->title, $error) || + !isset($value->preview) || !self::magnetPreview($value->preview, $error) || + !isset($value->description) || !self::magnetDescription($value->description, $error) || + + !isset($value->comments) || !self::magnetComments($value->comments, $error) || + !isset($value->sensitive) || !self::magnetSensitive($value->sensitive, $error) || + !isset($value->approved) || !self::magnetApproved($value->approved, $error) || + + !isset($value->timeAdded) || !self::magnetTimeAdded($value->timeAdded, $error) || + !isset($value->timeUpdated) || !self::magnetTimeUpdated($value->timeUpdated, $error) || + + !isset($value->dn) || !self::magnetDn($value->dn, $error) || + !isset($value->xt) || !self::magnetXt($value->xt, $error) || + + !isset($value->xl) || !self::magnetXl($value->xl, $error) || + + !isset($value->kt) || !self::magnetKt($value->kt, $error) || + !isset($value->tr) || !self::magnetTr($value->tr, $error) || + !isset($value->as) || !self::magnetAs($value->as, $error) || + !isset($value->xs) || !self::magnetWs($value->xs, $error) || + + (isset($value->public) && !self::magnetPublic($value->public, $error))) + { + array_push( + $error, + _('Invalid magnet data protocol') + ); + + return false; + } + + return true; + } + + public static function magnetId(mixed $value, array &$error = []) : bool + { + if (!is_int($value)) + { + array_push( + $error, + _('Invalid magnetId data type') + ); + + return false; + } + + return true; + } + + public static function magnetTitle(mixed $value, array &$error = []) : bool + { + if (!is_string($value)) + { + array_push( + $error, + _('Invalid magnet title data type') + ); + + return false; + } + + if (!preg_match(MAGNET_TITLE_REGEX, $value)) + { + array_push( + $error, + sprintf( + _('Magnet title format does not match condition "%s"'), + MAGNET_TITLE_REGEX + ) + ); + + return false; + } + + if (mb_strlen($value) < MAGNET_TITLE_MIN_LENGTH || + mb_strlen($value) > MAGNET_TITLE_MAX_LENGTH) + { + array_push( + $error, + sprintf( + _('Magnet title out of %s-%s chars range'), + MAGNET_TITLE_MIN_LENGTH, + MAGNET_TITLE_MAX_LENGTH + ) + ); + + return false; + } + + return true; + } + + public static function magnetPreview(mixed $value, array &$error = []) : bool + { + if (!is_string($value)) + { + array_push( + $error, + _('Invalid magnet preview data type') + ); + + return false; + } + + if (!preg_match(MAGNET_PREVIEW_REGEX, $value)) + { + array_push( + $error, + sprintf( + _('Magnet preview format does not match condition "%s"'), + MAGNET_PREVIEW_REGEX + ) + ); + + return false; + } + + if (mb_strlen($value) < MAGNET_PREVIEW_MIN_LENGTH || + mb_strlen($value) > MAGNET_PREVIEW_MAX_LENGTH) + { + array_push( + $error, + sprintf( + _('Magnet preview out of %s-%s chars range'), + MAGNET_PREVIEW_MIN_LENGTH, + MAGNET_PREVIEW_MAX_LENGTH + ) + ); + + return false; + } + + return true; + } + + public static function magnetDescription(mixed $value, array &$error = []) : bool + { + if (!is_string($value)) + { + array_push( + $error, + _('Invalid magnet description data type') + ); + + return false; + } + + if (!preg_match(MAGNET_DESCRIPTION_REGEX, $value)) + { + array_push( + $error, + sprintf( + _('Magnet description format does not match condition "%s"'), + MAGNET_DESCRIPTION_REGEX + ) + ); + + return false; + } + + if (mb_strlen($value) < MAGNET_DESCRIPTION_MIN_LENGTH || + mb_strlen($value) > MAGNET_DESCRIPTION_MAX_LENGTH) + { + array_push( + $error, + sprintf( + _('Magnet description out of %s-%s chars range'), + MAGNET_DESCRIPTION_MIN_LENGTH, + MAGNET_DESCRIPTION_MAX_LENGTH + ) + ); + + return false; + } + + return true; + } + + public static function magnetComments(mixed $value, array &$error = []) : bool + { + if (!is_bool($value)) + { + array_push( + $error, + _('Invalid magnet comments data type') + ); + + return false; + } + + return true; + } + + public static function magnetPublic(mixed $value, array &$error = []) : bool + { + if (!is_bool($value)) + { + array_push( + $error, + _('Invalid magnet public data type') + ); + + return false; + } + + return true; + } + + public static function magnetApproved(mixed $value, array &$error = []) : bool + { + if (!is_bool($value)) + { + array_push( + $error, + _('Invalid magnet approved data type') + ); + + return false; + } + + return true; + } + + public static function magnetSensitive(mixed $value, array &$error = []) : bool + { + if (!is_bool($value)) + { + array_push( + $error, + _('Invalid magnet sensitive data type') + ); + + return false; + } + + return true; + } + + public static function magnetTimeAdded(mixed $value, array &$error = []) : bool + { + if (!is_int($value)) + { + array_push( + $error, + _('Invalid magnet timeAdded data type') + ); + + return false; + } + + if ($value > time() || $value < 0) + { + array_push( + $error, + _('Magnet timeAdded out of range') + ); + + return false; + } + + return true; + } + + public static function magnetTimeUpdated(mixed $value, array &$error = []) : bool + { + if (!(is_int($value) || is_bool($value))) + { + array_push( + $error, + _('Invalid magnet timeUpdated data type') + ); + + return false; + } + + if (is_int($value) && ($value > time() || $value < 0)) + { + array_push( + $error, + _('Magnet timeUpdated out of range') + ); + + return false; + } + + return true; + } + + public static function magnetDn(mixed $value, array &$error = []) : bool + { + if (!is_string($value)) + { + array_push( + $error, + _('Invalid magnet display name data type') + ); + + return false; + } + + if (!preg_match(MAGNET_DN_REGEX, $value)) + { + array_push( + $error, + sprintf( + _('Magnet display name format does not match condition "%s"'), + MAGNET_DN_REGEX + ) + ); + + return false; + } + + if (mb_strlen($value) < MAGNET_DN_MIN_LENGTH || + mb_strlen($value) > MAGNET_DN_MAX_LENGTH) + { + array_push( + $error, + sprintf( + _('Magnet display name out of %s-%s chars range'), + MAGNET_DN_MIN_LENGTH, + MAGNET_DN_MAX_LENGTH + ) + ); + + return false; + } + + return true; + } + + public static function magnetXl(mixed $value, array &$error = []) : bool + { + if (!(is_int($value) || is_float($value))) + { + array_push( + $error, + _('Invalid magnet exact length data type') + ); + + return false; + } + + return true; + } + + public static function magnetKt(mixed $value, array &$error = []) : bool + { + if (!is_object($value)) + { + array_push( + $error, + _('Invalid magnet keyword data type') + ); + + return false; + } + + $total = 0; + + foreach ($value as $kt) + { + if (!is_string($kt)) + { + array_push( + $error, + _('Invalid magnet keyword value data type') + ); + + return false; + } + + if (!preg_match(MAGNET_KT_REGEX, $kt)) + { + array_push( + $error, + sprintf( + _('Magnet keyword format does not match condition "%s"'), + MAGNET_KT_REGEX + ) + ); + + return false; + } + + if (mb_strlen($kt) < MAGNET_KT_MIN_LENGTH || + mb_strlen($kt) > MAGNET_KT_MAX_LENGTH) + { + array_push( + $error, + sprintf( + _('Magnet keyword out of %s-%s chars range'), + MAGNET_KT_MIN_LENGTH, + MAGNET_KT_MAX_LENGTH + ) + ); + + return false; + } + + $total++; + } + + if ($total < MAGNET_KT_MIN_QUANTITY || + $total > MAGNET_KT_MAX_QUANTITY) + { + array_push( + $error, + sprintf( + _('Magnet keywords quantity out of %s-%s range'), + MAGNET_KT_MIN_QUANTITY, + MAGNET_KT_MAX_QUANTITY + ) + ); + + return false; + } + + return true; + } + + public static function magnetXt(mixed $value, array &$error = []) : bool + { + if (!is_object($value)) + { + array_push( + $error, + _('Invalid magnet info hash data type') + ); + + return false; + } + + foreach ($value as $xt) + { + if (empty($xt->version)) + { + array_push( + $error, + _('Magnet info hash version required') + ); + + return false; + } + + if (!(is_int($xt->version) || is_float($xt->version))) + { + array_push( + $error, + _('Invalid magnet info hash version data type') + ); + + return false; + } + + if (empty($xt->value)) + { + array_push( + $error, + _('Magnet info hash value required') + ); + + return false; + } + + if (!is_string($xt->value)) + { + array_push( + $error, + _('Invalid magnet info hash value data type') + ); + + return false; + } + + switch ($xt->version) + { + case 1: + + if (!preg_match('/^([A-z0-9]{40})$/i', $xt->value)) + { + array_push( + $error, + _('Invalid magnet info hash v1 value') + ); + + return false; + } + + break; + + case 2: + + if (!preg_match('/^([A-z0-9]{64})$/i', $xt->value)) + { + array_push( + $error, + _('Invalid magnet info hash v2 value') + ); + + return false; + } + + break; + + default: + + array_push( + $error, + _('Magnet info hash version not supported') + ); + + return false; + } + } + + return true; + } + + public static function magnetTr(mixed $value, array &$error = []) : bool + { + if (!is_object($value)) + { + array_push( + $error, + _('Invalid magnet address tracker data type') + ); + + return false; + } + + $total = 0; + + foreach ($value as $tr) + { + if (!self::url($tr, $error)) + { + array_push( + $error, + sprintf( + _('Invalid magnet address tracker URL "%s"'), + $tr + ) + ); + + return false; + } + + $total++; + } + + if ($total < MAGNET_TR_MIN_QUANTITY || + $total > MAGNET_TR_MAX_QUANTITY) + { + array_push( + $error, + sprintf( + _('Magnet address trackers quantity out of %s-%s range'), + MAGNET_TR_MIN_QUANTITY, + MAGNET_TR_MAX_QUANTITY + ) + ); + + return false; + } + + return true; + } + + public static function magnetAs(mixed $value, array &$error = []) : bool + { + if (!is_object($value)) + { + array_push( + $error, + _('Invalid magnet acceptable source data type') + ); + + return false; + } + + $total = 0; + + foreach ($value as $as) + { + if (!self::url($as, $error)) + { + array_push( + $error, + sprintf( + _('Invalid magnet acceptable source URL "%s"'), + $as + ) + ); + + return false; + } + + $total++; + } + + if ($total < MAGNET_AS_MIN_QUANTITY || + $total > MAGNET_AS_MAX_QUANTITY) + { + array_push( + $error, + sprintf( + _('Magnet acceptable sources quantity out of %s-%s range'), + MAGNET_AS_MIN_QUANTITY, + MAGNET_AS_MAX_QUANTITY + ) + ); + + return false; + } + + return true; + } + + public static function magnetWs(mixed $value, array &$error = []) : bool + { + if (!is_object($value)) + { + array_push( + $error, + _('Invalid magnet web seed data type') + ); + + return false; + } + + $total = 0; + + foreach ($value as $ws) + { + if (!self::url($ws, $error)) + { + array_push( + $error, + sprintf( + _('Invalid magnet web seed URL "%s"'), + $ws + ) + ); + + return false; + } + + $total++; + } + + if ($total < MAGNET_WS_MIN_QUANTITY || + $total > MAGNET_WS_MAX_QUANTITY) + { + array_push( + $error, + sprintf( + _('Magnet web seeds quantity out of %s-%s range'), + MAGNET_WS_MIN_QUANTITY, + MAGNET_WS_MAX_QUANTITY + ) + ); + + return false; + } + + return true; + } + + // Magnet comment + public static function magnetComment(mixed $value, array &$error = []) : bool + { + if (!is_object($value)) + { + array_push( + $error, + _('Invalid magnet comment data type') + ); + + return false; + } + + if (!isset($value->magnetCommentId) || !self::magnetCommentId($value->magnetCommentId, $error) || + !isset($value->magnetId) || !self::magnetId($value->magnetId, $error) || + !isset($value->userId) || !self::userId($value->userId, $error) || + !isset($value->timeAdded) || !self::magnetCommentTimeAdded($value->timeAdded, $error) || + !isset($value->approved) || !self::magnetCommentApproved($value->approved, $error) || + !isset($value->value) || !self::magnetCommentValue($value->value, $error) || + + (isset($value->magnetCommentIdParent) && !self::magnetCommentIdParent($value->magnetCommentIdParent, $error)) || + + (isset($value->public) && !self::magnetCommentPublic($value->public, $error))) + { + array_push( + $error, + _('Invalid magnet comment data protocol') + ); + + return false; + } + + return true; + } + + public static function magnetCommentId(mixed $value, array &$error = []) : bool + { + if (!is_int($value)) + { + array_push( + $error, + _('Invalid magnetCommentId data type') + ); + + return false; + } + + return true; + } + + public static function magnetCommentIdParent(mixed $value, array &$error = []) : bool + { + if (!(is_null($value) || is_int($value))) + { + array_push( + $error, + _('Invalid magnet magnetCommentIdParent data type') + ); + + return false; + } + + if (is_int($value) && !self::magnetCommentId($value, $error)) + { + return false; + } + + return true; + } + + public static function magnetCommentTimeAdded(mixed $value, array &$error = []) : bool + { + if (!is_int($value)) + { + array_push( + $error, + _('Invalid magnet comment timeAdded data type') + ); + + return false; + } + + if ($value > time() || $value < 0) + { + array_push( + $error, + _('Magnet comment timeAdded out of range') + ); + + return false; + } + + return true; + } + + public static function magnetCommentApproved(mixed $value, array &$error = []) : bool + { + if (!is_bool($value)) + { + array_push( + $error, + _('Invalid magnet comment approved data type') + ); + + return false; + } + + return true; + } + + public static function magnetCommentPublic(mixed $value, array &$error = []) : bool + { + if (!is_bool($value)) + { + array_push( + $error, + _('Invalid magnet comment public data type') + ); + + return false; + } + + return true; + } + + public static function magnetCommentValue(mixed $value, array &$error = []) : bool + { + if (!is_string($value)) + { + array_push( + $error, + _('Invalid magnet comment value data type') + ); + + return false; + } + + if (mb_strlen($value) < MAGNET_COMMENT_MIN_LENGTH || + mb_strlen($value) > MAGNET_COMMENT_MAX_LENGTH) + { + array_push( + $error, + sprintf( + _('Magnet comment value out of %s-%s chars range'), + MAGNET_COMMENT_MIN_LENGTH, + MAGNET_COMMENT_MAX_LENGTH + ) + ); + + return false; + } + + return true; + } + + // Magnet download + public static function magnetDownload(mixed $value, array &$error = []) : bool + { + if (!is_object($value)) + { + array_push( + $error, + _('Invalid magnet download data type') + ); + + return false; + } + + if (!isset($value->magnetDownloadId) || !self::magnetDownloadId($value->magnetDownloadId, $error) || + !isset($value->magnetId) || !self::magnetId($value->magnetId, $error) || + !isset($value->userId) || !self::userId($value->userId, $error) || + !isset($value->timeAdded) || !self::magnetDownloadTimeAdded($value->timeAdded, $error) + ) + { + array_push( + $error, + _('Invalid magnet download data protocol') + ); + + return false; + } + + return true; + } + + public static function magnetDownloadId(mixed $value, array &$error = []) : bool + { + if (!is_int($value)) + { + array_push( + $error, + _('Invalid magnetDownloadId data type') + ); + + return false; + } + + return true; + } + + public static function magnetDownloadTimeAdded(mixed $value, array &$error = []) : bool + { + if (!is_int($value)) + { + array_push( + $error, + _('Invalid magnet download timeAdded data type') + ); + + return false; + } + + if ($value > time() || $value < 0) + { + array_push( + $error, + _('Magnet download timeAdded out of range') + ); + + return false; + } + + return true; + } + + // Magnet star + public static function magnetStar(mixed $value, array &$error = []) : bool + { + if (!is_object($value)) + { + array_push( + $error, + _('Invalid magnet star data type') + ); + + return false; + } + + if (!isset($value->magnetStarId) || !self::magnetViewId($value->magnetStarId, $error) || + !isset($value->magnetId) || !self::magnetId($value->magnetId, $error) || + !isset($value->userId) || !self::userId($value->userId, $error) || + !isset($value->timeAdded) || !self::magnetStarTimeAdded($value->timeAdded, $error) || + !isset($value->value) || !self::magnetStarValue($value->value, $error) + ) + { + array_push( + $error, + _('Invalid magnet star data protocol') + ); + + return false; + } + + return true; + } + + public static function magnetStarId(mixed $value, array &$error = []) : bool + { + if (!is_int($value)) + { + array_push( + $error, + _('Invalid magnetStarId data type') + ); + + return false; + } + + return true; + } + + public static function magnetStarValue(mixed $value, array &$error = []) : bool + { + if (!is_bool($value)) + { + array_push( + $error, + _('Invalid magnet star value data type') + ); + + return false; + } + + return true; + } + + public static function magnetStarTimeAdded(mixed $value, array &$error = []) : bool + { + if (!is_int($value)) + { + array_push( + $error, + _('Invalid magnet star timeAdded data type') + ); + + return false; + } + + if ($value > time() || $value < 0) + { + array_push( + $error, + _('Magnet star timeAdded out of range') + ); + + return false; + } + + return true; + } + + // Magnet view + public static function magnetView(mixed $value, array &$error = []) : bool + { + if (!is_object($value)) + { + array_push( + $error, + _('Invalid magnet view data type') + ); + + return false; + } + + if (!isset($value->magnetViewId) || !self::magnetViewId($value->magnetViewId, $error) || + !isset($value->magnetId) || !self::magnetId($value->magnetId, $error) || + !isset($value->userId) || !self::userId($value->userId, $error) || + !isset($value->timeAdded) || !self::magnetViewTimeAdded($value->timeAdded, $error) + ) + { + array_push( + $error, + _('Invalid magnet view data protocol') + ); + + return false; + } + + return true; + } + + public static function magnetViewId(mixed $value, array &$error = []) : bool + { + if (!is_int($value)) + { + array_push( + $error, + _('Invalid magnetViewId data type') + ); + + return false; + } + + return true; + } + + public static function magnetViewTimeAdded(mixed $value, array &$error = []) : bool + { + if (!is_int($value)) + { + array_push( + $error, + _('Invalid magnet view timeAdded data type') + ); + + return false; + } + + if ($value > time() || $value < 0) + { + array_push( + $error, + _('Magnet view timeAdded out of range') + ); + + return false; + } + + return true; + } + + // Torrent + public static function torrentAnnounce(mixed $value, array &$error = []) : bool + { + if (!is_string($value)) + { + array_push( + $error, + _('Invalid torrent announce data type') + ); + + return false; + } + + if (!self::url($tr, $error)) + { + array_push( + $error, + sprintf( + _('Invalid torrent announce URL "%s"'), + $tr + ) + ); + + return false; + } + + return true; + } + + public static function torrentAnnounceList(mixed $value, array &$error = []) : bool + { + if (!is_array($value)) + { + array_push( + $error, + _('Invalid torrent announce data type') + ); + + return false; + } + + $total = 0; + + foreach ($value as $list) + { + if (!is_array($list)) + { + array_push( + $error, + _('Invalid torrent announce list') + ); + + return false; + } + + foreach ($list as $announce) + { + if (!self::torrentAnnounce($announce, $error)) + { + array_push( + $error, + sprintf( + _('Invalid torrent announce list URL "%s"'), + $announce + ) + ); + + return false; + } + + $total++; + } + } + + if ($total < TORRENT_ANNOUNCE_MIN_QUANTITY || + $total > TORRENT_ANNOUNCE_MAX_QUANTITY) + { + array_push( + $error, + sprintf( + _('Torrent announces quantity out of %s-%s range'), + TORRENT_ANNOUNCE_MIN_QUANTITY, + TORRENT_ANNOUNCE_MAX_QUANTITY + ) + ); + + return false; + } + + return true; + } + + public static function torrentComment(mixed $value, array &$error = []) : bool + { + if (!is_string($value)) + { + array_push( + $error, + _('Invalid torrent comment data type') + ); + + return false; + } + + if (!preg_match(TORRENT_COMMENT_REGEX, $value)) + { + array_push( + $error, + sprintf( + _('Torrent comment format does not match condition "%s"'), + TORRENT_COMMENT_REGEX + ) + ); + + return false; + } + + if (mb_strlen($value) < TORRENT_COMMENT_MIN_LENGTH || + mb_strlen($value) > TORRENT_COMMENT_MAX_LENGTH) + { + array_push( + $error, + sprintf( + _('Torrent comment out of %s-%s chars range'), + TORRENT_COMMENT_MIN_LENGTH, + TORRENT_COMMENT_MAX_LENGTH + ) + ); + + return false; + } + + return true; + } + + public static function torrentCreatedBy(mixed $value, array &$error = []) : bool + { + if (!is_string($value)) + { + array_push( + $error, + _('Invalid torrent created by data type') + ); + + return false; + } + + if (!preg_match(TORRENT_CREATED_BY_REGEX, $value)) + { + array_push( + $error, + sprintf( + _('Torrent created by format does not match condition "%s"'), + TORRENT_CREATED_BY_REGEX + ) + ); + + return false; + } + + if (mb_strlen($value) < TORRENT_CREATED_BY_MIN_LENGTH || + mb_strlen($value) > TORRENT_CREATED_BY_MAX_LENGTH) + { + array_push( + $error, + sprintf( + _('Torrent created by out of %s-%s chars range'), + TORRENT_CREATED_BY_MIN_LENGTH, + TORRENT_CREATED_BY_MAX_LENGTH + ) + ); + + return false; + } + + return true; + } + + public static function torrentCreationDate(mixed $value, array &$error = []) : bool + { + if (!is_int($value)) + { + array_push( + $error, + _('Invalid torrent creation date data type') + ); + + return false; + } + + if ($value > time() || $value < 0) + { + array_push( + $error, + _('Torrent creation date out of range') + ); + + return false; + } + + return true; + } + + public static function torrentInfo(mixed $value, array &$error = []) : bool + { + if (!is_array($value)) + { + array_push( + $error, + _('Invalid torrent info data type') + ); + + return false; + } + + if (empty($value)) + { + array_push( + $error, + _('Torrent info has no keys') + ); + + return false; + } + + foreach ($value as $info) + { + if (!is_array($info)) + { + array_push( + $error, + _('Invalid torrent info protocol') + ); + + return false; + } + + if (empty($info)) + { + array_push( + $error, + _('Torrent info has no values') + ); + + return false; + } + + foreach ($info as $key => $data) + { + switch ($key) + { + case 'file-duration': + + if (!self::torrentInfoFileDuration($data, $error)) + { + array_push( + $error, + _('Invalid torrent info file-duration') + ); + + return false; + } + + break; + case 'file-media': + + if (!self::torrentInfoFileMedia($data, $error)) + { + array_push( + $error, + _('Invalid torrent info file-media') + ); + + return false; + } + + break; + case 'files': + + if (!self::torrentInfoFiles($data, $error)) + { + array_push( + $error, + _('Invalid torrent info files') + ); + + return false; + } + + break; + case 'name': + + if (!self::torrentInfoName($data, $error)) + { + array_push( + $error, + _('Invalid torrent info name') + ); + + return false; + } + + break; + case 'piece length': + + if (!self::torrentInfoPieceLength($data, $error)) + { + array_push( + $error, + _('Invalid torrent info piece length') + ); + + return false; + } + + break; + case 'pieces': + + if (!self::torrentInfoPieces($data, $error)) + { + array_push( + $error, + _('Invalid torrent info pieces') + ); + + return false; + } + + break; + case 'private': + + if (!self::torrentInfoPrivate($data, $error)) + { + array_push( + $error, + _('Invalid torrent info private') + ); + + return false; + } + + break; + case 'profiles': + + if (!self::torrentInfoProfiles($data, $error)) + { + array_push( + $error, + _('Invalid torrent info profiles') + ); + + return false; + } + + break; + case 'source': + + if (!self::torrentInfoSource($data, $error)) + { + array_push( + $error, + _('Invalid torrent info source') + ); + + return false; + } + + break; + default: + array_push( + $error, + _('Not supported torrent info key') + ); + } + } + } + + return true; + } + + public static function torrentInfoName(mixed $value, array &$error = []) : bool + { + if (!is_string($value)) + { + array_push( + $error, + _('Invalid torrent info name data type') + ); + + return false; + } + + if (!preg_match(TORRENT_INFO_NAME_REGEX, $value)) + { + array_push( + $error, + sprintf( + _('Torrent info name format does not match condition "%s"'), + TORRENT_INFO_NAME_REGEX + ) + ); + + return false; + } + + if (mb_strlen($value) < TORRENT_INFO_NAME_MIN_LENGTH || + mb_strlen($value) > TORRENT_INFO_NAME_MAX_LENGTH) + { + array_push( + $error, + sprintf( + _('Torrent info name out of %s-%s chars range'), + TORRENT_INFO_NAME_MIN_LENGTH, + TORRENT_INFO_NAME_MAX_LENGTH + ) + ); + + return false; + } + + return true; + } + + public static function torrentInfoSource(mixed $value, array &$error = []) : bool + { + if (!is_string($value)) + { + array_push( + $error, + _('Invalid torrent info source data type') + ); + + return false; + } + + if (!preg_match(TORRENT_INFO_SOURCE_REGEX, $value)) + { + array_push( + $error, + sprintf( + _('Torrent info source format does not match condition "%s"'), + TORRENT_INFO_SOURCE_REGEX + ) + ); + + return false; + } + + if (mb_strlen($value) < TORRENT_INFO_SOURCE_MIN_LENGTH || + mb_strlen($value) > TORRENT_INFO_SOURCE_MAX_LENGTH) + { + array_push( + $error, + sprintf( + _('Torrent info source out of %s-%s chars range'), + TORRENT_INFO_SOURCE_MIN_LENGTH, + TORRENT_INFO_SOURCE_MAX_LENGTH + ) + ); + + return false; + } + + return true; + + return true; + } + + public static function torrentInfoFileDuration(mixed $value, array &$error = []) : bool + { + if (!is_int($value)) + { + array_push( + $error, + _('Invalid torrent file-duration data type') + ); + + return false; + } + + if ($value < 0) + { + array_push( + $error, + _('Torrent file-duration out of range') + ); + + return false; + } + + return true; + } + + public static function torrentInfoPieceLength(mixed $value, array &$error = []) : bool + { + if (!is_int($value)) + { + array_push( + $error, + _('Invalid torrent info piece length data type') + ); + + return false; + } + + if ($value < 0) + { + array_push( + $error, + _('Torrent torrent info piece length out of range') + ); + + return false; + } + + return true; + } + + public static function torrentInfoPieces(mixed $value, array &$error = []) : bool + { + // @TODO + + return true; + } + + public static function torrentInfoPrivate(mixed $value, array &$error = []) : bool + { + if (!is_int($value)) + { + array_push( + $error, + _('Invalid torrent info private data type') + ); + + return false; + } + + if (!in_array($value, [0, 1])) + { + array_push( + $error, + _('Invalid torrent info private value') + ); + + return false; + } + + return true; + } + + public static function torrentInfoProfiles(mixed $value, array &$error = []) : bool + { + // @TODO + + return true; + } + + public static function torrentInfoFileMedia(mixed $value, array &$error = []) : bool + { + // @TODO + + return true; + } + + public static function torrentInfoFiles(mixed $value, array &$error = []) : bool + { + // @TODO + + return true; + } +} \ No newline at end of file diff --git a/src/public/action.php b/src/public/action.php new file mode 100644 index 0000000..b4b1bdc --- /dev/null +++ b/src/public/action.php @@ -0,0 +1,670 @@ + true, + 'message' => _('Internal server error'), + 'title' => sprintf(_('Oops - %s'), WEBSITE_NAME) +]; + +// Begin action request +switch (isset($_GET['target']) ? urldecode($_GET['target']) : false) +{ + case 'profile': + + switch (isset($_GET['toggle']) ? $_GET['toggle'] : false) + { + case 'jidenticon': + + // Yggdrasil connections only + if (!Valid::host($_SERVER['REMOTE_ADDR'])) + { + $response->success = false; + $response->message = _('Yggdrasil connection required for this action'); + } + + // Init session + else if (!$userId = $db->initUserId($_SERVER['REMOTE_ADDR'], USER_DEFAULT_APPROVED, time())) + { + $response->success = false; + $response->message = _('Could not init user session'); + } + + // Get user + else if (!$user = $db->getUser($userId)) + { + $response->success = false; + $response->message = _('Could not init user info'); + } + + // On first visit, redirect user to the welcome page with access level question + else if (is_null($user->public)) + { + header( + sprintf('Location: %s/welcome.php', WEBSITE_URL) + ); + } + + // Render icon + else + { + header('Cache-Control: max-age=604800'); + + + $icon = new Jdenticon\Identicon(); + + $icon->setValue($user->{USER_IDENTICON_FIELD}); + $icon->setSize(empty($_GET['size']) ? 100 : (int) $_GET['size']); + $icon->setStyle( + [ + 'backgroundColor' => 'rgba(255, 255, 255, 0)', + ] + ); + $icon->displayImage('webp'); + } + + break; + } + + break; + + case 'comment': + + switch (isset($_GET['toggle']) ? $_GET['toggle'] : false) + { + case 'approved': + + // Yggdrasil connections only + if (!Valid::host($_SERVER['REMOTE_ADDR'])) + { + $response->success = false; + $response->message = _('Yggdrasil connection required for this action'); + } + + // Init session + else if (!$userId = $db->initUserId($_SERVER['REMOTE_ADDR'], USER_DEFAULT_APPROVED, time())) + { + $response->success = false; + $response->message = _('Could not init user session'); + } + + // Get user + else if (!$user = $db->getUser($userId)) + { + $response->success = false; + $response->message = _('Could not init user info'); + } + + // On first visit, redirect user to the welcome page with access level question + else if (is_null($user->public)) + { + header( + sprintf('Location: %s/welcome.php', WEBSITE_URL) + ); + } + + // Magnet comment exists + else if (!$magnetComment = $db->getMagnetComment(isset($_GET['magnetCommentId']) && $_GET['magnetCommentId'] > 0 ? (int) $_GET['magnetCommentId'] : 0)) + { + $response->success = false; + $response->message = _('Requested magnet comment not found'); + } + + // Access allowed + else if (!in_array($user->address, MODERATOR_IP_LIST)) { + + $response->success = false; + $response->message = _('Access denied'); + } + + // Validate callback + else if (empty($_GET['callback'])) + { + $response->success = false; + $response->message = _('Callback required'); + } + + // Validate base64 + else if (!$callback = (string) @base64_decode($_GET['callback'])) + { + $response->success = false; + $response->message = _('Invalid callback encoding'); + } + + // Request valid + else + { + if ($magnetComment->approved) + { + $db->updateMagnetCommentApproved($magnetComment->magnetCommentId, false); + + if (USER_AUTO_APPROVE_ON_COMMENT_APPROVE) + { + $db->updateUserApproved($magnetComment->userId, false, time()); + } + } + else + { + $db->updateMagnetCommentApproved($magnetComment->magnetCommentId, true); + + if (USER_AUTO_APPROVE_ON_COMMENT_APPROVE) + { + $db->updateUserApproved($magnetComment->userId, true, time()); + } + } + + // Redirect to edit page + header( + sprintf('Location: %s', $callback) + ); + } + + break; + + case 'new': + + // Yggdrasil connections only + if (!Valid::host($_SERVER['REMOTE_ADDR'])) + { + $response->success = false; + $response->message = _('Yggdrasil connection required for this action'); + } + + // Init session + else if (!$userId = $db->initUserId($_SERVER['REMOTE_ADDR'], USER_DEFAULT_APPROVED, time())) + { + $response->success = false; + $response->message = _('Could not init user session'); + } + + // Get user + else if (!$user = $db->getUser($userId)) + { + $response->success = false; + $response->message = _('Could not init user info'); + } + + // On first visit, redirect user to the welcome page with access level question + else if (is_null($user->public)) + { + header( + sprintf('Location: %s/welcome.php', WEBSITE_URL) + ); + } + + // Magnet exists + else if (!$magnet = $db->getMagnet(isset($_GET['magnetId']) && $_GET['magnetId'] > 0 ? (int) $_GET['magnetId'] : 0)) + { + $response->success = false; + $response->message = _('Requested magnet not found'); + } + + // Access allowed + else if (!($user->address == $db->getUser($magnet->userId)->address || in_array($user->address, MODERATOR_IP_LIST) || ($magnet->public && $magnet->approved))) { + + $response->success = false; + $response->message = _('Magnet not available for this action'); + } + + // Validate callback + else if (empty($_GET['callback'])) + { + $response->success = false; + $response->message = _('Callback required'); + } + + // Validate base64 + else if (!$callback = (string) @base64_decode($_GET['callback'])) + { + $response->success = false; + $response->message = _('Invalid callback encoding'); + } + + // Validate comment value + else if (empty($_POST['comment']) || + mb_strlen($_POST['comment']) < MAGNET_COMMENT_MIN_LENGTH || + mb_strlen($_POST['comment']) > MAGNET_COMMENT_MAX_LENGTH) + { + $response->success = false; + $response->message = sprintf(_('Valid comment value required, %s-%s chars allowed'), MAGNET_COMMENT_MIN_LENGTH, MAGNET_COMMENT_MAX_LENGTH); + } + + // Request valid + else + { + if ($magnetCommentId = $db->addMagnetComment($magnet->magnetId, + $user->userId, + null, // @TODO implement threads + trim($_POST['comment']), + $user->approved || in_array($user->address, MODERATOR_IP_LIST) ? true : MAGNET_COMMENT_DEFAULT_APPROVED, + MAGNET_COMMENT_DEFAULT_PUBLIC, + time())) + { + + // Push event to other nodes + if (API_EXPORT_ENABLED && + API_EXPORT_PUSH_ENABLED && + API_EXPORT_USERS_ENABLED && + API_EXPORT_MAGNETS_ENABLED && + API_EXPORT_MAGNET_COMMENTS_ENABLED) + { + if (!$memoryApiExportPush = $memory->get('api.export.push')) + { + $memoryApiExportPush = []; + } + + $memoryApiExportPush[] = (object) + [ + 'time' => time(), + 'userId' => $user->userId, + 'magnetId' => $magnet->magnetId, + 'magnetCommentId' => $magnetCommentId + ]; + + $memory->set('api.export.push', $memoryApiExportPush, 3600); + } + + // Redirect to referrer page + header( + sprintf('Location: %s#comment-%s', $callback, $magnetCommentId) + ); + } + } + + break; + + default: + + header( + sprintf('Location: %s', WEBSITE_URL) + ); + } + + break; + + case 'magnet': + + switch (isset($_GET['toggle']) ? $_GET['toggle'] : false) + { + case 'star': + + // Yggdrasil connections only + if (!Valid::host($_SERVER['REMOTE_ADDR'])) + { + $response->success = false; + $response->message = _('Yggdrasil connection required for this action'); + } + + // Init session + else if (!$userId = $db->initUserId($_SERVER['REMOTE_ADDR'], USER_DEFAULT_APPROVED, time())) + { + $response->success = false; + $response->message = _('Could not init user session'); + } + + // Get user + else if (!$user = $db->getUser($userId)) + { + $response->success = false; + $response->message = _('Could not init user info'); + } + + // On first visit, redirect user to the welcome page with access level question + else if (is_null($user->public)) + { + header( + sprintf('Location: %s/welcome.php', WEBSITE_URL) + ); + } + + // Magnet exists + else if (!$magnet = $db->getMagnet(isset($_GET['magnetId']) && $_GET['magnetId'] > 0 ? (int) $_GET['magnetId'] : 0)) + { + $response->success = false; + $response->message = _('Requested magnet not found'); + } + + // Access allowed + else if (!($_SERVER['REMOTE_ADDR'] == $db->getUser($magnet->userId)->address || in_array($_SERVER['REMOTE_ADDR'], MODERATOR_IP_LIST) || ($magnet->public && $magnet->approved))) { + + $response->success = false; + $response->message = _('Magnet not available for this action'); + } + + // Validate callback + else if (empty($_GET['callback'])) + { + $response->success = false; + $response->message = _('Callback required'); + } + + // Validate base64 + else if (!$callback = (string) @base64_decode($_GET['callback'])) + { + $response->success = false; + $response->message = _('Invalid callback encoding'); + } + + // Request valid + else + { + // Save star + if ($magnetStarId = $db->addMagnetStar( $magnet->magnetId, + $user->userId, + !$db->findLastMagnetStarValue($magnet->magnetId, $user->userId), + time())) + { + // Push event to other nodes + if (API_EXPORT_ENABLED && + API_EXPORT_PUSH_ENABLED && + API_EXPORT_USERS_ENABLED && + API_EXPORT_MAGNETS_ENABLED && + API_EXPORT_MAGNET_STARS_ENABLED) + { + if (!$memoryApiExportPush = $memory->get('api.export.push')) + { + $memoryApiExportPush = []; + } + + $memoryApiExportPush[] = (object) + [ + 'time' => time(), + 'userId' => $user->userId, + 'magnetId' => $magnet->magnetId, + 'magnetStarId' => $magnetStarId + ]; + + $memory->set('api.export.push', $memoryApiExportPush, 3600); + } + + // Redirect to edit page + header( + sprintf('Location: %s', $callback) + ); + } + } + + break; + + case 'new': + + // Yggdrasil connections only + if (!Valid::host($_SERVER['REMOTE_ADDR'])) + { + $response->success = false; + $response->message = _('Yggdrasil connection required for this action'); + } + + // Init session + else if (!$userId = $db->initUserId($_SERVER['REMOTE_ADDR'], USER_DEFAULT_APPROVED, time())) + { + $response->success = false; + $response->message = _('Could not init user session'); + } + + // Get user + else if (!$user = $db->getUser($userId)) + { + $response->success = false; + $response->message = _('Could not init user info'); + } + + // On first visit, redirect user to the welcome page with access level question + else if (is_null($user->public)) + { + header( + sprintf('Location: %s/welcome.php', WEBSITE_URL) + ); + } + + // Validate link + if (empty($_GET['magnet'])) + { + $response->success = false; + $response->message = _('Link required'); + } + + // Validate magnet + else if (!$magnet = Yggverse\Parser\Magnet::parse($_GET['magnet'])) + { + $response->success = false; + $response->message = _('Invalid magnet link'); + } + + // Request valid + else + { + // Begin magnet registration + try + { + $db->beginTransaction(); + + // Init magnet + if ($magnetId = $db->addMagnet( $user->userId, + $magnet->xl, + $magnet->dn, + '', // @TODO deprecated, remove + MAGNET_DEFAULT_PUBLIC, + MAGNET_DEFAULT_COMMENTS, + MAGNET_DEFAULT_SENSITIVE, + $user->approved ? true : MAGNET_DEFAULT_APPROVED, + time())) + { + foreach ($magnet as $key => $value) + { + switch ($key) + { + case 'xt': + foreach ($value as $xt) + { + if (Yggverse\Parser\Magnet::isXTv1($xt)) + { + $db->addMagnetToInfoHash( + $magnetId, + $db->initInfoHashId( + Yggverse\Parser\Magnet::filterInfoHash($xt), 1 + ) + ); + } + if (Yggverse\Parser\Magnet::isXTv2($xt)) + { + $db->addMagnetToInfoHash( + $magnetId, + $db->initInfoHashId( + Yggverse\Parser\Magnet::filterInfoHash($xt), 2 + ) + ); + } + } + break; + case 'tr': + foreach ($value as $tr) + { + if (Valid::url($tr)) + { + if ($url = Yggverse\Parser\Url::parse($tr)) + { + $db->initMagnetToAddressTrackerId( + $magnetId, + $db->initAddressTrackerId( + $db->initSchemeId($url->host->scheme), + $db->initHostId($url->host->name), + $db->initPortId($url->host->port), + $db->initUriId($url->page->uri) + ) + ); + } + } + } + break; + case 'ws': + foreach ($value as $ws) + { + // @TODO + } + break; + case 'as': + foreach ($value as $as) + { + if (Valid::url($as)) + { + if ($url = Yggverse\Parser\Url::parse($as)) + { + $db->initMagnetToAcceptableSourceId( + $magnetId, + $db->initAcceptableSourceId( + $db->initSchemeId($url->host->scheme), + $db->initHostId($url->host->name), + $db->initPortId($url->host->port), + $db->initUriId($url->page->uri) + ) + ); + } + } + } + break; + case 'xs': + foreach ($value as $xs) + { + if (Valid::url($xs)) + { + if ($url = Yggverse\Parser\Url::parse($xs)) + { + $db->initMagnetToExactSourceId( + $magnetId, + $db->initExactSourceId( + $db->initSchemeId($url->host->scheme), + $db->initHostId($url->host->name), + $db->initPortId($url->host->port), + $db->initUriId($url->page->uri) + ) + ); + } + } + } + break; + case 'mt': + foreach ($value as $mt) + { + // @TODO + } + break; + case 'x.pe': + foreach ($value as $xPe) + { + // @TODO + } + break; + case 'kt': + foreach ($value as $kt) + { + $db->initMagnetToKeywordTopicId( + $magnetId, + $db->initKeywordTopicId(trim(mb_strtolower(strip_tags(html_entity_decode($kt))))) + ); + } + break; + } + } + + $db->commit(); + + // Redirect to edit page + header(sprintf('Location: %s/edit.php?magnetId=%s', trim(WEBSITE_URL, '/'), $magnetId)); + } + + } catch (Exception $e) { + + var_dump($e); + + $db->rollBack(); + } + } + + break; + } + + break; +} + +?> + + + + + + + + <?php echo $response->title ?> + + + + + + +
+
+ +
+
+
+
+
+
+
+
message ?>
+
+
+
+ +
+
+ + + +
+
+ +
+
+ + + \ No newline at end of file diff --git a/src/public/api/push.php b/src/public/api/push.php new file mode 100644 index 0000000..ad63354 --- /dev/null +++ b/src/public/api/push.php @@ -0,0 +1,938 @@ + [ + 'ISO8601' => date('c'), + 'total' => microtime(true), + ], + 'memory' => + [ + 'start' => memory_get_usage(), + 'total' => 0, + 'peaks' => 0 + ], + 'exception' => [] +]; + +// Define response +$response = +[ + 'status' => false, + 'message' => _('Internal server error'), + 'data' => [ + 'user' => [], + 'magnet' => [], + 'magnetDownload' => [], + 'magnetComment' => [], + 'magnetView' => [], + 'magnetStar' => [], + ] +]; + +// Init connections whitelist +$connectionWhiteList = []; + +foreach (json_decode(file_get_contents(__DIR__ . '/../../config/nodes.json')) as $node) +{ + // Skip non-condition addresses + if (!Valid::url($node->manifest)) + { + continue; + } + + // Skip current host + $thisUrl = Yggverse\Parser\Url::parse(WEBSITE_URL); + $manifestUrl = Yggverse\Parser\Url::parse($node->manifest); + + if (empty($thisUrl->host->name) || + empty($manifestUrl->host->name) || + $manifestUrl->host->name == $thisUrl->host->name) // @TODO some mirrors could be available on same host sub-folders, improve condition + { + continue; + } + + $connectionWhiteList[] = str_replace(['[',']'], false, $manifestUrl->host->name); +} + +// API import enabled +$error = []; + +if (!API_IMPORT_ENABLED) +{ + $response = + [ + 'status' => false, + 'message' => _('Import API disabled') + ]; +} + +// Push API import enabled +else if (!API_IMPORT_PUSH_ENABLED) +{ + $response = + [ + 'status' => false, + 'message' => _('Push API import disabled') + ]; +} + +// Yggdrasil connections only +else if (!Valid::host($_SERVER['REMOTE_ADDR'], $error)) +{ + $response = + [ + 'status' => false, + 'message' => $error + ]; +} + +// Init session +else if (!in_array($_SERVER['REMOTE_ADDR'], $connectionWhiteList)) +{ + $response = + [ + 'status' => false, + 'message' => sprintf( + _('Push API access denied for host "%s"'), + $_SERVER['REMOTE_ADDR'] + ) + ]; +} + +// Init session +else if (!$userId = $db->initUserId($_SERVER['REMOTE_ADDR'], USER_DEFAULT_APPROVED, time())) +{ + $response = + [ + 'status' => false, + 'message' => _('Could not init user session for this connection') + ]; +} + +// Validate required fields +else if (empty($_POST['data'])) +{ + $response = + [ + 'status' => false, + 'message' => _('Request protocol invalid') + ]; +} + +// Validate required fields +else if (false === $data = json_decode($_POST['data'])) +{ + $response = + [ + 'status' => false, + 'message' => _('Could not decode data requested') + ]; +} + +// Import begin +else +{ + $response = + [ + 'status' => true, + 'message' => sprintf( + _('Connection for "%s" established'), + $_SERVER['REMOTE_ADDR'] + ) + ]; + + // Init alias registry + $aliasUserId = []; + $aliasMagnetId = []; + + try { + + // Transaction begin + $db->beginTransaction(); + + // Process request + foreach ((object) $data as $field => $remote) + { + // Process alias fields + switch ($field) + { + case 'user': + + if (!API_IMPORT_USERS_ENABLED) + { + $response['user'][] = [ + 'status' => false, + 'message' => _('Users import disabled on this node. Related content skipped.') + ]; + + continue 2; + } + + // Validate remote fields + $error = []; + + if (!Valid::user($remote, $error)) + { + $response['user'][] = [ + 'status' => false, + 'message' => sprintf( + _('User data mismatch protocol with error: %s'), + print_r($error, true) + ), + ]; + + continue 2; + } + + // Skip import on user approved required + if (API_IMPORT_USERS_APPROVED_ONLY && !$remote->approved) + { + $response['user'][] = [ + 'status' => false, + 'message' => _('Node accepting approved users only') + ]; + + continue 2; + } + + // Init local user by remote address + if (!$local = $db->getUser($db->initUserId($remote->address, + USER_AUTO_APPROVE_ON_IMPORT_APPROVED ? $remote->approved : USER_DEFAULT_APPROVED, + $remote->timeAdded))) + { + $response['user'][] = [ + 'status' => false, + 'message' => _('Could not init user profile') + ]; + + continue 2; + } + + else + { + $response['user'][] = [ + 'status' => true, + 'message' => sprintf( + _('User profile successfully associated with ID "%s"'), + $local->userId + ) + ]; + } + + // Register user alias + $aliasUserId[$remote->userId] = $local->userId; + + // Update time added if newer + if ($local->timeAdded < $remote->timeAdded) + { + $db->updateUserTimeAdded( + $local->userId, + $remote->timeAdded + ); + + $response['user'][] = [ + 'status' => true, + 'message' => sprintf( + _('Field "timeAdded" changed to newer value for user ID "%s"'), + $local->userId + ) + ]; + } + + // Update user info if newer + if ($local->timeUpdated < $remote->timeUpdated) + { + // Update time updated + $db->updateUserTimeUpdated( + $local->userId, + $remote->timeUpdated + ); + + $response['user'][] = [ + 'status' => true, + 'message' => sprintf( + _('Field "timeUpdated" changed to newer value for user ID "%s"'), + $local->userId + ) + ]; + + // Update approved for existing user + if (USER_AUTO_APPROVE_ON_IMPORT_APPROVED && $local->approved !== $remote->approved && $remote->approved) + { + $db->updateUserApproved( + $local->userId, + $remote->approved, + $remote->timeUpdated + ); + + $response['user'][] = [ + 'status' => true, + 'message' => sprintf( + _('Field "approved" changed to newer value for user ID "%s"'), + $local->userId + ) + ]; + } + + // Set public as received remotely + if (!$local->public) + { + $db->updateUserPublic( + $local->userId, + true, + $remote->timeUpdated + ); + + $response['user'][] = [ + 'status' => true, + 'message' => sprintf( + _('Field "public" changed to newer value for user ID "%s"'), + $local->userId + ) + ]; + } + } + + break; + case 'magnet': + + if (!API_IMPORT_MAGNETS_ENABLED) + { + $response['magnet'][] = [ + 'status' => false, + 'message' => _('Magnets import disabled on this node. Related content skipped.') + ]; + + continue 2; + } + + // Validate remote fields + $error = []; + + if (!Valid::magnet($remote, $error)) + { + $response['magnet'][] = [ + 'status' => false, + 'message' => sprintf( + _('Magnet data mismatch protocol with error: %s'), + print_r($error, true) + ), + ]; + + continue 2; + } + + // User local alias required + if (!isset($aliasUserId[$remote->userId])) + { + $response['magnet'][] = [ + 'status' => false, + 'message' => _('User data relation not found for magnet'), + ]; + + continue 2; + } + + // Skip import on magnet approved required + if (API_IMPORT_MAGNETS_APPROVED_ONLY && !$remote->approved) + { + $response['magnet'][] = [ + 'status' => false, + 'message' => _('Node accepting approved magnets only') + ]; + + continue 2; + } + + /// Add new magnet if not exist by timestamp added for this user + if ($local = $db->findMagnet($aliasUserId[$remote->userId], $remote->timeAdded)) + { + $response['magnet'][] = [ + 'status' => true, + 'message' => sprintf( + _('Magnet successfully associated with ID "%s"'), + $local->magnetId + ) + ]; + } + + /// Add and init new magnet if not exist + else if ($local = $db->getMagnet( + $db->addMagnet( + $aliasUserId[$remote->userId], + $remote->xl, + $remote->dn, + '', // @TODO linkSource used for debug only, will be deleted later + true, + $remote->comments, + $remote->sensitive, + MAGNET_AUTO_APPROVE_ON_IMPORT_APPROVED ? $remote->approved : MAGNET_DEFAULT_APPROVED, + $remote->timeAdded + ) + ) + ) + { + $response['magnet'][] = [ + 'status' => true, + 'message' => sprintf( + _('Magnet successfully synced with ID "%s"'), + $local->magnetId + ) + ]; + } + + else + { + $response['magnet'][] = [ + 'status' => false, + 'message' => sprintf( + _('Could not init magnet: %s'), + $remote + ) + ]; + + continue 2; + } + + /// Add magnet alias for this host + $aliasMagnetId[$remote->magnetId] = $local->magnetId; + + /// Update time added if newer + if ($local->timeAdded < $remote->timeAdded) + { + $db->updateMagnetTimeAdded( + $local->magnetId, + $remote->timeAdded + ); + + $response['magnet'][] = [ + 'status' => true, + 'message' => sprintf( + _('Field "timeAdded" changed to newer value for magnet ID "%s"'), + $local->magnetId + ) + ]; + } + + /// Update info if remote newer + if ($local->timeUpdated < $remote->timeUpdated) + { + // Magnet fields + $db->updateMagnetXl($local->magnetId, $remote->xl, $remote->timeUpdated); + $db->updateMagnetDn($local->magnetId, $remote->dn, $remote->timeUpdated); + $db->updateMagnetTitle($local->magnetId, $remote->title, $remote->timeUpdated); + $db->updateMagnetPreview($local->magnetId, $remote->preview, $remote->timeUpdated); + $db->updateMagnetDescription($local->magnetId, $remote->description, $remote->timeUpdated); + $db->updateMagnetComments($local->magnetId, $remote->comments, $remote->timeUpdated); + $db->updateMagnetSensitive($local->magnetId, $remote->sensitive, $remote->timeUpdated); + + if (MAGNET_AUTO_APPROVE_ON_IMPORT_APPROVED && $local->approved !== $remote->approved && $remote->approved) + { + $db->updateMagnetApproved($local->magnetId, $remote->approved, $remote->timeUpdated); + } + + // xt + foreach ((array) $remote->xt as $xt) + { + switch ($xt->version) + { + case 1: + + $exist = false; + + foreach ($db->findMagnetToInfoHashByMagnetId($local->magnetId) as $result) + { + if ($infoHash = $db->getInfoHash($result->infoHashId)) + { + if ($infoHash->version == 1) + { + $exist = true; + } + } + } + + if (!$exist) + { + $db->addMagnetToInfoHash( + $local->magnetId, + $db->initInfoHashId( + $xt->value, 1 + ) + ); + } + + break; + + case 2: + + $exist = false; + + foreach ($db->findMagnetToInfoHashByMagnetId($local->magnetId) as $result) + { + if ($infoHash = $db->getInfoHash($result->infoHashId)) + { + if ($infoHash->version == 2) + { + $exist = true; + } + } + } + + if (!$exist) + { + $db->addMagnetToInfoHash( + $local->magnetId, + $db->initInfoHashId( + $xt->value, 2 + ) + ); + } + + break; + } + } + + // kt + $db->deleteMagnetToKeywordTopicByMagnetId($local->magnetId); + + foreach ($remote->kt as $kt) + { + $db->initMagnetToKeywordTopicId( + $local->magnetId, + $db->initKeywordTopicId(trim(mb_strtolower($kt))) + ); + } + + // tr + $db->deleteMagnetToAddressTrackerByMagnetId($local->magnetId); + + foreach ($remote->tr as $tr) + { + if ($url = Yggverse\Parser\Url::parse($tr)) + { + $db->initMagnetToAddressTrackerId( + $local->magnetId, + $db->initAddressTrackerId( + $db->initSchemeId($url->host->scheme), + $db->initHostId($url->host->name), + $db->initPortId($url->host->port), + $db->initUriId($url->page->uri) + ) + ); + } + } + + // as + $db->deleteMagnetToAcceptableSourceByMagnetId($local->magnetId); + + foreach ($remote->as as $as) + { + if ($url = Yggverse\Parser\Url::parse($as)) + { + $db->initMagnetToAcceptableSourceId( + $local->magnetId, + $db->initAcceptableSourceId( + $db->initSchemeId($url->host->scheme), + $db->initHostId($url->host->name), + $db->initPortId($url->host->port), + $db->initUriId($url->page->uri) + ) + ); + } + } + + // xs + $db->deleteMagnetToExactSourceByMagnetId($local->magnetId); + + foreach ($remote->xs as $xs) + { + if ($url = Yggverse\Parser\Url::parse($xs)) + { + $db->initMagnetToExactSourceId( + $local->magnetId, + $db->initExactSourceId( + $db->initSchemeId($url->host->scheme), + $db->initHostId($url->host->name), + $db->initPortId($url->host->port), + $db->initUriId($url->page->uri) + ) + ); + } + } + + $response['magnet'][] = [ + 'status' => true, + 'message' => sprintf( + _('Magnet fields updated to newer version for magnet ID "%s"'), + $local->magnetId + ) + ]; + } + + break; + case 'magnetComment': + + if (!API_IMPORT_MAGNET_COMMENTS_ENABLED) + { + $response['magnetComment'][] = [ + 'status' => false, + 'message' => _('Magnet comments import disabled on this node') + ]; + + continue 2; + } + + // Validate + $error = []; + + if (!Valid::magnetComment($remote, $error)) + { + $response['magnetComment'][] = [ + 'status' => false, + 'message' => sprintf( + _('Magnet comment data mismatch protocol with error: %s'), + print_r($error, true) + ), + ]; + + continue 2; + } + + // Skip import on magnet approved required + if (API_IMPORT_MAGNET_COMMENTS_APPROVED_ONLY && !$remote->approved) + { + $response['magnetComment'][] = [ + 'status' => false, + 'message' => _('Node accepting approved magnet comments only: %s') + ]; + + continue 2; + } + + // User local alias required + if (!isset($aliasUserId[$remote->userId]) || !isset($aliasMagnetId[$remote->magnetId])) + { + $response['magnetComment'][] = [ + 'status' => false, + 'message' => _('Magnet comment data relation not found for: %s') + ]; + + continue 2; + } + + // Parent comment provided + if (is_int($remote->magnetCommentIdParent)) + { + $localMagnetCommentIdParent = null; // @TODO feature not in use yet + } + + else + { + $localMagnetCommentIdParent = null; + } + + // Magnet comment exists by timestamp added for this user + if ($local = $db->findMagnetComment($aliasMagnetId[$remote->magnetId], + $aliasUserId[$remote->userId], + $remote->timeAdded)) + { + $response['magnetComment'][] = [ + 'status' => true, + 'message' => sprintf( + _('Magnet comment successfully associated with ID "%s"'), + $local->magnetCommentId + ) + ]; + } + + // Magnet comment exists by timestamp added for this user, register new one + else if ($magnetCommentId = $db->addMagnetComment($aliasMagnetId[$remote->magnetId], + $aliasUserId[$remote->userId], + $localMagnetCommentIdParent, + $remote->value, + $remote->approved, + true, + $remote->timeAdded)) + { + $response['magnetComment'][] = [ + 'status' => true, + 'message' => sprintf( + _('Magnet comment successfully synced with ID "%s"'), + $magnetCommentId + ) + ]; + } + + break; + case 'magnetDownload': + + // Magnet downloads + if (!API_IMPORT_MAGNET_DOWNLOADS_ENABLED) + { + $response['magnetDownload'][] = [ + 'status' => false, + 'message' => _('Magnet downloads import disabled on this node') + ]; + + continue 2; + } + + // Validate + $error = []; + + if (!Valid::magnetDownload($remote, $error)) + { + $response['magnetDownload'][] = [ + 'status' => false, + 'message' => sprintf( + _('Magnet download data mismatch protocol with error: %s'), + print_r($error, true) + ), + ]; + + continue 2; + } + + // User local alias required + if (!isset($aliasUserId[$remote->userId]) || !isset($aliasMagnetId[$remote->magnetId])) + { + $response['magnetDownload'][] = [ + 'status' => false, + 'message' => _('Magnet download data relation not found') + ]; + + continue 2; + } + + // Magnet download exists by timestamp added for this user + if ($local = $db->findMagnetDownload($aliasMagnetId[$remote->magnetId], + $aliasUserId[$remote->userId], + $remote->timeAdded)) + { + $response['magnetDownload'][] = [ + 'status' => true, + 'message' => sprintf( + _('Magnet download successfully associated with ID "%s"'), + $local->magnetDownloadId + ) + ]; + } + + // Magnet download exists by timestamp added for this user, register new one + else if ($magnetDownloadId = $db->addMagnetDownload($aliasMagnetId[$remote->magnetId], + $aliasUserId[$remote->userId], + $remote->timeAdded)) + { + $response['magnetDownload'][] = [ + 'status' => true, + 'message' => sprintf( + _('Magnet download successfully synced with ID "%s"'), + $magnetDownloadId + ) + ]; + } + + break; + case 'magnetStar': + + if (!API_IMPORT_MAGNET_STARS_ENABLED) + { + $response['magnetStar'][] = [ + 'status' => false, + 'message' => _('Magnet stars import disabled on this node') + ]; + + continue 2; + } + + // Validate + $error = []; + + if (!Valid::magnetStar($remote, $error)) + { + $response['magnetStar'][] = [ + 'status' => false, + 'message' => sprintf( + _('Magnet star data mismatch protocol with error: %s'), + print_r($error, true) + ), + ]; + + continue 2; + } + + // User local alias required + if (!isset($aliasUserId[$remote->userId]) || !isset($aliasMagnetId[$remote->magnetId])) + { + $response['magnetStar'][] = [ + 'status' => false, + 'message' => _('Magnet star data relation not found') + ]; + + continue 2; + } + + // Magnet star exists by timestamp added for this user + if ($local = $db->findMagnetStar($aliasMagnetId[$remote->magnetId], + $aliasUserId[$remote->userId], + $remote->timeAdded)) + { + $response['magnetStar'][] = [ + 'status' => true, + 'message' => sprintf( + _('Magnet star successfully associated with ID "%s"'), + $local->magnetStarId + ) + ]; + } + + // Magnet star exists by timestamp added for this user, register new one + else if ($magnetStarId = $db->addMagnetStar($aliasMagnetId[$remote->magnetId], + $aliasUserId[$remote->userId], + $remote->value, + $remote->timeAdded)) + { + $response['magnetStar'][] = [ + 'status' => true, + 'message' => sprintf( + _('Magnet star successfully synced with ID "%s"'), + $magnetStarId + ) + ]; + } + + break; + case 'magnetView': + + if (!API_IMPORT_MAGNET_VIEWS_ENABLED) + { + $response['magnetView'][] = [ + 'status' => false, + 'message' => _('Magnet views import disabled on this node') + ]; + + continue 2; + } + + // Validate + $error = []; + + if (!Valid::magnetView($remote, $error)) + { + $response['magnetView'][] = [ + 'status' => false, + 'message' => sprintf( + _('Magnet view data mismatch protocol with error: %s'), + print_r($error, true) + ), + ]; + + continue 2; + } + + // User local alias required + if (!isset($aliasUserId[$remote->userId]) || !isset($aliasMagnetId[$remote->magnetId])) + { + $response['magnetView'][] = [ + 'status' => false, + 'message' => _('Magnet view data relation not found for: %s') + ]; + + continue 2; + } + + // Magnet view exists by timestamp added for this user + if ($local = $db->findMagnetView($aliasMagnetId[$remote->magnetId], + $aliasUserId[$remote->userId], + $remote->timeAdded)) + { + $response['magnetView'][] = [ + 'status' => true, + 'message' => sprintf( + _('Magnet view successfully associated with ID "%s"'), + $local->magnetViewId + ) + ]; + } + + // Magnet view exists by timestamp added for this user, register new one + else if ($magnetViewId = $db->addMagnetView($aliasMagnetId[$remote->magnetId], + $aliasUserId[$remote->userId], + $remote->timeAdded)) + { + $response['magnetView'][] = [ + 'status' => true, + 'message' => sprintf( + _('Magnet view successfully synced with ID "%s"'), + $magnetViewId + ) + ]; + } + + break; + default: + + $response[$field][] = + [ + 'status' => false, + 'message' => _('Field "%s" not supported by protocol') + ]; + + continue 2; + } + } + + $db->commit(); + } + + catch (Exception $error) + { + $debug['exception'][] = print_r($error, true); + + $db->rollBack(); + } +} + +// Debug log +if (LOG_API_PUSH_ENABLED) +{ + @mkdir(LOG_DIRECTORY, 0770, true); + + if ($handle = fopen(LOG_DIRECTORY . '/' . LOG_API_PUSH_FILENAME, 'a+')) + { + $debug['time']['total'] = microtime(true) - $debug['time']['total']; + + $debug['memory']['total'] = memory_get_usage() - $debug['memory']['start']; + $debug['memory']['peaks'] = memory_get_peak_usage(); + + $debug['db']['total']['select'] = $db->getDebug()->query->select->total; + $debug['db']['total']['insert'] = $db->getDebug()->query->insert->total; + $debug['db']['total']['update'] = $db->getDebug()->query->update->total; + $debug['db']['total']['delete'] = $db->getDebug()->query->delete->total; + + fwrite( + $handle, + print_r( + [ + 'response' => $response, + 'debug' => $debug + ], + true + ) + ); + + fclose($handle); + + chmod(LOG_DIRECTORY . '/' . LOG_API_PUSH_FILENAME, 0770); + } +} + +// Output +header('Content-Type: application/json; charset=utf-8'); + +echo json_encode($response); \ No newline at end of file diff --git a/src/public/assets/theme/default/css/common.css b/src/public/assets/theme/default/css/common.css new file mode 100644 index 0000000..c5f9fb2 --- /dev/null +++ b/src/public/assets/theme/default/css/common.css @@ -0,0 +1,115 @@ +* { + border: 0; + margin: 0; + padding: 0; + box-sizing: border-box; +} + +body { + background: #282b3c; + color: #ccc; + font-family: Sans-serif; + font-size: 13px; +} + +a, +a:visited, +a:active { + color: #96d9a1; + text-decoration: none; + opacity: .9; +} + +a:hover { + opacity: 1; + transition: opacity .5s ease-in-out; +} + +h1, h2, h3, h4, h5 { + display: inline-block; + font-weight: normal; +} + +h1 { + font-size: 16px; +} + +h2 { + color: #ccc; + font-size: 16px; +} + +a h2, +a:visited h2, +a:active h2 { + /* @TODO doubts + color: #a4d4ff; + */ +} + +input, +textarea { + background: #5d627d; + color: #ccc; + border: 0; + border-radius: 3px; + padding: 6px 8px; + font-size: 13px; +} + +textarea:focus, +input:focus { + outline: none; + color: #fff; +} + +textarea { + min-height: 86px; +} + +/* @TODO improve focus out +textarea:focus { + min-height: 120px; +} +*/ + +textarea::placeholder, +input::placeholder { + color: #9698a5; + opacity: 1; +} + +input:hover, +textarea:hover { + background: #636884; +} + +input[type="submit"] { + cursor: pointer; +} + +td { + padding: 2px 0; +} + +header a.logo { + color: #ccc; + font-size: 22px; +} + +header a.logo > span { + color: #96d9a1; +} + +a.button, +a.button:visited, +a.button:active, +a.button:hover, +.button { + background: #5d627d; + color: #ccc; + border: 0; + border-radius: 3px; + padding: 6px 8px; + font-size: 13px; +} \ No newline at end of file diff --git a/src/public/assets/theme/default/css/framework.css b/src/public/assets/theme/default/css/framework.css new file mode 100644 index 0000000..9b3ebff --- /dev/null +++ b/src/public/assets/theme/default/css/framework.css @@ -0,0 +1,338 @@ +.container { + position: relative; + overflow: hidden; + max-width: 748px; + margin: 0 auto; +} + +.row { + position: relative; + overflow: hidden; + padding: 8px; +} + +.column { + position: relative; + float: left; +} + +.float-right { + float: right; +} + +.text-center { + text-align: center; +} + +.text-left { + text-align: left; +} + +.text-right { + text-align: right; +} + +.text-color-green { + color: #96d9a1; +} + +.text-color-red { + color: #d77575; +} + +.text-color-pink { + color: #b55cab; +} + +.text-color-default { + color: #ccc; +} + +/* +.text-color-pink { + color: #a44399; +} +*/ + +.text-color-blue { + color: #5785b7; +} + +.text-color-night { + color: #838695; +} + +.label { + padding: 4px 8px; + border-radius: 3px; +} + +.label-green { + color: #fff; + background-color: #65916d; +} + +.position-relative { + position: relative; +} + +.top--2 { + top: -2px; +} + +.top-2 { + top: 2px; +} + +.line-height-26 { + line-height: 26px; +} + +.border-radius-3 { + border-radius: 3px; +} + +.border-pink-light { + border: 1px #9b6895 solid; +} + +.border-pink { + border: 1px #a44399 solid; +} + +.border-bottom-pink { + border-bottom: 1px #a44399 solid; +} + +.border-default { + border: 1px #5d627d solid; +} + +.border-bottom-default { + border-bottom: 1px #5d627d solid; +} + +.border-top-default { + border-top: 1px #5d627d solid; +} + +.background-color-night { + background-color: #34384f; +} + +/* +.background-color-hover-night-light:hover { + background-color: #363a51; +} +*/ + +.background-color-red { + background-color: #9b4a4a; +} + +.cursor-default { + cursor: default; +} + +.cursor-help { + cursor: help; +} + +.font-width-normal { + font-weight: normal; +} + +.font-size-10 { + font-size: 10px; +} + +.font-size-12 { + font-size: 12px; +} + +.font-size-22 { + font-size: 22px; +} + +.padding-0 { + padding: 0; +} + +.padding-x-0 { + padding-left: 0; + padding-right: 0; +} + +.padding-4 { + padding: 4px; +} + +.padding-t-4 { + padding-top: 4px; +} + +.padding-y-4 { + padding-top: 4px; + padding-bottom: 4px; +} + +.padding-x-4 { + padding-left: 4px; + padding-right: 4px; +} + +.padding-x-8 { + padding-left: 8px; + padding-right: 8px; +} + +.padding-8 { + padding: 8px; +} + +.padding-t-8 { + padding-top: 8px; +} + +.padding-b-8 { + padding-bottom: 8px; +} + +.padding-y-8 { + padding-top: 8px; + padding-bottom: 8px; +} + +.padding-b-16 { + padding-bottom: 16px; +} + +.padding-t-16 { + padding-top: 16px; +} + +.padding-y-16 { + padding-top: 16px; + padding-bottom: 16px; +} + +.padding-x-16 { + padding-left: 16px; + padding-right: 16px; +} + +.padding-16 { + padding: 16px; +} + +.margin-l-4 { + margin-left: 4px; +} + +.margin-l-8 { + margin-left: 8px; +} + +.margin-l-16 { + margin-left: 16px; +} + +.margin-x-4 { + margin-left: 4px; + margin-right: 4px; +} + +.margin-r-4 { + margin-right: 4px; +} + +.margin-r-8 { + margin-right: 8px; +} + +.margin-l-12 { + margin-left: 12px; +} + +.margin-y-8 { + margin-top: 8px; + margin-bottom: 8px; +} + +.margin-t-8 { + margin-top: 8px; +} + +.margin-b-8 { + margin-bottom: 8px; +} + +.margin-t-16 { + margin-top: 16px; +} + +.margin-b-16 { + margin-bottom: 16px; +} + +.margin-b-24 { + margin-bottom: 24px; +} + +.display-block { + display: block; +} + +.opacity-0 { + opacity: 0; +} + +.opacity-06 { + opacity: .6; +} + +.opacity-hover-1:hover { + opacity: 1; + transition: opacity .2s; +} + +*:hover > .parent-hover-opacity-09 { + opacity: .9; + transition: opacity .2s; +} + +.blur-2 { + filter: blur(2px); +} + +.blur-hover-0:hover { + filter: blur(0); +} + +/* responsive rules */ + +.width-100 { + width: 100%; +} + +.width-50 { + width: 50%; +} + +.width-13px { + width: 13px; +} + +@media (max-width: 1220px) { + + .width-tablet-100 { + width: 100%; + } +} + +@media (max-width: 512px) { + + .width-mobile-100 { + width: 100%; + } +} diff --git a/src/public/download.php b/src/public/download.php new file mode 100644 index 0000000..ddadb96 --- /dev/null +++ b/src/public/download.php @@ -0,0 +1,335 @@ + true, + 'message' => _('Internal server error'), + 'html' => (object) + [ + 'title' => sprintf(_('Oops - %s'), WEBSITE_NAME), + 'h1' => false, + 'link' => (object) [], + ] +]; + +// Yggdrasil connections only +if (!Valid::host($_SERVER['REMOTE_ADDR'])) +{ + $response->success = false; + $response->message = _('Yggdrasil connection required for this action'); +} + +// Init session +else if (!$userId = $db->initUserId($_SERVER['REMOTE_ADDR'], USER_DEFAULT_APPROVED, time())) +{ + $response->success = false; + $response->message = _('Could not init user session'); +} + +// Magnet exists +else if (!$magnet = $db->getMagnet(isset($_GET['magnetId']) && $_GET['magnetId'] > 0 ? (int) $_GET['magnetId'] : 0)) +{ + $response->success = false; + $response->message = _('Requested magnet not found'); +} + +// Access allowed +else if (!($_SERVER['REMOTE_ADDR'] == $db->getUser($magnet->userId)->address || in_array($_SERVER['REMOTE_ADDR'], MODERATOR_IP_LIST) || ($magnet->public && $magnet->approved))) { + + $response->success = false; + $response->message = _('Magnet not available for this action'); +} + +// Get user +else if (!$user = $db->getUser($userId)) +{ + $response->success = false; + $response->message = _('Could not init user info'); +} + +// On first visit, redirect user to the welcome page with access level question +else if (is_null($user->public)) +{ + header( + sprintf('Location: %s/welcome.php', WEBSITE_URL) + ); +} + +// Request valid +else +{ + // Register magnet download + if ($magnetDownloadId = $db->addMagnetDownload($magnet->magnetId, $user->userId, time())) + { + // Push event to other nodes + if (API_EXPORT_ENABLED && + API_EXPORT_PUSH_ENABLED && + API_EXPORT_USERS_ENABLED && + API_EXPORT_MAGNETS_ENABLED && + API_EXPORT_MAGNET_DOWNLOADS_ENABLED) + { + if (!$memoryApiExportPush = $memory->get('api.export.push')) + { + $memoryApiExportPush = []; + } + + $memoryApiExportPush[] = (object) + [ + 'time' => time(), + 'userId' => $user->userId, + 'magnetId' => $magnet->magnetId, + 'magnetDownloadId' => $magnetDownloadId + ]; + + $memory->set('api.export.push', $memoryApiExportPush, 3600); + } + } + + // Build magnet link + $link = (object) + [ + 'magnet' => [], + 'direct' => [], + ]; + + /// Exact Topic + $xt = []; + + foreach ($db->findMagnetToInfoHashByMagnetId($magnet->magnetId) as $result) + { + if ($infoHash = $db->getInfoHash($result->infoHashId)) + { + switch ($infoHash->version) + { + case 1: + + $xt[] = sprintf('xt=urn:btih:%s', $infoHash->value); + + break; + + case 2: + + $xt[] = sprintf('xt=urn:btmh:1220%s', $infoHash->value); + + break; + } + } + } + + $link->magnet[] = sprintf('magnet:?%s', implode('&', $xt)); + + /// Display Name + $link->magnet[] = sprintf('dn=%s', urlencode($magnet->dn)); + + // Keyword Topic + $kt = []; + + foreach ($db->findKeywordTopicByMagnetId($magnet->magnetId) as $result) + { + $kt[] = urlencode($db->getKeywordTopic($result->keywordTopicId)->value); + } + + $link->magnet[] = sprintf('kt=%s', implode('+', $kt)); + + /// Address Tracker + foreach ($db->findAddressTrackerByMagnetId($magnet->magnetId) as $result) + { + $addressTracker = $db->getAddressTracker($result->addressTrackerId); + + $scheme = $db->getScheme($addressTracker->schemeId); + $host = $db->getHost($addressTracker->hostId); + $port = $db->getPort($addressTracker->portId); + $uri = $db->getUri($addressTracker->uriId); + + // Yggdrasil host only + if (!Valid::host($host->value)) + { + continue; + } + + $link->magnet[] = sprintf('tr=%s', urlencode($port->value ? sprintf('%s://%s:%s%s', $scheme->value, + $host->value, + $port->value, + $uri->value) : sprintf('%s://%s%s', $scheme->value, + $host->value, + $uri->value))); + } + + // Append trackers.json + foreach (json_decode(file_get_contents(__DIR__ . '/../config/trackers.json')) as $tracker) + { + $link->magnet[] = sprintf('tr=%s', urlencode($tracker->announce)); + } + + /// Acceptable Source + foreach ($db->findAcceptableSourceByMagnetId($magnet->magnetId) as $result) + { + $acceptableSource = $db->getAcceptableSource($result->acceptableSourceId); + + $scheme = $db->getScheme($acceptableSource->schemeId); + $host = $db->getHost($acceptableSource->hostId); + $port = $db->getPort($acceptableSource->portId); + $uri = $db->getUri($acceptableSource->uriId); + + // Yggdrasil host only + if (!Valid::host($host->value)) + { + continue; + } + + $link->magnet[] = sprintf('as=%s', urlencode($port->value ? sprintf('%s://%s:%s%s', $scheme->value, + $host->value, + $port->value, + $uri->value) : sprintf('%s://%s%s', $scheme->value, + $host->value, + $uri->value))); + $link->direct[] = $port->value ? sprintf('%s://%s:%s%s', $scheme->value, + $host->value, + $port->value, + $uri->value) : sprintf('%s://%s%s', $scheme->value, + $host->value, + $uri->value); + } + + /// Exact Source + foreach ($db->findExactSourceByMagnetId($magnet->magnetId) as $result) + { + $eXactSource = $db->getExactSource($result->eXactSourceId); + + $scheme = $db->getScheme($eXactSource->schemeId); + $host = $db->getHost($eXactSource->hostId); + $port = $db->getPort($eXactSource->portId); + $uri = $db->getUri($eXactSource->uriId); + + // Yggdrasil host only + if (!Valid::host($host->value)) + { + continue; + } + + $link->magnet[] = sprintf('xs=%s', urlencode($port->value ? sprintf('%s://%s:%s%s', $scheme->value, + $host->value, + $port->value, + $uri->value) : sprintf('%s://%s%s', $scheme->value, + $host->value, + $uri->value))); + } + + // Return html + $response->html->title = sprintf( + _('%s - Download - %s'), + htmlentities($magnet->title), + WEBSITE_NAME + ); + + $response->html->h1 = htmlentities($magnet->title); + + // @TODO implement .bittorrent, separated v1/v2 magnet links + $response->html->link->magnet = implode('&', array_unique($link->magnet)); + $response->html->link->direct = $link->direct; +} + +?> + + + + + + + + <?php echo $response->html->title ?> + + + + + + +
+
+ +
+
+
+
+
+
+
+ success) { ?> +
+

html->h1 ?>

+
+ +
+ + + + + + html->link->direct as $direct) { ?> + + + + + + +
+ +
+ message ?> +
+ +
+
+
+ +
+
+ + + +
+
+ +
+
+ + + \ No newline at end of file diff --git a/src/public/edit.php b/src/public/edit.php new file mode 100644 index 0000000..e8bf3e9 --- /dev/null +++ b/src/public/edit.php @@ -0,0 +1,914 @@ + true, + 'message' => false, + 'form' => (object) + [ + 'title' => (object) + [ + 'value' => false, + 'valid' => (object) + [ + 'success' => true, + 'message' => false, + ] + ], + 'preview' => (object) + [ + 'value' => false, + 'valid' => (object) + [ + 'success' => true, + 'message' => false, + ] + ], + 'description' => (object) + [ + 'value' => false, + 'valid' => (object) + [ + 'success' => true, + 'message' => false, + ] + ], + 'dn' => (object) + [ + 'value' => false, + 'valid' => (object) + [ + 'success' => true, + 'message' => false, + ] + ], + 'xt' => (object) + [ + 'value' => [], + 'valid' => (object) + [ + 'success' => true, + 'message' => false, + ] + ], + 'kt' => (object) + [ + 'value' => [], + 'valid' => (object) + [ + 'success' => true, + 'message' => false, + ] + ], + 'tr' => (object) + [ + 'value' => [], + 'valid' => (object) + [ + 'success' => true, + 'message' => false, + ] + ], + 'as' => (object) + [ + 'value' => [], + 'valid' => (object) + [ + 'success' => true, + 'message' => false, + ] + ], + 'xs' => (object) + [ + 'value' => [], + 'valid' => (object) + [ + 'success' => true, + 'message' => false, + ] + ], + 'public' => (object) + [ + 'value' => false, + 'valid' => (object) + [ + 'success' => true, + 'message' => false, + ] + ], + 'comments' => (object) + [ + 'value' => false, + 'valid' => (object) + [ + 'success' => true, + 'message' => false, + ] + ], + 'sensitive' => (object) + [ + 'value' => false, + 'valid' => (object) + [ + 'success' => true, + 'message' => false, + ] + ], + 'approved' => (object) + [ + 'value' => false, + ], + ] +]; + +// Yggdrasil connections only +if (!Valid::host($_SERVER['REMOTE_ADDR'])) +{ + $response->success = false; + $response->message = _('Yggdrasil connection required to enable resource features'); +} + +// Init session +else if (!$userId = $db->initUserId($_SERVER['REMOTE_ADDR'], USER_DEFAULT_APPROVED, time())) +{ + $response->success = false; + $response->message = _('Could not init user session'); +} + +// Get user +else if (!$user = $db->getUser($userId)) +{ + $response->success = false; + $response->message = _('Could not init user info'); +} + +// Init magnet +else if (!$magnet = $db->getMagnet(isset($_GET['magnetId']) ? (int) $_GET['magnetId'] : 0)) { + + $response->success = false; + $response->message = _('Magnet not found!'); +} + +// Validate access +else if (!($user->address == $db->getUser($magnet->userId)->address || in_array($user->address, MODERATOR_IP_LIST))) { + + $response->success = false; + $response->message = _('You have no permissions to edit this magnet!'); +} + +// On first visit, redirect user to the welcome page with access level question +else if (is_null($user->public)) +{ + header( + sprintf('Location: %s/welcome.php', WEBSITE_URL) + ); +} + +// Process form +else { + + // Validate magnet lock + if ($lastMagnetLock = $db->findLastMagnetLock($magnet->magnetId)) + { + if ($lastMagnetLock->userId != $user->userId && + $lastMagnetLock->timeAdded > time() - MAGNET_EDITOR_LOCK_TIMEOUT) + { + $response->success = false; + $response->message = _('This form have opened by owner or moderator, to prevent overwriting, try attempt later!'); + } + } + + // Lock form for moderators + $db->addMagnetLock($magnet->magnetId, $user->userId, time()); + + // Update form + if (!empty($_POST)) { + + // Push event to other nodes + if (API_EXPORT_ENABLED && + API_EXPORT_PUSH_ENABLED && + API_EXPORT_USERS_ENABLED && + API_EXPORT_MAGNETS_ENABLED) + { + if (!$memoryApiExportPush = $memory->get('api.export.push')) + { + $memoryApiExportPush = []; + } + + $memoryApiExportPush[] = (object) + [ + 'time' => time(), + 'userId' => $user->userId, + 'magnetId' => $magnet->magnetId, + ]; + + $memory->set('api.export.push', $memoryApiExportPush, 3600); + } + + // Approve by moderation request + if (in_array($user->address, MODERATOR_IP_LIST)) + { + $db->updateMagnetApproved($magnet->magnetId, isset($_POST['approved']), time()); + + // Auto-approve user on magnet approve + if (USER_AUTO_APPROVE_ON_MAGNET_APPROVE) + { + $db->updateUserApproved($magnet->userId, isset($_POST['approved']), time()); + } + } + + // Approve by user approved status + else + { + $db->updateMagnetApproved($magnet->magnetId, (bool) $user->approved, time()); + } + + // Social + $db->updateMagnetComments($magnet->magnetId, isset($_POST['comments']) ? true : false, time()); + $db->updateMagnetSensitive($magnet->magnetId, isset($_POST['sensitive']) ? true : false, time()); + + if (isset($_POST['public'])) // could be enabled once only because of distributed database model #1 + { + $db->updateMagnetPublic($magnet->magnetId, true, time()); + } + + // Title + $response->form->title->valid->success = true; + $response->form->title->valid->message = []; + + if (!Valid::magnetTitle($_POST['title'], $response->form->title->valid->message)) + { + $response->form->title->valid->success = false; + } + + else + { + $db->updateMagnetTitle( + $magnet->magnetId, + Filter::magnetTitle($_POST['title']), + time() + ); + } + + // Preview + $response->form->preview->valid->success = true; + $response->form->preview->valid->message = []; + + if (!Valid::magnetPreview($_POST['preview'], $response->form->preview->valid->message)) + { + $response->form->preview->valid->success = false; + } + + else + { + $db->updateMagnetPreview( + $magnet->magnetId, + Filter::magnetPreview($_POST['preview']), + time() + ); + } + + // Description + $response->form->description->valid->success = true; + $response->form->description->valid->message = []; + + if (!Valid::magnetDescription($_POST['description'], $response->form->description->valid->message)) + { + $response->form->description->valid->success = false; + } + + else + { + $db->updateMagnetDescription( + $magnet->magnetId, + Filter::magnetDescription($_POST['description']), + time() + ); + } + + // Display Name + $response->form->dn->valid->success = true; + $response->form->dn->valid->message = []; + + if (!Valid::magnetDn($_POST['dn'], $response->form->dn->valid->message)) + { + $response->form->dn->valid->success = false; + } + + else + { + $db->updateMagnetDn( + $magnet->magnetId, + Filter::magnetDn($_POST['dn']), + time() + ); + } + + // Exact Topic + if (isset($_POST['xt'])) + { + foreach ((array) $_POST['xt'] as $version => $value) + { + switch ($version) + { + case 1: + + if (!empty($value) && Yggverse\Parser\Magnet::isXTv1($value)) + { + $exist = false; + + foreach ($db->findMagnetToInfoHashByMagnetId($magnet->magnetId) as $result) + { + if ($infoHash = $db->getInfoHash($result->infoHashId)) + { + if ($infoHash->version == 1) + { + $exist = true; + } + } + } + + if (!$exist) + { + $db->addMagnetToInfoHash( + $magnet->magnetId, + $db->initInfoHashId( + Yggverse\Parser\Magnet::filterInfoHash($value), 1 + ) + ); + } + } + + break; + + case 2: + + if (!empty($value) && Yggverse\Parser\Magnet::isXTv2($value)) + { + $exist = false; + + foreach ($db->findMagnetToInfoHashByMagnetId($magnet->magnetId) as $result) + { + if ($infoHash = $db->getInfoHash($result->infoHashId)) + { + if ($infoHash->version == 2) + { + $exist = true; + } + } + } + + if (!$exist) + { + $db->addMagnetToInfoHash( + $magnet->magnetId, + $db->initInfoHashId( + Yggverse\Parser\Magnet::filterInfoHash($value), 2 + ) + ); + } + } + + break; + } + } + } + + // Keyword Topic + $db->deleteMagnetToKeywordTopicByMagnetId($magnet->magnetId); + + if (!empty($_POST['kt'])) + { + foreach (explode(PHP_EOL, str_replace(['#', ',', ' '], PHP_EOL, $_POST['kt'])) as $kt) + { + $kt = trim($kt); + + if (!empty(trim($kt))) + { + $db->initMagnetToKeywordTopicId( + $magnet->magnetId, + $db->initKeywordTopicId(trim(mb_strtolower(strip_tags(html_entity_decode($kt))))) + ); + } + } + } + + // Address Tracker + $db->deleteMagnetToAddressTrackerByMagnetId($magnet->magnetId); + + if (!empty($_POST['tr'])) + { + $response->form->tr->valid->success = false; + $response->form->tr->valid->message = _('* please, provide at least one Yggdrasil address'); + + foreach (explode(PHP_EOL, str_replace(['#', ',', ' '], PHP_EOL, $_POST['tr'])) as $tr) + { + $tr = trim($tr); + + if (Valid::url($tr)) + { + if ($url = Yggverse\Parser\Url::parse($tr)) + { + $db->initMagnetToAddressTrackerId( + $magnet->magnetId, + $db->initAddressTrackerId( + $db->initSchemeId($url->host->scheme), + $db->initHostId($url->host->name), + $db->initPortId($url->host->port), + $db->initUriId($url->page->uri) + ) + ); + + $response->form->tr->valid->success = true; + $response->form->tr->valid->message = false; + } + } + } + } + + // Acceptable Source + $db->deleteMagnetToAcceptableSourceByMagnetId($magnet->magnetId); + + if (!empty($_POST['as'])) + { + $response->form->as->valid->success = false; + $response->form->as->valid->message = _('* please, provide at least one Yggdrasil address'); + + foreach (explode(PHP_EOL, str_replace(['#', ',', ' '], PHP_EOL, $_POST['as'])) as $as) + { + $xs = trim($as); + + if (Valid::url($as)) + { + if ($url = Yggverse\Parser\Url::parse($as)) + { + $db->initMagnetToAcceptableSourceId( + $magnet->magnetId, + $db->initAcceptableSourceId( + $db->initSchemeId($url->host->scheme), + $db->initHostId($url->host->name), + $db->initPortId($url->host->port), + $db->initUriId($url->page->uri) + ) + ); + + $response->form->as->valid->success = true; + $response->form->as->valid->message = false; + } + } + } + } + + // Exact Source + $db->deleteMagnetToExactSourceByMagnetId($magnet->magnetId); + + if (!empty($_POST['xs'])) + { + $response->form->xs->valid->success = false; + $response->form->xs->valid->message = _('* please, provide at least one Yggdrasil address'); + + foreach (explode(PHP_EOL, str_replace(['#', ',', ' '], PHP_EOL, $_POST['xs'])) as $xs) + { + $xs = trim($xs); + + if (Valid::url($xs)) + { + if ($url = Yggverse\Parser\Url::parse($xs)) + { + $db->initMagnetToExactSourceId( + $magnet->magnetId, + $db->initExactSourceId( + $db->initSchemeId($url->host->scheme), + $db->initHostId($url->host->name), + $db->initPortId($url->host->port), + $db->initUriId($url->page->uri) + ) + ); + + $response->form->xs->valid->success = true; + $response->form->xs->valid->message = false; + } + } + } + } + + // Is valid + if ($response->success && + $response->form->title->valid->success && + $response->form->preview->valid->success && + $response->form->description->valid->success && + $response->form->dn->valid->success && + $response->form->tr->valid->success && + $response->form->as->valid->success && + $response->form->xs->valid->success) + { + // Unlock form + $db->flushMagnetLock($magnet->magnetId); + + // Return redirect to the magnet page + header( + sprintf('Location: %s/magnet.php?magnetId=%s', WEBSITE_URL, $magnet->magnetId) + ); + } + else + { + // Refresh magnet data + $magnet = $db->getMagnet($magnet->magnetId); + + // Replace fields by last POST data + foreach ($_POST as $key => $value) + { + $magnet->{$key} = $value; + } + } + } + + // Meta Title, auto-replace with Display Name on empty value + $response->form->title->value = $magnet->title ? $magnet->title : $magnet->dn; + + // Meta Description + $response->form->preview->value = $magnet->preview; + + // Description + $response->form->description->value = $magnet->description; + + // Magnet settings + $response->form->public->value = (bool) $magnet->public; + $response->form->comments->value = (bool) $magnet->comments; + $response->form->sensitive->value = (bool) $magnet->sensitive; + $response->form->approved->value = (bool) $magnet->approved; + + // Display Name + $response->form->dn->value = $magnet->dn; + + // Exact Topic + foreach ($db->findMagnetToInfoHashByMagnetId($magnet->magnetId) as $result) + { + if ($infoHash = $db->getInfoHash($result->infoHashId)) + { + $response->form->xt->value[$infoHash->version] = $infoHash->value; + } + } + + // Keyword Topic + $kt = []; + foreach ($db->findKeywordTopicByMagnetId($magnet->magnetId) as $result) + { + $kt[] = $db->getKeywordTopic($result->keywordTopicId)->value; + } + + $response->form->kt->value = implode(', ', $kt); + + // Address Tracker + $tr = []; + foreach ($db->findAddressTrackerByMagnetId($magnet->magnetId) as $result) + { + $addressTracker = $db->getAddressTracker($result->addressTrackerId); + + $scheme = $db->getScheme($addressTracker->schemeId); + $host = $db->getHost($addressTracker->hostId); + $port = $db->getPort($addressTracker->portId); + $uri = $db->getUri($addressTracker->uriId); + + $tr[] = $port->value ? sprintf('%s://%s:%s%s', $scheme->value, + $host->value, + $port->value, + $uri->value) : sprintf('%s://%s%s', $scheme->value, + $host->value, + $uri->value); + } + + $response->form->tr->value = implode(PHP_EOL, $tr); + + // Acceptable Source + $as = []; + foreach ($db->findAcceptableSourceByMagnetId($magnet->magnetId) as $result) + { + $acceptableSource = $db->getAcceptableSource($result->acceptableSourceId); + + $scheme = $db->getScheme($acceptableSource->schemeId); + $host = $db->getHost($acceptableSource->hostId); + $port = $db->getPort($acceptableSource->portId); + $uri = $db->getUri($acceptableSource->uriId); + + $as[] = $port->value ? sprintf('%s://%s:%s%s', $scheme->value, + $host->value, + $port->value, + $uri->value) : sprintf('%s://%s%s', $scheme->value, + $host->value, + $uri->value); + } + + $response->form->as->value = implode(PHP_EOL, $as); + + // Exact Source + $xs = []; + foreach ($db->findExactSourceByMagnetId($magnet->magnetId) as $result) + { + $eXactSource = $db->getExactSource($result->eXactSourceId); + + $scheme = $db->getScheme($eXactSource->schemeId); + $host = $db->getHost($eXactSource->hostId); + $port = $db->getPort($eXactSource->portId); + $uri = $db->getUri($eXactSource->uriId); + + $xs[] = $port->value ? sprintf('%s://%s:%s%s', $scheme->value, + $host->value, + $port->value, + $uri->value) : sprintf('%s://%s%s', $scheme->value, + $host->value, + $uri->value); + } + + $response->form->xs->value = implode(PHP_EOL, $xs); +} + +?> + + + + + + + + <?php echo sprintf(_('Edit - %s'), WEBSITE_NAME) ?> + + + + + + + +
+
+ +
+
+
+
+
+
+ success) { ?> +
+ + +
+
+

+
+
+ + + + +
+
+ + + + form->xt->value[1]) && empty($response->form->xt->value[2])) { ?> +
+ + + + + + +
+
+ +
+ +
+
+ +
+
+ +
+ address, MODERATOR_IP_LIST)) { ?> +
+ +
+ +
+
+ +
+
+
+ +
+
message ?>
+
+ +
+
+
+
+ + + \ No newline at end of file diff --git a/src/public/faq.php b/src/public/faq.php new file mode 100644 index 0000000..06000d9 --- /dev/null +++ b/src/public/faq.php @@ -0,0 +1,228 @@ + + true, + 'message' => _('Internal server error'), +]; + +// Yggdrasil connections only +if (!Valid::host($_SERVER['REMOTE_ADDR'])) +{ + $response->success = false; + $response->message = _('Yggdrasil connection required for this action'); +} + +// Init session +else if (!$userId = $db->initUserId($_SERVER['REMOTE_ADDR'], USER_DEFAULT_APPROVED, time())) +{ + $response->success = false; + $response->message = _('Could not init user session'); +} + +// Get user +else if (!$user = $db->getUser($userId)) +{ + $response->success = false; + $response->message = _('Could not init user info'); +} + +// On first visit, redirect user to the welcome page with access level question +/* Allow to users read this page before accepting data access type in welcome form +else if (is_null($user->public)) +{ + header( + sprintf('Location: %s/welcome.php', WEBSITE_URL) + ); +} +*/ + +?> + + + + + + + <?php echo sprintf(_('F.A.Q. - %s'), WEBSITE_NAME) ?> + + + + + +
+
+ +
+
+
+
+
+
+
+ success) { ?> +

+
+ +
+
+

+ + + + + + +
+

open source community-driven BitTorrent registry for Yggdrasil ecosystem.') ?>

+

+
+
+
+

+ + + + + + +
+

+

+

+
+
+
+

+ + + + + + +
+

Node page.'), WEBSITE_URL) ?>

+
+
+
+ +
+
+

+ + + + + + +
+

Submit.') ?>

+

+

+
+
+
+

+ + + + + + +
+

+

qBittorrent supports all required features, just check Preferences - Advanced - Optional IP address to bind and set to All addresses or Yggdrasil address only.') ?>

+

') ?>

+
+
+
+

+ + + + + + +
+

+

+

+
+
+
+ +
+
+

+ + + + + + +
+

+

Install section.') ?>

+

trackers.json registry to participate shared model testing.') ?>

+
+
+
+

+ + + + + + +
+

Issues page!') ?>

+
+
+ +
message ?>
+ +
+
+
+
+
+ + + \ No newline at end of file diff --git a/src/public/import.php b/src/public/import.php new file mode 100644 index 0000000..a233cd9 --- /dev/null +++ b/src/public/import.php @@ -0,0 +1,303 @@ + + true, + 'message' => _('Internal server error'), +]; + +// Yggdrasil connections only +if (!Valid::host($_SERVER['REMOTE_ADDR'])) +{ + $response->success = false; + $response->message = _('Yggdrasil connection required for this action'); +} + +// Init session +else if (!$userId = $db->initUserId($_SERVER['REMOTE_ADDR'], USER_DEFAULT_APPROVED, time())) +{ + $response->success = false; + $response->message = _('Could not init user session'); +} + +// Init user +else if (!$user = $db->getUser($userId)) +{ + $response->success = false; + $response->message = _('Could not get user session'); +} + +// On first visit, redirect user to the welcome page with access level question +else if (is_null($user->public)) +{ + header( + sprintf('Location: %s/welcome.php', WEBSITE_URL) + ); +} + +// Import form magnet link request +else if (!empty($_POST['magnet'])) +{ + // Validate magnet + if (!$magnet = Yggverse\Parser\Magnet::parse($_POST['magnet'])) + { + $response->success = false; + $response->message = _('Could not parse magnet link'); + } + + // Request valid + else + { + // Begin magnet registration + try + { + $db->beginTransaction(); + + // Init magnet + if ($magnetId = $db->addMagnet( $user->userId, + $magnet->xl, + $magnet->dn, + '', // @TODO deprecated, remove + MAGNET_DEFAULT_PUBLIC, + MAGNET_DEFAULT_COMMENTS, + MAGNET_DEFAULT_SENSITIVE, + $user->approved ? true : MAGNET_DEFAULT_APPROVED, + time())) + { + foreach ($magnet as $key => $value) + { + switch ($key) + { + case 'xt': + foreach ($value as $xt) + { + if (Yggverse\Parser\Magnet::isXTv1($xt)) + { + $db->addMagnetToInfoHash( + $magnetId, + $db->initInfoHashId( + Yggverse\Parser\Magnet::filterInfoHash($xt), 1 + ) + ); + } + if (Yggverse\Parser\Magnet::isXTv2($xt)) + { + $db->addMagnetToInfoHash( + $magnetId, + $db->initInfoHashId( + Yggverse\Parser\Magnet::filterInfoHash($xt), 2 + ) + ); + } + } + break; + case 'tr': + foreach ($value as $tr) + { + if (Valid::url($tr)) + { + if ($url = Yggverse\Parser\Url::parse($tr)) + { + $db->initMagnetToAddressTrackerId( + $magnetId, + $db->initAddressTrackerId( + $db->initSchemeId($url->host->scheme), + $db->initHostId($url->host->name), + $db->initPortId($url->host->port), + $db->initUriId($url->page->uri) + ) + ); + } + } + } + break; + case 'ws': + foreach ($value as $ws) + { + // @TODO + } + break; + case 'as': + foreach ($value as $as) + { + if (Valid::url($as)) + { + if ($url = Yggverse\Parser\Url::parse($as)) + { + $db->initMagnetToAcceptableSourceId( + $magnetId, + $db->initAcceptableSourceId( + $db->initSchemeId($url->host->scheme), + $db->initHostId($url->host->name), + $db->initPortId($url->host->port), + $db->initUriId($url->page->uri) + ) + ); + } + } + } + break; + case 'xs': + foreach ($value as $xs) + { + if (Valid::url($xs)) + { + if ($url = Yggverse\Parser\Url::parse($xs)) + { + $db->initMagnetToExactSourceId( + $magnetId, + $db->initExactSourceId( + $db->initSchemeId($url->host->scheme), + $db->initHostId($url->host->name), + $db->initPortId($url->host->port), + $db->initUriId($url->page->uri) + ) + ); + } + } + } + break; + case 'mt': + foreach ($value as $mt) + { + // @TODO + } + break; + case 'x.pe': + foreach ($value as $xPe) + { + // @TODO + } + break; + case 'kt': + foreach ($value as $kt) + { + $db->initMagnetToKeywordTopicId( + $magnetId, + $db->initKeywordTopicId(trim(mb_strtolower(strip_tags(html_entity_decode($kt))))) + ); + } + break; + } + } + + $db->commit(); + } + } + + catch (Exception $error) + { + $response->success = false; + $response->message = sprintf( + _('Internal server error: %s'), + print_r($error, true) + ); + + $db->rollBack(); + } + } + + // Redirect to edit page on success + if ($response->success) + { + header(sprintf('Location: %s/edit.php?magnetId=%s', trim(WEBSITE_URL, '/'), $magnetId)); + } +} + +// Import form torrent file request +else if (!empty($_FILE['torrent'])) +{ + // @TODO +} + +?> + + + + + + + <?php echo sprintf(_('Add - %s'), WEBSITE_NAME) ?> + + + + + + +
+
+ +
+
+
+
+
+
+
+ success) { ?> +
+

+
+
+
+ + +
+
+ + +
+
+ +
+
+ +
+ message ?> +
+ +
+
+
+
+
+ + + \ No newline at end of file diff --git a/src/public/index.php b/src/public/index.php new file mode 100644 index 0000000..13cf940 --- /dev/null +++ b/src/public/index.php @@ -0,0 +1,431 @@ + false, + 'page' => 1, +]; + +// Prepare request +$request->query = isset($_GET['query']) ? urldecode((string) $_GET['query']) : ''; +$request->page = isset($_GET['page']) && $_GET['page'] > 0 ? (int) $_GET['page'] : 1; + +// Define response +$response = (object) +[ + 'success' => true, + 'message' => false, + 'magnets' => [], +]; + +// Yggdrasil connections only +if (!Valid::host($_SERVER['REMOTE_ADDR'])) +{ + $response->success = false; + $response->message = _('Yggdrasil connection required to enable resource features'); +} + +// Init session +else if (!$userId = $db->initUserId($_SERVER['REMOTE_ADDR'], USER_DEFAULT_APPROVED, time())) +{ + $response->success = false; + $response->message = _('Could not init user session'); +} + +// Get user +else if (!$user = $db->getUser($userId)) +{ + $response->success = false; + $response->message = _('Could not init user info'); +} + +// On first visit, redirect user to the welcome page with access level question +else if (is_null($user->public) && !isset($_GET['rss'])) +{ + header( + sprintf('Location: %s/welcome.php', WEBSITE_URL) + ); +} + +// Request valid +else +{ + // Query is magnet link + if ($magnet = Yggverse\Parser\Magnet::is($request->query)) + { + header( + sprintf('Location: %s/action.php?target=magnet&toggle=new&magnet=%s', WEBSITE_URL, urlencode($request->query)) + ); + } + + // Get index + $response->total = $sphinx->searchMagnetsTotal($request->query); + $results = $sphinx->searchMagnets( + $request->query, + $request->page * WEBSITE_PAGINATION_LIMIT - WEBSITE_PAGINATION_LIMIT, + WEBSITE_PAGINATION_LIMIT, + $response->total + ); + + foreach ($results as $result) + { + if ($magnet = $db->getMagnet($result->magnetid)) + { + // Get access info + $accessRead = ($user->address == $db->getUser($magnet->userId)->address || in_array($user->address, MODERATOR_IP_LIST) || ($magnet->public && $magnet->approved)); + $accessEdit = ($user->address == $db->getUser($magnet->userId)->address || in_array($user->address, MODERATOR_IP_LIST)); + + // Keywords + $keywords = []; + + foreach ($db->findKeywordTopicByMagnetId($magnet->magnetId) as $keyword) + { + $keywords[] = $db->getKeywordTopic($keyword->keywordTopicId)->value; + } + + $response->magnets[] = (object) + [ + 'magnetId' => $magnet->magnetId, + 'title' => $magnet->title ? htmlentities($magnet->title) : ($magnet->dn ? htmlentities($magnet->dn): false), + 'preview' => $magnet->preview ? nl2br( + htmlentities( + $magnet->preview + ) + ) : false, + 'approved' => (bool) $magnet->approved, + 'public' => (bool) $magnet->public, + 'sensitive' => (bool) $magnet->sensitive, + 'comments' => (bool) $magnet->comments, + 'timeAdded' => $magnet->timeAdded ? Time::ago((int) $magnet->timeAdded) : false, + 'timeUpdated' => $magnet->timeUpdated ? Time::ago((int) $magnet->timeUpdated) : false, + 'keywords' => $keywords, + 'comment' => (object) + [ + 'total' => $db->findMagnetCommentsTotalByMagnetId($magnet->magnetId), + 'status' => $db->findMagnetCommentsTotal($magnet->magnetId, $userId), + ], + 'download' => (object) + [ + 'total' => $db->findMagnetDownloadsTotalByMagnetId($magnet->magnetId), + 'status' => $db->findMagnetDownloadsTotal($magnet->magnetId, $userId), + ], + 'star' => (object) + [ + 'total' => $db->findMagnetStarsTotalByMagnetId($magnet->magnetId, true), + 'status' => $db->findLastMagnetStarValue($magnet->magnetId, $userId), + ], + 'access' => (object) + [ + 'read' => $accessRead, + 'edit' => $accessEdit, + ], + 'seeders' => $db->getMagnetToAddressTrackerSeedersSumByMagnetId($magnet->magnetId), + 'completed' => $db->getMagnetToAddressTrackerCompletedSumByMagnetId($magnet->magnetId), + 'leechers' => $db->getMagnetToAddressTrackerLeechersSumByMagnetId($magnet->magnetId), + 'directs' => $db->getMagnetToAcceptableSourceTotalByMagnetId($magnet->magnetId) + ]; + } + } +} + +if (isset($_GET['rss']) && $response->success) { ?>' . PHP_EOL ?> + + + + <?php echo !empty($request->query) ? sprintf(_('%s - Search - %s'), htmlspecialchars($request->query, ENT_QUOTES, 'UTF-8'), WEBSITE_NAME) + : WEBSITE_NAME ?> + + query ? sprintf('?query=%s', urlencode($request->query)) : false) ?> + magnets as $magnet) { ?> + access->read) { ?> + + <?php echo htmlspecialchars($magnet->title, ENT_QUOTES, 'UTF-8') ?> + preview), ENT_QUOTES, 'UTF-8') ?> + magnetId) ?> + magnetId) ?> + + + + + + + + + + + + + <?php echo !empty($request->query) ? sprintf(_('%s - Search - %s'), htmlspecialchars($request->query, ENT_QUOTES, 'UTF-8'), WEBSITE_NAME) + : sprintf(_('%s - BitTorrent Registry for Yggdrasil'), WEBSITE_NAME) ?> + + + + + + + +
+
+ +
+
+
+
+
+
+ success) { ?> + magnets) { ?> + magnets as $magnet) { ?> + access->read) { ?> + +
+
+ +

title ?>

+ leechers && !$magnet->seeders) { ?> + + + + +
+
+ public) { ?> + + + + + + + + approved) { ?> + + + + + + + access->edit) { ?> + + + + + + + +
+ preview) { ?> +
preview ?>
+ + keywords) { ?> +
+ keywords as $keyword) { ?> + + # + + +
+ +
+ + + + timeUpdated ? _('Updated') : _('Added') ?> + timeUpdated ? $magnet->timeUpdated : $magnet->timeAdded ?> + + + + + + + seeders ?> + + + + + + completed ?> + + + + + + + leechers ?> + + directs) { ?> + + + + + directs ?> + + + + + + star->status) { ?> + + + + + + + + + + star->total ?> + + comments) { ?> + + + comment->status) { ?> + + + + + + + + + + comment->total ?> + + + + + download->status) { ?> + + + + + + + + + + download->total ?> + +
+
+ + + + + +
+

+ +

+
+
+ + +
+
message ?>
+
+ +
+
+ total > WEBSITE_PAGINATION_LIMIT) { ?> +
+
+ page, ceil($response->total / WEBSITE_PAGINATION_LIMIT)) ?> + page > 1) { ?> + + + + + page < ceil($response->total / WEBSITE_PAGINATION_LIMIT)) { ?> + + + + +
+
+ +
+
+ + + + \ No newline at end of file diff --git a/src/public/magnet.php b/src/public/magnet.php new file mode 100644 index 0000000..2c3f1e0 --- /dev/null +++ b/src/public/magnet.php @@ -0,0 +1,508 @@ + true, + 'message' => false, + 'magnet' => [], + 'comments' => [], +]; + +// Yggdrasil connections only +if (!Valid::host($_SERVER['REMOTE_ADDR'])) +{ + $response->success = false; + $response->message = _('Yggdrasil connection required to enable resource features'); +} + +// Init session +else if (!$userId = $db->initUserId($_SERVER['REMOTE_ADDR'], USER_DEFAULT_APPROVED, time())) +{ + $response->success = false; + $response->message = _('Could not init user session'); +} + +// Get user +else if (!$user = $db->getUser($userId)) +{ + $response->success = false; + $response->message = _('Could not init user info'); +} + +// Init magnet +else if (!$magnet = $db->getMagnet(isset($_GET['magnetId']) ? (int) $_GET['magnetId'] : 0)) +{ + $response->success = false; + $response->message = _('Magnet not found! Submit new magnet link by sending address to the search field.'); +} + +// On first visit, redirect user to the welcome page with access level question +else if (is_null($user->public) && !isset($_GET['rss'])) +{ + header( + sprintf('Location: %s/welcome.php', WEBSITE_URL) + ); +} + +// Request valid +else +{ + // Get access info + $accessRead = ($user->address == $db->getUser($magnet->userId)->address || in_array($user->address, MODERATOR_IP_LIST) || ($magnet->public && $magnet->approved)); + $accessEdit = ($user->address == $db->getUser($magnet->userId)->address || in_array($user->address, MODERATOR_IP_LIST)); + + // Update magnet viewed + if ($accessRead) + { + if ($magnetViewId = $db->addMagnetView($magnet->magnetId, $userId, time())) + { + // Push event to other nodes + if (API_EXPORT_ENABLED && + API_EXPORT_PUSH_ENABLED && + API_EXPORT_USERS_ENABLED && + API_EXPORT_MAGNETS_ENABLED && + API_EXPORT_MAGNET_VIEWS_ENABLED) + { + if (!$memoryApiExportPush = $memory->get('api.export.push')) + { + $memoryApiExportPush = []; + } + + $memoryApiExportPush[] = (object) + [ + 'time' => time(), + 'userId' => $user->userId, + 'magnetId' => $magnet->magnetId, + 'magnetViewId' => $magnetViewId + ]; + + $memory->set('api.export.push', $memoryApiExportPush, 3600); + } + } + } + + // Keywords + $keywords = []; + + foreach ($db->findKeywordTopicByMagnetId($magnet->magnetId) as $keyword) + { + $keywords[] = $db->getKeywordTopic($keyword->keywordTopicId)->value; + } + + $response->user = $user; + $response->magnet = (object) + [ + 'magnetId' => $magnet->magnetId, + 'title' => $magnet->title ? htmlentities($magnet->title) : ($magnet->dn ? htmlentities($magnet->dn): false), + 'preview' => $magnet->preview ? nl2br( + htmlentities( + $magnet->preview + ) + ) : false, + 'description' => $magnet->description ? nl2br( + htmlentities( + $magnet->description + ) + ) : false, + 'approved' => (bool) $magnet->approved, + 'public' => (bool) $magnet->public, + 'sensitive' => (bool) $magnet->sensitive, + 'comments' => (bool) $magnet->comments, + 'timeAdded' => $magnet->timeAdded ? Time::ago((int) $magnet->timeAdded) : false, + 'timeUpdated' => $magnet->timeUpdated ? Time::ago((int) $magnet->timeUpdated) : false, + 'keywords' => $keywords, + 'comment' => (object) + [ + 'total' => $db->findMagnetCommentsTotalByMagnetId($magnet->magnetId), + 'status' => $db->findMagnetCommentsTotal($magnet->magnetId, $userId), + ], + 'download' => (object) + [ + 'total' => $db->findMagnetDownloadsTotalByMagnetId($magnet->magnetId), + 'status' => $db->findMagnetDownloadsTotal($magnet->magnetId, $userId), + ], + 'star' => (object) + [ + 'total' => $db->findMagnetStarsTotalByMagnetId($magnet->magnetId, true), + 'status' => $db->findLastMagnetStarValue($magnet->magnetId, $userId), + ], + 'access' => (object) + [ + 'read' => $accessRead, + 'edit' => $accessEdit, + ], + 'seeders' => $db->getMagnetToAddressTrackerSeedersSumByMagnetId($magnet->magnetId), + 'completed' => $db->getMagnetToAddressTrackerCompletedSumByMagnetId($magnet->magnetId), + 'leechers' => $db->getMagnetToAddressTrackerLeechersSumByMagnetId($magnet->magnetId), + 'directs' => $db->getMagnetToAcceptableSourceTotalByMagnetId($magnet->magnetId), + ]; +} + +if (isset($_GET['rss']) && isset($_GET['target']) && $_GET['target'] == 'comment' && $response->success) { ?>' . PHP_EOL ?> + + + + magnet->magnetId) ?> + <?php echo sprintf(_('%s - Comments - %s'), htmlentities($response->magnet->title), WEBSITE_NAME) ?> + + findMagnetComments($response->magnet->magnetId) as $magnetComment) { ?> + user->address == $db->getUser($magnetComment->userId)->address || in_array($response->user->address, MODERATOR_IP_LIST)) { ?> + + <?php echo sprintf('%s - comment #%s', htmlspecialchars($magnet->title, ENT_QUOTES, 'UTF-8'), $magnetComment->magnetCommentId) ?> + value, ENT_QUOTES, 'UTF-8') ?> + magnet->magnetId, $magnetComment->magnetCommentId) ?> + magnet->magnetId, $magnetComment->magnetCommentId) ?> + + + + + + + + + + + + success) { ?> + <?php echo sprintf(_('%s - %s'), htmlentities($response->magnet->title), WEBSITE_NAME) ?> + + + + <?php echo $response->message ?> + + + + + +
+
+ +
+
+
+
+
+
+ success) { ?> + magnet->access->read) { ?> +
+
+ +

magnet->title ?>

+ magnet->leechers && !$response->magnet->seeders) { ?> + + + + +
+ magnet->public) { ?> + + + + + + + + magnet->approved) { ?> + + + + + + + magnet->access->edit) { ?> + + + + + + + + + +
+ magnet->preview) { ?> +
magnet->preview ?>
+ + magnet->description) { ?> +
magnet->description ?>
+ + magnet->keywords) { ?> +
+ magnet->keywords as $keyword) { ?> + + # + + +
+ +
+ + + + magnet->timeUpdated ? _('Updated') : _('Added') ?> + magnet->timeUpdated ? $response->magnet->timeUpdated : $response->magnet->timeAdded ?> + + + + + + + magnet->seeders ?> + + + + + + magnet->completed ?> + + + + + + + magnet->leechers ?> + + magnet->directs) { ?> + + + + + magnet->directs ?> + + + + + magnet->star->status) { ?> + + + + + + + + + + magnet->star->total ?> + + magnet->comments) { ?> + + + magnet->comment->status) { ?> + + + + + + + + + + magnet->comment->total ?> + + + + + magnet->download->status) { ?> + + + + + + + + + + magnet->download->total ?> + +
+
+ searchMagnetsTotal($magnet->title ? $magnet->title : $magnet->dn, 'similar', MAGNET_STOP_WORDS_SIMILAR)) { ?> + 1) { // skip current magnet ?> +
+ +

+
+
+
+ searchMagnets( + $magnet->title ? $magnet->title : $magnet->dn, + 0, + 10, + $similarMagnetsTotal, + 'similar', + MAGNET_STOP_WORDS_SIMILAR + ) as $result) { ?> + getMagnet($result->magnetid)) { ?> + magnetid != $response->magnet->magnetId && // skip current magnet + ($response->user->address == $db->getUser($magnet->userId)->address || + in_array($response->user->address, MODERATOR_IP_LIST) || ($magnet->approved && $magnet->public))) { ?> + + + + +
+
+ + + magnet->comments) { ?> +
+ +

+ +
+
+ findMagnetComments($response->magnet->magnetId) as $magnetComment) { ?> +
+ + user->address == $db->getUser($magnetComment->userId)->address || + in_array($response->user->address, MODERATOR_IP_LIST) || + ($magnetComment->approved && $magnetComment->public)) { ?> +
+ value)) ?> +
+ + + + + timeAdded) ?> + + + public) { ?> + + + + + + + + approved) { ?> + + + + + + + + user->address, MODERATOR_IP_LIST)) { ?> + + approved) { ?> + + + + + + + + + +
+ +
+ +
+
+ +
+
+ +
+
+
+ + +
+
+
+ + +
+
message ?>
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/src/public/node.php b/src/public/node.php new file mode 100644 index 0000000..08df253 --- /dev/null +++ b/src/public/node.php @@ -0,0 +1,534 @@ + + true, + 'message' => _('Internal server error'), +]; + +// Yggdrasil connections only +if (!Valid::host($_SERVER['REMOTE_ADDR'])) +{ + $response->success = false; + $response->message = _('Yggdrasil connection required for this action'); +} + +// Init session +else if (!$userId = $db->initUserId($_SERVER['REMOTE_ADDR'], USER_DEFAULT_APPROVED, time())) +{ + $response->success = false; + $response->message = _('Could not init user session'); +} + +// Get user +else if (!$user = $db->getUser($userId)) +{ + $response->success = false; + $response->message = _('Could not init user info'); +} + +// On first visit, redirect user to the welcome page with access level question +else if (is_null($user->public)) +{ + header( + sprintf('Location: %s/welcome.php', WEBSITE_URL) + ); +} + +?> + + + + + + + <?php echo sprintf(_('%s instance info'), WEBSITE_NAME) ?> + + + + + + +
+
+ +
+
+
+
+
+
+
+ success) { ?> +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + $tracker) { ?> + + + + $value) { ?> + + + + + + + + + + + + + + + + $node) { ?> + + + + $value) { ?> + + + + + + + + + + + + + + + + $peer) { ?> + + + + $value) { ?> + + + + + + + + + + + + + + +
+ +
+ public ? _('Distributed') : _('Local') ?> + + + + + +
+ address ?> +
+ timeUpdated) ?> +
+ +
+ +
+ getUsersTotal() ?> + getUsersTotalByPublic(true)) { ?> + / + + + + + getUsersTotalByPublic(false)) { ?> + / + + + + + + + + + +
+ getMagnetsTotal() ?> + getMagnetsTotalByUsersPublic(true)) { ?> + / + + + + + getMagnetsTotalByUsersPublic(false)) { ?> + / + + + + + + + + + +
+ getMagnetDownloadsTotal() ?> + findMagnetDownloadsTotalByUsersPublic(true)) { ?> + / + + + + + findMagnetDownloadsTotalByUsersPublic(false)) { ?> + / + + + + + + + + + +
+ getMagnetCommentsTotal() ?> + findMagnetCommentsTotalByUsersPublic(true)) { ?> + / + + + + + findMagnetCommentsTotalByUsersPublic(false)) { ?> + / + + + + + + + + + +
+ getMagnetStarsTotal() ?> + findMagnetStarsTotalByUsersPublic(true)) { ?> + / + + + + + findMagnetStarsTotalByUsersPublic(false)) { ?> + / + + + + + + + + + +
+ getMagnetViewsTotal() ?> + findMagnetViewsTotalByUsersPublic(true)) { ?> + / + + + + + findMagnetViewsTotalByUsersPublic(false)) { ?> + / + + + + + + + + + +
getMagnetToAddressTrackerSeedersSum() ?>
getMagnetToAddressTrackerCompletedSum() ?>
getMagnetToAddressTrackerLeechersSum() ?>
+ +
+ +
-
-
-
+ - + / + - +
+ - +
+ - +
+ - +
+ +
-
+ + + + + + + + + +
+ + + + + +
+ + + + + + + + + +
+ + + + + +
+ + + + + + + + + +
+ + + + + +
+ +
message ?>
+ +
+
+
+
+
+ + + \ No newline at end of file diff --git a/src/public/welcome.php b/src/public/welcome.php new file mode 100644 index 0000000..aaac011 --- /dev/null +++ b/src/public/welcome.php @@ -0,0 +1,146 @@ + + true, + 'message' => _('Internal server error'), +]; + +// Yggdrasil connections only +if (!Valid::host($_SERVER['REMOTE_ADDR'])) +{ + $response->success = false; + $response->message = _('Yggdrasil connection required for this action'); +} + +// Init session +else if (!$userId = $db->initUserId($_SERVER['REMOTE_ADDR'], USER_DEFAULT_APPROVED, time())) +{ + $response->success = false; + $response->message = _('Could not init user session'); +} + +// Init user +else if (!$user = $db->getUser($userId)) +{ + $response->success = false; + $response->message = _('Could not get user session'); +} + +// User can change public level once, because by agreement data could be already sent +// Otherwise, local access level could be changed to public on settings page later +// Redirect to website features +else if (!is_null($user->public)) +{ + header( + sprintf('Location: %s', WEBSITE_URL) + ); +} + +// Apply answer on form submit +else if (isset($_POST['public'])) +{ + if ($db->updateUserPublic($user->userId, (bool) $_POST['public'], time())) + { + header( + sprintf('Location: %s', WEBSITE_URL) + ); + } +} + +?> + + + + + + + <?php echo sprintf(_('Welcome to %s'), WEBSITE_NAME) ?> + + + + + + +
+
+ +
+
+
+
+
+
+
+ success) { ?> +
+
+

+
+

+

+

address ?>

+
+
+ + +
+
+ +
+
+
+ +
message ?>
+ +
+
+
+
+
+ + + \ No newline at end of file diff --git a/migrations/.gitignore b/src/storage/log/index.html similarity index 100% rename from migrations/.gitignore rename to src/storage/log/index.html diff --git a/symfony.lock b/symfony.lock deleted file mode 100644 index c7eb7ca..0000000 --- a/symfony.lock +++ /dev/null @@ -1,279 +0,0 @@ -{ - "doctrine/annotations": { - "version": "2.0", - "recipe": { - "repo": "github.com/symfony/recipes", - "branch": "main", - "version": "1.10", - "ref": "64d8583af5ea57b7afa4aba4b159907f3a148b05" - } - }, - "doctrine/doctrine-bundle": { - "version": "2.10", - "recipe": { - "repo": "github.com/symfony/recipes", - "branch": "main", - "version": "2.10", - "ref": "e025a6cb69b195970543820b2f18ad21724473fa" - }, - "files": [ - "config/packages/doctrine.yaml", - "src/Entity/.gitignore", - "src/Repository/.gitignore" - ] - }, - "doctrine/doctrine-migrations-bundle": { - "version": "3.2", - "recipe": { - "repo": "github.com/symfony/recipes", - "branch": "main", - "version": "3.1", - "ref": "1d01ec03c6ecbd67c3375c5478c9a423ae5d6a33" - }, - "files": [ - "config/packages/doctrine_migrations.yaml", - "migrations/.gitignore" - ] - }, - "phpunit/phpunit": { - "version": "9.6", - "recipe": { - "repo": "github.com/symfony/recipes", - "branch": "main", - "version": "9.6", - "ref": "7364a21d87e658eb363c5020c072ecfdc12e2326" - }, - "files": [ - ".env.test", - "phpunit.xml.dist", - "tests/bootstrap.php" - ] - }, - "symfony/console": { - "version": "6.3", - "recipe": { - "repo": "github.com/symfony/recipes", - "branch": "main", - "version": "5.3", - "ref": "da0c8be8157600ad34f10ff0c9cc91232522e047" - }, - "files": [ - "bin/console" - ] - }, - "symfony/crowdin-translation-provider": { - "version": "6.3", - "recipe": { - "repo": "github.com/symfony/recipes", - "branch": "main", - "version": "5.3", - "ref": "9f5f1508bc80ed56c8a3ae7febc53a8aa982e424" - } - }, - "symfony/debug-bundle": { - "version": "6.3", - "recipe": { - "repo": "github.com/symfony/recipes", - "branch": "main", - "version": "5.3", - "ref": "5aa8aa48234c8eb6dbdd7b3cd5d791485d2cec4b" - }, - "files": [ - "config/packages/debug.yaml" - ] - }, - "symfony/flex": { - "version": "2.3", - "recipe": { - "repo": "github.com/symfony/recipes", - "branch": "main", - "version": "1.0", - "ref": "146251ae39e06a95be0fe3d13c807bcf3938b172" - }, - "files": [ - ".env" - ] - }, - "symfony/framework-bundle": { - "version": "6.3", - "recipe": { - "repo": "github.com/symfony/recipes", - "branch": "main", - "version": "6.2", - "ref": "af47254c5e4cd543e6af3e4508298ffebbdaddd3" - }, - "files": [ - "config/packages/cache.yaml", - "config/packages/framework.yaml", - "config/preload.php", - "config/routes/framework.yaml", - "config/services.yaml", - "public/index.php", - "src/Controller/.gitignore", - "src/Kernel.php" - ] - }, - "symfony/mailer": { - "version": "6.3", - "recipe": { - "repo": "github.com/symfony/recipes", - "branch": "main", - "version": "4.3", - "ref": "2bf89438209656b85b9a49238c4467bff1b1f939" - }, - "files": [ - "config/packages/mailer.yaml" - ] - }, - "symfony/maker-bundle": { - "version": "1.51", - "recipe": { - "repo": "github.com/symfony/recipes", - "branch": "main", - "version": "1.0", - "ref": "fadbfe33303a76e25cb63401050439aa9b1a9c7f" - } - }, - "symfony/messenger": { - "version": "6.3", - "recipe": { - "repo": "github.com/symfony/recipes", - "branch": "main", - "version": "6.0", - "ref": "ba1ac4e919baba5644d31b57a3284d6ba12d52ee" - }, - "files": [ - "config/packages/messenger.yaml" - ] - }, - "symfony/monolog-bundle": { - "version": "3.8", - "recipe": { - "repo": "github.com/symfony/recipes", - "branch": "main", - "version": "3.7", - "ref": "213676c4ec929f046dfde5ea8e97625b81bc0578" - }, - "files": [ - "config/packages/monolog.yaml" - ] - }, - "symfony/notifier": { - "version": "6.3", - "recipe": { - "repo": "github.com/symfony/recipes", - "branch": "main", - "version": "5.0", - "ref": "178877daf79d2dbd62129dd03612cb1a2cb407cc" - }, - "files": [ - "config/packages/notifier.yaml" - ] - }, - "symfony/phpunit-bridge": { - "version": "6.3", - "recipe": { - "repo": "github.com/symfony/recipes", - "branch": "main", - "version": "6.3", - "ref": "01dfaa98c58f7a7b5a9b30e6edb7074af7ed9819" - }, - "files": [ - ".env.test", - "bin/phpunit", - "phpunit.xml.dist", - "tests/bootstrap.php" - ] - }, - "symfony/routing": { - "version": "6.3", - "recipe": { - "repo": "github.com/symfony/recipes", - "branch": "main", - "version": "6.2", - "ref": "e0a11b4ccb8c9e70b574ff5ad3dfdcd41dec5aa6" - }, - "files": [ - "config/packages/routing.yaml", - "config/routes.yaml" - ] - }, - "symfony/security-bundle": { - "version": "6.3", - "recipe": { - "repo": "github.com/symfony/recipes", - "branch": "main", - "version": "6.0", - "ref": "8a5b112826f7d3d5b07027f93786ae11a1c7de48" - }, - "files": [ - "config/packages/security.yaml" - ] - }, - "symfony/translation": { - "version": "6.3", - "recipe": { - "repo": "github.com/symfony/recipes", - "branch": "main", - "version": "6.3", - "ref": "64fe617084223633e1dedf9112935d8c95410d3e" - }, - "files": [ - "config/packages/translation.yaml", - "translations/.gitignore" - ] - }, - "symfony/twig-bundle": { - "version": "6.3", - "recipe": { - "repo": "github.com/symfony/recipes", - "branch": "main", - "version": "6.3", - "ref": "b7772eb20e92f3fb4d4fe756e7505b4ba2ca1a2c" - }, - "files": [ - "config/packages/twig.yaml", - "templates/base.html.twig" - ] - }, - "symfony/validator": { - "version": "6.3", - "recipe": { - "repo": "github.com/symfony/recipes", - "branch": "main", - "version": "5.3", - "ref": "c32cfd98f714894c4f128bb99aa2530c1227603c" - }, - "files": [ - "config/packages/validator.yaml" - ] - }, - "symfony/web-profiler-bundle": { - "version": "6.3", - "recipe": { - "repo": "github.com/symfony/recipes", - "branch": "main", - "version": "6.1", - "ref": "e42b3f0177df239add25373083a564e5ead4e13a" - }, - "files": [ - "config/packages/web_profiler.yaml", - "config/routes/web_profiler.yaml" - ] - }, - "symfony/webapp-pack": { - "version": "1.2", - "recipe": { - "repo": "github.com/symfony/recipes", - "branch": "main", - "version": "1.0", - "ref": "aece95c8a188f6e6d04f01ccb8678d1764fd2642" - }, - "files": [ - "config/packages/messenger.yaml" - ] - }, - "twig/extra-bundle": { - "version": "v3.7.1" - } -} diff --git a/templates/bundles/TwigBundle/Exception/error404.html.twig b/templates/bundles/TwigBundle/Exception/error404.html.twig deleted file mode 100644 index 4509a25..0000000 --- a/templates/bundles/TwigBundle/Exception/error404.html.twig +++ /dev/null @@ -1,14 +0,0 @@ -{% extends theme ~ '/layout.html.twig' %} -{% block title %}{{ 'Not found' | trans }} - {{ name }}{% endblock %} -{% block main_content %} -
-
-

- 404 -

-
- {{ 'Page not found!' | trans }} -
-
-
-{% endblock %} \ No newline at end of file diff --git a/templates/bundles/TwigBundle/Exception/error500.html.twig b/templates/bundles/TwigBundle/Exception/error500.html.twig deleted file mode 100644 index 8567d21..0000000 --- a/templates/bundles/TwigBundle/Exception/error500.html.twig +++ /dev/null @@ -1,17 +0,0 @@ -{% extends theme ~ '/layout.html.twig' %} -{% block title %}{{ 'Error' | trans }} - {{ name }}{% endblock %} -{% block main_content %} -
-
-

- {{ 'Oops!' | trans }} -

-
- {{ 'Internal server error' | trans }} -
- - {{ 'Report' | trans }} - -
-
-{% endblock %} \ No newline at end of file diff --git a/templates/default/activity/event/torrent/add.html.twig b/templates/default/activity/event/torrent/add.html.twig deleted file mode 100644 index b7e2610..0000000 --- a/templates/default/activity/event/torrent/add.html.twig +++ /dev/null @@ -1,28 +0,0 @@ -
-
- - {{ 'identicon' | trans }} - - {{ 'have added torrent' | trans }} - {% if session.user.moderator or session.user.owner %} - - {{ torrent.name }} - - {% else %} - {% if torrent.status == false %} - #{{ torrent.id }} ({{ 'disabled' | trans }}) - {% elseif torrent.approved == false %} - #{{ torrent.id }} ({{ 'waiting for approve' | trans }}) - {% elseif torrent.sensitive == true and session.user.sensitive == true %} - #{{ torrent.id }} ({{ 'sensitive' | trans }}) - {% else %} - - {{ torrent.name }} - - {% endif %} - {% endif %} -
-
- {{ added | format_ago }} -
-
\ No newline at end of file diff --git a/templates/default/activity/event/torrent/add.rss.twig b/templates/default/activity/event/torrent/add.rss.twig deleted file mode 100644 index db55c4c..0000000 --- a/templates/default/activity/event/torrent/add.rss.twig +++ /dev/null @@ -1,24 +0,0 @@ - - - {{ 'User' | trans }} - #{{ user.id }} - {{ 'have added torrent' | trans }} - {% if session.user.moderator or session.user.owner %} - {{ torrent.name }} - {% else %} - {% if torrent.status == false %} - #{{ torrent.id }} ({{ 'disabled' | trans }}) - {% elseif torrent.approved == false %} - #{{ torrent.id }} ({{ 'waiting for approve' | trans }}) - {% elseif torrent.sensitive == true and session.user.sensitive == true %} - #{{ torrent.id }} ({{ 'sensitive' | trans }}) - {% else %} - {{ torrent.name }} - {% endif %} - {% endif %} - - #{{ user.id }} - {{ added | date('D, d M Y h:i:s O') }} - {{ url('torrent_info', { torrentId : torrent.id }) }}#activity-{{ id }} - {{ url('torrent_info', { torrentId : torrent.id }) }}#activity - \ No newline at end of file diff --git a/templates/default/activity/event/torrent/approve/add.html.twig b/templates/default/activity/event/torrent/approve/add.html.twig deleted file mode 100644 index e394ecb..0000000 --- a/templates/default/activity/event/torrent/approve/add.html.twig +++ /dev/null @@ -1,30 +0,0 @@ -
-
- - {{ 'identicon' | trans }} - - - {{ 'have approved torrent' | trans }} - - {% if session.user.moderator or session.user.owner %} - - {{ torrent.name }} - - {% else %} - {% if torrent.status == false %} - #{{ torrent.id }} ({{ 'disabled' | trans }}) - {% elseif torrent.approved == false %} - #{{ torrent.id }} ({{ 'waiting for approve' | trans }}) - {% elseif torrent.sensitive == true and session.user.sensitive == true %} - #{{ torrent.id }} ({{ 'sensitive' | trans }}) - {% else %} - - {{ torrent.name }} - - {% endif %} - {% endif %} -
-
- {{ added | format_ago }} -
-
\ No newline at end of file diff --git a/templates/default/activity/event/torrent/approve/add.rss.twig b/templates/default/activity/event/torrent/approve/add.rss.twig deleted file mode 100644 index e378199..0000000 --- a/templates/default/activity/event/torrent/approve/add.rss.twig +++ /dev/null @@ -1,24 +0,0 @@ - - - {{ 'User' | trans }} - #{{ user.id }} - {{ 'have approved torrent' | trans }} - {% if session.user.moderator or session.user.owner %} - {{ torrent.name }} - {% else %} - {% if torrent.status == false %} - #{{ torrent.id }} ({{ 'disabled' | trans }}) - {% elseif torrent.approved == false %} - #{{ torrent.id }} ({{ 'waiting for approve' | trans }}) - {% elseif torrent.sensitive == true and session.user.sensitive == true %} - #{{ torrent.id }} ({{ 'sensitive' | trans }}) - {% else %} - {{ torrent.name }} - {% endif %} - {% endif %} - - #{{ user.id }} - {{ added | date('D, d M Y h:i:s O') }} - {{ url('torrent_info', { torrentId : torrent.id }) }}#activity-{{ id }} - {{ url('torrent_info', { torrentId : torrent.id }) }}#activity - \ No newline at end of file diff --git a/templates/default/activity/event/torrent/approve/delete.html.twig b/templates/default/activity/event/torrent/approve/delete.html.twig deleted file mode 100644 index 50d6079..0000000 --- a/templates/default/activity/event/torrent/approve/delete.html.twig +++ /dev/null @@ -1,30 +0,0 @@ -
-
- - {{ 'identicon' | trans }} - - - {{ 'have disapproved torrent' | trans }} - - {% if session.user.moderator or session.user.owner %} - - {{ torrent.name }} - - {% else %} - {% if torrent.status == false %} - #{{ torrent.id }} ({{ 'disabled' | trans }}) - {% elseif torrent.approved == false %} - #{{ torrent.id }} ({{ 'waiting for approve' | trans }}) - {% elseif torrent.sensitive == true and session.user.sensitive == true %} - #{{ torrent.id }} ({{ 'sensitive' | trans }}) - {% else %} - - {{ torrent.name }} - - {% endif %} - {% endif %} -
-
- {{ added | format_ago }} -
-
\ No newline at end of file diff --git a/templates/default/activity/event/torrent/approve/delete.rss.twig b/templates/default/activity/event/torrent/approve/delete.rss.twig deleted file mode 100644 index 7252d9f..0000000 --- a/templates/default/activity/event/torrent/approve/delete.rss.twig +++ /dev/null @@ -1,24 +0,0 @@ - - - {{ 'User' | trans }} - #{{ user.id }} - {{ 'have disapproved torrent' | trans }} - {% if session.user.moderator or session.user.owner %} - {{ torrent.name }} - {% else %} - {% if torrent.status == false %} - #{{ torrent.id }} ({{ 'disabled' | trans }}) - {% elseif torrent.approved == false %} - #{{ torrent.id }} ({{ 'waiting for approve' | trans }}) - {% elseif torrent.sensitive == true and session.user.sensitive == true %} - #{{ torrent.id }} ({{ 'sensitive' | trans }}) - {% else %} - {{ torrent.name }} - {% endif %} - {% endif %} - - #{{ user.id }} - {{ added | date('D, d M Y h:i:s O') }} - {{ url('torrent_info', { torrentId : torrent.id }) }}#activity-{{ id }} - {{ url('torrent_info', { torrentId : torrent.id }) }}#activity - \ No newline at end of file diff --git a/templates/default/activity/event/torrent/categories/add.html.twig b/templates/default/activity/event/torrent/categories/add.html.twig deleted file mode 100644 index 1d081c7..0000000 --- a/templates/default/activity/event/torrent/categories/add.html.twig +++ /dev/null @@ -1,39 +0,0 @@ -
-
- - {{ 'identicon' | trans }} - - {{ 'have added categories edition' | trans }} - {% if torrent.categories.exist %} - - #{{ torrent.categories.id }} - - {% else %} - #{{ torrent.categories.id }} - {% endif %} - {{ 'for torrent' | trans }} - {% if session.user.moderator or session.user.owner %} - - {{ torrent.name }} - - {% if torrent.approved == false %} - #{{ torrent.id }} ({{ 'waiting for approve' | trans }}) - {% endif %} - {% else %} - {% if torrent.status == false %} - #{{ torrent.id }} ({{ 'disabled' | trans }}) - {% elseif torrent.approved == false %} - #{{ torrent.id }} ({{ 'waiting for approve' | trans }}) - {% elseif torrent.sensitive == true and session.user.sensitive == true %} - #{{ torrent.id }} ({{ 'sensitive' | trans }}) - {% else %} - - {{ torrent.name }} - - {% endif %} - {% endif %} -
-
- {{ added | format_ago }} -
-
\ No newline at end of file diff --git a/templates/default/activity/event/torrent/categories/add.rss.twig b/templates/default/activity/event/torrent/categories/add.rss.twig deleted file mode 100644 index 2262f72..0000000 --- a/templates/default/activity/event/torrent/categories/add.rss.twig +++ /dev/null @@ -1,26 +0,0 @@ - - - {{ 'User' | trans }} - #{{ user.id }} - {{ 'have added categories edition' | trans }} - #{{ torrent.categories.id }} - {{ 'for torrent' | trans }} - {% if session.user.moderator or session.user.owner %} - {{ torrent.name }} - {% else %} - {% if torrent.status == false %} - #{{ torrent.id }} ({{ 'disabled' | trans }}) - {% elseif torrent.approved == false %} - #{{ torrent.id }} ({{ 'waiting for approve' | trans }}) - {% elseif torrent.sensitive == true and session.user.sensitive == true %} - #{{ torrent.id }} ({{ 'sensitive' | trans }}) - {% else %} - {{ torrent.name }} - {% endif %} - {% endif %} - - #{{ user.id }} - {{ added | date('D, d M Y h:i:s O') }} - {{ url('torrent_categories_edit', { torrentId : torrent.id, torrentCategoriesId : torrent.categories.id }) }}#activity-{{ id }} - {{ url('torrent_categories_edit', { torrentId : torrent.id, torrentCategoriesId : torrent.categories.id }) }}#activity - \ No newline at end of file diff --git a/templates/default/activity/event/torrent/categories/approve/add.html.twig b/templates/default/activity/event/torrent/categories/approve/add.html.twig deleted file mode 100644 index 19c4836..0000000 --- a/templates/default/activity/event/torrent/categories/approve/add.html.twig +++ /dev/null @@ -1,39 +0,0 @@ -
-
- - {{ 'identicon' | trans }} - - {{ 'have approved categories edition' | trans }} - {% if torrent.categories.exist %} - - #{{ torrent.categories.id }} - - {% else %} - #{{ torrent.categories.id }} - {% endif %} - {{ 'for torrent' | trans }} - {% if session.user.moderator or session.user.owner %} - - {{ torrent.name }} - - {% if torrent.approved == false %} - #{{ torrent.id }} ({{ 'waiting for approve' | trans }}) - {% endif %} - {% else %} - {% if torrent.status == false %} - #{{ torrent.id }} ({{ 'disabled' | trans }}) - {% elseif torrent.approved == false %} - #{{ torrent.id }} ({{ 'waiting for approve' | trans }}) - {% elseif torrent.sensitive == true and session.user.sensitive == true %} - #{{ torrent.id }} ({{ 'sensitive' | trans }}) - {% else %} - - {{ torrent.name }} - - {% endif %} - {% endif %} -
-
- {{ added | format_ago }} -
-
\ No newline at end of file diff --git a/templates/default/activity/event/torrent/categories/approve/add.rss.twig b/templates/default/activity/event/torrent/categories/approve/add.rss.twig deleted file mode 100644 index 9395f46..0000000 --- a/templates/default/activity/event/torrent/categories/approve/add.rss.twig +++ /dev/null @@ -1,26 +0,0 @@ - - - {{ 'User' | trans }} - #{{ user.id }} - {{ 'have approved categories edition' | trans }} - #{{ torrent.categories.id }} - {{ 'for torrent' | trans }} - {% if session.user.moderator or session.user.owner %} - {{ torrent.name }} - {% else %} - {% if torrent.status == false %} - #{{ torrent.id }} ({{ 'disabled' | trans }}) - {% elseif torrent.approved == false %} - #{{ torrent.id }} ({{ 'waiting for approve' | trans }}) - {% elseif torrent.sensitive == true and session.user.sensitive == true %} - #{{ torrent.id }} ({{ 'sensitive' | trans }}) - {% else %} - {{ torrent.name }} - {% endif %} - {% endif %} - - #{{ user.id }} - {{ added | date('D, d M Y h:i:s O') }} - {{ url('torrent_categories_edit', { torrentId : torrent.id, torrentCategoriesId : torrent.categories.id }) }}#activity-{{ id }} - {{ url('torrent_categories_edit', { torrentId : torrent.id, torrentCategoriesId : torrent.categories.id }) }}#activity - \ No newline at end of file diff --git a/templates/default/activity/event/torrent/categories/approve/delete.html.twig b/templates/default/activity/event/torrent/categories/approve/delete.html.twig deleted file mode 100644 index 2d9b682..0000000 --- a/templates/default/activity/event/torrent/categories/approve/delete.html.twig +++ /dev/null @@ -1,41 +0,0 @@ -
-
- - {{ 'identicon' | trans }} - - - {{ 'have disapproved categories edition' | trans }} - - {% if torrent.categories.exist %} - - #{{ torrent.categories.id }} - - {% else %} - #{{ torrent.categories.id }} - {% endif %} - {{ 'for torrent' | trans }} - {% if session.user.moderator or session.user.owner %} - - {{ torrent.name }} - - {% if torrent.approved == false %} - #{{ torrent.id }} ({{ 'waiting for approve' | trans }}) - {% endif %} - {% else %} - {% if torrent.status == false %} - #{{ torrent.id }} ({{ 'disabled' | trans }}) - {% elseif torrent.approved == false %} - #{{ torrent.id }} ({{ 'waiting for approve' | trans }}) - {% elseif torrent.sensitive == true and session.user.sensitive == true %} - #{{ torrent.id }} ({{ 'sensitive' | trans }}) - {% else %} - - {{ torrent.name }} - - {% endif %} - {% endif %} -
-
- {{ added | format_ago }} -
-
\ No newline at end of file diff --git a/templates/default/activity/event/torrent/categories/approve/delete.rss.twig b/templates/default/activity/event/torrent/categories/approve/delete.rss.twig deleted file mode 100644 index a6a6970..0000000 --- a/templates/default/activity/event/torrent/categories/approve/delete.rss.twig +++ /dev/null @@ -1,26 +0,0 @@ - - - {{ 'User' | trans }} - #{{ user.id }} - {{ 'have disapproved categories edition' | trans }} - #{{ torrent.categories.id }} - {{ 'for torrent' | trans }} - {% if session.user.moderator or session.user.owner %} - {{ torrent.name }} - {% else %} - {% if torrent.status == false %} - #{{ torrent.id }} ({{ 'disabled' | trans }}) - {% elseif torrent.approved == false %} - #{{ torrent.id }} ({{ 'waiting for approve' | trans }}) - {% elseif torrent.sensitive == true and session.user.sensitive == true %} - #{{ torrent.id }} ({{ 'sensitive' | trans }}) - {% else %} - {{ torrent.name }} - {% endif %} - {% endif %} - - #{{ user.id }} - {{ added | date('D, d M Y h:i:s O') }} - {{ url('torrent_categories_edit', { torrentId : torrent.id, torrentCategoriesId : torrent.categories.id }) }}#activity-{{ id }} - {{ url('torrent_categories_edit', { torrentId : torrent.id, torrentCategoriesId : torrent.categories.id }) }}#activity - \ No newline at end of file diff --git a/templates/default/activity/event/torrent/categories/delete.html.twig b/templates/default/activity/event/torrent/categories/delete.html.twig deleted file mode 100644 index 06b972b..0000000 --- a/templates/default/activity/event/torrent/categories/delete.html.twig +++ /dev/null @@ -1,39 +0,0 @@ -
-
- - {{ 'identicon' | trans }} - - {{ 'have deleted categories edition' | trans }} - {% if torrent.categories.exist %} - - #{{ torrent.categories.id }} - - {% else %} - #{{ torrent.categories.id }} - {% endif %} - {{ 'for torrent' | trans }} - {% if session.user.moderator or session.user.owner %} - - {{ torrent.name }} - - {% if torrent.approved == false %} - #{{ torrent.id }} ({{ 'waiting for approve' | trans }}) - {% endif %} - {% else %} - {% if torrent.status == false %} - #{{ torrent.id }} ({{ 'disabled' | trans }}) - {% elseif torrent.approved == false %} - #{{ torrent.id }} ({{ 'waiting for approve' | trans }}) - {% elseif torrent.sensitive == true and session.user.sensitive == true %} - #{{ torrent.id }} ({{ 'sensitive' | trans }}) - {% else %} - - {{ torrent.name }} - - {% endif %} - {% endif %} -
-
- {{ added | format_ago }} -
-
\ No newline at end of file diff --git a/templates/default/activity/event/torrent/categories/delete.rss.twig b/templates/default/activity/event/torrent/categories/delete.rss.twig deleted file mode 100644 index 063750b..0000000 --- a/templates/default/activity/event/torrent/categories/delete.rss.twig +++ /dev/null @@ -1,26 +0,0 @@ - - - {{ 'User' | trans }} - #{{ user.id }} - {{ 'have deleted categories edition' | trans }} - #{{ torrent.categories.id }} - {{ 'for torrent' | trans }} - {% if session.user.moderator or session.user.owner %} - {{ torrent.name }} - {% else %} - {% if torrent.status == false %} - #{{ torrent.id }} ({{ 'disabled' | trans }}) - {% elseif torrent.approved == false %} - #{{ torrent.id }} ({{ 'waiting for approve' | trans }}) - {% elseif torrent.sensitive == true and session.user.sensitive == true %} - #{{ torrent.id }} ({{ 'sensitive' | trans }}) - {% else %} - {{ torrent.name }} - {% endif %} - {% endif %} - - #{{ user.id }} - {{ added | date('D, d M Y h:i:s O') }} - {{ url('torrent_categories_edit', { torrentId : torrent.id }) }}#activity-{{ id }} - {{ url('torrent_categories_edit', { torrentId : torrent.id }) }}#activity - \ No newline at end of file diff --git a/templates/default/activity/event/torrent/download/file/add.html.twig b/templates/default/activity/event/torrent/download/file/add.html.twig deleted file mode 100644 index 1e0e5e3..0000000 --- a/templates/default/activity/event/torrent/download/file/add.html.twig +++ /dev/null @@ -1,33 +0,0 @@ -
-
- - {{ 'identicon' | trans }} - - - {{ 'have downloaded torrent file' | trans }} - - {% if session.user.moderator or session.user.owner %} - - {{ torrent.name }} - - {% if torrent.approved == false %} - ({{ 'waiting for approve' | trans }}) - {% endif %} - {% else %} - {% if torrent.status == false %} - #{{ torrent.id }} ({{ 'disabled' | trans }}) - {% elseif torrent.approved == false %} - #{{ torrent.id }} ({{ 'waiting for approve' | trans }}) - {% elseif torrent.sensitive == true and session.user.sensitive == true %} - #{{ torrent.id }} ({{ 'sensitive' | trans }}) - {% else %} - - {{ torrent.name }} - - {% endif %} - {% endif %} -
-
- {{ added | format_ago }} -
-
\ No newline at end of file diff --git a/templates/default/activity/event/torrent/download/file/add.rss.twig b/templates/default/activity/event/torrent/download/file/add.rss.twig deleted file mode 100644 index d9bee5b..0000000 --- a/templates/default/activity/event/torrent/download/file/add.rss.twig +++ /dev/null @@ -1,24 +0,0 @@ - - - {{ 'User' | trans }} - #{{ user.id }} - {{ 'have downloaded torrent file' | trans }} - {% if session.user.moderator or session.user.owner %} - {{ torrent.name }} - {% else %} - {% if torrent.status == false %} - #{{ torrent.id }} ({{ 'disabled' | trans }}) - {% elseif torrent.approved == false %} - #{{ torrent.id }} ({{ 'waiting for approve' | trans }}) - {% elseif torrent.sensitive == true and session.user.sensitive == true %} - #{{ torrent.id }} ({{ 'sensitive' | trans }}) - {% else %} - {{ torrent.name }} - {% endif %} - {% endif %} - - #{{ user.id }} - {{ added | date('D, d M Y h:i:s O') }} - {{ url('torrent_info', { torrentId : torrent.id }) }}#activity-{{ id }} - {{ url('torrent_info', { torrentId : torrent.id }) }}#activity - \ No newline at end of file diff --git a/templates/default/activity/event/torrent/download/magnet/add.html.twig b/templates/default/activity/event/torrent/download/magnet/add.html.twig deleted file mode 100644 index edfc68c..0000000 --- a/templates/default/activity/event/torrent/download/magnet/add.html.twig +++ /dev/null @@ -1,33 +0,0 @@ -
-
- - {{ 'identicon' | trans }} - - - {{ 'have downloaded magnet link' | trans }} - - {% if session.user.moderator or session.user.owner %} - - {{ torrent.name }} - - {% if torrent.approved == false %} - ({{ 'waiting for approve' | trans }}) - {% endif %} - {% else %} - {% if torrent.status == false %} - #{{ torrent.id }} ({{ 'disabled' | trans }}) - {% elseif torrent.approved == false %} - #{{ torrent.id }} ({{ 'waiting for approve' | trans }}) - {% elseif torrent.sensitive == true and session.user.sensitive == true %} - #{{ torrent.id }} ({{ 'sensitive' | trans }}) - {% else %} - - {{ torrent.name }} - - {% endif %} - {% endif %} -
-
- {{ added | format_ago }} -
-
\ No newline at end of file diff --git a/templates/default/activity/event/torrent/download/magnet/add.rss.twig b/templates/default/activity/event/torrent/download/magnet/add.rss.twig deleted file mode 100644 index e29157f..0000000 --- a/templates/default/activity/event/torrent/download/magnet/add.rss.twig +++ /dev/null @@ -1,24 +0,0 @@ - - - {{ 'User' | trans }} - #{{ user.id }} - {{ 'have downloaded magnet link' | trans }} - {% if session.user.moderator or session.user.owner %} - {{ torrent.name }} - {% else %} - {% if torrent.status == false %} - #{{ torrent.id }} ({{ 'disabled' | trans }}) - {% elseif torrent.approved == false %} - #{{ torrent.id }} ({{ 'waiting for approve' | trans }}) - {% elseif torrent.sensitive == true and session.user.sensitive == true %} - #{{ torrent.id }} ({{ 'sensitive' | trans }}) - {% else %} - {{ torrent.name }} - {% endif %} - {% endif %} - - #{{ user.id }} - {{ added | date('D, d M Y h:i:s O') }} - {{ url('torrent_info', { torrentId : torrent.id }) }}#activity-{{ id }} - {{ url('torrent_info', { torrentId : torrent.id }) }}#activity - \ No newline at end of file diff --git a/templates/default/activity/event/torrent/locales/add.html.twig b/templates/default/activity/event/torrent/locales/add.html.twig deleted file mode 100644 index facd581..0000000 --- a/templates/default/activity/event/torrent/locales/add.html.twig +++ /dev/null @@ -1,39 +0,0 @@ -
-
- - {{ 'identicon' | trans }} - - {{ 'have added locales edition' | trans }} - {% if torrent.locales.exist %} - - #{{ torrent.locales.id }} - - {% else %} - #{{ torrent.locales.id }} - {% endif %} - {{ 'for torrent' | trans }} - {% if session.user.moderator or session.user.owner %} - - {{ torrent.name }} - - {% if torrent.approved == false %} - #{{ torrent.id }} ({{ 'waiting for approve' | trans }}) - {% endif %} - {% else %} - {% if torrent.status == false %} - #{{ torrent.id }} ({{ 'disabled' | trans }}) - {% elseif torrent.approved == false %} - #{{ torrent.id }} ({{ 'waiting for approve' | trans }}) - {% elseif torrent.sensitive == true and session.user.sensitive == true %} - #{{ torrent.id }} ({{ 'sensitive' | trans }}) - {% else %} - - {{ torrent.name }} - - {% endif %} - {% endif %} -
-
- {{ added | format_ago }} -
-
\ No newline at end of file diff --git a/templates/default/activity/event/torrent/locales/add.rss.twig b/templates/default/activity/event/torrent/locales/add.rss.twig deleted file mode 100644 index 81ec578..0000000 --- a/templates/default/activity/event/torrent/locales/add.rss.twig +++ /dev/null @@ -1,26 +0,0 @@ - - - {{ 'User' | trans }} - #{{ user.id }} - {{ 'have added locales edition' | trans }} - #{{ torrent.locales.id }} - {{ 'for torrent' | trans }} - {% if session.user.moderator or session.user.owner %} - {{ torrent.name }} - {% else %} - {% if torrent.status == false %} - #{{ torrent.id }} ({{ 'disabled' | trans }}) - {% elseif torrent.approved == false %} - #{{ torrent.id }} ({{ 'waiting for approve' | trans }}) - {% elseif torrent.sensitive == true and session.user.sensitive == true %} - #{{ torrent.id }} ({{ 'sensitive' | trans }}) - {% else %} - {{ torrent.name }} - {% endif %} - {% endif %} - - #{{ user.id }} - {{ added | date('D, d M Y h:i:s O') }} - {{ url('torrent_locales_edit', { torrentId : torrent.id, torrentLocalesId : torrent.locales.id }) }}#activity-{{ id }} - {{ url('torrent_locales_edit', { torrentId : torrent.id, torrentLocalesId : torrent.locales.id }) }}#activity - \ No newline at end of file diff --git a/templates/default/activity/event/torrent/locales/approve/add.html.twig b/templates/default/activity/event/torrent/locales/approve/add.html.twig deleted file mode 100644 index 27ed85b..0000000 --- a/templates/default/activity/event/torrent/locales/approve/add.html.twig +++ /dev/null @@ -1,39 +0,0 @@ -
-
- - {{ 'identicon' | trans }} - - {{ 'have approved locales edition' | trans }} - {% if torrent.locales.exist %} - - #{{ torrent.locales.id }} - - {% else %} - #{{ torrent.locales.id }} - {% endif %} - {{ 'for torrent' | trans }} - {% if session.user.moderator or session.user.owner %} - - {{ torrent.name }} - - {% if torrent.approved == false %} - #{{ torrent.id }} ({{ 'waiting for approve' | trans }}) - {% endif %} - {% else %} - {% if torrent.status == false %} - #{{ torrent.id }} ({{ 'disabled' | trans }}) - {% elseif torrent.approved == false %} - #{{ torrent.id }} ({{ 'waiting for approve' | trans }}) - {% elseif torrent.sensitive == true and session.user.sensitive == true %} - #{{ torrent.id }} ({{ 'sensitive' | trans }}) - {% else %} - - {{ torrent.name }} - - {% endif %} - {% endif %} -
-
- {{ added | format_ago }} -
-
\ No newline at end of file diff --git a/templates/default/activity/event/torrent/locales/approve/add.rss.twig b/templates/default/activity/event/torrent/locales/approve/add.rss.twig deleted file mode 100644 index 64dbcdd..0000000 --- a/templates/default/activity/event/torrent/locales/approve/add.rss.twig +++ /dev/null @@ -1,26 +0,0 @@ - - - {{ 'User' | trans }} - #{{ user.id }} - {{ 'have approved locales edition' | trans }} - #{{ torrent.locales.id }} - {{ 'for torrent' | trans }} - {% if session.user.moderator or session.user.owner %} - {{ torrent.name }} - {% else %} - {% if torrent.status == false %} - #{{ torrent.id }} ({{ 'disabled' | trans }}) - {% elseif torrent.approved == false %} - #{{ torrent.id }} ({{ 'waiting for approve' | trans }}) - {% elseif torrent.sensitive == true and session.user.sensitive == true %} - #{{ torrent.id }} ({{ 'sensitive' | trans }}) - {% else %} - {{ torrent.name }} - {% endif %} - {% endif %} - - #{{ user.id }} - {{ added | date('D, d M Y h:i:s O') }} - {{ url('torrent_locales_edit', { torrentId : torrent.id, torrentLocalesId : torrent.locales.id }) }}#activity-{{ id }} - {{ url('torrent_locales_edit', { torrentId : torrent.id, torrentLocalesId : torrent.locales.id }) }}#activity - \ No newline at end of file diff --git a/templates/default/activity/event/torrent/locales/approve/delete.html.twig b/templates/default/activity/event/torrent/locales/approve/delete.html.twig deleted file mode 100644 index d49dcb1..0000000 --- a/templates/default/activity/event/torrent/locales/approve/delete.html.twig +++ /dev/null @@ -1,41 +0,0 @@ -
-
- - {{ 'identicon' | trans }} - - - {{ 'have disapproved locales edition' | trans }} - - {% if torrent.locales.exist %} - - #{{ torrent.locales.id }} - - {% else %} - #{{ torrent.locales.id }} - {% endif %} - {{ 'for torrent' | trans }} - {% if session.user.moderator or session.user.owner %} - - {{ torrent.name }} - - {% if torrent.approved == false %} - #{{ torrent.id }} ({{ 'waiting for approve' | trans }}) - {% endif %} - {% else %} - {% if torrent.status == false %} - #{{ torrent.id }} ({{ 'disabled' | trans }}) - {% elseif torrent.approved == false %} - #{{ torrent.id }} ({{ 'waiting for approve' | trans }}) - {% elseif torrent.sensitive == true and session.user.sensitive == true %} - #{{ torrent.id }} ({{ 'sensitive' | trans }}) - {% else %} - - {{ torrent.name }} - - {% endif %} - {% endif %} -
-
- {{ added | format_ago }} -
-
\ No newline at end of file diff --git a/templates/default/activity/event/torrent/locales/approve/delete.rss.twig b/templates/default/activity/event/torrent/locales/approve/delete.rss.twig deleted file mode 100644 index b0cbada..0000000 --- a/templates/default/activity/event/torrent/locales/approve/delete.rss.twig +++ /dev/null @@ -1,26 +0,0 @@ - - - {{ 'User' | trans }} - #{{ user.id }} - {{ 'have disapproved locales edition' | trans }} - #{{ torrent.locales.id }} - {{ 'for torrent' | trans }} - {% if session.user.moderator or session.user.owner %} - {{ torrent.name }} - {% else %} - {% if torrent.status == false %} - #{{ torrent.id }} ({{ 'disabled' | trans }}) - {% elseif torrent.approved == false %} - #{{ torrent.id }} ({{ 'waiting for approve' | trans }}) - {% elseif torrent.sensitive == true and session.user.sensitive == true %} - #{{ torrent.id }} ({{ 'sensitive' | trans }}) - {% else %} - {{ torrent.name }} - {% endif %} - {% endif %} - - #{{ user.id }} - {{ added | date('D, d M Y h:i:s O') }} - {{ url('torrent_locales_edit', { torrentId : torrent.id, torrentLocalesId : torrent.locales.id }) }}#activity-{{ id }} - {{ url('torrent_locales_edit', { torrentId : torrent.id, torrentLocalesId : torrent.locales.id }) }}#activity - \ No newline at end of file diff --git a/templates/default/activity/event/torrent/locales/delete.html.twig b/templates/default/activity/event/torrent/locales/delete.html.twig deleted file mode 100644 index 4327e41..0000000 --- a/templates/default/activity/event/torrent/locales/delete.html.twig +++ /dev/null @@ -1,39 +0,0 @@ -
-
- - {{ 'identicon' | trans }} - - {{ 'have deleted locales edition' | trans }} - {% if torrent.locales.exist %} - - #{{ torrent.locales.id }} - - {% else %} - #{{ torrent.locales.id }} - {% endif %} - {{ 'for torrent' | trans }} - {% if session.user.moderator or session.user.owner %} - - {{ torrent.name }} - - {% if torrent.approved == false %} - #{{ torrent.id }} ({{ 'waiting for approve' | trans }}) - {% endif %} - {% else %} - {% if torrent.status == false %} - #{{ torrent.id }} ({{ 'disabled' | trans }}) - {% elseif torrent.approved == false %} - #{{ torrent.id }} ({{ 'waiting for approve' | trans }}) - {% elseif torrent.sensitive == true and session.user.sensitive == true %} - #{{ torrent.id }} ({{ 'sensitive' | trans }}) - {% else %} - - {{ torrent.name }} - - {% endif %} - {% endif %} -
-
- {{ added | format_ago }} -
-
\ No newline at end of file diff --git a/templates/default/activity/event/torrent/locales/delete.rss.twig b/templates/default/activity/event/torrent/locales/delete.rss.twig deleted file mode 100644 index 1bb311d..0000000 --- a/templates/default/activity/event/torrent/locales/delete.rss.twig +++ /dev/null @@ -1,26 +0,0 @@ - - - {{ 'User' | trans }} - #{{ user.id }} - {{ 'have deleted locales edition' | trans }} - #{{ torrent.locales.id }} - {{ 'for torrent' | trans }} - {% if session.user.moderator or session.user.owner %} - {{ torrent.name }} - {% else %} - {% if torrent.status == false %} - #{{ torrent.id }} ({{ 'disabled' | trans }}) - {% elseif torrent.approved == false %} - #{{ torrent.id }} ({{ 'waiting for approve' | trans }}) - {% elseif torrent.sensitive == true and session.user.sensitive == true %} - #{{ torrent.id }} ({{ 'sensitive' | trans }}) - {% else %} - {{ torrent.name }} - {% endif %} - {% endif %} - - #{{ user.id }} - {{ added | date('D, d M Y h:i:s O') }} - {{ url('torrent_locales_edit', { torrentId : torrent.id }) }}#activity-{{ id }} - {{ url('torrent_locales_edit', { torrentId : torrent.id }) }}#activity - \ No newline at end of file diff --git a/templates/default/activity/event/torrent/poster/add.html.twig b/templates/default/activity/event/torrent/poster/add.html.twig deleted file mode 100644 index 519a6f0..0000000 --- a/templates/default/activity/event/torrent/poster/add.html.twig +++ /dev/null @@ -1,39 +0,0 @@ -
-
- - {{ 'identicon' | trans }} - - {{ 'have added poster edition' | trans }} - {% if torrent.poster.exist %} - - #{{ torrent.poster.id }} - - {% else %} - #{{ torrent.poster.id }} - {% endif %} - {{ 'for torrent' | trans }} - {% if session.user.moderator or session.user.owner %} - - {{ torrent.name }} - - {% if torrent.approved == false %} - #{{ torrent.id }} ({{ 'waiting for approve' | trans }}) - {% endif %} - {% else %} - {% if torrent.status == false %} - #{{ torrent.id }} ({{ 'disabled' | trans }}) - {% elseif torrent.approved == false %} - #{{ torrent.id }} ({{ 'waiting for approve' | trans }}) - {% elseif torrent.sensitive == true and session.user.sensitive == true %} - #{{ torrent.id }} - {% else %} - - {{ torrent.name }} - - {% endif %} - {% endif %} -
-
- {{ added | format_ago }} -
-
\ No newline at end of file diff --git a/templates/default/activity/event/torrent/poster/add.rss.twig b/templates/default/activity/event/torrent/poster/add.rss.twig deleted file mode 100644 index 348e851..0000000 --- a/templates/default/activity/event/torrent/poster/add.rss.twig +++ /dev/null @@ -1,26 +0,0 @@ - - - {{ 'User' | trans }} - #{{ user.id }} - {{ 'have added poster edition' | trans }} - #{{ torrent.poster.id }} - {{ 'for torrent' | trans }} - {% if session.user.moderator or session.user.owner %} - {{ torrent.name }} - {% else %} - {% if torrent.status == false %} - #{{ torrent.id }} ({{ 'disabled' | trans }}) - {% elseif torrent.approved == false %} - #{{ torrent.id }} ({{ 'waiting for approve' | trans }}) - {% elseif torrent.sensitive == true and session.user.sensitive == true %} - #{{ torrent.id }} - {% else %} - {{ torrent.name }} - {% endif %} - {% endif %} - - #{{ user.id }} - {{ added | date('D, d M Y h:i:s O') }} - {{ url('torrent_poster_edit', { torrentId : torrent.id, torrentPosterId : torrent.poster.id }) }}#activity-{{ id }} - {{ url('torrent_poster_edit', { torrentId : torrent.id, torrentPosterId : torrent.poster.id }) }}#activity - \ No newline at end of file diff --git a/templates/default/activity/event/torrent/poster/approve/add.html.twig b/templates/default/activity/event/torrent/poster/approve/add.html.twig deleted file mode 100644 index 35685c0..0000000 --- a/templates/default/activity/event/torrent/poster/approve/add.html.twig +++ /dev/null @@ -1,39 +0,0 @@ -
-
- - {{ 'identicon' | trans }} - - {{ 'have approved poster edition' | trans }} - {% if torrent.poster.exist %} - - #{{ torrent.poster.id }} - - {% else %} - #{{ torrent.poster.id }} - {% endif %} - {{ 'for torrent' | trans }} - {% if session.user.moderator or session.user.owner %} - - {{ torrent.name }} - - {% if torrent.approved == false %} - #{{ torrent.id }} ({{ 'waiting for approve' | trans }}) - {% endif %} - {% else %} - {% if torrent.status == false %} - #{{ torrent.id }} ({{ 'disabled' | trans }}) - {% elseif torrent.approved == false %} - #{{ torrent.id }} ({{ 'waiting for approve' | trans }}) - {% elseif torrent.sensitive == true and session.user.sensitive == true %} - #{{ torrent.id }} - {% else %} - - {{ torrent.name }} - - {% endif %} - {% endif %} -
-
- {{ added | format_ago }} -
-
\ No newline at end of file diff --git a/templates/default/activity/event/torrent/poster/approve/add.rss.twig b/templates/default/activity/event/torrent/poster/approve/add.rss.twig deleted file mode 100644 index 3a75b3d..0000000 --- a/templates/default/activity/event/torrent/poster/approve/add.rss.twig +++ /dev/null @@ -1,26 +0,0 @@ - - - {{ 'User' | trans }} - #{{ user.id }} - {{ 'have approved poster edition' | trans }} - #{{ torrent.poster.id }} - {{ 'for torrent' | trans }} - {% if session.user.moderator or session.user.owner %} - {{ torrent.name }} - {% else %} - {% if torrent.status == false %} - #{{ torrent.id }} ({{ 'disabled' | trans }}) - {% elseif torrent.approved == false %} - #{{ torrent.id }} ({{ 'waiting for approve' | trans }}) - {% elseif torrent.sensitive == true and session.user.sensitive == true %} - #{{ torrent.id }} - {% else %} - {{ torrent.name }} - {% endif %} - {% endif %} - - #{{ user.id }} - {{ added | date('D, d M Y h:i:s O') }} - {{ url('torrent_poster_edit', { torrentId : torrent.id, torrentPosterId : torrent.poster.id }) }}#activity-{{ id }} - {{ url('torrent_poster_edit', { torrentId : torrent.id, torrentPosterId : torrent.poster.id }) }}#activity - \ No newline at end of file diff --git a/templates/default/activity/event/torrent/poster/approve/delete.html.twig b/templates/default/activity/event/torrent/poster/approve/delete.html.twig deleted file mode 100644 index 483a79f..0000000 --- a/templates/default/activity/event/torrent/poster/approve/delete.html.twig +++ /dev/null @@ -1,39 +0,0 @@ -
-
- - {{ 'identicon' | trans }} - - {{ 'have disapproved poster edition' | trans }} - {% if torrent.poster.exist %} - - #{{ torrent.poster.id }} - - {% else %} - #{{ torrent.poster.id }} - {% endif %} - {{ 'for torrent' | trans }} - {% if session.user.moderator or session.user.owner %} - - {{ torrent.name }} - - {% if torrent.approved == false %} - #{{ torrent.id }} ({{ 'waiting for approve' | trans }}) - {% endif %} - {% else %} - {% if torrent.status == false %} - #{{ torrent.id }} ({{ 'disabled' | trans }}) - {% elseif torrent.approved == false %} - #{{ torrent.id }} ({{ 'waiting for approve' | trans }}) - {% elseif torrent.sensitive == true and session.user.sensitive == true %} - #{{ torrent.id }} - {% else %} - - {{ torrent.name }} - - {% endif %} - {% endif %} -
-
- {{ added | format_ago }} -
-
\ No newline at end of file diff --git a/templates/default/activity/event/torrent/poster/approve/delete.rss.twig b/templates/default/activity/event/torrent/poster/approve/delete.rss.twig deleted file mode 100644 index 42d6527..0000000 --- a/templates/default/activity/event/torrent/poster/approve/delete.rss.twig +++ /dev/null @@ -1,26 +0,0 @@ - - - {{ 'User' | trans }} - #{{ user.id }} - {{ 'have disapproved poster edition' | trans }} - #{{ torrent.poster.id }} - {{ 'for torrent' | trans }} - {% if session.user.moderator or session.user.owner %} - {{ torrent.name }} - {% else %} - {% if torrent.status == false %} - #{{ torrent.id }} ({{ 'disabled' | trans }}) - {% elseif torrent.approved == false %} - #{{ torrent.id }} ({{ 'waiting for approve' | trans }}) - {% elseif torrent.sensitive == true and session.user.sensitive == true %} - #{{ torrent.id }} - {% else %} - {{ torrent.name }} - {% endif %} - {% endif %} - - #{{ user.id }} - {{ added | date('D, d M Y h:i:s O') }} - {{ url('torrent_poster_edit', { torrentId : torrent.id, torrentPosterId : torrent.poster.id }) }}#activity-{{ id }} - {{ url('torrent_poster_edit', { torrentId : torrent.id, torrentPosterId : torrent.poster.id }) }}#activity - \ No newline at end of file diff --git a/templates/default/activity/event/torrent/poster/delete.html.twig b/templates/default/activity/event/torrent/poster/delete.html.twig deleted file mode 100644 index c3c7293..0000000 --- a/templates/default/activity/event/torrent/poster/delete.html.twig +++ /dev/null @@ -1,39 +0,0 @@ -
-
- - {{ 'identicon' | trans }} - - {{ 'have deleted poster edition' | trans }} - {% if torrent.poster.exist %} - - #{{ torrent.poster.id }} - - {% else %} - #{{ torrent.poster.id }} - {% endif %} - {{ 'for torrent' | trans }} - {% if session.user.moderator or session.user.owner %} - - {{ torrent.name }} - - {% if torrent.approved == false %} - #{{ torrent.id }} ({{ 'waiting for approve' | trans }}) - {% endif %} - {% else %} - {% if torrent.status == false %} - #{{ torrent.id }} ({{ 'disabled' | trans }}) - {% elseif torrent.approved == false %} - #{{ torrent.id }} ({{ 'waiting for approve' | trans }}) - {% elseif torrent.sensitive == true and session.user.sensitive == true %} - #{{ torrent.id }} - {% else %} - - {{ torrent.name }} - - {% endif %} - {% endif %} -
-
- {{ added | format_ago }} -
-
\ No newline at end of file diff --git a/templates/default/activity/event/torrent/poster/delete.rss.twig b/templates/default/activity/event/torrent/poster/delete.rss.twig deleted file mode 100644 index 4b7bf6a..0000000 --- a/templates/default/activity/event/torrent/poster/delete.rss.twig +++ /dev/null @@ -1,26 +0,0 @@ - - - {{ 'User' | trans }} - #{{ user.id }} - {{ 'have deleted poster edition' | trans }} - #{{ torrent.poster.id }} - {{ 'for torrent' | trans }} - {% if session.user.moderator or session.user.owner %} - {{ torrent.name }} - {% else %} - {% if torrent.status == false %} - #{{ torrent.id }} ({{ 'disabled' | trans }}) - {% elseif torrent.approved == false %} - #{{ torrent.id }} ({{ 'waiting for approve' | trans }}) - {% elseif torrent.sensitive == true and session.user.sensitive == true %} - #{{ torrent.id }} - {% else %} - {{ torrent.name }} - {% endif %} - {% endif %} - - #{{ user.id }} - {{ added | date('D, d M Y h:i:s O') }} - {{ url('torrent_poster_edit', { torrentId : torrent.id }) }}#activity-{{ id }} - {{ url('torrent_poster_edit', { torrentId : torrent.id }) }}#activity - \ No newline at end of file diff --git a/templates/default/activity/event/torrent/sensitive/add.html.twig b/templates/default/activity/event/torrent/sensitive/add.html.twig deleted file mode 100644 index e21705a..0000000 --- a/templates/default/activity/event/torrent/sensitive/add.html.twig +++ /dev/null @@ -1,39 +0,0 @@ -
-
- - {{ 'identicon' | trans }} - - {{ 'have added sensitive edition' | trans }} - {% if torrent.sensitive.exist %} - - #{{ torrent.sensitive.id }} - - {% else %} - #{{ torrent.sensitive.id }} - {% endif %} - {{ 'for torrent' | trans }} - {% if session.user.moderator or session.user.owner %} - - {{ torrent.name }} - - {% if torrent.approved == false %} - #{{ torrent.id }} ({{ 'waiting for approve' | trans }}) - {% endif %} - {% else %} - {% if torrent.status == false %} - #{{ torrent.id }} ({{ 'disabled' | trans }}) - {% elseif torrent.approved == false %} - #{{ torrent.id }} ({{ 'waiting for approve' | trans }}) - {% elseif torrent.sensitive == true and session.user.sensitive == true %} - #{{ torrent.id }} - {% else %} - - {{ torrent.name }} - - {% endif %} - {% endif %} -
-
- {{ added | format_ago }} -
-
\ No newline at end of file diff --git a/templates/default/activity/event/torrent/sensitive/add.rss.twig b/templates/default/activity/event/torrent/sensitive/add.rss.twig deleted file mode 100644 index e1036bb..0000000 --- a/templates/default/activity/event/torrent/sensitive/add.rss.twig +++ /dev/null @@ -1,26 +0,0 @@ - - - {{ 'User' | trans }} - #{{ user.id }} - {{ 'have added sensitive edition' | trans }} - #{{ torrent.sensitive.id }} - {{ 'for torrent' | trans }} - {% if session.user.moderator or session.user.owner %} - {{ torrent.name }} - {% else %} - {% if torrent.status == false %} - #{{ torrent.id }} ({{ 'disabled' | trans }}) - {% elseif torrent.approved == false %} - #{{ torrent.id }} ({{ 'waiting for approve' | trans }}) - {% elseif torrent.sensitive == true and session.user.sensitive == true %} - #{{ torrent.id }} - {% else %} - {{ torrent.name }} - {% endif %} - {% endif %} - - #{{ user.id }} - {{ added | date('D, d M Y h:i:s O') }} - {{ url('torrent_sensitive_edit', { torrentId : torrent.id, torrentSensitiveId : torrent.sensitive.id }) }}#activity-{{ id }} - {{ url('torrent_sensitive_edit', { torrentId : torrent.id, torrentSensitiveId : torrent.sensitive.id }) }}#activity - \ No newline at end of file diff --git a/templates/default/activity/event/torrent/sensitive/approve/add.html.twig b/templates/default/activity/event/torrent/sensitive/approve/add.html.twig deleted file mode 100644 index 4bad7b0..0000000 --- a/templates/default/activity/event/torrent/sensitive/approve/add.html.twig +++ /dev/null @@ -1,39 +0,0 @@ -
-
- - {{ 'identicon' | trans }} - - {{ 'have approved sensitive edition' | trans }} - {% if torrent.sensitive.exist %} - - #{{ torrent.sensitive.id }} - - {% else %} - #{{ torrent.sensitive.id }} - {% endif %} - {{ 'for torrent' | trans }} - {% if session.user.moderator or session.user.owner %} - - {{ torrent.name }} - - {% if torrent.approved == false %} - #{{ torrent.id }} ({{ 'waiting for approve' | trans }}) - {% endif %} - {% else %} - {% if torrent.status == false %} - #{{ torrent.id }} ({{ 'disabled' | trans }}) - {% elseif torrent.approved == false %} - #{{ torrent.id }} ({{ 'waiting for approve' | trans }}) - {% elseif torrent.sensitive == true and session.user.sensitive == true %} - #{{ torrent.id }} - {% else %} - - {{ torrent.name }} - - {% endif %} - {% endif %} -
-
- {{ added | format_ago }} -
-
\ No newline at end of file diff --git a/templates/default/activity/event/torrent/sensitive/approve/add.rss.twig b/templates/default/activity/event/torrent/sensitive/approve/add.rss.twig deleted file mode 100644 index 583a42f..0000000 --- a/templates/default/activity/event/torrent/sensitive/approve/add.rss.twig +++ /dev/null @@ -1,26 +0,0 @@ - - - {{ 'User' | trans }} - #{{ user.id }} - {{ 'have approved sensitive edition' | trans }} - #{{ torrent.sensitive.id }} - {{ 'for torrent' | trans }} - {% if session.user.moderator or session.user.owner %} - {{ torrent.name }} - {% else %} - {% if torrent.status == false %} - #{{ torrent.id }} ({{ 'disabled' | trans }}) - {% elseif torrent.approved == false %} - #{{ torrent.id }} ({{ 'waiting for approve' | trans }}) - {% elseif torrent.sensitive == true and session.user.sensitive == true %} - #{{ torrent.id }} - {% else %} - {{ torrent.name }} - {% endif %} - {% endif %} - - #{{ user.id }} - {{ added | date('D, d M Y h:i:s O') }} - {{ url('torrent_sensitive_edit', { torrentId : torrent.id, torrentSensitiveId : torrent.sensitive.id }) }}#activity-{{ id }} - {{ url('torrent_sensitive_edit', { torrentId : torrent.id, torrentSensitiveId : torrent.sensitive.id }) }}#activity - \ No newline at end of file diff --git a/templates/default/activity/event/torrent/sensitive/approve/delete.html.twig b/templates/default/activity/event/torrent/sensitive/approve/delete.html.twig deleted file mode 100644 index c02a804..0000000 --- a/templates/default/activity/event/torrent/sensitive/approve/delete.html.twig +++ /dev/null @@ -1,39 +0,0 @@ -
-
- - {{ 'identicon' | trans }} - - {{ 'have disapproved sensitive edition' | trans }} - {% if torrent.sensitive.exist %} - - #{{ torrent.sensitive.id }} - - {% else %} - #{{ torrent.sensitive.id }} - {% endif %} - {{ 'for torrent' | trans }} - {% if session.user.moderator or session.user.owner %} - - {{ torrent.name }} - - {% if torrent.approved == false %} - #{{ torrent.id }} ({{ 'waiting for approve' | trans }}) - {% endif %} - {% else %} - {% if torrent.status == false %} - #{{ torrent.id }} ({{ 'disabled' | trans }}) - {% elseif torrent.approved == false %} - #{{ torrent.id }} ({{ 'waiting for approve' | trans }}) - {% elseif torrent.sensitive == true and session.user.sensitive == true %} - #{{ torrent.id }} - {% else %} - - {{ torrent.name }} - - {% endif %} - {% endif %} -
-
- {{ added | format_ago }} -
-
\ No newline at end of file diff --git a/templates/default/activity/event/torrent/sensitive/approve/delete.rss.twig b/templates/default/activity/event/torrent/sensitive/approve/delete.rss.twig deleted file mode 100644 index f1a697f..0000000 --- a/templates/default/activity/event/torrent/sensitive/approve/delete.rss.twig +++ /dev/null @@ -1,26 +0,0 @@ - - - {{ 'User' | trans }} - #{{ user.id }} - {{ 'have disapproved sensitive edition' | trans }} - #{{ torrent.sensitive.id }} - {{ 'for torrent' | trans }} - {% if session.user.moderator or session.user.owner %} - {{ torrent.name }} - {% else %} - {% if torrent.status == false %} - #{{ torrent.id }} ({{ 'disabled' | trans }}) - {% elseif torrent.approved == false %} - #{{ torrent.id }} ({{ 'waiting for approve' | trans }}) - {% elseif torrent.sensitive == true and session.user.sensitive == true %} - #{{ torrent.id }} - {% else %} - {{ torrent.name }} - {% endif %} - {% endif %} - - #{{ user.id }} - {{ added | date('D, d M Y h:i:s O') }} - {{ url('torrent_sensitive_edit', { torrentId : torrent.id, torrentSensitiveId : torrent.sensitive.id }) }}#activity-{{ id }} - {{ url('torrent_sensitive_edit', { torrentId : torrent.id, torrentSensitiveId : torrent.sensitive.id }) }}#activity - \ No newline at end of file diff --git a/templates/default/activity/event/torrent/sensitive/delete.html.twig b/templates/default/activity/event/torrent/sensitive/delete.html.twig deleted file mode 100644 index a2640dc..0000000 --- a/templates/default/activity/event/torrent/sensitive/delete.html.twig +++ /dev/null @@ -1,39 +0,0 @@ -
-
- - {{ 'identicon' | trans }} - - {{ 'have deleted sensitive edition' | trans }} - {% if torrent.sensitive.exist %} - - #{{ torrent.sensitive.id }} - - {% else %} - #{{ torrent.sensitive.id }} - {% endif %} - {{ 'for torrent' | trans }} - {% if session.user.moderator or session.user.owner %} - - {{ torrent.name }} - - {% if torrent.approved == false %} - #{{ torrent.id }} ({{ 'waiting for approve' | trans }}) - {% endif %} - {% else %} - {% if torrent.status == false %} - #{{ torrent.id }} ({{ 'disabled' | trans }}) - {% elseif torrent.approved == false %} - #{{ torrent.id }} ({{ 'waiting for approve' | trans }}) - {% elseif torrent.sensitive == true and session.user.sensitive == true %} - #{{ torrent.id }} - {% else %} - - {{ torrent.name }} - - {% endif %} - {% endif %} -
-
- {{ added | format_ago }} -
-
\ No newline at end of file diff --git a/templates/default/activity/event/torrent/sensitive/delete.rss.twig b/templates/default/activity/event/torrent/sensitive/delete.rss.twig deleted file mode 100644 index 3c13424..0000000 --- a/templates/default/activity/event/torrent/sensitive/delete.rss.twig +++ /dev/null @@ -1,26 +0,0 @@ - - - {{ 'User' | trans }} - #{{ user.id }} - {{ 'have deleted sensitive edition' | trans }} - #{{ torrent.sensitive.id }} - {{ 'for torrent' | trans }} - {% if session.user.moderator or session.user.owner %} - {{ torrent.name }} - {% else %} - {% if torrent.status == false %} - #{{ torrent.id }} ({{ 'disabled' | trans }}) - {% elseif torrent.approved == false %} - #{{ torrent.id }} ({{ 'waiting for approve' | trans }}) - {% elseif torrent.sensitive == true and session.user.sensitive == true %} - #{{ torrent.id }} - {% else %} - {{ torrent.name }} - {% endif %} - {% endif %} - - #{{ user.id }} - {{ added | date('D, d M Y h:i:s O') }} - {{ url('torrent_sensitive_edit', { torrentId : torrent.id }) }}#activity-{{ id }} - {{ url('torrent_sensitive_edit', { torrentId : torrent.id }) }}#activity - \ No newline at end of file diff --git a/templates/default/activity/event/torrent/star/add.html.twig b/templates/default/activity/event/torrent/star/add.html.twig deleted file mode 100644 index 9d27547..0000000 --- a/templates/default/activity/event/torrent/star/add.html.twig +++ /dev/null @@ -1,31 +0,0 @@ -
-
- - {{ 'identicon' | trans }} - - {{ 'have added star for torrent' | trans }} - {% if session.user.moderator or session.user.owner %} - - {{ torrent.name }} - - {% if torrent.approved == false %} - #{{ torrent.id }} ({{ 'waiting for approve' | trans }}) - {% endif %} - {% else %} - {% if torrent.status == false %} - #{{ torrent.id }} ({{ 'disabled' | trans }}) - {% elseif torrent.approved == false %} - #{{ torrent.id }} ({{ 'waiting for approve' | trans }}) - {% elseif torrent.sensitive == true and session.user.sensitive == true %} - #{{ torrent.id }} ({{ 'sensitive' | trans }}) - {% else %} - - {{ torrent.name }} - - {% endif %} - {% endif %} -
-
- {{ added | format_ago }} -
-
\ No newline at end of file diff --git a/templates/default/activity/event/torrent/star/add.rss.twig b/templates/default/activity/event/torrent/star/add.rss.twig deleted file mode 100644 index a5fb324..0000000 --- a/templates/default/activity/event/torrent/star/add.rss.twig +++ /dev/null @@ -1,24 +0,0 @@ - - - {{ 'User' | trans }} - #{{ user.id }} - {{ 'have added star for torrent' | trans }} - {% if session.user.moderator or session.user.owner %} - {{ torrent.name }} - {% else %} - {% if torrent.status == false %} - #{{ torrent.id }} ({{ 'disabled' | trans }}) - {% elseif torrent.approved == false %} - #{{ torrent.id }} ({{ 'waiting for approve' | trans }}) - {% elseif torrent.sensitive == true and session.user.sensitive == true %} - #{{ torrent.id }} ({{ 'sensitive' | trans }}) - {% else %} - {{ torrent.name }} - {% endif %} - {% endif %} - - #{{ user.id }} - {{ added | date('D, d M Y h:i:s O') }} - {{ url('torrent_info', { torrentId : torrent.id }) }}#activity-{{ id }} - {{ url('torrent_info', { torrentId : torrent.id }) }}#activity - \ No newline at end of file diff --git a/templates/default/activity/event/torrent/star/delete.html.twig b/templates/default/activity/event/torrent/star/delete.html.twig deleted file mode 100644 index a160792..0000000 --- a/templates/default/activity/event/torrent/star/delete.html.twig +++ /dev/null @@ -1,32 +0,0 @@ - -
-
- - {{ 'identicon' | trans }} - - {{ 'have removed star from torrent' | trans }} - {% if session.user.moderator or session.user.owner %} - - {{ torrent.name }} - - {% if torrent.approved == false %} - #{{ torrent.id }} ({{ 'waiting for approve' | trans }}) - {% endif %} - {% else %} - {% if torrent.status == false %} - #{{ torrent.id }} ({{ 'disabled' | trans }}) - {% elseif torrent.approved == false %} - #{{ torrent.id }} ({{ 'waiting for approve' | trans }}) - {% elseif torrent.sensitive == true and session.user.sensitive == true %} - #{{ torrent.id }} ({{ 'sensitive' | trans }}) - {% else %} - - {{ torrent.name }} - - {% endif %} - {% endif %} -
-
- {{ added | format_ago }} -
-
\ No newline at end of file diff --git a/templates/default/activity/event/torrent/star/delete.rss.twig b/templates/default/activity/event/torrent/star/delete.rss.twig deleted file mode 100644 index 6c4c02c..0000000 --- a/templates/default/activity/event/torrent/star/delete.rss.twig +++ /dev/null @@ -1,24 +0,0 @@ - - - {{ 'User' | trans }} - #{{ user.id }} - {{ 'have removed star from torrent' | trans }} - {% if session.user.moderator or session.user.owner %} - {{ torrent.name }} - {% else %} - {% if torrent.status == false %} - #{{ torrent.id }} ({{ 'disabled' | trans }}) - {% elseif torrent.approved == false %} - #{{ torrent.id }} ({{ 'waiting for approve' | trans }}) - {% elseif torrent.sensitive == true and session.user.sensitive == true %} - #{{ torrent.id }} ({{ 'sensitive' | trans }}) - {% else %} - {{ torrent.name }} - {% endif %} - {% endif %} - - #{{ user.id }} - {{ added | date('D, d M Y h:i:s O') }} - {{ url('torrent_info', { torrentId : torrent.id }) }}#activity-{{ id }} - {{ url('torrent_info', { torrentId : torrent.id }) }}#activity - \ No newline at end of file diff --git a/templates/default/activity/event/torrent/status/add.html.twig b/templates/default/activity/event/torrent/status/add.html.twig deleted file mode 100644 index 0466adc..0000000 --- a/templates/default/activity/event/torrent/status/add.html.twig +++ /dev/null @@ -1,30 +0,0 @@ -
-
- - {{ 'identicon' | trans }} - - - {{ 'have enabled torrent' | trans }} - - {% if session.user.moderator or session.user.owner %} - - {{ torrent.name }} - - {% else %} - {% if torrent.status == false %} - #{{ torrent.id }} ({{ 'disabled' | trans }}) - {% elseif torrent.approved == false %} - #{{ torrent.id }} ({{ 'waiting for approve' | trans }}) - {% elseif torrent.sensitive == true and session.user.sensitive == true %} - #{{ torrent.id }} ({{ 'sensitive' | trans }}) - {% else %} - - {{ torrent.name }} - - {% endif %} - {% endif %} -
-
- {{ added | format_ago }} -
-
\ No newline at end of file diff --git a/templates/default/activity/event/torrent/status/add.rss.twig b/templates/default/activity/event/torrent/status/add.rss.twig deleted file mode 100644 index 1f21d67..0000000 --- a/templates/default/activity/event/torrent/status/add.rss.twig +++ /dev/null @@ -1,26 +0,0 @@ - - - {{ 'User' | trans }} - #{{ user.id }} - {{ 'have enabled torrent' | trans }} - {% if session.user.moderator or session.user.owner %} - {{ torrent.name }} - {% else %} - {% if torrent.status == false %} - #{{ torrent.id }} ({{ 'disabled' | trans }}) - {% elseif torrent.approved == false %} - #{{ torrent.id }} ({{ 'waiting for approve' | trans }}) - {% elseif torrent.sensitive == true and session.user.sensitive == true %} - #{{ torrent.id }} ({{ 'sensitive' | trans }}) - {% else %} - <a href="{{ path('torrent_info', { torrentId : torrent.id }) }}"> - {{ torrent.name }} - </a> - {% endif %} - {% endif %} - - #{{ user.id }} - {{ added | date('D, d M Y h:i:s O') }} - {{ url('torrent_info', { torrentId : torrent.id }) }}#activity-{{ id }} - {{ url('torrent_info', { torrentId : torrent.id }) }}#activity - \ No newline at end of file diff --git a/templates/default/activity/event/torrent/status/delete.html.twig b/templates/default/activity/event/torrent/status/delete.html.twig deleted file mode 100644 index 3c5dea3..0000000 --- a/templates/default/activity/event/torrent/status/delete.html.twig +++ /dev/null @@ -1,30 +0,0 @@ -
-
- - {{ 'identicon' | trans }} - - - {{ 'have disabled torrent' | trans }} - - {% if session.user.moderator or session.user.owner %} - - {{ torrent.name }} - - {% else %} - {% if torrent.status == false %} - #{{ torrent.id }} - {% elseif torrent.approved == false %} - #{{ torrent.id }} ({{ 'waiting for approve' | trans }}) - {% elseif torrent.sensitive == true and session.user.sensitive == true %} - #{{ torrent.id }} ({{ 'sensitive' | trans }}) - {% else %} - - {{ torrent.name }} - - {% endif %} - {% endif %} -
-
- {{ added | format_ago }} -
-
\ No newline at end of file diff --git a/templates/default/activity/event/torrent/status/delete.rss.twig b/templates/default/activity/event/torrent/status/delete.rss.twig deleted file mode 100644 index f1ef108..0000000 --- a/templates/default/activity/event/torrent/status/delete.rss.twig +++ /dev/null @@ -1,26 +0,0 @@ - - - {{ 'User' | trans }} - #{{ user.id }} - {{ 'have disabled torrent' | trans }} - {% if session.user.moderator or session.user.owner %} - {{ torrent.name }} - {% else %} - {% if torrent.status == false %} - #{{ torrent.id }} - {% elseif torrent.approved == false %} - #{{ torrent.id }} ({{ 'waiting for approve' | trans }}) - {% elseif torrent.sensitive == true and session.user.sensitive == true %} - #{{ torrent.id }} ({{ 'sensitive' | trans }}) - {% else %} - <a href="{{ path('torrent_info', { torrentId : torrent.id }) }}"> - {{ torrent.name }} - </a> - {% endif %} - {% endif %} - - #{{ user.id }} - {{ added | date('D, d M Y h:i:s O') }} - {{ url('torrent_info', { torrentId : torrent.id }) }}#activity-{{ id }} - {{ url('torrent_info', { torrentId : torrent.id }) }}#activity - \ No newline at end of file diff --git a/templates/default/activity/event/torrent/wanted/add.html.twig b/templates/default/activity/event/torrent/wanted/add.html.twig deleted file mode 100644 index 86a8744..0000000 --- a/templates/default/activity/event/torrent/wanted/add.html.twig +++ /dev/null @@ -1,25 +0,0 @@ -
-
- {{ 'Seeders wanted for torrent' | trans }} - {% if session.user.moderator or session.user.owner %} - - {{ torrent.name }} - - {% else %} - {% if torrent.status == false %} - #{{ torrent.id }} ({{ 'disabled' | trans }}) - {% elseif torrent.approved == false %} - #{{ torrent.id }} ({{ 'waiting for approve' | trans }}) - {% elseif torrent.sensitive == true and session.user.sensitive == true %} - #{{ torrent.id }} ({{ 'sensitive' | trans }}) - {% else %} - - {{ torrent.name }} - - {% endif %} - {% endif %} -
-
- {{ added | format_ago }} -
-
\ No newline at end of file diff --git a/templates/default/activity/event/torrent/wanted/add.rss.twig b/templates/default/activity/event/torrent/wanted/add.rss.twig deleted file mode 100644 index 9459b57..0000000 --- a/templates/default/activity/event/torrent/wanted/add.rss.twig +++ /dev/null @@ -1,21 +0,0 @@ - - - {{ 'Seeders wanted for torrent' | trans }} - {% if session.user.moderator or session.user.owner %} - {{ torrent.name }} - {% else %} - {% if torrent.status == false %} - #{{ torrent.id }} ({{ 'disabled' | trans }}) - {% elseif torrent.approved == false %} - #{{ torrent.id }} ({{ 'waiting for approve' | trans }}) - {% elseif torrent.sensitive == true and session.user.sensitive == true %} - #{{ torrent.id }} ({{ 'sensitive' | trans }}) - {% else %} - {{ torrent.name }} - {% endif %} - {% endif %} - - {{ added | date('D, d M Y h:i:s O') }} - {{ url('torrent_info', { torrentId : torrent.id }) }}#activity-{{ id }} - {{ url('torrent_info', { torrentId : torrent.id }) }}#activity - \ No newline at end of file diff --git a/templates/default/activity/event/undefined.html.twig b/templates/default/activity/event/undefined.html.twig deleted file mode 100644 index ba40c72..0000000 --- a/templates/default/activity/event/undefined.html.twig +++ /dev/null @@ -1,13 +0,0 @@ -
-
- - {{ 'identicon' | trans }} - - - {{ 'undefined event' | trans }} - -
-
- {{ added | format_ago }} -
-
\ No newline at end of file diff --git a/templates/default/activity/event/undefined.rss.twig b/templates/default/activity/event/undefined.rss.twig deleted file mode 100644 index 34ab004..0000000 --- a/templates/default/activity/event/undefined.rss.twig +++ /dev/null @@ -1,7 +0,0 @@ - - {{ 'undefined event' | trans }} {{ 'by' | trans }} #{{ user.id }} - #{{ user.id }} - {{ added | date('D, d M Y h:i:s O') }} - {{ url('user_info', { userId : user.id }) }}#activity-{{ id }} - {{ url('user_info', { userId : user.id }) }}#activity - \ No newline at end of file diff --git a/templates/default/activity/event/user/add.html.twig b/templates/default/activity/event/user/add.html.twig deleted file mode 100644 index 974a8d1..0000000 --- a/templates/default/activity/event/user/add.html.twig +++ /dev/null @@ -1,14 +0,0 @@ - -
-
- - {{ 'identicon' | trans }} - - - {{ 'have joined' | trans }} - -
-
- {{ added | format_ago }} -
-
\ No newline at end of file diff --git a/templates/default/activity/event/user/add.rss.twig b/templates/default/activity/event/user/add.rss.twig deleted file mode 100644 index 4f4fdd1..0000000 --- a/templates/default/activity/event/user/add.rss.twig +++ /dev/null @@ -1,7 +0,0 @@ - - {{ 'User' | trans }} #{{ user.id }} {{ 'have joined' | trans }} - #{{ user.id }} - {{ added | date('D, d M Y h:i:s O') }} - {{ url('user_info', { userId : user.id }) }}#activity-{{ id }} - {{ url('user_info', { userId : user.id }) }}#activity - \ No newline at end of file diff --git a/templates/default/activity/event/user/approve/add.html.twig b/templates/default/activity/event/user/approve/add.html.twig deleted file mode 100644 index 2866bdf..0000000 --- a/templates/default/activity/event/user/approve/add.html.twig +++ /dev/null @@ -1,16 +0,0 @@ -
-
- - {{ 'identicon' | trans }} - - - {{ 'have approved' | trans }} - - - {{ 'identicon' | trans }} - -
-
- {{ added | format_ago }} -
-
\ No newline at end of file diff --git a/templates/default/activity/event/user/approve/add.rss.twig b/templates/default/activity/event/user/approve/add.rss.twig deleted file mode 100644 index ad0c2e8..0000000 --- a/templates/default/activity/event/user/approve/add.rss.twig +++ /dev/null @@ -1,12 +0,0 @@ - - - {{ 'User' | trans }} - #{{ user.id }} - {{ 'have approved user' | trans }} - #{{ to.user.id }} - - #{{ user.id }} - {{ added | date('D, d M Y h:i:s O') }} - {{ url('user_info', { userId : to.user.id }) }}#activity-{{ id }} - {{ url('user_info', { userId : to.user.id }) }}#activity - \ No newline at end of file diff --git a/templates/default/activity/event/user/approve/delete.html.twig b/templates/default/activity/event/user/approve/delete.html.twig deleted file mode 100644 index 1283a04..0000000 --- a/templates/default/activity/event/user/approve/delete.html.twig +++ /dev/null @@ -1,16 +0,0 @@ -
-
- - {{ 'identicon' | trans }} - - - {{ 'have disapproved' | trans }} - - - {{ 'identicon' | trans }} - -
-
- {{ added | format_ago }} -
-
\ No newline at end of file diff --git a/templates/default/activity/event/user/approve/delete.rss.twig b/templates/default/activity/event/user/approve/delete.rss.twig deleted file mode 100644 index 0008063..0000000 --- a/templates/default/activity/event/user/approve/delete.rss.twig +++ /dev/null @@ -1,12 +0,0 @@ - - - {{ 'User' | trans }} - #{{ user.id }} - {{ 'have disapproved user' | trans }} - #{{ to.user.id }} - - #{{ user.id }} - {{ added | date('D, d M Y h:i:s O') }} - {{ url('user_info', { userId : to.user.id }) }}#activity-{{ id }} - {{ url('user_info', { userId : to.user.id }) }}#activity - \ No newline at end of file diff --git a/templates/default/activity/event/user/moderator/add.html.twig b/templates/default/activity/event/user/moderator/add.html.twig deleted file mode 100644 index 68cfd16..0000000 --- a/templates/default/activity/event/user/moderator/add.html.twig +++ /dev/null @@ -1,16 +0,0 @@ -
-
- - {{ 'identicon' | trans }} - - - {{ 'have granted moderator permissions to' | trans }} - - - {{ 'identicon' | trans }} - -
-
- {{ added | format_ago }} -
-
\ No newline at end of file diff --git a/templates/default/activity/event/user/moderator/add.rss.twig b/templates/default/activity/event/user/moderator/add.rss.twig deleted file mode 100644 index ed7513f..0000000 --- a/templates/default/activity/event/user/moderator/add.rss.twig +++ /dev/null @@ -1,12 +0,0 @@ - - - {{ 'User' | trans }} - #{{ user.id }} - {{ 'have granted moderator permissions to user' | trans }} - #{{ to.user.id }} - - #{{ to.user.id }} - {{ added | date('D, d M Y h:i:s O') }} - {{ url('user_info', { userId : to.user.id }) }}#activity-{{ id }} - {{ url('user_info', { userId : to.user.id }) }}#activity - \ No newline at end of file diff --git a/templates/default/activity/event/user/moderator/delete.html.twig b/templates/default/activity/event/user/moderator/delete.html.twig deleted file mode 100644 index f3e577c..0000000 --- a/templates/default/activity/event/user/moderator/delete.html.twig +++ /dev/null @@ -1,16 +0,0 @@ -
-
- - {{ 'identicon' | trans }} - - - {{ 'have removed moderator permissions from' | trans }} - - - {{ 'identicon' | trans }} - -
-
- {{ added | format_ago }} -
-
\ No newline at end of file diff --git a/templates/default/activity/event/user/moderator/delete.rss.twig b/templates/default/activity/event/user/moderator/delete.rss.twig deleted file mode 100644 index 9ef9978..0000000 --- a/templates/default/activity/event/user/moderator/delete.rss.twig +++ /dev/null @@ -1,12 +0,0 @@ - - - {{ 'User' | trans }} - #{{ user.id }} - {{ 'have removed moderator permissions from user' | trans }} - #{{ to.user.id }} - - #{{ to.user.id }} - {{ added | date('D, d M Y h:i:s O') }} - {{ url('user_info', { userId : to.user.id }) }}#activity-{{ id }} - {{ url('user_info', { userId : to.user.id }) }}#activity - \ No newline at end of file diff --git a/templates/default/activity/event/user/star/add.html.twig b/templates/default/activity/event/user/star/add.html.twig deleted file mode 100644 index 138be52..0000000 --- a/templates/default/activity/event/user/star/add.html.twig +++ /dev/null @@ -1,16 +0,0 @@ -
-
- - {{ 'identicon' | trans }} - - - {{ 'have added star for' | trans }} - - - {{ 'identicon' | trans }} - -
-
- {{ added | format_ago }} -
-
\ No newline at end of file diff --git a/templates/default/activity/event/user/star/add.rss.twig b/templates/default/activity/event/user/star/add.rss.twig deleted file mode 100644 index a7b1470..0000000 --- a/templates/default/activity/event/user/star/add.rss.twig +++ /dev/null @@ -1,12 +0,0 @@ - - - {{ 'User' | trans }} - #{{ user.id }} - {{ 'have added star for user' | trans }} - #{{ to.user.id }} - - #{{ to.user.id }} - {{ added | date('D, d M Y h:i:s O') }} - {{ url('user_info', { userId : to.user.id }) }}#activity-{{ id }} - {{ url('user_info', { userId : to.user.id }) }}#activity - \ No newline at end of file diff --git a/templates/default/activity/event/user/star/delete.html.twig b/templates/default/activity/event/user/star/delete.html.twig deleted file mode 100644 index f42b206..0000000 --- a/templates/default/activity/event/user/star/delete.html.twig +++ /dev/null @@ -1,16 +0,0 @@ -
-
- - {{ 'identicon' | trans }} - - - {{ 'have removed star from' | trans }} - - - {{ 'identicon' | trans }} - -
-
- {{ added | format_ago }} -
-
\ No newline at end of file diff --git a/templates/default/activity/event/user/star/delete.rss.twig b/templates/default/activity/event/user/star/delete.rss.twig deleted file mode 100644 index f46562e..0000000 --- a/templates/default/activity/event/user/star/delete.rss.twig +++ /dev/null @@ -1,12 +0,0 @@ - - - {{ 'User' | trans }} - #{{ user.id }} - {{ 'have removed star from user' | trans }} - #{{ to.user.id }} - - #{{ to.user.id }} - {{ added | date('D, d M Y h:i:s O') }} - {{ url('user_info', { userId : to.user.id }) }}#activity-{{ id }} - {{ url('user_info', { userId : to.user.id }) }}#activity - \ No newline at end of file diff --git a/templates/default/activity/event/user/status/add.html.twig b/templates/default/activity/event/user/status/add.html.twig deleted file mode 100644 index a68fd52..0000000 --- a/templates/default/activity/event/user/status/add.html.twig +++ /dev/null @@ -1,16 +0,0 @@ -
-
- - {{ 'identicon' | trans }} - - - {{ 'have enabled' | trans }} - - - {{ 'identicon' | trans }} - -
-
- {{ added | format_ago }} -
-
\ No newline at end of file diff --git a/templates/default/activity/event/user/status/add.rss.twig b/templates/default/activity/event/user/status/add.rss.twig deleted file mode 100644 index d07d6c5..0000000 --- a/templates/default/activity/event/user/status/add.rss.twig +++ /dev/null @@ -1,12 +0,0 @@ - - - {{ 'User' | trans }} - #{{ user.id }} - {{ 'have enabled user' | trans }} - #{{ to.user.id }} - - #{{ to.user.id }} - {{ added | date('D, d M Y h:i:s O') }} - {{ url('user_info', { userId : to.user.id }) }}#activity-{{ id }} - {{ url('user_info', { userId : to.user.id }) }}#activity - \ No newline at end of file diff --git a/templates/default/activity/event/user/status/delete.html.twig b/templates/default/activity/event/user/status/delete.html.twig deleted file mode 100644 index be723d9..0000000 --- a/templates/default/activity/event/user/status/delete.html.twig +++ /dev/null @@ -1,17 +0,0 @@ - -
-
- - {{ 'identicon' | trans }} - - - {{ 'have disabled' | trans }} - - - {{ 'identicon' | trans }} - -
-
- {{ added | format_ago }} -
-
\ No newline at end of file diff --git a/templates/default/activity/event/user/status/delete.rss.twig b/templates/default/activity/event/user/status/delete.rss.twig deleted file mode 100644 index 6542d28..0000000 --- a/templates/default/activity/event/user/status/delete.rss.twig +++ /dev/null @@ -1,12 +0,0 @@ - - - {{ 'User' | trans }} - #{{ user.id }} - {{ 'have disabled user' | trans }} - #{{ to.user.id }} - - #{{ to.user.id }} - {{ added | date('D, d M Y h:i:s O') }} - {{ url('user_info', { userId : to.user.id }) }}#activity-{{ id }} - {{ url('user_info', { userId : to.user.id }) }}#activity - \ No newline at end of file diff --git a/templates/default/activity/list.html.twig b/templates/default/activity/list.html.twig deleted file mode 100644 index 5a1c883..0000000 --- a/templates/default/activity/list.html.twig +++ /dev/null @@ -1,43 +0,0 @@ -{% extends 'default/layout.html.twig' %} -{% block title %}{{ 'Activity' | trans }}{% if pagination.page > 1 %} - {{ 'Page' | trans }} {{ pagination.page }}{% endif %} - {{ name }}{% endblock %} -{% block main_content %} -
-

{{ 'Recent activity' | trans }}

- - - - - - - -
- {% for activity in activities %} -
- {{ render(controller( - 'App\\Controller\\ActivityController::event', - { user : session.user, activity : activity } - )) }} -
- {% endfor %} -
- {% if pagination.pages > 1 %} - {{ 'Page' | trans | lower }} {{ pagination.page }} / {{ pagination.pages }} - {% if pagination.page > 1 %} - {% if pagination.page == 2 %} - - {{ 'Back' | trans | lower }} - - {% else %} - - {{ 'Back' | trans | lower }} - - {% endif %} - {% endif %} - {% if pagination.page < pagination.pages %} - - {{ 'Next' | trans | lower }} - - {% endif %} - {% endif %} -
-{% endblock %} \ No newline at end of file diff --git a/templates/default/activity/list.rss.twig b/templates/default/activity/list.rss.twig deleted file mode 100644 index 2fabaaa..0000000 --- a/templates/default/activity/list.rss.twig +++ /dev/null @@ -1,14 +0,0 @@ - - - - - {{ name }} - {{ 'Activity' | trans }} - {{ url('torrent_recent') }} - {% for activity in activities %} - {{ render(controller( - 'App\\Controller\\ActivityController::event', - { user : session.user, activity : activity, format : 'rss' } - )) }} - {% endfor %} - - diff --git a/templates/default/layout.html.twig b/templates/default/layout.html.twig deleted file mode 100644 index 99c0eeb..0000000 --- a/templates/default/layout.html.twig +++ /dev/null @@ -1,69 +0,0 @@ - - - - - {% block title %}{{ name }}{% endblock %} - {% block keywords %} - - {% endblock %} - {% block stylesheets %} - - - {% endblock %} - - - {% block header %} -
-
-
- - {#32 -
- {{ 'Upload any torrent - download with Yggdrasil' | trans | format(path('torrent_submit')) | raw }} -
- #} - {% block header_search %} - {{ render(controller( - 'App\\Controller\\SearchController::module', - { - request: app.request - } - )) }} - {% endblock %} -
-
-
- {% endblock %} - {% block main %} -
-
-
-
- {% block main_profile %} - {{ render(controller( - 'App\\Controller\\UserController::module', - { route : app.request.get('_route') } - )) }} - {% endblock %} - {% block main_content %}{% endblock %} -
-
-
-
- {% endblock %} - {% block footer %} -
-
-
-
- {% block footer_trackers %}{% endblock %} - GitHub -
-
-
-
- {% endblock %} - - diff --git a/templates/default/search/module.html.twig b/templates/default/search/module.html.twig deleted file mode 100644 index 8b1b99b..0000000 --- a/templates/default/search/module.html.twig +++ /dev/null @@ -1,69 +0,0 @@ -
- - - {% if filter %} - -
-
- {{ 'Locales' | trans }} -
-
- {% for locale in locales | sort %} - {#{% if locale.total %}#} -
- {% if locale.checked %} - - {% else %} - - {% endif %} - -
- {#{% endif %}#} - {% endfor %} -
-
- {{ 'Categories' | trans }} -
-
- {% for category in categories | sort %} - {#{% if category.total %}#} -
- {% if category.checked %} - - {% else %} - - {% endif %} - -
- {#{% endif %}#} - {% endfor %} -
-
- {{ 'other' | trans | u.title }} -
-
- {% if sensitive.checked %} - - {% else %} - - {% endif %} - -
-
- {% endif %} -
\ No newline at end of file diff --git a/templates/default/torrent/edit/categories.html.twig b/templates/default/torrent/edit/categories.html.twig deleted file mode 100644 index 417828d..0000000 --- a/templates/default/torrent/edit/categories.html.twig +++ /dev/null @@ -1,109 +0,0 @@ -{% extends 'default/layout.html.twig' %} -{% block title %}{{'Edit categories'|trans }} - {{'Torrent'|trans }} #{{ torrentId }} - {{ name }}{% endblock %} -{% block main_content %} -
-
-

- {{'Edit categories for torrent' | trans }} - #{{ torrentId }} -

-
-
-
- - - - - - - {% for error in form.categories.error %} -
- {{ error }} -
- {% endfor %} -
- {% for category in categories | sort %} -
- {% if category in form.categories.attribute.value %} - - {% else %} - - {% endif %} - -
- {% endfor %} - {# - - #} -
-
-
- -
-
- {% for edition in editions %} -
- {% if edition.active %} - {{ edition.added | format_ago }} - {% else %} - - {{ edition.added | format_ago }} - - {% endif %} - {{ 'by'|trans }} - - {{'identicon'|trans }} - -
- {% if session.moderator or session.owner %} - - - - - - - {% endif %} - {% if edition.approved %} - {% if session.moderator %} - - - - - - {% else %} - - - - - - {% endif %} - {% else %} - {% if session.moderator %} - - - - - - {% else %} - - - - - - {% endif %} - {% endif %} -
-
- {% endfor %} -{% endblock %} diff --git a/templates/default/torrent/edit/locales.html.twig b/templates/default/torrent/edit/locales.html.twig deleted file mode 100644 index dcab8db..0000000 --- a/templates/default/torrent/edit/locales.html.twig +++ /dev/null @@ -1,109 +0,0 @@ -{% extends 'default/layout.html.twig' %} -{% block title %}{{'Edit locales'|trans }} - {{'Torrent'|trans }} #{{ torrentId }} - {{ name }}{% endblock %} -{% block main_content %} -
-
-

- {{'Edit locales for torrent' | trans }} - #{{ torrentId }} -

-
-
-
- - - - - - - {% for error in form.locales.error %} -
- {{ error }} -
- {% endfor %} -
- {% for locale in locales | sort %} -
- {% if locale in form.locales.attribute.value %} - - {% else %} - - {% endif %} - -
- {% endfor %} - {# - - #} -
-
-
- -
-
- {% for edition in editions %} -
- {% if edition.active %} - {{ edition.added | format_ago }} - {% else %} - - {{ edition.added | format_ago }} - - {% endif %} - {{ 'by'|trans }} - - {{'identicon'|trans }} - -
- {% if session.moderator or session.owner %} - - - - - - - {% endif %} - {% if edition.approved %} - {% if session.moderator %} - - - - - - {% else %} - - - - - - {% endif %} - {% else %} - {% if session.moderator %} - - - - - - {% else %} - - - - - - {% endif %} - {% endif %} -
-
- {% endfor %} -{% endblock %} diff --git a/templates/default/torrent/edit/poster.html.twig b/templates/default/torrent/edit/poster.html.twig deleted file mode 100644 index e4ed5e9..0000000 --- a/templates/default/torrent/edit/poster.html.twig +++ /dev/null @@ -1,121 +0,0 @@ -{% extends 'default/layout.html.twig' %} -{% block title %}{{ 'Edit torrent poster' | trans }} - {{ 'Torrent' | trans }} #{{ torrentId }} - {{ name }}{% endblock %} -{% block main_content %} -
-
-

- {{'Edit poster for torrent' | trans }} - #{{ torrentId }} -

-
-
-
- {% for error in form.poster.error %} -
- {{ error }} -
- {% endfor %} - -
-
- - - - - - -
-
- -
-
- {% for edition in editions %} -
- {% if edition.active %} - {{ edition.added | format_ago }} - {% else %} - - {{ edition.added | format_ago }} - - {% endif %} - {{ 'by' | trans }} - - {{'identicon'|trans }} - -
- {% if session.moderator or session.owner %} - - - - - - - {% endif %} - {% if edition.approved %} - {% if session.moderator %} - - - - - - {% else %} - - - - - - {% endif %} - {% else %} - {% if session.moderator %} - - - - - - {% else %} - - - - - - {% endif %} - {% endif %} -
- {% if edition.active %} -
- -
- - - - - - -
-
-
- -
-
- {% endif %} -
- {% endfor %} -{% endblock %} diff --git a/templates/default/torrent/edit/sensitive.html.twig b/templates/default/torrent/edit/sensitive.html.twig deleted file mode 100644 index cadd2a2..0000000 --- a/templates/default/torrent/edit/sensitive.html.twig +++ /dev/null @@ -1,86 +0,0 @@ -{% extends 'default/layout.html.twig' %} -{% block title %}{{ 'Edit sensitive status' | trans }} - {{ 'Torrent' | trans }} #{{ torrentId }} - {{ name }}{% endblock %} -{% block main_content %} -
-
-

- {{'Edit sensitive status for torrent' | trans }} - #{{ torrentId }} -

-
-
-
- - - - - - - -
-
- -
-
- {% for edition in editions %} -
- {% if edition.active %} - {{ edition.added | format_ago }} - {% else %} - - {{ edition.added | format_ago }} - - {% endif %} - {{ 'by' | trans }} - - {{'identicon'|trans }} - -
- {% if session.moderator or session.owner %} - - - - - - - {% endif %} - {% if edition.approved %} - {% if session.moderator %} - - - - - - {% else %} - - - - - - {% endif %} - {% else %} - {% if session.moderator %} - - - - - - {% else %} - - - - - - {% endif %} - {% endif %} -
-
- {% endfor %} -{% endblock %} diff --git a/templates/default/torrent/info.html.twig b/templates/default/torrent/info.html.twig deleted file mode 100644 index dda2a72..0000000 --- a/templates/default/torrent/info.html.twig +++ /dev/null @@ -1,467 +0,0 @@ -{% macro recursive_file_tree(tree) %} - {% import _self as self %} - {% for key, value in tree %} - {% if value is iterable %} -
- {{ key }} -
-
- {{ self.recursive_file_tree(value) }} -
- {% else %} -
-
- {{ key }} -
-
- {{ value | format_bytes }} -
-
- {% endif %} - {% endfor %} -{% endmacro %} -{% from _self import recursive_file_tree %} -{% extends 'default/layout.html.twig' %} -{% block title %}{{ file.name }} - {{ 'Torrent' | trans }} #{{ torrent.id }}{% if pagination.page > 1 %} - {{ 'Page' | trans }} {{ pagination.page }}{% endif %} - {{ name }}{% endblock %} -{% block keywords %} - {% if torrent.keywords %} - - {% endif %} -{% endblock %} -{% block main_content %} -
-

- {{ file.name }} - {#{{ 'Torrent' | trans }} #{{ torrent.id }}#} -

- - - - {% if session.moderator or session.owner %} - - - - - - - - {% if session.moderator %} - - - - - {% endif %} - {% endif %} - - - - - - - - - - - - {% if file.hash.v1 %} - - - - - {% endif %} - {% if file.hash.v2 %} - - - - - {% endif %} - {# visible in H1 - - - - - #} - {% if file.created %} - - - - - {% endif %} - - {% if file.size %} - - - - - {% endif %} - {% if file.pieces %} - - - - - {% endif %} - - - - - {% if file.source %} - - - - - {% endif %} - {% if file.software %} - - - - - {% endif %} - {% if file.comment %} - - - - - {% endif %} - - - - - - - - - - - - - - - - - - - - -
-
- {{ 'Moderation' | trans }} -
-
- {{ 'Enabled' | trans }} - - {% if torrent.status %} - {{ 'Yes' | trans }} - - - - - - {% else %} - {{ 'No' | trans }} - - - - - - {% endif %} -
- {{ 'Approved' | trans }} - - {% if torrent.approved %} - {{ 'Yes' | trans }} - - - - - - {% else %} - {{ 'No' | trans }} - - - - - - {% endif %} -
-
- {{ 'Common' | trans }} -
-
- {{ 'ID' | trans }} - - #{{ torrent.id }} -
- {{ 'MD5' | trans }} - - {{ torrent.md5file }} -
- {{ 'Info hash v1' | trans }} - - {{ file.hash.v1 }} -
- {{ 'Info hash v2' | trans }} - - {{ file.hash.v2 }} -
- {{ 'Filename'|trans }} - - {{ file.name }} -
- {{ 'Created' | trans }} - - {{ file.created | format_date }} -
- {{ 'Size' | trans }} - - {{ file.size | format_bytes }} -
- {{ 'Pieces' | trans }} - - {{ file.pieces | format_number }} -
- {{ 'Private' | trans }} - - {% if file.private %} - {{ 'Yes' | trans }} - {% else %} - {{ 'No' | trans }} - {% endif %} -
- {{ 'Source' | trans }} - - {# strip all tags then apply whitelist markdown filters to prevent ping from remote #} - {{ file.source | trim | striptags | url_to_markdown | markdown_to_html | nl2br }} -
- {{ 'Software' | trans }} - - {# strip all tags then apply whitelist markdown filters to prevent ping from remote #} - {{ file.software | trim | striptags | url_to_markdown | markdown_to_html | nl2br }} -
- {{ 'Comment' | trans }} - - {# strip all tags then apply whitelist markdown filters to prevent ping from remote #} - {{ file.comment | trim | striptags | url_to_markdown | markdown_to_html | nl2br }} -
- {{ 'Contributors' | trans }} - - {% for id, identicon in torrent.contributors %} - - {{'identicon'|trans }} - - {% endfor %} -
-
- {{ 'Scrape' | trans }} -
-
- {{ 'Seeders' | trans }} - - {{ torrent.scrape.seeders }} -
- {{ 'Peers' | trans }} - - {{ torrent.scrape.peers }} -
- {{ 'Leechers' | trans }} - - {{ torrent.scrape.leechers }} -
-
- {{ 'Files' | trans }} -
-
- {% for key, value in file.tree %} - {% if value is iterable %} - {{ recursive_file_tree(value) }} - {% else %} -
- {{ key }} -
- {{ value | format_bytes }} -
-
- {% endif %} - {% endfor %} -
-
- {{ 'Trackers' | trans }} -
-
- {% for tracker, status in trackers %} -
- {% if status %} - {{ tracker }} - {% else %} - - {{ tracker }} - - - - - - - {% endif %} -
- {% endfor %} -
-
- - - - - - {{ 'Locale' | trans }} -
-
- {% if torrent.locales %} -
- {% set i = 0 %} - {% for locale in torrent.locales | sort %}{% if i > 0 %},{% endif %} {{ locale | locale_name(locale) | u.title }}{% set i = i + 1 %}{% endfor %} -
- {% endif %} -
-
-
- - - - - - {{ 'Category' | trans }} -
-
- {% if torrent.categories %} -
- {% set i = 0 %} - {% for category in torrent.categories | sort %}{% if i > 0 %},{% endif %} {{ category | trans_category | u.title }}{% set i = i + 1 %}{% endfor %} -
- {% endif %} -
-
-
- - - - - - {{ 'Sensitive' | trans }} -
-
- {% if torrent.sensitive %} - {{ 'Yes' | trans }} - {% else %} - {{ 'No' | trans }} - {% endif %} -
-
-
- - - - - - {{ 'Poster' | trans }} -
-
- {% if torrent.poster %} - {{ 'Yes' | trans }} - {% else %} - {{ 'No' | trans }} - {% endif %} -
-
-
- -
-

{{ 'Recent activity' | trans }}

- - - - - - - -
- {% if activities %} - {% for activity in activities %} -
- {{ render(controller( - 'App\\Controller\\ActivityController::event', - { user : session.user, activity : activity } - )) }} -
- {% endfor %} - {% if pagination.pages > 1 %} -
-
-   -
-
- {% if pagination.pages > 1 %} - {{ 'Page' | trans | lower }} {{ pagination.page }} / {{ pagination.pages }} - {% if pagination.page > 1 %} - {% if pagination.page == 2 %} - - {{ 'Back' | trans | lower }} - - {% else %} - - {{ 'Back' | trans | lower }} - - {% endif %} - {% endif %} - {% if pagination.page < pagination.pages %} - - {{ 'Next' | trans | lower }} - - {% endif %} - {% endif %} -
-
- {% endif %} - {% endif %} -{% endblock %} \ No newline at end of file diff --git a/templates/default/torrent/list.html.twig b/templates/default/torrent/list.html.twig deleted file mode 100644 index 93e27d1..0000000 --- a/templates/default/torrent/list.html.twig +++ /dev/null @@ -1,269 +0,0 @@ -{% extends 'default/layout.html.twig' %} -{% block title %}{% if query %}{{ query }} - {{ 'Search' | trans }} - {% endif %}{{ name }}{% endblock %} -{% block main_content %} -
- {% if query %} -

{{ 'Search results' | trans }}

- - {% if app.request.get('filter') %} - - - - - - - - - - - {% else %} - - - - - - - - - - - {% endif %} - - {% else %} -

{{ 'Recent uploads' | trans }}

- - - - - - - - {% endif %} -
- {% if torrents %} - {% for torrent in torrents %} -
- -
-

- - {{ torrent.file.name }} - -

- {% if torrent.scrape.leechers > 0 and torrent.scrape.seeders == 0 %} - - {{ 'wanted' | trans }} - - {% endif %} - {% if torrent.status == false %} - - - - - - - {% endif %} - {% if torrent.approved == false %} - - - - - - {% endif %} - {% if torrent.sensitive == true %} - - - - - - {% endif %} - {% if torrent.file.hash.v2 %} - - - - - - {% endif %} - {% if torrent.file.hash.v1 and torrent.file.hash.v2 %} - - - - - - {% endif %} -
- {% if torrent.keywords %} -
- {% for keyword, quantity in torrent.keywords %} - - #{{ keyword }} - - {% endfor %} -
- {% endif %} -
- - - {{ torrent.file.size | format_bytes }} - - - - - - - - {{ torrent.scrape.seeders }} - - - - - - - - {{ torrent.scrape.peers }} - - - - - - - - - {{ torrent.scrape.leechers }} - - - -
- {% endfor %} - {% if pagination.pages > 1 %} -
- {{ 'Page' | trans | lower }} {{ pagination.page }} / {{ pagination.pages }} - {% if query %} - {% if pagination.page > 1 %} - {% if pagination.page == 2 %} - - {{ 'Back' | trans | lower }} - - {% else %} - - {{ 'Back' | trans | lower }} - - {% endif %} - {% endif %} - {% if pagination.page < pagination.pages %} - - {{ 'Next' | trans | lower }} - - {% endif %} - {% else %} - {% if pagination.page > 1 %} - {% if pagination.page == 2 %} - - {{ 'Back' | trans | lower }} - - {% else %} - - {{ 'Back' | trans | lower }} - - {% endif %} - {% endif %} - {% if pagination.page < pagination.pages %} - - {{ 'Next' | trans | lower }} - - {% endif %} - {% endif %} -
- {% endif %} - {% else %} -
-
-

- {{ 'Nothing found' | trans }} -

-
- {{ '* share new torrent file to change it' | trans }} -
-
- -
-
-
- {% endif %} -{% endblock %} \ No newline at end of file diff --git a/templates/default/torrent/list.rss.twig b/templates/default/torrent/list.rss.twig deleted file mode 100644 index 31fa74b..0000000 --- a/templates/default/torrent/list.rss.twig +++ /dev/null @@ -1,17 +0,0 @@ - - - - - {{ name }} - {{ 'Torrents' | trans }} - {{ url('torrent_recent') }} - {% for torrent in torrents %} - - {{ torrent.file.name }} - #{{ torrent.user.id }} - {{ torrent.added | date('D, d M Y h:i:s O') }} - {{ url('torrent_info', { torrentId : torrent.id }) }} - {{ url('torrent_info', { torrentId : torrent.id }) }} - - {% endfor %} - - diff --git a/templates/default/torrent/sitemap.xml.twig b/templates/default/torrent/sitemap.xml.twig deleted file mode 100644 index 99d77e5..0000000 --- a/templates/default/torrent/sitemap.xml.twig +++ /dev/null @@ -1,15 +0,0 @@ - - - {% for torrent in torrents %} - - {{ torrent.added | date('Y-m-d') }} - {% for code in locales %} - {% if code == locale %} - {{ url('torrent_info', { '_locale': code , torrentId : torrent.id }) }} - {% else %} - - {% endif %} - {% endfor %} - - {% endfor %} - diff --git a/templates/default/torrent/submit.html.twig b/templates/default/torrent/submit.html.twig deleted file mode 100644 index c36da9a..0000000 --- a/templates/default/torrent/submit.html.twig +++ /dev/null @@ -1,100 +0,0 @@ -{% extends 'default/layout.html.twig' %} -{% block title %}{{'Submit torrent' | trans }} - {{ name }}{% endblock %} -{% block main_content %} -
-
-

{{'Submit torrent' | trans }}

-
-
-
- {% for error in form.torrent.error %} -
- {{ error }} -
- {% endfor %} - -
-
-
-
- - - - - - - {% for error in form.locales.error %} -
- {{ error }} -
- {% endfor %} -
- {% for locale in locales | sort %} -
- {% if locale in form.locales.attribute.value %} - - {% else %} - - {% endif %} - -
- {% endfor %} - {# - {{'Other...'|trans }} - #} -
-
-
-
- - - - - - - {% for error in form.categories.error %} -
- {{ error }} -
- {% endfor %} -
- {% for category in categories | sort %} -
- {% if category in form.categories.attribute.value %} - - {% else %} - - {% endif %} - -
- {% endfor %} - {# - {{'Other...'|trans }} - #} -
-
-
- - - - - - - -
-
- -
-
-
-{% endblock %} diff --git a/templates/default/user/info.html.twig b/templates/default/user/info.html.twig deleted file mode 100644 index a22da9e..0000000 --- a/templates/default/user/info.html.twig +++ /dev/null @@ -1,299 +0,0 @@ -{% extends 'default/layout.html.twig' %} -{% block title %}{{ 'User'|trans }} #{{ user.id }}{% if pagination.page > 1 %} - {{ 'Page' | trans }} {{ pagination.page }}{% endif %} - {{ name }}{% endblock %} -{% block main_content %} -
-
- {{ 'identicon'|trans }} -
- {# @TODO username feature -
-

- {{ 'User'|trans }} #{{ user.id }} -

-
- #} - - - - - - - {% if session.owner or session.moderator %} - - - - - - - - - {% else %} - - - - - {% endif %} - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
{{ 'Common'|trans }}
{{ 'Address' | trans }} - {{ user.address }} - - - - - - - - -
{{ 'Joined' | trans }}{{ user.added | format_ago }}
{{ 'Joined' | trans }}{{ user.added | format_ago }}
{{ 'Access' | trans }}
- {{ 'Status' | trans }} - - {% if user.status %} - {{ 'Active' | trans }} - {% if session.moderator %} - - - - - - {% endif %} - {% else %} - {{ 'Disabled' | trans }} - {% if session.moderator %} - - - - - - {% endif %} - {% endif %} -
- {{ 'Approved' | trans }} - - {% if user.approved %} - {{ 'Yes'| trans }} - {% if session.moderator %} - - - - - - {% endif %} - {% else %} - {{ 'No'| trans }} - {% if session.moderator %} - - - - - - {% endif %} - {% endif %} -
- {{ 'Moderator' | trans }} - - {% if user.moderator %} - {{ 'Yes'| trans }} - {% if session.moderator %} - - - - - - {% endif %} - {% else %} - {{ 'No'| trans }} - {% if session.moderator %} - - - - - - {% endif %} - {% endif %} -
- {% if user.owner %} - - - - - - {% endif %} - {{ 'Settings' | trans }} -
- {{ 'Theme' | trans }} - - {{ user.theme | u.title }} -
- {{ 'Interface' | trans }} - - {{ user.locale | locale_name(user.locale) | u.title }} -
- {{ 'Languages' | trans }} - - {% set i = 0 %} - {% for locale in user.locales | sort %}{% if i > 0 %},{% endif %} {{ locale | locale_name(locale) | u.title }}{% set i = i + 1 %}{% endfor %} -
- {{ 'Categories' | trans }} - - {% set i = 0 %} - {% for category in user.categories | sort %}{% if i > 0 %},{% endif %} {{ category | trans_category | u.title }}{% set i = i + 1 %}{% endfor %} -
- {{ 'Posters' | trans }} - - {% if user.posters %} - {{ 'Yes' | trans }} - {% else %} - {{ 'No' | trans }} - {% endif %} -
- {{ 'Sensitive' | trans }} - - {% if user.sensitive %} - {{ 'Yes' | trans }} - {% else %} - {{ 'No' | trans }} - {% endif %} -
- {{ 'Events subscribed' | trans }} - - {% for group, event in events %} -
- - {{ group }}: - - {% set i = 0 %} - {% for key, value in event %}{% if value in user.events %}{% if i > 0 %}, {% endif %}{{ key | lower }}{% set i = i + 1 %}{% endif %}{% endfor %} -
- {% endfor %} -
- {{ 'Yggdrasil only' | trans }} - - {% if user.yggdrasil %} - {{ 'Yes'|trans }} - {% else %} - {{ 'No'|trans }} - {% endif %} -
-
- -
-

{{ 'Recent activity' | trans }}

- - - - - - - -
- {% if user.activities %} - {% for activity in user.activities %} -
- {{ render(controller( - 'App\\Controller\\ActivityController::event', - { user: session.user, activity : activity } - )) }} -
- {% endfor %} - {% if pagination.pages > 1 %} -
-
-   - {# @TODO - - - - - - #} -
-
- {% if pagination.pages > 1 %} - {{ 'Page' | trans | lower }} {{ pagination.page }} / {{ pagination.pages }} - {% if pagination.page > 1 %} - {% if pagination.page == 2 %} - - {{ 'Back' | trans | lower }} - - {% else %} - - {{ 'Back' | trans | lower }} - - {% endif %} - {% endif %} - {% if pagination.page < pagination.pages %} - - {{ 'Next' | trans | lower }} - - {% endif %} - {% endif %} -
-
- {% endif %} - {% endif %} -{% endblock %} \ No newline at end of file diff --git a/templates/default/user/module.html.twig b/templates/default/user/module.html.twig deleted file mode 100644 index 5dc7e51..0000000 --- a/templates/default/user/module.html.twig +++ /dev/null @@ -1,67 +0,0 @@ -
- {% if route == 'torrent_recent' %} - - - - - - {% else %} - - - - - - {% endif %} - {% if route == 'activity_all' %} - - - - - - {% else %} - - - - - - {% endif %} - {% if route == 'user_info' %} - - - - - - {% else %} - - - - - - {% endif %} - {% if route == 'user_settings' %} - - - - - - {% else %} - - - - - - {% endif %} - {% if route == 'torrent_submit' or route == 'torrent_submit' %} - - - - - - {% else %} - - - - - - {% endif %} -
\ No newline at end of file diff --git a/templates/default/user/settings.html.twig b/templates/default/user/settings.html.twig deleted file mode 100644 index 49fcbed..0000000 --- a/templates/default/user/settings.html.twig +++ /dev/null @@ -1,200 +0,0 @@ -{% extends 'default/layout.html.twig' %} -{% block title %}{{ 'Settings' | trans }} - {{ name }}{% endblock %} -{% block main_content %} -
-
-

{{ 'Settings' | trans }}

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - {% set i = 0 %} - {% for group, event in events %} - {% set i = i + 1 %} - - - - - {% endfor %} - - - - - - - - -
- {{ 'Interface' | trans }} -
- {{ 'Theme' | trans }} - - -
{{ 'Language' | trans }} - - -
- {{ 'Posters' | trans }} - -
- {% if user.posters %} - - {% else %} - - {% endif %} - -
-
- {{ 'Search' | trans }} -
-
- {{ 'Locales' | trans }} -
-
- {% for locale in locales | sort %} -
- {% if locale in user.locales %} - - {% else %} - - {% endif %} - -
- {% endfor %} -
-
- {{ 'Categories' | trans }} -
-
- {% for category in categories | sort %} -
- {% if category in user.categories %} - - {% else %} - - {% endif %} - -
- {% endfor %} -
- {{ 'Sensitive' | trans }} - -
- {% if user.sensitive %} - - {% else %} - - {% endif %} - -
-
- {{ 'Activity' | trans }} -
- {{ group }} - - {% for key, value in event %} - - {% if value in user.events %} - - {% else %} - - {% endif %} - - - {% endfor %} -
- {{ 'Downloads' | trans }} -
- {{ 'Yggdrasil only' | trans }} - - {% if user.yggdrasil %} - - {% else %} - - {% endif %} - -
-
- -
-
-
-{% endblock %} \ No newline at end of file diff --git a/tests/bootstrap.php b/tests/bootstrap.php deleted file mode 100644 index 469dcce..0000000 --- a/tests/bootstrap.php +++ /dev/null @@ -1,11 +0,0 @@ -bootEnv(dirname(__DIR__).'/.env'); -} diff --git a/translations/.gitignore b/translations/.gitignore deleted file mode 100644 index e69de29..0000000 diff --git a/translations/messages+intl-icu.cs.xlf b/translations/messages+intl-icu.cs.xlf deleted file mode 100644 index e661df7..0000000 --- a/translations/messages+intl-icu.cs.xlf +++ /dev/null @@ -1,918 +0,0 @@ - - - -
- -
- - - Users - Users - - - Joined - Joined - - - Approved - Approved - - - Disapproved - Disapproved - - - User statuses - User statuses - - - Enabled - Enabled - - - Disabled - Disabled - - - User moderators - User moderators - - - Added - Added - - - Removed - Removed - - - User stars - User stars - - - Torrents - Torrents - - - Torrent locales - Torrent locales - - - Deleted - Deleted - - - Torrent sensitive - Torrent sensitive - - - Torrent stars - Torrent stars - - - Torrent downloads - Torrent downloads - - - Files - Files - - - Magnet links - Magnet links - - - Access denied - Access denied - - - At least one locale required - At least one locale required - - - Torrent file out of size limit - Torrent file out of size limit - - - Torrent file already exists - Torrent file already exists - - - Could not parse torrent file - Could not parse torrent file - - - Torrent file required - Torrent file required - - - B - B - - - Kb - Kb - - - Mb - Mb - - - Gb - Gb - - - Tb - Tb - - - Pb - Pb - - - Eb - Eb - - - Zb - Zb - - - Yb - Yb - - - now - now - - - Keyword, file, hash... - Keyword, file, hash... - - - Search - Search - - - Recent uploads - Recent uploads - - - Active leechers waiting for seeders - Active leechers waiting for seeders - - - wanted - wanted - - - Waiting for approve - Waiting for approve - - - Size - Size - - - Seeders - Seeders - - - Peers - Peers - - - Leechers - Leechers - - - Open magnet link - Open magnet link - - - Total - Total - - - Download torrent file - Download torrent file - - - Star - Star - - - Nothing found - Nothing found - - - * share new torrent file to change it - * share new torrent file to change it - - - Submit - Submit - - - Submit torrent - Submit torrent - - - Content language - Content language - - - This torrent contains selected languages - This torrent contains selected languages - - - Sensitive - Sensitive - - - Mark torrent content as sensitive - Mark torrent content as sensitive - - - Edit locales - Edit locales - - - Torrent - Torrent - - - Edit locales for torrent - Edit locales for torrent - - - cancel - cancel - - - by - by - - - identicon - identicon - - - Delete - Delete - - - Disapprove - Disapprove - - - Approve - Approve - - - Edit sensitive status - Edit sensitive status - - - Edit sensitive status for torrent - Edit sensitive status for torrent - - - Page - Page - - - Moderation - Moderation - - - Yes - Yes - - - Toggle - Toggle - - - No - No - - - Common - Common - - - ID - ID - - - MD5 - MD5 - - - Info hash v1 - Info hash v1 - - - Info hash v2 - Info hash v2 - - - Created - Created - - - Pieces - Pieces - - - Source - Source - - - Software - Software - - - Comment - Comment - - - Contributors - Contributors - - - Scrape - Scrape - - - Trackers - Trackers - - - Filtered by settings - Filtered by settings - - - Edit - Edit - - - Locales - Locales - - - Recent activity - Recent activity - - - Back - Back - - - Next - Next - - - Settings - Settings - - - Interface - Interface - - - Theme - Theme - - - Language - Language - - - Join translation - Join translation - - - Activity - Activity - - - Downloads - Downloads - - - Yggdrasil only - Yggdrasil only - - - Save - Save - - - Home - Home - - - Profile - Profile - - - User - User - - - Bookmark - Bookmark - - - Address - Address - - - Address hidden for others - Address hidden for others - - - Access - Access - - - Status - Status - - - Active - Active - - - Moderator - Moderator - - - Languages - Languages - - - Events subscribed - Events subscribed - - - undefined event - undefined event - - - have downloaded torrent file - have downloaded torrent file - - - waiting for approve - waiting for approve - - - sensitive - sensitive - - - have downloaded magnet link - have downloaded magnet link - - - have disapproved torrent - have disapproved torrent - - - have approved torrent - have approved torrent - - - have added torrent - have added torrent - - - have deleted locales edition - have deleted locales edition - - - for torrent - for torrent - - - have disapproved locales edition - have disapproved locales edition - - - have approved locales edition - have approved locales edition - - - have added locales edition - have added locales edition - - - have removed star from torrent - have removed star from torrent - - - have added star for torrent - have added star for torrent - - - have deleted sensitive edition - have deleted sensitive edition - - - have disapproved sensitive edition - have disapproved sensitive edition - - - have approved sensitive edition - have approved sensitive edition - - - have added sensitive edition - have added sensitive edition - - - have disabled - have disabled - - - have disabled user - have disabled user - - - have enabled - have enabled - - - have enabled user - have enabled user - - - have disapproved - have disapproved - - - have disapproved user - have disapproved user - - - have approved - have approved - - - have approved user - have approved user - - - have joined - have joined - - - have removed moderator permissions from - have removed moderator permissions from - - - have removed moderator permissions from user - have removed moderator permissions from user - - - have granted moderator permissions to - have granted moderator permissions to - - - have granted moderator permissions to user - have granted moderator permissions to user - - - have removed star from - have removed star from - - - have removed star from user - have removed star from user - - - have added star for - have added star for - - - have added star for user - have added star for user - - - Error - Error - - - Oops! - Oops! - - - Internal server error - Internal server error - - - Report - Report - - - Not found - Not found - - - Page not found! - Page not found! - - - BitTorrent protocol version 2 - BitTorrent protocol version 2 - - - BitTorrent protocol version 1 - BitTorrent protocol version 1 - - - year ago - year ago - - - month ago - month ago - - - day ago - day ago - - - hour ago - hour ago - - - minute ago - minute ago - - - second ago - second ago - - - years ago - years ago - - - months ago - months ago - - - days ago - days ago - - - hours ago - hours ago - - - minutes ago - minutes ago - - - seconds ago - seconds ago - - - years ago - years ago - - - months ago - months ago - - - days ago - days ago - - - hours ago - hours ago - - - minutes ago - minutes ago - - - seconds ago - seconds ago - - - Search results - Search results - - - <a href="%s">Upload</a> any torrent - download with Yggdrasil - Upload any torrent - download with Yggdrasil]]> - - - Wanted - Wanted - - - Seeders wanted for torrent - Seeders wanted for torrent - - - Hide - Hide - - - have disabled torrent - have disabled torrent - - - have enabled torrent - have enabled torrent - - - disabled - disabled - - - Poster file out of size limit - Poster file out of size limit - - - Image file not supported - Image file not supported - - - Poster file required - Poster file required - - - Edit torrent poster - Edit torrent poster - - - Edit poster for torrent - Edit poster for torrent - - - Poster - Poster - - - Posters - Posters - - - have deleted poster edition - have deleted poster edition - - - have disapproved poster edition - have disapproved poster edition - - - have approved poster edition - have approved poster edition - - - have added poster edition - have added poster edition - - - Torrent posters - Torrent posters - - - Center - Center - - - Top - Top - - - Bottom - Bottom - - - Categories - Categories - - - At least one category required - At least one category required - - - Content category - Content category - - - This torrent have selected categories - This torrent have selected categories - - - Edit categories - Edit categories - - - Edit categories for torrent - Edit categories for torrent - - - Locale - Locale - - - Category - Category - - - Torrent categories - Torrent categories - - - have deleted categories edition - have deleted categories edition - - - have disapproved categories edition - have disapproved categories edition - - - have approved categories edition - have approved categories edition - - - have added categories edition - have added categories edition - - - movie - movie - - - series - series - - - tv - tv - - - animation - animation - - - music - music - - - game - game - - - audiobook - audiobook - - - podcast - podcast - - - book - book - - - archive - archive - - - picture - picture - - - software - software - - - other - other - - - Hide filter - Hide filter - - - Show filter - Show filter - - - Private - Private - - -
-
diff --git a/translations/messages+intl-icu.de.xlf b/translations/messages+intl-icu.de.xlf deleted file mode 100644 index 754006d..0000000 --- a/translations/messages+intl-icu.de.xlf +++ /dev/null @@ -1,918 +0,0 @@ - - - -
- -
- - - Users - Users - - - Joined - Joined - - - Approved - Approved - - - Disapproved - Disapproved - - - User statuses - User statuses - - - Enabled - Enabled - - - Disabled - Disabled - - - User moderators - User moderators - - - Added - Added - - - Removed - Removed - - - User stars - User stars - - - Torrents - Torrents - - - Torrent locales - Torrent locales - - - Deleted - Deleted - - - Torrent sensitive - Torrent sensitive - - - Torrent stars - Torrent stars - - - Torrent downloads - Torrent downloads - - - Files - Files - - - Magnet links - Magnet links - - - Access denied - Access denied - - - At least one locale required - At least one locale required - - - Torrent file out of size limit - Torrent file out of size limit - - - Torrent file already exists - Torrent file already exists - - - Could not parse torrent file - Could not parse torrent file - - - Torrent file required - Torrent file required - - - B - B - - - Kb - Kb - - - Mb - Mb - - - Gb - Gb - - - Tb - Tb - - - Pb - Pb - - - Eb - Eb - - - Zb - Zb - - - Yb - Yb - - - now - now - - - Keyword, file, hash... - Keyword, file, hash... - - - Search - Search - - - Recent uploads - Recent uploads - - - Active leechers waiting for seeders - Active leechers waiting for seeders - - - wanted - wanted - - - Waiting for approve - Waiting for approve - - - Size - Size - - - Seeders - Seeders - - - Peers - Peers - - - Leechers - Leechers - - - Open magnet link - Open magnet link - - - Total - Total - - - Download torrent file - Download torrent file - - - Star - Star - - - Nothing found - Nothing found - - - * share new torrent file to change it - * share new torrent file to change it - - - Submit - Submit - - - Submit torrent - Submit torrent - - - Content language - Content language - - - This torrent contains selected languages - This torrent contains selected languages - - - Sensitive - Sensitive - - - Mark torrent content as sensitive - Mark torrent content as sensitive - - - Edit locales - Edit locales - - - Torrent - Torrent - - - Edit locales for torrent - Edit locales for torrent - - - cancel - cancel - - - by - by - - - identicon - identicon - - - Delete - Delete - - - Disapprove - Disapprove - - - Approve - Approve - - - Edit sensitive status - Edit sensitive status - - - Edit sensitive status for torrent - Edit sensitive status for torrent - - - Page - Page - - - Moderation - Moderation - - - Yes - Yes - - - Toggle - Toggle - - - No - No - - - Common - Common - - - ID - ID - - - MD5 - MD5 - - - Info hash v1 - Info hash v1 - - - Info hash v2 - Info hash v2 - - - Created - Created - - - Pieces - Pieces - - - Source - Source - - - Software - Software - - - Comment - Comment - - - Contributors - Contributors - - - Scrape - Scrape - - - Trackers - Trackers - - - Filtered by settings - Filtered by settings - - - Edit - Edit - - - Locales - Locales - - - Recent activity - Recent activity - - - Back - Back - - - Next - Next - - - Settings - Settings - - - Interface - Interface - - - Theme - Theme - - - Language - Language - - - Join translation - Join translation - - - Activity - Activity - - - Downloads - Downloads - - - Yggdrasil only - Yggdrasil only - - - Save - Save - - - Home - Home - - - Profile - Profile - - - User - User - - - Bookmark - Bookmark - - - Address - Address - - - Address hidden for others - Address hidden for others - - - Access - Access - - - Status - Status - - - Active - Active - - - Moderator - Moderator - - - Languages - Languages - - - Events subscribed - Events subscribed - - - undefined event - undefined event - - - have downloaded torrent file - have downloaded torrent file - - - waiting for approve - waiting for approve - - - sensitive - sensitive - - - have downloaded magnet link - have downloaded magnet link - - - have disapproved torrent - have disapproved torrent - - - have approved torrent - have approved torrent - - - have added torrent - have added torrent - - - have deleted locales edition - have deleted locales edition - - - for torrent - for torrent - - - have disapproved locales edition - have disapproved locales edition - - - have approved locales edition - have approved locales edition - - - have added locales edition - have added locales edition - - - have removed star from torrent - have removed star from torrent - - - have added star for torrent - have added star for torrent - - - have deleted sensitive edition - have deleted sensitive edition - - - have disapproved sensitive edition - have disapproved sensitive edition - - - have approved sensitive edition - have approved sensitive edition - - - have added sensitive edition - have added sensitive edition - - - have disabled - have disabled - - - have disabled user - have disabled user - - - have enabled - have enabled - - - have enabled user - have enabled user - - - have disapproved - have disapproved - - - have disapproved user - have disapproved user - - - have approved - have approved - - - have approved user - have approved user - - - have joined - have joined - - - have removed moderator permissions from - have removed moderator permissions from - - - have removed moderator permissions from user - have removed moderator permissions from user - - - have granted moderator permissions to - have granted moderator permissions to - - - have granted moderator permissions to user - have granted moderator permissions to user - - - have removed star from - have removed star from - - - have removed star from user - have removed star from user - - - have added star for - have added star for - - - have added star for user - have added star for user - - - Error - Error - - - Oops! - Oops! - - - Internal server error - Internal server error - - - Report - Report - - - Not found - Not found - - - Page not found! - Page not found! - - - BitTorrent protocol version 2 - BitTorrent protocol version 2 - - - BitTorrent protocol version 1 - BitTorrent protocol version 1 - - - year ago - year ago - - - month ago - month ago - - - day ago - day ago - - - hour ago - hour ago - - - minute ago - minute ago - - - second ago - second ago - - - years ago - years ago - - - months ago - months ago - - - days ago - days ago - - - hours ago - hours ago - - - minutes ago - minutes ago - - - seconds ago - seconds ago - - - years ago - years ago - - - months ago - months ago - - - days ago - days ago - - - hours ago - hours ago - - - minutes ago - minutes ago - - - seconds ago - seconds ago - - - Search results - Search results - - - <a href="%s">Upload</a> any torrent - download with Yggdrasil - Upload any torrent - download with Yggdrasil]]> - - - Wanted - Wanted - - - Seeders wanted for torrent - Seeders wanted for torrent - - - Hide - Hide - - - have disabled torrent - have disabled torrent - - - have enabled torrent - have enabled torrent - - - disabled - disabled - - - Poster file out of size limit - Poster file out of size limit - - - Image file not supported - Image file not supported - - - Poster file required - Poster file required - - - Edit torrent poster - Edit torrent poster - - - Edit poster for torrent - Edit poster for torrent - - - Poster - Poster - - - Posters - Posters - - - have deleted poster edition - have deleted poster edition - - - have disapproved poster edition - have disapproved poster edition - - - have approved poster edition - have approved poster edition - - - have added poster edition - have added poster edition - - - Torrent posters - Torrent posters - - - Center - Center - - - Top - Top - - - Bottom - Bottom - - - Categories - Categories - - - At least one category required - At least one category required - - - Content category - Content category - - - This torrent have selected categories - This torrent have selected categories - - - Edit categories - Edit categories - - - Edit categories for torrent - Edit categories for torrent - - - Locale - Locale - - - Category - Category - - - Torrent categories - Torrent categories - - - have deleted categories edition - have deleted categories edition - - - have disapproved categories edition - have disapproved categories edition - - - have approved categories edition - have approved categories edition - - - have added categories edition - have added categories edition - - - movie - movie - - - series - series - - - tv - tv - - - animation - animation - - - music - music - - - game - game - - - audiobook - audiobook - - - podcast - podcast - - - book - book - - - archive - archive - - - picture - picture - - - software - software - - - other - other - - - Hide filter - Hide filter - - - Show filter - Show filter - - - Private - Private - - -
-
diff --git a/translations/messages+intl-icu.en.xlf b/translations/messages+intl-icu.en.xlf deleted file mode 100644 index cbd0dc2..0000000 --- a/translations/messages+intl-icu.en.xlf +++ /dev/null @@ -1,918 +0,0 @@ - - - -
- -
- - - Users - Users - - - Joined - Joined - - - Approved - Approved - - - Disapproved - Disapproved - - - User statuses - User statuses - - - Enabled - Enabled - - - Disabled - Disabled - - - User moderators - User moderators - - - Added - Added - - - Removed - Removed - - - User stars - User stars - - - Torrents - Torrents - - - Torrent locales - Torrent locales - - - Deleted - Deleted - - - Torrent sensitive - Torrent sensitive - - - Torrent stars - Torrent stars - - - Torrent downloads - Torrent downloads - - - Files - Files - - - Magnet links - Magnet links - - - Access denied - Access denied - - - At least one locale required - At least one locale required - - - Torrent file out of size limit - Torrent file out of size limit - - - Torrent file already exists - Torrent file already exists - - - Could not parse torrent file - Could not parse torrent file - - - Torrent file required - Torrent file required - - - B - B - - - Kb - Kb - - - Mb - Mb - - - Gb - Gb - - - Tb - Tb - - - Pb - Pb - - - Eb - Eb - - - Zb - Zb - - - Yb - Yb - - - now - now - - - Keyword, file, hash... - Keyword, file, hash... - - - Search - Search - - - Recent uploads - Recent uploads - - - Active leechers waiting for seeders - Active leechers waiting for seeders - - - wanted - wanted - - - Waiting for approve - Waiting for approve - - - Size - Size - - - Seeders - Seeders - - - Peers - Peers - - - Leechers - Leechers - - - Open magnet link - Open magnet link - - - Total - Total - - - Download torrent file - Download torrent file - - - Star - Star - - - Nothing found - Nothing found - - - * share new torrent file to change it - * share new torrent file to change it - - - Submit - Submit - - - Submit torrent - Submit torrent - - - Content language - Content language - - - This torrent contains selected languages - This torrent contains selected languages - - - Sensitive - Sensitive - - - Mark torrent content as sensitive - Mark torrent content as sensitive - - - Edit locales - Edit locales - - - Torrent - Torrent - - - Edit locales for torrent - Edit locales for torrent - - - cancel - cancel - - - by - by - - - identicon - identicon - - - Delete - Delete - - - Disapprove - Disapprove - - - Approve - Approve - - - Edit sensitive status - Edit sensitive status - - - Edit sensitive status for torrent - Edit sensitive status for torrent - - - Page - Page - - - Moderation - Moderation - - - Yes - Yes - - - Toggle - Toggle - - - No - No - - - Common - Common - - - ID - ID - - - MD5 - MD5 - - - Info hash v1 - Info hash v1 - - - Info hash v2 - Info hash v2 - - - Created - Created - - - Pieces - Pieces - - - Source - Source - - - Software - Software - - - Comment - Comment - - - Contributors - Contributors - - - Scrape - Scrape - - - Trackers - Trackers - - - Filtered by settings - Filtered by settings - - - Edit - Edit - - - Locales - Locales - - - Recent activity - Recent activity - - - Back - Back - - - Next - Next - - - Settings - Settings - - - Interface - Interface - - - Theme - Theme - - - Language - Language - - - Join translation - Join translation - - - Activity - Activity - - - Downloads - Downloads - - - Yggdrasil only - Yggdrasil only - - - Save - Save - - - Home - Home - - - Profile - Profile - - - User - User - - - Bookmark - Bookmark - - - Address - Address - - - Address hidden for others - Address hidden for others - - - Access - Access - - - Status - Status - - - Active - Active - - - Moderator - Moderator - - - Languages - Languages - - - Events subscribed - Events subscribed - - - undefined event - undefined event - - - have downloaded torrent file - have downloaded torrent file - - - waiting for approve - waiting for approve - - - sensitive - sensitive - - - have downloaded magnet link - have downloaded magnet link - - - have disapproved torrent - have disapproved torrent - - - have approved torrent - have approved torrent - - - have added torrent - have added torrent - - - have deleted locales edition - have deleted locales edition - - - for torrent - for torrent - - - have disapproved locales edition - have disapproved locales edition - - - have approved locales edition - have approved locales edition - - - have added locales edition - have added locales edition - - - have removed star from torrent - have removed star from torrent - - - have added star for torrent - have added star for torrent - - - have deleted sensitive edition - have deleted sensitive edition - - - have disapproved sensitive edition - have disapproved sensitive edition - - - have approved sensitive edition - have approved sensitive edition - - - have added sensitive edition - have added sensitive edition - - - have disabled - have disabled - - - have disabled user - have disabled user - - - have enabled - have enabled - - - have enabled user - have enabled user - - - have disapproved - have disapproved - - - have disapproved user - have disapproved user - - - have approved - have approved - - - have approved user - have approved user - - - have joined - have joined - - - have removed moderator permissions from - have removed moderator permissions from - - - have removed moderator permissions from user - have removed moderator permissions from user - - - have granted moderator permissions to - have granted moderator permissions to - - - have granted moderator permissions to user - have granted moderator permissions to user - - - have removed star from - have removed star from - - - have removed star from user - have removed star from user - - - have added star for - have added star for - - - have added star for user - have added star for user - - - Error - Error - - - Oops! - Oops! - - - Internal server error - Internal server error - - - Report - Report - - - Not found - Not found - - - Page not found! - Page not found! - - - BitTorrent protocol version 2 - BitTorrent protocol version 2 - - - BitTorrent protocol version 1 - BitTorrent protocol version 1 - - - year ago - year ago - - - month ago - month ago - - - day ago - day ago - - - hour ago - hour ago - - - minute ago - minute ago - - - second ago - second ago - - - years ago - years ago - - - months ago - months ago - - - days ago - days ago - - - hours ago - hours ago - - - minutes ago - minutes ago - - - seconds ago - seconds ago - - - years ago - years ago - - - months ago - months ago - - - days ago - days ago - - - hours ago - hours ago - - - minutes ago - minutes ago - - - seconds ago - seconds ago - - - Search results - Search results - - - <a href="%s">Upload</a> any torrent - download with Yggdrasil - Upload any torrent - download with Yggdrasil]]> - - - Wanted - Wanted - - - Seeders wanted for torrent - Seeders wanted for torrent - - - Hide - Hide - - - have disabled torrent - have disabled torrent - - - have enabled torrent - have enabled torrent - - - disabled - disabled - - - Poster file out of size limit - Poster file out of size limit - - - Image file not supported - Image file not supported - - - Poster file required - Poster file required - - - Edit torrent poster - Edit torrent poster - - - Edit poster for torrent - Edit poster for torrent - - - Poster - Poster - - - Posters - Posters - - - have deleted poster edition - have deleted poster edition - - - have disapproved poster edition - have disapproved poster edition - - - have approved poster edition - have approved poster edition - - - have added poster edition - have added poster edition - - - Torrent posters - Torrent posters - - - Center - Center - - - Top - Top - - - Bottom - Bottom - - - Categories - Categories - - - At least one category required - At least one category required - - - Content category - Content category - - - This torrent have selected categories - This torrent have selected categories - - - Edit categories - Edit categories - - - Edit categories for torrent - Edit categories for torrent - - - Locale - Locale - - - Category - Category - - - Torrent categories - Torrent categories - - - have deleted categories edition - have deleted categories edition - - - have disapproved categories edition - have disapproved categories edition - - - have approved categories edition - have approved categories edition - - - have added categories edition - have added categories edition - - - movie - movie - - - series - series - - - tv - tv - - - animation - animation - - - music - music - - - game - game - - - audiobook - audiobook - - - podcast - podcast - - - book - book - - - archive - archive - - - picture - picture - - - software - software - - - other - other - - - Hide filter - Hide filter - - - Show filter - Show filter - - - Private - Private - - -
-
diff --git a/translations/messages+intl-icu.eo.xlf b/translations/messages+intl-icu.eo.xlf deleted file mode 100644 index 5e611d1..0000000 --- a/translations/messages+intl-icu.eo.xlf +++ /dev/null @@ -1,918 +0,0 @@ - - - -
- -
- - - Users - Users - - - Joined - Joined - - - Approved - Approved - - - Disapproved - Disapproved - - - User statuses - User statuses - - - Enabled - Enabled - - - Disabled - Disabled - - - User moderators - User moderators - - - Added - Added - - - Removed - Removed - - - User stars - User stars - - - Torrents - Torrents - - - Torrent locales - Torrent locales - - - Deleted - Deleted - - - Torrent sensitive - Torrent sensitive - - - Torrent stars - Torrent stars - - - Torrent downloads - Torrent downloads - - - Files - Files - - - Magnet links - Magnet links - - - Access denied - Access denied - - - At least one locale required - At least one locale required - - - Torrent file out of size limit - Torrent file out of size limit - - - Torrent file already exists - Torrent file already exists - - - Could not parse torrent file - Could not parse torrent file - - - Torrent file required - Torrent file required - - - B - B - - - Kb - Kb - - - Mb - Mb - - - Gb - Gb - - - Tb - Tb - - - Pb - Pb - - - Eb - Eb - - - Zb - Zb - - - Yb - Yb - - - now - now - - - Keyword, file, hash... - Keyword, file, hash... - - - Search - Search - - - Recent uploads - Recent uploads - - - Active leechers waiting for seeders - Active leechers waiting for seeders - - - wanted - wanted - - - Waiting for approve - Waiting for approve - - - Size - Size - - - Seeders - Seeders - - - Peers - Peers - - - Leechers - Leechers - - - Open magnet link - Open magnet link - - - Total - Total - - - Download torrent file - Download torrent file - - - Star - Star - - - Nothing found - Nothing found - - - * share new torrent file to change it - * share new torrent file to change it - - - Submit - Submit - - - Submit torrent - Submit torrent - - - Content language - Content language - - - This torrent contains selected languages - This torrent contains selected languages - - - Sensitive - Sensitive - - - Mark torrent content as sensitive - Mark torrent content as sensitive - - - Edit locales - Edit locales - - - Torrent - Torrent - - - Edit locales for torrent - Edit locales for torrent - - - cancel - cancel - - - by - by - - - identicon - identicon - - - Delete - Delete - - - Disapprove - Disapprove - - - Approve - Approve - - - Edit sensitive status - Edit sensitive status - - - Edit sensitive status for torrent - Edit sensitive status for torrent - - - Page - Page - - - Moderation - Moderation - - - Yes - Yes - - - Toggle - Toggle - - - No - No - - - Common - Common - - - ID - ID - - - MD5 - MD5 - - - Info hash v1 - Info hash v1 - - - Info hash v2 - Info hash v2 - - - Created - Created - - - Pieces - Pieces - - - Source - Source - - - Software - Software - - - Comment - Comment - - - Contributors - Contributors - - - Scrape - Scrape - - - Trackers - Trackers - - - Filtered by settings - Filtered by settings - - - Edit - Edit - - - Locales - Locales - - - Recent activity - Recent activity - - - Back - Back - - - Next - Next - - - Settings - Settings - - - Interface - Interface - - - Theme - Theme - - - Language - Language - - - Join translation - Join translation - - - Activity - Activity - - - Downloads - Downloads - - - Yggdrasil only - Yggdrasil only - - - Save - Save - - - Home - Home - - - Profile - Profile - - - User - User - - - Bookmark - Bookmark - - - Address - Address - - - Address hidden for others - Address hidden for others - - - Access - Access - - - Status - Status - - - Active - Active - - - Moderator - Moderator - - - Languages - Languages - - - Events subscribed - Events subscribed - - - undefined event - undefined event - - - have downloaded torrent file - have downloaded torrent file - - - waiting for approve - waiting for approve - - - sensitive - sensitive - - - have downloaded magnet link - have downloaded magnet link - - - have disapproved torrent - have disapproved torrent - - - have approved torrent - have approved torrent - - - have added torrent - have added torrent - - - have deleted locales edition - have deleted locales edition - - - for torrent - for torrent - - - have disapproved locales edition - have disapproved locales edition - - - have approved locales edition - have approved locales edition - - - have added locales edition - have added locales edition - - - have removed star from torrent - have removed star from torrent - - - have added star for torrent - have added star for torrent - - - have deleted sensitive edition - have deleted sensitive edition - - - have disapproved sensitive edition - have disapproved sensitive edition - - - have approved sensitive edition - have approved sensitive edition - - - have added sensitive edition - have added sensitive edition - - - have disabled - have disabled - - - have disabled user - have disabled user - - - have enabled - have enabled - - - have enabled user - have enabled user - - - have disapproved - have disapproved - - - have disapproved user - have disapproved user - - - have approved - have approved - - - have approved user - have approved user - - - have joined - have joined - - - have removed moderator permissions from - have removed moderator permissions from - - - have removed moderator permissions from user - have removed moderator permissions from user - - - have granted moderator permissions to - have granted moderator permissions to - - - have granted moderator permissions to user - have granted moderator permissions to user - - - have removed star from - have removed star from - - - have removed star from user - have removed star from user - - - have added star for - have added star for - - - have added star for user - have added star for user - - - Error - Error - - - Oops! - Oops! - - - Internal server error - Internal server error - - - Report - Report - - - Not found - Not found - - - Page not found! - Page not found! - - - BitTorrent protocol version 2 - BitTorrent protocol version 2 - - - BitTorrent protocol version 1 - BitTorrent protocol version 1 - - - year ago - year ago - - - month ago - month ago - - - day ago - day ago - - - hour ago - hour ago - - - minute ago - minute ago - - - second ago - second ago - - - years ago - years ago - - - months ago - months ago - - - days ago - days ago - - - hours ago - hours ago - - - minutes ago - minutes ago - - - seconds ago - seconds ago - - - years ago - years ago - - - months ago - months ago - - - days ago - days ago - - - hours ago - hours ago - - - minutes ago - minutes ago - - - seconds ago - seconds ago - - - Search results - Search results - - - <a href="%s">Upload</a> any torrent - download with Yggdrasil - Upload any torrent - download with Yggdrasil]]> - - - Wanted - Wanted - - - Seeders wanted for torrent - Seeders wanted for torrent - - - Hide - Hide - - - have disabled torrent - have disabled torrent - - - have enabled torrent - have enabled torrent - - - disabled - disabled - - - Poster file out of size limit - Poster file out of size limit - - - Image file not supported - Image file not supported - - - Poster file required - Poster file required - - - Edit torrent poster - Edit torrent poster - - - Edit poster for torrent - Edit poster for torrent - - - Poster - Poster - - - Posters - Posters - - - have deleted poster edition - have deleted poster edition - - - have disapproved poster edition - have disapproved poster edition - - - have approved poster edition - have approved poster edition - - - have added poster edition - have added poster edition - - - Torrent posters - Torrent posters - - - Center - Center - - - Top - Top - - - Bottom - Bottom - - - Categories - Categories - - - At least one category required - At least one category required - - - Content category - Content category - - - This torrent have selected categories - This torrent have selected categories - - - Edit categories - Edit categories - - - Edit categories for torrent - Edit categories for torrent - - - Locale - Locale - - - Category - Category - - - Torrent categories - Torrent categories - - - have deleted categories edition - have deleted categories edition - - - have disapproved categories edition - have disapproved categories edition - - - have approved categories edition - have approved categories edition - - - have added categories edition - have added categories edition - - - movie - movie - - - series - series - - - tv - tv - - - animation - animation - - - music - music - - - game - game - - - audiobook - audiobook - - - podcast - podcast - - - book - book - - - archive - archive - - - picture - picture - - - software - software - - - other - other - - - Hide filter - Hide filter - - - Show filter - Show filter - - - Private - Private - - -
-
diff --git a/translations/messages+intl-icu.es.xlf b/translations/messages+intl-icu.es.xlf deleted file mode 100644 index 9638ae5..0000000 --- a/translations/messages+intl-icu.es.xlf +++ /dev/null @@ -1,918 +0,0 @@ - - - -
- -
- - - Users - Users - - - Joined - Joined - - - Approved - Approved - - - Disapproved - Disapproved - - - User statuses - User statuses - - - Enabled - Enabled - - - Disabled - Disabled - - - User moderators - User moderators - - - Added - Added - - - Removed - Removed - - - User stars - User stars - - - Torrents - Torrents - - - Torrent locales - Torrent locales - - - Deleted - Deleted - - - Torrent sensitive - Torrent sensitive - - - Torrent stars - Torrent stars - - - Torrent downloads - Torrent downloads - - - Files - Files - - - Magnet links - Magnet links - - - Access denied - Access denied - - - At least one locale required - At least one locale required - - - Torrent file out of size limit - Torrent file out of size limit - - - Torrent file already exists - Torrent file already exists - - - Could not parse torrent file - Could not parse torrent file - - - Torrent file required - Torrent file required - - - B - B - - - Kb - Kb - - - Mb - Mb - - - Gb - Gb - - - Tb - Tb - - - Pb - Pb - - - Eb - Eb - - - Zb - Zb - - - Yb - Yb - - - now - now - - - Keyword, file, hash... - Keyword, file, hash... - - - Search - Search - - - Recent uploads - Recent uploads - - - Active leechers waiting for seeders - Active leechers waiting for seeders - - - wanted - wanted - - - Waiting for approve - Waiting for approve - - - Size - Size - - - Seeders - Seeders - - - Peers - Peers - - - Leechers - Leechers - - - Open magnet link - Open magnet link - - - Total - Total - - - Download torrent file - Download torrent file - - - Star - Star - - - Nothing found - Nothing found - - - * share new torrent file to change it - * share new torrent file to change it - - - Submit - Submit - - - Submit torrent - Submit torrent - - - Content language - Content language - - - This torrent contains selected languages - This torrent contains selected languages - - - Sensitive - Sensitive - - - Mark torrent content as sensitive - Mark torrent content as sensitive - - - Edit locales - Edit locales - - - Torrent - Torrent - - - Edit locales for torrent - Edit locales for torrent - - - cancel - cancel - - - by - by - - - identicon - identicon - - - Delete - Delete - - - Disapprove - Disapprove - - - Approve - Approve - - - Edit sensitive status - Edit sensitive status - - - Edit sensitive status for torrent - Edit sensitive status for torrent - - - Page - Page - - - Moderation - Moderation - - - Yes - Yes - - - Toggle - Toggle - - - No - No - - - Common - Common - - - ID - ID - - - MD5 - MD5 - - - Info hash v1 - Info hash v1 - - - Info hash v2 - Info hash v2 - - - Created - Created - - - Pieces - Pieces - - - Source - Source - - - Software - Software - - - Comment - Comment - - - Contributors - Contributors - - - Scrape - Scrape - - - Trackers - Trackers - - - Filtered by settings - Filtered by settings - - - Edit - Edit - - - Locales - Locales - - - Recent activity - Recent activity - - - Back - Back - - - Next - Next - - - Settings - Settings - - - Interface - Interface - - - Theme - Theme - - - Language - Language - - - Join translation - Join translation - - - Activity - Activity - - - Downloads - Downloads - - - Yggdrasil only - Yggdrasil only - - - Save - Save - - - Home - Home - - - Profile - Profile - - - User - User - - - Bookmark - Bookmark - - - Address - Address - - - Address hidden for others - Address hidden for others - - - Access - Access - - - Status - Status - - - Active - Active - - - Moderator - Moderator - - - Languages - Languages - - - Events subscribed - Events subscribed - - - undefined event - undefined event - - - have downloaded torrent file - have downloaded torrent file - - - waiting for approve - waiting for approve - - - sensitive - sensitive - - - have downloaded magnet link - have downloaded magnet link - - - have disapproved torrent - have disapproved torrent - - - have approved torrent - have approved torrent - - - have added torrent - have added torrent - - - have deleted locales edition - have deleted locales edition - - - for torrent - for torrent - - - have disapproved locales edition - have disapproved locales edition - - - have approved locales edition - have approved locales edition - - - have added locales edition - have added locales edition - - - have removed star from torrent - have removed star from torrent - - - have added star for torrent - have added star for torrent - - - have deleted sensitive edition - have deleted sensitive edition - - - have disapproved sensitive edition - have disapproved sensitive edition - - - have approved sensitive edition - have approved sensitive edition - - - have added sensitive edition - have added sensitive edition - - - have disabled - have disabled - - - have disabled user - have disabled user - - - have enabled - have enabled - - - have enabled user - have enabled user - - - have disapproved - have disapproved - - - have disapproved user - have disapproved user - - - have approved - have approved - - - have approved user - have approved user - - - have joined - have joined - - - have removed moderator permissions from - have removed moderator permissions from - - - have removed moderator permissions from user - have removed moderator permissions from user - - - have granted moderator permissions to - have granted moderator permissions to - - - have granted moderator permissions to user - have granted moderator permissions to user - - - have removed star from - have removed star from - - - have removed star from user - have removed star from user - - - have added star for - have added star for - - - have added star for user - have added star for user - - - Error - Error - - - Oops! - Oops! - - - Internal server error - Internal server error - - - Report - Report - - - Not found - Not found - - - Page not found! - Page not found! - - - BitTorrent protocol version 2 - BitTorrent protocol version 2 - - - BitTorrent protocol version 1 - BitTorrent protocol version 1 - - - year ago - year ago - - - month ago - month ago - - - day ago - day ago - - - hour ago - hour ago - - - minute ago - minute ago - - - second ago - second ago - - - years ago - years ago - - - months ago - months ago - - - days ago - days ago - - - hours ago - hours ago - - - minutes ago - minutes ago - - - seconds ago - seconds ago - - - years ago - years ago - - - months ago - months ago - - - days ago - days ago - - - hours ago - hours ago - - - minutes ago - minutes ago - - - seconds ago - seconds ago - - - Search results - Search results - - - <a href="%s">Upload</a> any torrent - download with Yggdrasil - Upload any torrent - download with Yggdrasil]]> - - - Wanted - Wanted - - - Seeders wanted for torrent - Seeders wanted for torrent - - - Hide - Hide - - - have disabled torrent - have disabled torrent - - - have enabled torrent - have enabled torrent - - - disabled - disabled - - - Poster file out of size limit - Poster file out of size limit - - - Image file not supported - Image file not supported - - - Poster file required - Poster file required - - - Edit torrent poster - Edit torrent poster - - - Edit poster for torrent - Edit poster for torrent - - - Poster - Poster - - - Posters - Posters - - - have deleted poster edition - have deleted poster edition - - - have disapproved poster edition - have disapproved poster edition - - - have approved poster edition - have approved poster edition - - - have added poster edition - have added poster edition - - - Torrent posters - Torrent posters - - - Center - Center - - - Top - Top - - - Bottom - Bottom - - - Categories - Categories - - - At least one category required - At least one category required - - - Content category - Content category - - - This torrent have selected categories - This torrent have selected categories - - - Edit categories - Edit categories - - - Edit categories for torrent - Edit categories for torrent - - - Locale - Locale - - - Category - Category - - - Torrent categories - Torrent categories - - - have deleted categories edition - have deleted categories edition - - - have disapproved categories edition - have disapproved categories edition - - - have approved categories edition - have approved categories edition - - - have added categories edition - have added categories edition - - - movie - movie - - - series - series - - - tv - tv - - - animation - animation - - - music - music - - - game - game - - - audiobook - audiobook - - - podcast - podcast - - - book - book - - - archive - archive - - - picture - picture - - - software - software - - - other - other - - - Hide filter - Hide filter - - - Show filter - Show filter - - - Private - Private - - -
-
diff --git a/translations/messages+intl-icu.fr.xlf b/translations/messages+intl-icu.fr.xlf deleted file mode 100644 index daae954..0000000 --- a/translations/messages+intl-icu.fr.xlf +++ /dev/null @@ -1,918 +0,0 @@ - - - -
- -
- - - Users - Users - - - Joined - Joined - - - Approved - Approved - - - Disapproved - Disapproved - - - User statuses - User statuses - - - Enabled - Enabled - - - Disabled - Disabled - - - User moderators - User moderators - - - Added - Added - - - Removed - Removed - - - User stars - User stars - - - Torrents - Torrents - - - Torrent locales - Torrent locales - - - Deleted - Deleted - - - Torrent sensitive - Torrent sensitive - - - Torrent stars - Torrent stars - - - Torrent downloads - Torrent downloads - - - Files - Files - - - Magnet links - Magnet links - - - Access denied - Access denied - - - At least one locale required - At least one locale required - - - Torrent file out of size limit - Torrent file out of size limit - - - Torrent file already exists - Torrent file already exists - - - Could not parse torrent file - Could not parse torrent file - - - Torrent file required - Torrent file required - - - B - B - - - Kb - Kb - - - Mb - Mb - - - Gb - Gb - - - Tb - Tb - - - Pb - Pb - - - Eb - Eb - - - Zb - Zb - - - Yb - Yb - - - now - now - - - Keyword, file, hash... - Keyword, file, hash... - - - Search - Search - - - Recent uploads - Recent uploads - - - Active leechers waiting for seeders - Active leechers waiting for seeders - - - wanted - wanted - - - Waiting for approve - Waiting for approve - - - Size - Size - - - Seeders - Seeders - - - Peers - Peers - - - Leechers - Leechers - - - Open magnet link - Open magnet link - - - Total - Total - - - Download torrent file - Download torrent file - - - Star - Star - - - Nothing found - Nothing found - - - * share new torrent file to change it - * share new torrent file to change it - - - Submit - Submit - - - Submit torrent - Submit torrent - - - Content language - Content language - - - This torrent contains selected languages - This torrent contains selected languages - - - Sensitive - Sensitive - - - Mark torrent content as sensitive - Mark torrent content as sensitive - - - Edit locales - Edit locales - - - Torrent - Torrent - - - Edit locales for torrent - Edit locales for torrent - - - cancel - cancel - - - by - by - - - identicon - identicon - - - Delete - Delete - - - Disapprove - Disapprove - - - Approve - Approve - - - Edit sensitive status - Edit sensitive status - - - Edit sensitive status for torrent - Edit sensitive status for torrent - - - Page - Page - - - Moderation - Moderation - - - Yes - Yes - - - Toggle - Toggle - - - No - No - - - Common - Common - - - ID - ID - - - MD5 - MD5 - - - Info hash v1 - Info hash v1 - - - Info hash v2 - Info hash v2 - - - Created - Created - - - Pieces - Pieces - - - Source - Source - - - Software - Software - - - Comment - Comment - - - Contributors - Contributors - - - Scrape - Scrape - - - Trackers - Trackers - - - Filtered by settings - Filtered by settings - - - Edit - Edit - - - Locales - Locales - - - Recent activity - Recent activity - - - Back - Back - - - Next - Next - - - Settings - Settings - - - Interface - Interface - - - Theme - Theme - - - Language - Language - - - Join translation - Join translation - - - Activity - Activity - - - Downloads - Downloads - - - Yggdrasil only - Yggdrasil only - - - Save - Save - - - Home - Home - - - Profile - Profile - - - User - User - - - Bookmark - Bookmark - - - Address - Address - - - Address hidden for others - Address hidden for others - - - Access - Access - - - Status - Status - - - Active - Active - - - Moderator - Moderator - - - Languages - Languages - - - Events subscribed - Events subscribed - - - undefined event - undefined event - - - have downloaded torrent file - have downloaded torrent file - - - waiting for approve - waiting for approve - - - sensitive - sensitive - - - have downloaded magnet link - have downloaded magnet link - - - have disapproved torrent - have disapproved torrent - - - have approved torrent - have approved torrent - - - have added torrent - have added torrent - - - have deleted locales edition - have deleted locales edition - - - for torrent - for torrent - - - have disapproved locales edition - have disapproved locales edition - - - have approved locales edition - have approved locales edition - - - have added locales edition - have added locales edition - - - have removed star from torrent - have removed star from torrent - - - have added star for torrent - have added star for torrent - - - have deleted sensitive edition - have deleted sensitive edition - - - have disapproved sensitive edition - have disapproved sensitive edition - - - have approved sensitive edition - have approved sensitive edition - - - have added sensitive edition - have added sensitive edition - - - have disabled - have disabled - - - have disabled user - have disabled user - - - have enabled - have enabled - - - have enabled user - have enabled user - - - have disapproved - have disapproved - - - have disapproved user - have disapproved user - - - have approved - have approved - - - have approved user - have approved user - - - have joined - have joined - - - have removed moderator permissions from - have removed moderator permissions from - - - have removed moderator permissions from user - have removed moderator permissions from user - - - have granted moderator permissions to - have granted moderator permissions to - - - have granted moderator permissions to user - have granted moderator permissions to user - - - have removed star from - have removed star from - - - have removed star from user - have removed star from user - - - have added star for - have added star for - - - have added star for user - have added star for user - - - Error - Error - - - Oops! - Oops! - - - Internal server error - Internal server error - - - Report - Report - - - Not found - Not found - - - Page not found! - Page not found! - - - BitTorrent protocol version 2 - BitTorrent protocol version 2 - - - BitTorrent protocol version 1 - BitTorrent protocol version 1 - - - year ago - year ago - - - month ago - month ago - - - day ago - day ago - - - hour ago - hour ago - - - minute ago - minute ago - - - second ago - second ago - - - years ago - years ago - - - months ago - months ago - - - days ago - days ago - - - hours ago - hours ago - - - minutes ago - minutes ago - - - seconds ago - seconds ago - - - years ago - years ago - - - months ago - months ago - - - days ago - days ago - - - hours ago - hours ago - - - minutes ago - minutes ago - - - seconds ago - seconds ago - - - Search results - Search results - - - <a href="%s">Upload</a> any torrent - download with Yggdrasil - Upload any torrent - download with Yggdrasil]]> - - - Wanted - Wanted - - - Seeders wanted for torrent - Seeders wanted for torrent - - - Hide - Hide - - - have disabled torrent - have disabled torrent - - - have enabled torrent - have enabled torrent - - - disabled - disabled - - - Poster file out of size limit - Poster file out of size limit - - - Image file not supported - Image file not supported - - - Poster file required - Poster file required - - - Edit torrent poster - Edit torrent poster - - - Edit poster for torrent - Edit poster for torrent - - - Poster - Poster - - - Posters - Posters - - - have deleted poster edition - have deleted poster edition - - - have disapproved poster edition - have disapproved poster edition - - - have approved poster edition - have approved poster edition - - - have added poster edition - have added poster edition - - - Torrent posters - Torrent posters - - - Center - Center - - - Top - Top - - - Bottom - Bottom - - - Categories - Categories - - - At least one category required - At least one category required - - - Content category - Content category - - - This torrent have selected categories - This torrent have selected categories - - - Edit categories - Edit categories - - - Edit categories for torrent - Edit categories for torrent - - - Locale - Locale - - - Category - Category - - - Torrent categories - Torrent categories - - - have deleted categories edition - have deleted categories edition - - - have disapproved categories edition - have disapproved categories edition - - - have approved categories edition - have approved categories edition - - - have added categories edition - have added categories edition - - - movie - movie - - - series - series - - - tv - tv - - - animation - animation - - - music - music - - - game - game - - - audiobook - audiobook - - - podcast - podcast - - - book - book - - - archive - archive - - - picture - picture - - - software - software - - - other - other - - - Hide filter - Hide filter - - - Show filter - Show filter - - - Private - Private - - -
-
diff --git a/translations/messages+intl-icu.he.xlf b/translations/messages+intl-icu.he.xlf deleted file mode 100644 index a324b84..0000000 --- a/translations/messages+intl-icu.he.xlf +++ /dev/null @@ -1,918 +0,0 @@ - - - -
- -
- - - Users - Users - - - Joined - Joined - - - Approved - Approved - - - Disapproved - Disapproved - - - User statuses - User statuses - - - Enabled - Enabled - - - Disabled - Disabled - - - User moderators - User moderators - - - Added - Added - - - Removed - Removed - - - User stars - User stars - - - Torrents - Torrents - - - Torrent locales - Torrent locales - - - Deleted - Deleted - - - Torrent sensitive - Torrent sensitive - - - Torrent stars - Torrent stars - - - Torrent downloads - Torrent downloads - - - Files - Files - - - Magnet links - Magnet links - - - Access denied - Access denied - - - At least one locale required - At least one locale required - - - Torrent file out of size limit - Torrent file out of size limit - - - Torrent file already exists - Torrent file already exists - - - Could not parse torrent file - Could not parse torrent file - - - Torrent file required - Torrent file required - - - B - B - - - Kb - Kb - - - Mb - Mb - - - Gb - Gb - - - Tb - Tb - - - Pb - Pb - - - Eb - Eb - - - Zb - Zb - - - Yb - Yb - - - now - now - - - Keyword, file, hash... - Keyword, file, hash... - - - Search - Search - - - Recent uploads - Recent uploads - - - Active leechers waiting for seeders - Active leechers waiting for seeders - - - wanted - wanted - - - Waiting for approve - Waiting for approve - - - Size - Size - - - Seeders - Seeders - - - Peers - Peers - - - Leechers - Leechers - - - Open magnet link - Open magnet link - - - Total - Total - - - Download torrent file - Download torrent file - - - Star - Star - - - Nothing found - Nothing found - - - * share new torrent file to change it - * share new torrent file to change it - - - Submit - Submit - - - Submit torrent - Submit torrent - - - Content language - Content language - - - This torrent contains selected languages - This torrent contains selected languages - - - Sensitive - Sensitive - - - Mark torrent content as sensitive - Mark torrent content as sensitive - - - Edit locales - Edit locales - - - Torrent - Torrent - - - Edit locales for torrent - Edit locales for torrent - - - cancel - cancel - - - by - by - - - identicon - identicon - - - Delete - Delete - - - Disapprove - Disapprove - - - Approve - Approve - - - Edit sensitive status - Edit sensitive status - - - Edit sensitive status for torrent - Edit sensitive status for torrent - - - Page - Page - - - Moderation - Moderation - - - Yes - Yes - - - Toggle - Toggle - - - No - No - - - Common - Common - - - ID - ID - - - MD5 - MD5 - - - Info hash v1 - Info hash v1 - - - Info hash v2 - Info hash v2 - - - Created - Created - - - Pieces - Pieces - - - Source - Source - - - Software - Software - - - Comment - Comment - - - Contributors - Contributors - - - Scrape - Scrape - - - Trackers - Trackers - - - Filtered by settings - Filtered by settings - - - Edit - Edit - - - Locales - Locales - - - Recent activity - Recent activity - - - Back - Back - - - Next - Next - - - Settings - Settings - - - Interface - Interface - - - Theme - Theme - - - Language - Language - - - Join translation - Join translation - - - Activity - Activity - - - Downloads - Downloads - - - Yggdrasil only - Yggdrasil only - - - Save - Save - - - Home - Home - - - Profile - Profile - - - User - User - - - Bookmark - Bookmark - - - Address - Address - - - Address hidden for others - Address hidden for others - - - Access - Access - - - Status - Status - - - Active - Active - - - Moderator - Moderator - - - Languages - Languages - - - Events subscribed - Events subscribed - - - undefined event - undefined event - - - have downloaded torrent file - have downloaded torrent file - - - waiting for approve - waiting for approve - - - sensitive - sensitive - - - have downloaded magnet link - have downloaded magnet link - - - have disapproved torrent - have disapproved torrent - - - have approved torrent - have approved torrent - - - have added torrent - have added torrent - - - have deleted locales edition - have deleted locales edition - - - for torrent - for torrent - - - have disapproved locales edition - have disapproved locales edition - - - have approved locales edition - have approved locales edition - - - have added locales edition - have added locales edition - - - have removed star from torrent - have removed star from torrent - - - have added star for torrent - have added star for torrent - - - have deleted sensitive edition - have deleted sensitive edition - - - have disapproved sensitive edition - have disapproved sensitive edition - - - have approved sensitive edition - have approved sensitive edition - - - have added sensitive edition - have added sensitive edition - - - have disabled - have disabled - - - have disabled user - have disabled user - - - have enabled - have enabled - - - have enabled user - have enabled user - - - have disapproved - have disapproved - - - have disapproved user - have disapproved user - - - have approved - have approved - - - have approved user - have approved user - - - have joined - have joined - - - have removed moderator permissions from - have removed moderator permissions from - - - have removed moderator permissions from user - have removed moderator permissions from user - - - have granted moderator permissions to - have granted moderator permissions to - - - have granted moderator permissions to user - have granted moderator permissions to user - - - have removed star from - have removed star from - - - have removed star from user - have removed star from user - - - have added star for - have added star for - - - have added star for user - have added star for user - - - Error - Error - - - Oops! - Oops! - - - Internal server error - Internal server error - - - Report - Report - - - Not found - Not found - - - Page not found! - Page not found! - - - BitTorrent protocol version 2 - BitTorrent protocol version 2 - - - BitTorrent protocol version 1 - BitTorrent protocol version 1 - - - year ago - year ago - - - month ago - month ago - - - day ago - day ago - - - hour ago - hour ago - - - minute ago - minute ago - - - second ago - second ago - - - years ago - years ago - - - months ago - months ago - - - days ago - days ago - - - hours ago - hours ago - - - minutes ago - minutes ago - - - seconds ago - seconds ago - - - years ago - years ago - - - months ago - months ago - - - days ago - days ago - - - hours ago - hours ago - - - minutes ago - minutes ago - - - seconds ago - seconds ago - - - Search results - Search results - - - <a href="%s">Upload</a> any torrent - download with Yggdrasil - Upload any torrent - download with Yggdrasil]]> - - - Wanted - Wanted - - - Seeders wanted for torrent - Seeders wanted for torrent - - - Hide - Hide - - - have disabled torrent - have disabled torrent - - - have enabled torrent - have enabled torrent - - - disabled - disabled - - - Poster file out of size limit - Poster file out of size limit - - - Image file not supported - Image file not supported - - - Poster file required - Poster file required - - - Edit torrent poster - Edit torrent poster - - - Edit poster for torrent - Edit poster for torrent - - - Poster - Poster - - - Posters - Posters - - - have deleted poster edition - have deleted poster edition - - - have disapproved poster edition - have disapproved poster edition - - - have approved poster edition - have approved poster edition - - - have added poster edition - have added poster edition - - - Torrent posters - Torrent posters - - - Center - Center - - - Top - Top - - - Bottom - Bottom - - - Categories - Categories - - - At least one category required - At least one category required - - - Content category - Content category - - - This torrent have selected categories - This torrent have selected categories - - - Edit categories - Edit categories - - - Edit categories for torrent - Edit categories for torrent - - - Locale - Locale - - - Category - Category - - - Torrent categories - Torrent categories - - - have deleted categories edition - have deleted categories edition - - - have disapproved categories edition - have disapproved categories edition - - - have approved categories edition - have approved categories edition - - - have added categories edition - have added categories edition - - - movie - movie - - - series - series - - - tv - tv - - - animation - animation - - - music - music - - - game - game - - - audiobook - audiobook - - - podcast - podcast - - - book - book - - - archive - archive - - - picture - picture - - - software - software - - - other - other - - - Hide filter - Hide filter - - - Show filter - Show filter - - - Private - Private - - -
-
diff --git a/translations/messages+intl-icu.it.xlf b/translations/messages+intl-icu.it.xlf deleted file mode 100644 index e31236c..0000000 --- a/translations/messages+intl-icu.it.xlf +++ /dev/null @@ -1,918 +0,0 @@ - - - -
- -
- - - Users - Users - - - Joined - Joined - - - Approved - Approved - - - Disapproved - Disapproved - - - User statuses - User statuses - - - Enabled - Enabled - - - Disabled - Disabled - - - User moderators - User moderators - - - Added - Added - - - Removed - Removed - - - User stars - User stars - - - Torrents - Torrents - - - Torrent locales - Torrent locales - - - Deleted - Deleted - - - Torrent sensitive - Torrent sensitive - - - Torrent stars - Torrent stars - - - Torrent downloads - Torrent downloads - - - Files - Files - - - Magnet links - Magnet links - - - Access denied - Access denied - - - At least one locale required - At least one locale required - - - Torrent file out of size limit - Torrent file out of size limit - - - Torrent file already exists - Torrent file already exists - - - Could not parse torrent file - Could not parse torrent file - - - Torrent file required - Torrent file required - - - B - B - - - Kb - Kb - - - Mb - Mb - - - Gb - Gb - - - Tb - Tb - - - Pb - Pb - - - Eb - Eb - - - Zb - Zb - - - Yb - Yb - - - now - now - - - Keyword, file, hash... - Keyword, file, hash... - - - Search - Search - - - Recent uploads - Recent uploads - - - Active leechers waiting for seeders - Active leechers waiting for seeders - - - wanted - wanted - - - Waiting for approve - Waiting for approve - - - Size - Size - - - Seeders - Seeders - - - Peers - Peers - - - Leechers - Leechers - - - Open magnet link - Open magnet link - - - Total - Total - - - Download torrent file - Download torrent file - - - Star - Star - - - Nothing found - Nothing found - - - * share new torrent file to change it - * share new torrent file to change it - - - Submit - Submit - - - Submit torrent - Submit torrent - - - Content language - Content language - - - This torrent contains selected languages - This torrent contains selected languages - - - Sensitive - Sensitive - - - Mark torrent content as sensitive - Mark torrent content as sensitive - - - Edit locales - Edit locales - - - Torrent - Torrent - - - Edit locales for torrent - Edit locales for torrent - - - cancel - cancel - - - by - by - - - identicon - identicon - - - Delete - Delete - - - Disapprove - Disapprove - - - Approve - Approve - - - Edit sensitive status - Edit sensitive status - - - Edit sensitive status for torrent - Edit sensitive status for torrent - - - Page - Page - - - Moderation - Moderation - - - Yes - Yes - - - Toggle - Toggle - - - No - No - - - Common - Common - - - ID - ID - - - MD5 - MD5 - - - Info hash v1 - Info hash v1 - - - Info hash v2 - Info hash v2 - - - Created - Created - - - Pieces - Pieces - - - Source - Source - - - Software - Software - - - Comment - Comment - - - Contributors - Contributors - - - Scrape - Scrape - - - Trackers - Trackers - - - Filtered by settings - Filtered by settings - - - Edit - Edit - - - Locales - Locales - - - Recent activity - Recent activity - - - Back - Back - - - Next - Next - - - Settings - Settings - - - Interface - Interface - - - Theme - Theme - - - Language - Language - - - Join translation - Join translation - - - Activity - Activity - - - Downloads - Downloads - - - Yggdrasil only - Yggdrasil only - - - Save - Save - - - Home - Home - - - Profile - Profile - - - User - User - - - Bookmark - Bookmark - - - Address - Address - - - Address hidden for others - Address hidden for others - - - Access - Access - - - Status - Status - - - Active - Active - - - Moderator - Moderator - - - Languages - Languages - - - Events subscribed - Events subscribed - - - undefined event - undefined event - - - have downloaded torrent file - have downloaded torrent file - - - waiting for approve - waiting for approve - - - sensitive - sensitive - - - have downloaded magnet link - have downloaded magnet link - - - have disapproved torrent - have disapproved torrent - - - have approved torrent - have approved torrent - - - have added torrent - have added torrent - - - have deleted locales edition - have deleted locales edition - - - for torrent - for torrent - - - have disapproved locales edition - have disapproved locales edition - - - have approved locales edition - have approved locales edition - - - have added locales edition - have added locales edition - - - have removed star from torrent - have removed star from torrent - - - have added star for torrent - have added star for torrent - - - have deleted sensitive edition - have deleted sensitive edition - - - have disapproved sensitive edition - have disapproved sensitive edition - - - have approved sensitive edition - have approved sensitive edition - - - have added sensitive edition - have added sensitive edition - - - have disabled - have disabled - - - have disabled user - have disabled user - - - have enabled - have enabled - - - have enabled user - have enabled user - - - have disapproved - have disapproved - - - have disapproved user - have disapproved user - - - have approved - have approved - - - have approved user - have approved user - - - have joined - have joined - - - have removed moderator permissions from - have removed moderator permissions from - - - have removed moderator permissions from user - have removed moderator permissions from user - - - have granted moderator permissions to - have granted moderator permissions to - - - have granted moderator permissions to user - have granted moderator permissions to user - - - have removed star from - have removed star from - - - have removed star from user - have removed star from user - - - have added star for - have added star for - - - have added star for user - have added star for user - - - Error - Error - - - Oops! - Oops! - - - Internal server error - Internal server error - - - Report - Report - - - Not found - Not found - - - Page not found! - Page not found! - - - BitTorrent protocol version 2 - BitTorrent protocol version 2 - - - BitTorrent protocol version 1 - BitTorrent protocol version 1 - - - year ago - year ago - - - month ago - month ago - - - day ago - day ago - - - hour ago - hour ago - - - minute ago - minute ago - - - second ago - second ago - - - years ago - years ago - - - months ago - months ago - - - days ago - days ago - - - hours ago - hours ago - - - minutes ago - minutes ago - - - seconds ago - seconds ago - - - years ago - years ago - - - months ago - months ago - - - days ago - days ago - - - hours ago - hours ago - - - minutes ago - minutes ago - - - seconds ago - seconds ago - - - Search results - Search results - - - <a href="%s">Upload</a> any torrent - download with Yggdrasil - Upload any torrent - download with Yggdrasil]]> - - - Wanted - Wanted - - - Seeders wanted for torrent - Seeders wanted for torrent - - - Hide - Hide - - - have disabled torrent - have disabled torrent - - - have enabled torrent - have enabled torrent - - - disabled - disabled - - - Poster file out of size limit - Poster file out of size limit - - - Image file not supported - Image file not supported - - - Poster file required - Poster file required - - - Edit torrent poster - Edit torrent poster - - - Edit poster for torrent - Edit poster for torrent - - - Poster - Poster - - - Posters - Posters - - - have deleted poster edition - have deleted poster edition - - - have disapproved poster edition - have disapproved poster edition - - - have approved poster edition - have approved poster edition - - - have added poster edition - have added poster edition - - - Torrent posters - Torrent posters - - - Center - Center - - - Top - Top - - - Bottom - Bottom - - - Categories - Categories - - - At least one category required - At least one category required - - - Content category - Content category - - - This torrent have selected categories - This torrent have selected categories - - - Edit categories - Edit categories - - - Edit categories for torrent - Edit categories for torrent - - - Locale - Locale - - - Category - Category - - - Torrent categories - Torrent categories - - - have deleted categories edition - have deleted categories edition - - - have disapproved categories edition - have disapproved categories edition - - - have approved categories edition - have approved categories edition - - - have added categories edition - have added categories edition - - - movie - movie - - - series - series - - - tv - tv - - - animation - animation - - - music - music - - - game - game - - - audiobook - audiobook - - - podcast - podcast - - - book - book - - - archive - archive - - - picture - picture - - - software - software - - - other - other - - - Hide filter - Hide filter - - - Show filter - Show filter - - - Private - Private - - -
-
diff --git a/translations/messages+intl-icu.ja.xlf b/translations/messages+intl-icu.ja.xlf deleted file mode 100644 index 56c715b..0000000 --- a/translations/messages+intl-icu.ja.xlf +++ /dev/null @@ -1,918 +0,0 @@ - - - -
- -
- - - Users - Users - - - Joined - Joined - - - Approved - Approved - - - Disapproved - Disapproved - - - User statuses - User statuses - - - Enabled - Enabled - - - Disabled - Disabled - - - User moderators - User moderators - - - Added - Added - - - Removed - Removed - - - User stars - User stars - - - Torrents - Torrents - - - Torrent locales - Torrent locales - - - Deleted - Deleted - - - Torrent sensitive - Torrent sensitive - - - Torrent stars - Torrent stars - - - Torrent downloads - Torrent downloads - - - Files - Files - - - Magnet links - Magnet links - - - Access denied - Access denied - - - At least one locale required - At least one locale required - - - Torrent file out of size limit - Torrent file out of size limit - - - Torrent file already exists - Torrent file already exists - - - Could not parse torrent file - Could not parse torrent file - - - Torrent file required - Torrent file required - - - B - B - - - Kb - Kb - - - Mb - Mb - - - Gb - Gb - - - Tb - Tb - - - Pb - Pb - - - Eb - Eb - - - Zb - Zb - - - Yb - Yb - - - now - now - - - Keyword, file, hash... - Keyword, file, hash... - - - Search - Search - - - Recent uploads - Recent uploads - - - Active leechers waiting for seeders - Active leechers waiting for seeders - - - wanted - wanted - - - Waiting for approve - Waiting for approve - - - Size - Size - - - Seeders - Seeders - - - Peers - Peers - - - Leechers - Leechers - - - Open magnet link - Open magnet link - - - Total - Total - - - Download torrent file - Download torrent file - - - Star - Star - - - Nothing found - Nothing found - - - * share new torrent file to change it - * share new torrent file to change it - - - Submit - Submit - - - Submit torrent - Submit torrent - - - Content language - Content language - - - This torrent contains selected languages - This torrent contains selected languages - - - Sensitive - Sensitive - - - Mark torrent content as sensitive - Mark torrent content as sensitive - - - Edit locales - Edit locales - - - Torrent - Torrent - - - Edit locales for torrent - Edit locales for torrent - - - cancel - cancel - - - by - by - - - identicon - identicon - - - Delete - Delete - - - Disapprove - Disapprove - - - Approve - Approve - - - Edit sensitive status - Edit sensitive status - - - Edit sensitive status for torrent - Edit sensitive status for torrent - - - Page - Page - - - Moderation - Moderation - - - Yes - Yes - - - Toggle - Toggle - - - No - No - - - Common - Common - - - ID - ID - - - MD5 - MD5 - - - Info hash v1 - Info hash v1 - - - Info hash v2 - Info hash v2 - - - Created - Created - - - Pieces - Pieces - - - Source - Source - - - Software - Software - - - Comment - Comment - - - Contributors - Contributors - - - Scrape - Scrape - - - Trackers - Trackers - - - Filtered by settings - Filtered by settings - - - Edit - Edit - - - Locales - Locales - - - Recent activity - Recent activity - - - Back - Back - - - Next - Next - - - Settings - Settings - - - Interface - Interface - - - Theme - Theme - - - Language - Language - - - Join translation - Join translation - - - Activity - Activity - - - Downloads - Downloads - - - Yggdrasil only - Yggdrasil only - - - Save - Save - - - Home - Home - - - Profile - Profile - - - User - User - - - Bookmark - Bookmark - - - Address - Address - - - Address hidden for others - Address hidden for others - - - Access - Access - - - Status - Status - - - Active - Active - - - Moderator - Moderator - - - Languages - Languages - - - Events subscribed - Events subscribed - - - undefined event - undefined event - - - have downloaded torrent file - have downloaded torrent file - - - waiting for approve - waiting for approve - - - sensitive - sensitive - - - have downloaded magnet link - have downloaded magnet link - - - have disapproved torrent - have disapproved torrent - - - have approved torrent - have approved torrent - - - have added torrent - have added torrent - - - have deleted locales edition - have deleted locales edition - - - for torrent - for torrent - - - have disapproved locales edition - have disapproved locales edition - - - have approved locales edition - have approved locales edition - - - have added locales edition - have added locales edition - - - have removed star from torrent - have removed star from torrent - - - have added star for torrent - have added star for torrent - - - have deleted sensitive edition - have deleted sensitive edition - - - have disapproved sensitive edition - have disapproved sensitive edition - - - have approved sensitive edition - have approved sensitive edition - - - have added sensitive edition - have added sensitive edition - - - have disabled - have disabled - - - have disabled user - have disabled user - - - have enabled - have enabled - - - have enabled user - have enabled user - - - have disapproved - have disapproved - - - have disapproved user - have disapproved user - - - have approved - have approved - - - have approved user - have approved user - - - have joined - have joined - - - have removed moderator permissions from - have removed moderator permissions from - - - have removed moderator permissions from user - have removed moderator permissions from user - - - have granted moderator permissions to - have granted moderator permissions to - - - have granted moderator permissions to user - have granted moderator permissions to user - - - have removed star from - have removed star from - - - have removed star from user - have removed star from user - - - have added star for - have added star for - - - have added star for user - have added star for user - - - Error - Error - - - Oops! - Oops! - - - Internal server error - Internal server error - - - Report - Report - - - Not found - Not found - - - Page not found! - Page not found! - - - BitTorrent protocol version 2 - BitTorrent protocol version 2 - - - BitTorrent protocol version 1 - BitTorrent protocol version 1 - - - year ago - year ago - - - month ago - month ago - - - day ago - day ago - - - hour ago - hour ago - - - minute ago - minute ago - - - second ago - second ago - - - years ago - years ago - - - months ago - months ago - - - days ago - days ago - - - hours ago - hours ago - - - minutes ago - minutes ago - - - seconds ago - seconds ago - - - years ago - years ago - - - months ago - months ago - - - days ago - days ago - - - hours ago - hours ago - - - minutes ago - minutes ago - - - seconds ago - seconds ago - - - Search results - Search results - - - <a href="%s">Upload</a> any torrent - download with Yggdrasil - Upload any torrent - download with Yggdrasil]]> - - - Wanted - Wanted - - - Seeders wanted for torrent - Seeders wanted for torrent - - - Hide - Hide - - - have disabled torrent - have disabled torrent - - - have enabled torrent - have enabled torrent - - - disabled - disabled - - - Poster file out of size limit - Poster file out of size limit - - - Image file not supported - Image file not supported - - - Poster file required - Poster file required - - - Edit torrent poster - Edit torrent poster - - - Edit poster for torrent - Edit poster for torrent - - - Poster - Poster - - - Posters - Posters - - - have deleted poster edition - have deleted poster edition - - - have disapproved poster edition - have disapproved poster edition - - - have approved poster edition - have approved poster edition - - - have added poster edition - have added poster edition - - - Torrent posters - Torrent posters - - - Center - Center - - - Top - Top - - - Bottom - Bottom - - - Categories - Categories - - - At least one category required - At least one category required - - - Content category - Content category - - - This torrent have selected categories - This torrent have selected categories - - - Edit categories - Edit categories - - - Edit categories for torrent - Edit categories for torrent - - - Locale - Locale - - - Category - Category - - - Torrent categories - Torrent categories - - - have deleted categories edition - have deleted categories edition - - - have disapproved categories edition - have disapproved categories edition - - - have approved categories edition - have approved categories edition - - - have added categories edition - have added categories edition - - - movie - movie - - - series - series - - - tv - tv - - - animation - animation - - - music - music - - - game - game - - - audiobook - audiobook - - - podcast - podcast - - - book - book - - - archive - archive - - - picture - picture - - - software - software - - - other - other - - - Hide filter - Hide filter - - - Show filter - Show filter - - - Private - Private - - -
-
diff --git a/translations/messages+intl-icu.ka.xlf b/translations/messages+intl-icu.ka.xlf deleted file mode 100644 index 944c10a..0000000 --- a/translations/messages+intl-icu.ka.xlf +++ /dev/null @@ -1,918 +0,0 @@ - - - -
- -
- - - Users - Users - - - Joined - Joined - - - Approved - Approved - - - Disapproved - Disapproved - - - User statuses - User statuses - - - Enabled - Enabled - - - Disabled - Disabled - - - User moderators - User moderators - - - Added - Added - - - Removed - Removed - - - User stars - User stars - - - Torrents - Torrents - - - Torrent locales - Torrent locales - - - Deleted - Deleted - - - Torrent sensitive - Torrent sensitive - - - Torrent stars - Torrent stars - - - Torrent downloads - Torrent downloads - - - Files - Files - - - Magnet links - Magnet links - - - Access denied - Access denied - - - At least one locale required - At least one locale required - - - Torrent file out of size limit - Torrent file out of size limit - - - Torrent file already exists - Torrent file already exists - - - Could not parse torrent file - Could not parse torrent file - - - Torrent file required - Torrent file required - - - B - B - - - Kb - Kb - - - Mb - Mb - - - Gb - Gb - - - Tb - Tb - - - Pb - Pb - - - Eb - Eb - - - Zb - Zb - - - Yb - Yb - - - now - now - - - Keyword, file, hash... - Keyword, file, hash... - - - Search - Search - - - Recent uploads - Recent uploads - - - Active leechers waiting for seeders - Active leechers waiting for seeders - - - wanted - wanted - - - Waiting for approve - Waiting for approve - - - Size - Size - - - Seeders - Seeders - - - Peers - Peers - - - Leechers - Leechers - - - Open magnet link - Open magnet link - - - Total - Total - - - Download torrent file - Download torrent file - - - Star - Star - - - Nothing found - Nothing found - - - * share new torrent file to change it - * share new torrent file to change it - - - Submit - Submit - - - Submit torrent - Submit torrent - - - Content language - Content language - - - This torrent contains selected languages - This torrent contains selected languages - - - Sensitive - Sensitive - - - Mark torrent content as sensitive - Mark torrent content as sensitive - - - Edit locales - Edit locales - - - Torrent - Torrent - - - Edit locales for torrent - Edit locales for torrent - - - cancel - cancel - - - by - by - - - identicon - identicon - - - Delete - Delete - - - Disapprove - Disapprove - - - Approve - Approve - - - Edit sensitive status - Edit sensitive status - - - Edit sensitive status for torrent - Edit sensitive status for torrent - - - Page - Page - - - Moderation - Moderation - - - Yes - Yes - - - Toggle - Toggle - - - No - No - - - Common - Common - - - ID - ID - - - MD5 - MD5 - - - Info hash v1 - Info hash v1 - - - Info hash v2 - Info hash v2 - - - Created - Created - - - Pieces - Pieces - - - Source - Source - - - Software - Software - - - Comment - Comment - - - Contributors - Contributors - - - Scrape - Scrape - - - Trackers - Trackers - - - Filtered by settings - Filtered by settings - - - Edit - Edit - - - Locales - Locales - - - Recent activity - Recent activity - - - Back - Back - - - Next - Next - - - Settings - Settings - - - Interface - Interface - - - Theme - Theme - - - Language - Language - - - Join translation - Join translation - - - Activity - Activity - - - Downloads - Downloads - - - Yggdrasil only - Yggdrasil only - - - Save - Save - - - Home - Home - - - Profile - Profile - - - User - User - - - Bookmark - Bookmark - - - Address - Address - - - Address hidden for others - Address hidden for others - - - Access - Access - - - Status - Status - - - Active - Active - - - Moderator - Moderator - - - Languages - Languages - - - Events subscribed - Events subscribed - - - undefined event - undefined event - - - have downloaded torrent file - have downloaded torrent file - - - waiting for approve - waiting for approve - - - sensitive - sensitive - - - have downloaded magnet link - have downloaded magnet link - - - have disapproved torrent - have disapproved torrent - - - have approved torrent - have approved torrent - - - have added torrent - have added torrent - - - have deleted locales edition - have deleted locales edition - - - for torrent - for torrent - - - have disapproved locales edition - have disapproved locales edition - - - have approved locales edition - have approved locales edition - - - have added locales edition - have added locales edition - - - have removed star from torrent - have removed star from torrent - - - have added star for torrent - have added star for torrent - - - have deleted sensitive edition - have deleted sensitive edition - - - have disapproved sensitive edition - have disapproved sensitive edition - - - have approved sensitive edition - have approved sensitive edition - - - have added sensitive edition - have added sensitive edition - - - have disabled - have disabled - - - have disabled user - have disabled user - - - have enabled - have enabled - - - have enabled user - have enabled user - - - have disapproved - have disapproved - - - have disapproved user - have disapproved user - - - have approved - have approved - - - have approved user - have approved user - - - have joined - have joined - - - have removed moderator permissions from - have removed moderator permissions from - - - have removed moderator permissions from user - have removed moderator permissions from user - - - have granted moderator permissions to - have granted moderator permissions to - - - have granted moderator permissions to user - have granted moderator permissions to user - - - have removed star from - have removed star from - - - have removed star from user - have removed star from user - - - have added star for - have added star for - - - have added star for user - have added star for user - - - Error - Error - - - Oops! - Oops! - - - Internal server error - Internal server error - - - Report - Report - - - Not found - Not found - - - Page not found! - Page not found! - - - BitTorrent protocol version 2 - BitTorrent protocol version 2 - - - BitTorrent protocol version 1 - BitTorrent protocol version 1 - - - year ago - year ago - - - month ago - month ago - - - day ago - day ago - - - hour ago - hour ago - - - minute ago - minute ago - - - second ago - second ago - - - years ago - years ago - - - months ago - months ago - - - days ago - days ago - - - hours ago - hours ago - - - minutes ago - minutes ago - - - seconds ago - seconds ago - - - years ago - years ago - - - months ago - months ago - - - days ago - days ago - - - hours ago - hours ago - - - minutes ago - minutes ago - - - seconds ago - seconds ago - - - Search results - Search results - - - <a href="%s">Upload</a> any torrent - download with Yggdrasil - Upload any torrent - download with Yggdrasil]]> - - - Wanted - Wanted - - - Seeders wanted for torrent - Seeders wanted for torrent - - - Hide - Hide - - - have disabled torrent - have disabled torrent - - - have enabled torrent - have enabled torrent - - - disabled - disabled - - - Poster file out of size limit - Poster file out of size limit - - - Image file not supported - Image file not supported - - - Poster file required - Poster file required - - - Edit torrent poster - Edit torrent poster - - - Edit poster for torrent - Edit poster for torrent - - - Poster - Poster - - - Posters - Posters - - - have deleted poster edition - have deleted poster edition - - - have disapproved poster edition - have disapproved poster edition - - - have approved poster edition - have approved poster edition - - - have added poster edition - have added poster edition - - - Torrent posters - Torrent posters - - - Center - Center - - - Top - Top - - - Bottom - Bottom - - - Categories - Categories - - - At least one category required - At least one category required - - - Content category - Content category - - - This torrent have selected categories - This torrent have selected categories - - - Edit categories - Edit categories - - - Edit categories for torrent - Edit categories for torrent - - - Locale - Locale - - - Category - Category - - - Torrent categories - Torrent categories - - - have deleted categories edition - have deleted categories edition - - - have disapproved categories edition - have disapproved categories edition - - - have approved categories edition - have approved categories edition - - - have added categories edition - have added categories edition - - - movie - movie - - - series - series - - - tv - tv - - - animation - animation - - - music - music - - - game - game - - - audiobook - audiobook - - - podcast - podcast - - - book - book - - - archive - archive - - - picture - picture - - - software - software - - - other - other - - - Hide filter - Hide filter - - - Show filter - Show filter - - - Private - Private - - -
-
diff --git a/translations/messages+intl-icu.lv.xlf b/translations/messages+intl-icu.lv.xlf deleted file mode 100644 index 814cec1..0000000 --- a/translations/messages+intl-icu.lv.xlf +++ /dev/null @@ -1,918 +0,0 @@ - - - -
- -
- - - Users - Users - - - Joined - Joined - - - Approved - Approved - - - Disapproved - Disapproved - - - User statuses - User statuses - - - Enabled - Enabled - - - Disabled - Disabled - - - User moderators - User moderators - - - Added - Added - - - Removed - Removed - - - User stars - User stars - - - Torrents - Torrents - - - Torrent locales - Torrent locales - - - Deleted - Deleted - - - Torrent sensitive - Torrent sensitive - - - Torrent stars - Torrent stars - - - Torrent downloads - Torrent downloads - - - Files - Files - - - Magnet links - Magnet links - - - Access denied - Access denied - - - At least one locale required - At least one locale required - - - Torrent file out of size limit - Torrent file out of size limit - - - Torrent file already exists - Torrent file already exists - - - Could not parse torrent file - Could not parse torrent file - - - Torrent file required - Torrent file required - - - B - B - - - Kb - Kb - - - Mb - Mb - - - Gb - Gb - - - Tb - Tb - - - Pb - Pb - - - Eb - Eb - - - Zb - Zb - - - Yb - Yb - - - now - now - - - Keyword, file, hash... - Keyword, file, hash... - - - Search - Search - - - Recent uploads - Recent uploads - - - Active leechers waiting for seeders - Active leechers waiting for seeders - - - wanted - wanted - - - Waiting for approve - Waiting for approve - - - Size - Size - - - Seeders - Seeders - - - Peers - Peers - - - Leechers - Leechers - - - Open magnet link - Open magnet link - - - Total - Total - - - Download torrent file - Download torrent file - - - Star - Star - - - Nothing found - Nothing found - - - * share new torrent file to change it - * share new torrent file to change it - - - Submit - Submit - - - Submit torrent - Submit torrent - - - Content language - Content language - - - This torrent contains selected languages - This torrent contains selected languages - - - Sensitive - Sensitive - - - Mark torrent content as sensitive - Mark torrent content as sensitive - - - Edit locales - Edit locales - - - Torrent - Torrent - - - Edit locales for torrent - Edit locales for torrent - - - cancel - cancel - - - by - by - - - identicon - identicon - - - Delete - Delete - - - Disapprove - Disapprove - - - Approve - Approve - - - Edit sensitive status - Edit sensitive status - - - Edit sensitive status for torrent - Edit sensitive status for torrent - - - Page - Page - - - Moderation - Moderation - - - Yes - Yes - - - Toggle - Toggle - - - No - No - - - Common - Common - - - ID - ID - - - MD5 - MD5 - - - Info hash v1 - Info hash v1 - - - Info hash v2 - Info hash v2 - - - Created - Created - - - Pieces - Pieces - - - Source - Source - - - Software - Software - - - Comment - Comment - - - Contributors - Contributors - - - Scrape - Scrape - - - Trackers - Trackers - - - Filtered by settings - Filtered by settings - - - Edit - Edit - - - Locales - Locales - - - Recent activity - Recent activity - - - Back - Back - - - Next - Next - - - Settings - Settings - - - Interface - Interface - - - Theme - Theme - - - Language - Language - - - Join translation - Join translation - - - Activity - Activity - - - Downloads - Downloads - - - Yggdrasil only - Yggdrasil only - - - Save - Save - - - Home - Home - - - Profile - Profile - - - User - User - - - Bookmark - Bookmark - - - Address - Address - - - Address hidden for others - Address hidden for others - - - Access - Access - - - Status - Status - - - Active - Active - - - Moderator - Moderator - - - Languages - Languages - - - Events subscribed - Events subscribed - - - undefined event - undefined event - - - have downloaded torrent file - have downloaded torrent file - - - waiting for approve - waiting for approve - - - sensitive - sensitive - - - have downloaded magnet link - have downloaded magnet link - - - have disapproved torrent - have disapproved torrent - - - have approved torrent - have approved torrent - - - have added torrent - have added torrent - - - have deleted locales edition - have deleted locales edition - - - for torrent - for torrent - - - have disapproved locales edition - have disapproved locales edition - - - have approved locales edition - have approved locales edition - - - have added locales edition - have added locales edition - - - have removed star from torrent - have removed star from torrent - - - have added star for torrent - have added star for torrent - - - have deleted sensitive edition - have deleted sensitive edition - - - have disapproved sensitive edition - have disapproved sensitive edition - - - have approved sensitive edition - have approved sensitive edition - - - have added sensitive edition - have added sensitive edition - - - have disabled - have disabled - - - have disabled user - have disabled user - - - have enabled - have enabled - - - have enabled user - have enabled user - - - have disapproved - have disapproved - - - have disapproved user - have disapproved user - - - have approved - have approved - - - have approved user - have approved user - - - have joined - have joined - - - have removed moderator permissions from - have removed moderator permissions from - - - have removed moderator permissions from user - have removed moderator permissions from user - - - have granted moderator permissions to - have granted moderator permissions to - - - have granted moderator permissions to user - have granted moderator permissions to user - - - have removed star from - have removed star from - - - have removed star from user - have removed star from user - - - have added star for - have added star for - - - have added star for user - have added star for user - - - Error - Error - - - Oops! - Oops! - - - Internal server error - Internal server error - - - Report - Report - - - Not found - Not found - - - Page not found! - Page not found! - - - BitTorrent protocol version 2 - BitTorrent protocol version 2 - - - BitTorrent protocol version 1 - BitTorrent protocol version 1 - - - year ago - year ago - - - month ago - month ago - - - day ago - day ago - - - hour ago - hour ago - - - minute ago - minute ago - - - second ago - second ago - - - years ago - years ago - - - months ago - months ago - - - days ago - days ago - - - hours ago - hours ago - - - minutes ago - minutes ago - - - seconds ago - seconds ago - - - years ago - years ago - - - months ago - months ago - - - days ago - days ago - - - hours ago - hours ago - - - minutes ago - minutes ago - - - seconds ago - seconds ago - - - Search results - Search results - - - <a href="%s">Upload</a> any torrent - download with Yggdrasil - Upload any torrent - download with Yggdrasil]]> - - - Wanted - Wanted - - - Seeders wanted for torrent - Seeders wanted for torrent - - - Hide - Hide - - - have disabled torrent - have disabled torrent - - - have enabled torrent - have enabled torrent - - - disabled - disabled - - - Poster file out of size limit - Poster file out of size limit - - - Image file not supported - Image file not supported - - - Poster file required - Poster file required - - - Edit torrent poster - Edit torrent poster - - - Edit poster for torrent - Edit poster for torrent - - - Poster - Poster - - - Posters - Posters - - - have deleted poster edition - have deleted poster edition - - - have disapproved poster edition - have disapproved poster edition - - - have approved poster edition - have approved poster edition - - - have added poster edition - have added poster edition - - - Torrent posters - Torrent posters - - - Center - Center - - - Top - Top - - - Bottom - Bottom - - - Categories - Categories - - - At least one category required - At least one category required - - - Content category - Content category - - - This torrent have selected categories - This torrent have selected categories - - - Edit categories - Edit categories - - - Edit categories for torrent - Edit categories for torrent - - - Locale - Locale - - - Category - Category - - - Torrent categories - Torrent categories - - - have deleted categories edition - have deleted categories edition - - - have disapproved categories edition - have disapproved categories edition - - - have approved categories edition - have approved categories edition - - - have added categories edition - have added categories edition - - - movie - movie - - - series - series - - - tv - tv - - - animation - animation - - - music - music - - - game - game - - - audiobook - audiobook - - - podcast - podcast - - - book - book - - - archive - archive - - - picture - picture - - - software - software - - - other - other - - - Hide filter - Hide filter - - - Show filter - Show filter - - - Private - Private - - -
-
diff --git a/translations/messages+intl-icu.nl.xlf b/translations/messages+intl-icu.nl.xlf deleted file mode 100644 index cb827de..0000000 --- a/translations/messages+intl-icu.nl.xlf +++ /dev/null @@ -1,918 +0,0 @@ - - - -
- -
- - - Users - Users - - - Joined - Joined - - - Approved - Approved - - - Disapproved - Disapproved - - - User statuses - User statuses - - - Enabled - Enabled - - - Disabled - Disabled - - - User moderators - User moderators - - - Added - Added - - - Removed - Removed - - - User stars - User stars - - - Torrents - Torrents - - - Torrent locales - Torrent locales - - - Deleted - Deleted - - - Torrent sensitive - Torrent sensitive - - - Torrent stars - Torrent stars - - - Torrent downloads - Torrent downloads - - - Files - Files - - - Magnet links - Magnet links - - - Access denied - Access denied - - - At least one locale required - At least one locale required - - - Torrent file out of size limit - Torrent file out of size limit - - - Torrent file already exists - Torrent file already exists - - - Could not parse torrent file - Could not parse torrent file - - - Torrent file required - Torrent file required - - - B - B - - - Kb - Kb - - - Mb - Mb - - - Gb - Gb - - - Tb - Tb - - - Pb - Pb - - - Eb - Eb - - - Zb - Zb - - - Yb - Yb - - - now - now - - - Keyword, file, hash... - Keyword, file, hash... - - - Search - Search - - - Recent uploads - Recent uploads - - - Active leechers waiting for seeders - Active leechers waiting for seeders - - - wanted - wanted - - - Waiting for approve - Waiting for approve - - - Size - Size - - - Seeders - Seeders - - - Peers - Peers - - - Leechers - Leechers - - - Open magnet link - Open magnet link - - - Total - Total - - - Download torrent file - Download torrent file - - - Star - Star - - - Nothing found - Nothing found - - - * share new torrent file to change it - * share new torrent file to change it - - - Submit - Submit - - - Submit torrent - Submit torrent - - - Content language - Content language - - - This torrent contains selected languages - This torrent contains selected languages - - - Sensitive - Sensitive - - - Mark torrent content as sensitive - Mark torrent content as sensitive - - - Edit locales - Edit locales - - - Torrent - Torrent - - - Edit locales for torrent - Edit locales for torrent - - - cancel - cancel - - - by - by - - - identicon - identicon - - - Delete - Delete - - - Disapprove - Disapprove - - - Approve - Approve - - - Edit sensitive status - Edit sensitive status - - - Edit sensitive status for torrent - Edit sensitive status for torrent - - - Page - Page - - - Moderation - Moderation - - - Yes - Yes - - - Toggle - Toggle - - - No - No - - - Common - Common - - - ID - ID - - - MD5 - MD5 - - - Info hash v1 - Info hash v1 - - - Info hash v2 - Info hash v2 - - - Created - Created - - - Pieces - Pieces - - - Source - Source - - - Software - Software - - - Comment - Comment - - - Contributors - Contributors - - - Scrape - Scrape - - - Trackers - Trackers - - - Filtered by settings - Filtered by settings - - - Edit - Edit - - - Locales - Locales - - - Recent activity - Recent activity - - - Back - Back - - - Next - Next - - - Settings - Settings - - - Interface - Interface - - - Theme - Theme - - - Language - Language - - - Join translation - Join translation - - - Activity - Activity - - - Downloads - Downloads - - - Yggdrasil only - Yggdrasil only - - - Save - Save - - - Home - Home - - - Profile - Profile - - - User - User - - - Bookmark - Bookmark - - - Address - Address - - - Address hidden for others - Address hidden for others - - - Access - Access - - - Status - Status - - - Active - Active - - - Moderator - Moderator - - - Languages - Languages - - - Events subscribed - Events subscribed - - - undefined event - undefined event - - - have downloaded torrent file - have downloaded torrent file - - - waiting for approve - waiting for approve - - - sensitive - sensitive - - - have downloaded magnet link - have downloaded magnet link - - - have disapproved torrent - have disapproved torrent - - - have approved torrent - have approved torrent - - - have added torrent - have added torrent - - - have deleted locales edition - have deleted locales edition - - - for torrent - for torrent - - - have disapproved locales edition - have disapproved locales edition - - - have approved locales edition - have approved locales edition - - - have added locales edition - have added locales edition - - - have removed star from torrent - have removed star from torrent - - - have added star for torrent - have added star for torrent - - - have deleted sensitive edition - have deleted sensitive edition - - - have disapproved sensitive edition - have disapproved sensitive edition - - - have approved sensitive edition - have approved sensitive edition - - - have added sensitive edition - have added sensitive edition - - - have disabled - have disabled - - - have disabled user - have disabled user - - - have enabled - have enabled - - - have enabled user - have enabled user - - - have disapproved - have disapproved - - - have disapproved user - have disapproved user - - - have approved - have approved - - - have approved user - have approved user - - - have joined - have joined - - - have removed moderator permissions from - have removed moderator permissions from - - - have removed moderator permissions from user - have removed moderator permissions from user - - - have granted moderator permissions to - have granted moderator permissions to - - - have granted moderator permissions to user - have granted moderator permissions to user - - - have removed star from - have removed star from - - - have removed star from user - have removed star from user - - - have added star for - have added star for - - - have added star for user - have added star for user - - - Error - Error - - - Oops! - Oops! - - - Internal server error - Internal server error - - - Report - Report - - - Not found - Not found - - - Page not found! - Page not found! - - - BitTorrent protocol version 2 - BitTorrent protocol version 2 - - - BitTorrent protocol version 1 - BitTorrent protocol version 1 - - - year ago - year ago - - - month ago - month ago - - - day ago - day ago - - - hour ago - hour ago - - - minute ago - minute ago - - - second ago - second ago - - - years ago - years ago - - - months ago - months ago - - - days ago - days ago - - - hours ago - hours ago - - - minutes ago - minutes ago - - - seconds ago - seconds ago - - - years ago - years ago - - - months ago - months ago - - - days ago - days ago - - - hours ago - hours ago - - - minutes ago - minutes ago - - - seconds ago - seconds ago - - - Search results - Search results - - - <a href="%s">Upload</a> any torrent - download with Yggdrasil - Upload any torrent - download with Yggdrasil]]> - - - Wanted - Wanted - - - Seeders wanted for torrent - Seeders wanted for torrent - - - Hide - Hide - - - have disabled torrent - have disabled torrent - - - have enabled torrent - have enabled torrent - - - disabled - disabled - - - Poster file out of size limit - Poster file out of size limit - - - Image file not supported - Image file not supported - - - Poster file required - Poster file required - - - Edit torrent poster - Edit torrent poster - - - Edit poster for torrent - Edit poster for torrent - - - Poster - Poster - - - Posters - Posters - - - have deleted poster edition - have deleted poster edition - - - have disapproved poster edition - have disapproved poster edition - - - have approved poster edition - have approved poster edition - - - have added poster edition - have added poster edition - - - Torrent posters - Torrent posters - - - Center - Center - - - Top - Top - - - Bottom - Bottom - - - Categories - Categories - - - At least one category required - At least one category required - - - Content category - Content category - - - This torrent have selected categories - This torrent have selected categories - - - Edit categories - Edit categories - - - Edit categories for torrent - Edit categories for torrent - - - Locale - Locale - - - Category - Category - - - Torrent categories - Torrent categories - - - have deleted categories edition - have deleted categories edition - - - have disapproved categories edition - have disapproved categories edition - - - have approved categories edition - have approved categories edition - - - have added categories edition - have added categories edition - - - movie - movie - - - series - series - - - tv - tv - - - animation - animation - - - music - music - - - game - game - - - audiobook - audiobook - - - podcast - podcast - - - book - book - - - archive - archive - - - picture - picture - - - software - software - - - other - other - - - Hide filter - Hide filter - - - Show filter - Show filter - - - Private - Private - - -
-
diff --git a/translations/messages+intl-icu.pl.xlf b/translations/messages+intl-icu.pl.xlf deleted file mode 100644 index b9debc7..0000000 --- a/translations/messages+intl-icu.pl.xlf +++ /dev/null @@ -1,918 +0,0 @@ - - - -
- -
- - - Users - Users - - - Joined - Joined - - - Approved - Approved - - - Disapproved - Disapproved - - - User statuses - User statuses - - - Enabled - Enabled - - - Disabled - Disabled - - - User moderators - User moderators - - - Added - Added - - - Removed - Removed - - - User stars - User stars - - - Torrents - Torrents - - - Torrent locales - Torrent locales - - - Deleted - Deleted - - - Torrent sensitive - Torrent sensitive - - - Torrent stars - Torrent stars - - - Torrent downloads - Torrent downloads - - - Files - Files - - - Magnet links - Magnet links - - - Access denied - Access denied - - - At least one locale required - At least one locale required - - - Torrent file out of size limit - Torrent file out of size limit - - - Torrent file already exists - Torrent file already exists - - - Could not parse torrent file - Could not parse torrent file - - - Torrent file required - Torrent file required - - - B - B - - - Kb - Kb - - - Mb - Mb - - - Gb - Gb - - - Tb - Tb - - - Pb - Pb - - - Eb - Eb - - - Zb - Zb - - - Yb - Yb - - - now - now - - - Keyword, file, hash... - Keyword, file, hash... - - - Search - Search - - - Recent uploads - Recent uploads - - - Active leechers waiting for seeders - Active leechers waiting for seeders - - - wanted - wanted - - - Waiting for approve - Waiting for approve - - - Size - Size - - - Seeders - Seeders - - - Peers - Peers - - - Leechers - Leechers - - - Open magnet link - Open magnet link - - - Total - Total - - - Download torrent file - Download torrent file - - - Star - Star - - - Nothing found - Nothing found - - - * share new torrent file to change it - * share new torrent file to change it - - - Submit - Submit - - - Submit torrent - Submit torrent - - - Content language - Content language - - - This torrent contains selected languages - This torrent contains selected languages - - - Sensitive - Sensitive - - - Mark torrent content as sensitive - Mark torrent content as sensitive - - - Edit locales - Edit locales - - - Torrent - Torrent - - - Edit locales for torrent - Edit locales for torrent - - - cancel - cancel - - - by - by - - - identicon - identicon - - - Delete - Delete - - - Disapprove - Disapprove - - - Approve - Approve - - - Edit sensitive status - Edit sensitive status - - - Edit sensitive status for torrent - Edit sensitive status for torrent - - - Page - Page - - - Moderation - Moderation - - - Yes - Yes - - - Toggle - Toggle - - - No - No - - - Common - Common - - - ID - ID - - - MD5 - MD5 - - - Info hash v1 - Info hash v1 - - - Info hash v2 - Info hash v2 - - - Created - Created - - - Pieces - Pieces - - - Source - Source - - - Software - Software - - - Comment - Comment - - - Contributors - Contributors - - - Scrape - Scrape - - - Trackers - Trackers - - - Filtered by settings - Filtered by settings - - - Edit - Edit - - - Locales - Locales - - - Recent activity - Recent activity - - - Back - Back - - - Next - Next - - - Settings - Settings - - - Interface - Interface - - - Theme - Theme - - - Language - Language - - - Join translation - Join translation - - - Activity - Activity - - - Downloads - Downloads - - - Yggdrasil only - Yggdrasil only - - - Save - Save - - - Home - Home - - - Profile - Profile - - - User - User - - - Bookmark - Bookmark - - - Address - Address - - - Address hidden for others - Address hidden for others - - - Access - Access - - - Status - Status - - - Active - Active - - - Moderator - Moderator - - - Languages - Languages - - - Events subscribed - Events subscribed - - - undefined event - undefined event - - - have downloaded torrent file - have downloaded torrent file - - - waiting for approve - waiting for approve - - - sensitive - sensitive - - - have downloaded magnet link - have downloaded magnet link - - - have disapproved torrent - have disapproved torrent - - - have approved torrent - have approved torrent - - - have added torrent - have added torrent - - - have deleted locales edition - have deleted locales edition - - - for torrent - for torrent - - - have disapproved locales edition - have disapproved locales edition - - - have approved locales edition - have approved locales edition - - - have added locales edition - have added locales edition - - - have removed star from torrent - have removed star from torrent - - - have added star for torrent - have added star for torrent - - - have deleted sensitive edition - have deleted sensitive edition - - - have disapproved sensitive edition - have disapproved sensitive edition - - - have approved sensitive edition - have approved sensitive edition - - - have added sensitive edition - have added sensitive edition - - - have disabled - have disabled - - - have disabled user - have disabled user - - - have enabled - have enabled - - - have enabled user - have enabled user - - - have disapproved - have disapproved - - - have disapproved user - have disapproved user - - - have approved - have approved - - - have approved user - have approved user - - - have joined - have joined - - - have removed moderator permissions from - have removed moderator permissions from - - - have removed moderator permissions from user - have removed moderator permissions from user - - - have granted moderator permissions to - have granted moderator permissions to - - - have granted moderator permissions to user - have granted moderator permissions to user - - - have removed star from - have removed star from - - - have removed star from user - have removed star from user - - - have added star for - have added star for - - - have added star for user - have added star for user - - - Error - Error - - - Oops! - Oops! - - - Internal server error - Internal server error - - - Report - Report - - - Not found - Not found - - - Page not found! - Page not found! - - - BitTorrent protocol version 2 - BitTorrent protocol version 2 - - - BitTorrent protocol version 1 - BitTorrent protocol version 1 - - - year ago - year ago - - - month ago - month ago - - - day ago - day ago - - - hour ago - hour ago - - - minute ago - minute ago - - - second ago - second ago - - - years ago - years ago - - - months ago - months ago - - - days ago - days ago - - - hours ago - hours ago - - - minutes ago - minutes ago - - - seconds ago - seconds ago - - - years ago - years ago - - - months ago - months ago - - - days ago - days ago - - - hours ago - hours ago - - - minutes ago - minutes ago - - - seconds ago - seconds ago - - - Search results - Search results - - - <a href="%s">Upload</a> any torrent - download with Yggdrasil - Upload any torrent - download with Yggdrasil]]> - - - Wanted - Wanted - - - Seeders wanted for torrent - Seeders wanted for torrent - - - Hide - Hide - - - have disabled torrent - have disabled torrent - - - have enabled torrent - have enabled torrent - - - disabled - disabled - - - Poster file out of size limit - Poster file out of size limit - - - Image file not supported - Image file not supported - - - Poster file required - Poster file required - - - Edit torrent poster - Edit torrent poster - - - Edit poster for torrent - Edit poster for torrent - - - Poster - Poster - - - Posters - Posters - - - have deleted poster edition - have deleted poster edition - - - have disapproved poster edition - have disapproved poster edition - - - have approved poster edition - have approved poster edition - - - have added poster edition - have added poster edition - - - Torrent posters - Torrent posters - - - Center - Center - - - Top - Top - - - Bottom - Bottom - - - Categories - Categories - - - At least one category required - At least one category required - - - Content category - Content category - - - This torrent have selected categories - This torrent have selected categories - - - Edit categories - Edit categories - - - Edit categories for torrent - Edit categories for torrent - - - Locale - Locale - - - Category - Category - - - Torrent categories - Torrent categories - - - have deleted categories edition - have deleted categories edition - - - have disapproved categories edition - have disapproved categories edition - - - have approved categories edition - have approved categories edition - - - have added categories edition - have added categories edition - - - movie - movie - - - series - series - - - tv - tv - - - animation - animation - - - music - music - - - game - game - - - audiobook - audiobook - - - podcast - podcast - - - book - book - - - archive - archive - - - picture - picture - - - software - software - - - other - other - - - Hide filter - Hide filter - - - Show filter - Show filter - - - Private - Private - - -
-
diff --git a/translations/messages+intl-icu.pt.xlf b/translations/messages+intl-icu.pt.xlf deleted file mode 100644 index bc8dc0f..0000000 --- a/translations/messages+intl-icu.pt.xlf +++ /dev/null @@ -1,918 +0,0 @@ - - - -
- -
- - - Users - Users - - - Joined - Joined - - - Approved - Approved - - - Disapproved - Disapproved - - - User statuses - User statuses - - - Enabled - Enabled - - - Disabled - Disabled - - - User moderators - User moderators - - - Added - Added - - - Removed - Removed - - - User stars - User stars - - - Torrents - Torrents - - - Torrent locales - Torrent locales - - - Deleted - Deleted - - - Torrent sensitive - Torrent sensitive - - - Torrent stars - Torrent stars - - - Torrent downloads - Torrent downloads - - - Files - Files - - - Magnet links - Magnet links - - - Access denied - Access denied - - - At least one locale required - At least one locale required - - - Torrent file out of size limit - Torrent file out of size limit - - - Torrent file already exists - Torrent file already exists - - - Could not parse torrent file - Could not parse torrent file - - - Torrent file required - Torrent file required - - - B - B - - - Kb - Kb - - - Mb - Mb - - - Gb - Gb - - - Tb - Tb - - - Pb - Pb - - - Eb - Eb - - - Zb - Zb - - - Yb - Yb - - - now - now - - - Keyword, file, hash... - Keyword, file, hash... - - - Search - Search - - - Recent uploads - Recent uploads - - - Active leechers waiting for seeders - Active leechers waiting for seeders - - - wanted - wanted - - - Waiting for approve - Waiting for approve - - - Size - Size - - - Seeders - Seeders - - - Peers - Peers - - - Leechers - Leechers - - - Open magnet link - Open magnet link - - - Total - Total - - - Download torrent file - Download torrent file - - - Star - Star - - - Nothing found - Nothing found - - - * share new torrent file to change it - * share new torrent file to change it - - - Submit - Submit - - - Submit torrent - Submit torrent - - - Content language - Content language - - - This torrent contains selected languages - This torrent contains selected languages - - - Sensitive - Sensitive - - - Mark torrent content as sensitive - Mark torrent content as sensitive - - - Edit locales - Edit locales - - - Torrent - Torrent - - - Edit locales for torrent - Edit locales for torrent - - - cancel - cancel - - - by - by - - - identicon - identicon - - - Delete - Delete - - - Disapprove - Disapprove - - - Approve - Approve - - - Edit sensitive status - Edit sensitive status - - - Edit sensitive status for torrent - Edit sensitive status for torrent - - - Page - Page - - - Moderation - Moderation - - - Yes - Yes - - - Toggle - Toggle - - - No - No - - - Common - Common - - - ID - ID - - - MD5 - MD5 - - - Info hash v1 - Info hash v1 - - - Info hash v2 - Info hash v2 - - - Created - Created - - - Pieces - Pieces - - - Source - Source - - - Software - Software - - - Comment - Comment - - - Contributors - Contributors - - - Scrape - Scrape - - - Trackers - Trackers - - - Filtered by settings - Filtered by settings - - - Edit - Edit - - - Locales - Locales - - - Recent activity - Recent activity - - - Back - Back - - - Next - Next - - - Settings - Settings - - - Interface - Interface - - - Theme - Theme - - - Language - Language - - - Join translation - Join translation - - - Activity - Activity - - - Downloads - Downloads - - - Yggdrasil only - Yggdrasil only - - - Save - Save - - - Home - Home - - - Profile - Profile - - - User - User - - - Bookmark - Bookmark - - - Address - Address - - - Address hidden for others - Address hidden for others - - - Access - Access - - - Status - Status - - - Active - Active - - - Moderator - Moderator - - - Languages - Languages - - - Events subscribed - Events subscribed - - - undefined event - undefined event - - - have downloaded torrent file - have downloaded torrent file - - - waiting for approve - waiting for approve - - - sensitive - sensitive - - - have downloaded magnet link - have downloaded magnet link - - - have disapproved torrent - have disapproved torrent - - - have approved torrent - have approved torrent - - - have added torrent - have added torrent - - - have deleted locales edition - have deleted locales edition - - - for torrent - for torrent - - - have disapproved locales edition - have disapproved locales edition - - - have approved locales edition - have approved locales edition - - - have added locales edition - have added locales edition - - - have removed star from torrent - have removed star from torrent - - - have added star for torrent - have added star for torrent - - - have deleted sensitive edition - have deleted sensitive edition - - - have disapproved sensitive edition - have disapproved sensitive edition - - - have approved sensitive edition - have approved sensitive edition - - - have added sensitive edition - have added sensitive edition - - - have disabled - have disabled - - - have disabled user - have disabled user - - - have enabled - have enabled - - - have enabled user - have enabled user - - - have disapproved - have disapproved - - - have disapproved user - have disapproved user - - - have approved - have approved - - - have approved user - have approved user - - - have joined - have joined - - - have removed moderator permissions from - have removed moderator permissions from - - - have removed moderator permissions from user - have removed moderator permissions from user - - - have granted moderator permissions to - have granted moderator permissions to - - - have granted moderator permissions to user - have granted moderator permissions to user - - - have removed star from - have removed star from - - - have removed star from user - have removed star from user - - - have added star for - have added star for - - - have added star for user - have added star for user - - - Error - Error - - - Oops! - Oops! - - - Internal server error - Internal server error - - - Report - Report - - - Not found - Not found - - - Page not found! - Page not found! - - - BitTorrent protocol version 2 - BitTorrent protocol version 2 - - - BitTorrent protocol version 1 - BitTorrent protocol version 1 - - - year ago - year ago - - - month ago - month ago - - - day ago - day ago - - - hour ago - hour ago - - - minute ago - minute ago - - - second ago - second ago - - - years ago - years ago - - - months ago - months ago - - - days ago - days ago - - - hours ago - hours ago - - - minutes ago - minutes ago - - - seconds ago - seconds ago - - - years ago - years ago - - - months ago - months ago - - - days ago - days ago - - - hours ago - hours ago - - - minutes ago - minutes ago - - - seconds ago - seconds ago - - - Search results - Search results - - - <a href="%s">Upload</a> any torrent - download with Yggdrasil - Upload any torrent - download with Yggdrasil]]> - - - Wanted - Wanted - - - Seeders wanted for torrent - Seeders wanted for torrent - - - Hide - Hide - - - have disabled torrent - have disabled torrent - - - have enabled torrent - have enabled torrent - - - disabled - disabled - - - Poster file out of size limit - Poster file out of size limit - - - Image file not supported - Image file not supported - - - Poster file required - Poster file required - - - Edit torrent poster - Edit torrent poster - - - Edit poster for torrent - Edit poster for torrent - - - Poster - Poster - - - Posters - Posters - - - have deleted poster edition - have deleted poster edition - - - have disapproved poster edition - have disapproved poster edition - - - have approved poster edition - have approved poster edition - - - have added poster edition - have added poster edition - - - Torrent posters - Torrent posters - - - Center - Center - - - Top - Top - - - Bottom - Bottom - - - Categories - Categories - - - At least one category required - At least one category required - - - Content category - Content category - - - This torrent have selected categories - This torrent have selected categories - - - Edit categories - Edit categories - - - Edit categories for torrent - Edit categories for torrent - - - Locale - Locale - - - Category - Category - - - Torrent categories - Torrent categories - - - have deleted categories edition - have deleted categories edition - - - have disapproved categories edition - have disapproved categories edition - - - have approved categories edition - have approved categories edition - - - have added categories edition - have added categories edition - - - movie - movie - - - series - series - - - tv - tv - - - animation - animation - - - music - music - - - game - game - - - audiobook - audiobook - - - podcast - podcast - - - book - book - - - archive - archive - - - picture - picture - - - software - software - - - other - other - - - Hide filter - Hide filter - - - Show filter - Show filter - - - Private - Private - - -
-
diff --git a/translations/messages+intl-icu.ru.xlf b/translations/messages+intl-icu.ru.xlf deleted file mode 100644 index a452819..0000000 --- a/translations/messages+intl-icu.ru.xlf +++ /dev/null @@ -1,918 +0,0 @@ - - - -
- -
- - - Users - Пользователи - - - Joined - Присоединился - - - Approved - Утвержден - - - Disapproved - Отклонен - - - User statuses - Статусы пользователей - - - Enabled - Включено - - - Disabled - Отключено - - - User moderators - Модерация пользователей - - - Added - Добавлено - - - Removed - Удалено - - - User stars - Звезды пользователей - - - Torrents - Торренты - - - Torrent locales - Локали торрента - - - Deleted - Удалено - - - Torrent sensitive - Чувствительное содержимое - - - Torrent stars - Звезды торрента - - - Torrent downloads - Загрузки торрентов - - - Files - Файлы - - - Magnet links - Magnet-ссылки - - - Access denied - Доступ запрещен - - - At least one locale required - Требуется хотя бы одна локаль - - - Torrent file out of size limit - Превышен размер торрент-файла - - - Torrent file already exists - Торрент-файл уже существует - - - Could not parse torrent file - Не удалось проанализировать торрент-файл - - - Torrent file required - Требуется указать торрент-файл - - - B - Б - - - Kb - Кб - - - Mb - Мб - - - Gb - Гб - - - Tb - Тб - - - Pb - Пб - - - Eb - Эб - - - Zb - Зб - - - Yb - Иб - - - now - сейчас - - - Keyword, file, hash... - Ключевое слово, файл, хэш... - - - Search - Поиск - - - Recent uploads - Последние загрузки - - - Active leechers waiting for seeders - Активные пиры ожидают раздачи - - - wanted - розыск - - - Waiting for approve - На рассмотрении - - - Size - Размер - - - Seeders - Сиды - - - Peers - Пиры - - - Leechers - Личеры - - - Open magnet link - Открыть magnet-ссылку - - - Total - Всего - - - Download torrent file - Скачать торрент-файл - - - Star - Звезда - - - Nothing found - Ничего не найдено - - - * share new torrent file to change it - * поделитесь новым торрент-файлом, чтобы исправить это - - - Submit - Отправить - - - Submit torrent - Отправить торрент - - - Content language - Язык контента - - - This torrent contains selected languages - Этот торрент содержит выбранные языки - - - Sensitive - Чувствительность - - - Mark torrent content as sensitive - Отметить содержимое торрента как чувствительное - - - Edit locales - Изменить локали - - - Torrent - Торрент - - - Edit locales for torrent - Изменить локали для торрента - - - cancel - отменить - - - by - от - - - identicon - пиктограмма - - - Delete - Удалить - - - Disapprove - Отклонить - - - Approve - Утвердить - - - Edit sensitive status - Изменить статус чувствительности - - - Edit sensitive status for torrent - Редактировать статус чувствительности для торрента - - - Page - Страница - - - Moderation - Модерация - - - Yes - Да - - - Toggle - Переключить - - - No - Нет - - - Common - Общее - - - ID - ID - - - MD5 - MD5 - - - Info hash v1 - Инфо-хэш v1 - - - Info hash v2 - Инфо-хэш v2 - - - Created - Создано - - - Pieces - Фрагменты - - - Source - Источник - - - Software - Программа - - - Comment - Комментарий - - - Contributors - Участники - - - Scrape - Статус - - - Trackers - Трекеры - - - Filtered by settings - Отфильтровано согласно настройкам - - - Edit - Редактировать - - - Locales - Локали - - - Recent activity - Недавняя активность - - - Back - Назад - - - Next - Далее - - - Settings - Настройки - - - Interface - Интерфейс - - - Theme - Тема - - - Language - Язык - - - Join translation - Присоединиться к переводам - - - Activity - Активность - - - Downloads - Загрузки - - - Yggdrasil only - Только Yggdrasil - - - Save - Сохранить - - - Home - Главная - - - Profile - Профиль - - - User - Пользователь - - - Bookmark - Закладка - - - Address - Адрес - - - Address hidden for others - Адрес скрыт для других - - - Access - Доступ - - - Status - Статус - - - Active - Активный - - - Moderator - Модератор - - - Languages - Языки - - - Events subscribed - Подписка на события - - - undefined event - неизвестное событие - - - have downloaded torrent file - скачал торрент-файл - - - waiting for approve - на рассмотрении - - - sensitive - чувствительность - - - have downloaded magnet link - скачал magnet-ссылку - - - have disapproved torrent - отменил утверждение торрента - - - have approved torrent - утвердил торрент - - - have added torrent - добавил торрент - - - have deleted locales edition - удалил редакцию локалей - - - for torrent - для торрента - - - have disapproved locales edition - отклонил редакцию локалей - - - have approved locales edition - утвердил редакцию локалей - - - have added locales edition - добавил редакцию локалей - - - have removed star from torrent - удалил звезду с торрента - - - have added star for torrent - добавил звезду для торрента - - - have deleted sensitive edition - удалил редакцию чувствительного контента - - - have disapproved sensitive edition - отклонил редакцию чувствительного контента - - - have approved sensitive edition - утвердил редакцию чувствительного контента - - - have added sensitive edition - добавил редакцию чувствительного контента - - - have disabled - отключил - - - have disabled user - отключил пользователя - - - have enabled - включил - - - have enabled user - включил пользователя - - - have disapproved - отклонил - - - have disapproved user - отключил пользователя - - - have approved - утвердил - - - have approved user - утвердил пользователя - - - have joined - присоединился - - - have removed moderator permissions from - удалил права модератора от - - - have removed moderator permissions from user - удалил права модератора от пользователя - - - have granted moderator permissions to - предоставил права модератора для - - - have granted moderator permissions to user - предоставил права модератора для пользователя - - - have removed star from - удалил звезду от - - - have removed star from user - удалили звезду от пользователя - - - have added star for - добавил звезду для - - - have added star for user - добавил звезду для пользователя - - - Error - Ошибка - - - Oops! - Ой! - - - Internal server error - Внутренняя ошибка сервера - - - Report - Сообщить - - - Not found - Не найдено - - - Page not found! - Страница не найдена! - - - BitTorrent protocol version 2 - BitTorrent протокол версии 2 - - - BitTorrent protocol version 1 - BitTorrent протокол версии 1 - - - year ago - год назад - - - month ago - месяц назад - - - day ago - день назад - - - hour ago - час назад - - - minute ago - минуту назад - - - second ago - секунду назад - - - years ago - год назад - - - months ago - месяца назад - - - days ago - дня назад - - - hours ago - часа назад - - - minutes ago - минуты назад - - - seconds ago - секунды назад - - - years ago - лет назад - - - months ago - месяцев назад - - - days ago - дней назад - - - hours ago - часов назад - - - minutes ago - минут назад - - - seconds ago - секунд назад - - - Search results - Результаты поиска - - - <a href="%s">Upload</a> any torrent - download with Yggdrasil - Загрузить любой торрент - скачать с Yggdrasil]]> - - - Wanted - Розыск - - - Seeders wanted for torrent - Требуется раздача для торрента - - - Hide - Скрыть - - - have disabled torrent - отключил торрент - - - have enabled torrent - включил торрент - - - disabled - отключено - - - Poster file out of size limit - Размер файла постера превышает максимальный размер - - - Image file not supported - Формат изображения не поддерживается - - - Poster file required - Требуется указать файл постера - - - Edit torrent poster - Редактировать постер торрента - - - Edit poster for torrent - Редактировать постер для торрента - - - Poster - Постер - - - Posters - Постеры - - - have deleted poster edition - удалил редакцию постера - - - have disapproved poster edition - отклонил редакцию постера - - - have approved poster edition - утвердил редакцию постера - - - have added poster edition - добавил редакцию постера - - - Torrent posters - Постеры торрентов - - - Center - Центр - - - Top - Верх - - - Bottom - Низ - - - Categories - Категории - - - At least one category required - Необходимо указать минимум одну категорию - - - Content category - Категория содержимого - - - This torrent have selected categories - Этот торрент содержит выбранные категории - - - Edit categories - Редактировать категории - - - Edit categories for torrent - Редактировать категории для торрента - - - Locale - Локаль - - - Category - Категория - - - Torrent categories - Категории торрента - - - have deleted categories edition - удалил редакцию категорий - - - have disapproved categories edition - отклонил редакцию категорий - - - have approved categories edition - утвердил редакцию категорий - - - have added categories edition - добавил редакцию категорий - - - movie - фильм - - - series - сериал - - - tv - ТВ шоу - - - animation - анимация - - - music - музыка - - - game - игра - - - audiobook - аудиокнига - - - podcast - подкаст - - - book - книга - - - archive - архив - - - picture - изображение - - - software - программа - - - other - другое - - - Hide filter - Скрыть фильтр - - - Show filter - Показать фильтр - - - Private - Приватный - - -
-
diff --git a/translations/messages+intl-icu.uk.xlf b/translations/messages+intl-icu.uk.xlf deleted file mode 100644 index ffea2ef..0000000 --- a/translations/messages+intl-icu.uk.xlf +++ /dev/null @@ -1,918 +0,0 @@ - - - -
- -
- - - Users - Користувачі - - - Joined - Приєднався - - - Approved - Затверджено - - - Disapproved - Відхилено - - - User statuses - Статуси користувача - - - Enabled - Увімкнено - - - Disabled - Вимкнено - - - User moderators - Модератори - - - Added - Додано - - - Removed - Видалено - - - User stars - Зірки користувача - - - Torrents - Торенти - - - Torrent locales - Файли торентів - - - Deleted - Видалено - - - Torrent sensitive - Чутливий вміст - - - Torrent stars - Зірки торенту - - - Torrent downloads - Завантаження торенту - - - Files - Файли - - - Magnet links - Magnet-посилання - - - Access denied - Відмовлено у доступі - - - At least one locale required - Необхідна принаймні одна локаль - - - Torrent file out of size limit - Торент-файл поза розміром - - - Torrent file already exists - Торент-файл вже існує - - - Could not parse torrent file - Не вдалося проаналізувати торент-файл - - - Torrent file required - Необхідно надати торент файл - - - B - Б - - - Kb - Кб - - - Mb - Мб - - - Gb - Гб - - - Tb - Тб - - - Pb - Пб - - - Eb - Еб - - - Zb - Зб - - - Yb - Іб - - - now - щойно - - - Keyword, file, hash... - Ключове слово, файл, хеш... - - - Search - Пошук - - - Recent uploads - Останні завантаження - - - Active leechers waiting for seeders - Активні лічери очікують сідів - - - wanted - розшук - - - Waiting for approve - Очікує на підтвердження - - - Size - Розмір - - - Seeders - Сідери - - - Peers - Піри - - - Leechers - Лічери - - - Open magnet link - Відкрити посилання на magnet - - - Total - Всього - - - Download torrent file - Завантажити торрент файл - - - Star - Зірка - - - Nothing found - Нічого не знайдено - - - * share new torrent file to change it - * поширте новий торент-файл, щоб змінити це - - - Submit - Надіслати - - - Submit torrent - Надіслати торент - - - Content language - Мова контенту - - - This torrent contains selected languages - Цей торрент містить обрані мови - - - Sensitive - Чутливий вміст - - - Mark torrent content as sensitive - Помітити вміст торенту як чутливий - - - Edit locales - Редагувати локалі - - - Torrent - Торент - - - Edit locales for torrent - Редагування локалей для торенту - - - cancel - скасувати - - - by - за участі - - - identicon - піктограма - - - Delete - Видалити - - - Disapprove - Відхилити - - - Approve - Затвердити - - - Edit sensitive status - Редагувати статус чутливості - - - Edit sensitive status for torrent - Редагувати статус чутливості для торенту - - - Page - Сторінка - - - Moderation - Модерація - - - Yes - Так - - - Toggle - Перемкнути - - - No - Ні - - - Common - Загальні - - - ID - ID - - - MD5 - MD5 - - - Info hash v1 - Інфо-хеш версії 1 - - - Info hash v2 - Інфо-хеш версії 2 - - - Created - Створено - - - Pieces - Частини - - - Source - Джерело - - - Software - Програма - - - Comment - Коментар - - - Contributors - Учасники - - - Scrape - Стан - - - Trackers - Трекери - - - Filtered by settings - Відфільтровано згідно з налаштуваннями - - - Edit - Редагувати - - - Locales - Локалі - - - Recent activity - Остання активність - - - Back - Назад - - - Next - Далі - - - Settings - Налаштування - - - Interface - Інтерфейс - - - Theme - Тема - - - Language - Мова - - - Join translation - Приєднатись до перекладу - - - Activity - Активність - - - Downloads - Завантаження - - - Yggdrasil only - Тільки Іґдрасіль - - - Save - Зберегти - - - Home - Головна - - - Profile - Профіль - - - User - Користувач - - - Bookmark - Додати до обраного - - - Address - Адреса - - - Address hidden for others - Адресу приховано для інших - - - Access - Доступ - - - Status - Статус - - - Active - Активний - - - Moderator - Модератор - - - Languages - Мови - - - Events subscribed - Підписка на події - - - undefined event - невідома подія - - - have downloaded torrent file - завантажив торрент файл - - - waiting for approve - очікує на підтвердження - - - sensitive - чутливий вміст - - - have downloaded magnet link - завантажив торрент файл - - - have disapproved torrent - відхилив торент - - - have approved torrent - затвердив торент - - - have added torrent - додав торент - - - have deleted locales edition - видалено версію локалей - - - for torrent - для торенту - - - have disapproved locales edition - відхилив версію локалей - - - have approved locales edition - затвердив версію локалей - - - have added locales edition - додав редакцію локалей - - - have removed star from torrent - видалив зірку з торента - - - have added star for torrent - додав зірку для торента - - - have deleted sensitive edition - видалив редакцію чутливого вмісту - - - have disapproved sensitive edition - відхилив редакцію чутливого вмісту - - - have approved sensitive edition - затвердив редакцію чутливого вмісту - - - have added sensitive edition - додав редакцію чутливого вмісту - - - have disabled - вимкнув - - - have disabled user - вимкнув користувача - - - have enabled - увімкнув - - - have enabled user - увімкнув користувача - - - have disapproved - відхилив - - - have disapproved user - відхилив користувача - - - have approved - затвердив - - - have approved user - затвердив користувача - - - have joined - приєднався - - - have removed moderator permissions from - видалив права модератора від - - - have removed moderator permissions from user - видалив права модератора від користувача - - - have granted moderator permissions to - надано права модератора - - - have granted moderator permissions to user - надано права модератора користувачеві - - - have removed star from - видалив зірку від - - - have removed star from user - видалив зірку від користувача - - - have added star for - додав зірку до - - - have added star for user - додав зірку користувачеві - - - Error - Помилка - - - Oops! - Ой! - - - Internal server error - Внутрішня помилка сервера - - - Report - Звіт - - - Not found - Не знайдено - - - Page not found! - Сторінку не знайдено! - - - BitTorrent protocol version 2 - BitTorrent протокол версії 2 - - - BitTorrent protocol version 1 - BitTorrent протокол версії 1 - - - year ago - рік тому - - - month ago - місяць тому - - - day ago - день тому - - - hour ago - годину тому - - - minute ago - хвилину тому - - - second ago - секунду тому - - - years ago - роки тому - - - months ago - місяці тому - - - days ago - дні тому - - - hours ago - години тому - - - minutes ago - хвилини тому - - - seconds ago - секунди тому - - - years ago - років тому - - - months ago - місяців тому - - - days ago - днів тому - - - hours ago - годин тому - - - minutes ago - хвилин тому - - - seconds ago - секунд тому - - - Search results - Результати пошуку - - - <a href="%s">Upload</a> any torrent - download with Yggdrasil - Надіслати будь-який торент - завантажити з Yggdrasil]]> - - - Wanted - Розшук - - - Seeders wanted for torrent - Розшукуються роздачі для торенту - - - Hide - Приховати - - - have disabled torrent - вимкнув торент - - - have enabled torrent - увімкнув торент - - - disabled - вимкнено - - - Poster file out of size limit - Розмір файлу постера перевищує ліміти - - - Image file not supported - Формат зображення не підтримується - - - Poster file required - Необхідно вказати файл постера - - - Edit torrent poster - Редагувати постер торента - - - Edit poster for torrent - Редагувати постер для торента - - - Poster - Постер - - - Posters - Постери - - - have deleted poster edition - видалив редакцію постера - - - have disapproved poster edition - відхилив редакцію постера - - - have approved poster edition - додав редакцію постера - - - have added poster edition - додав редакцію постера - - - Torrent posters - Постери торентів - - - Center - Центр - - - Top - Верх - - - Bottom - Низ - - - Categories - Категорії - - - At least one category required - Потрібно вказати щонайменше одну категорію - - - Content category - Категорія вмісту - - - This torrent have selected categories - Цей торрент має виділені категорії - - - Edit categories - Змінити категорії - - - Edit categories for torrent - Редагувати категорії для торенту - - - Locale - Локаль - - - Category - Категорія - - - Torrent categories - Категорії торенту - - - have deleted categories edition - видалив редакцію категорій - - - have disapproved categories edition - відхилив редакцію категорій - - - have approved categories edition - затвердив редакцію категорій - - - have added categories edition - додав редакцію категорій - - - movie - кіно - - - series - серіал - - - tv - ТБ шоу - - - animation - анімація - - - music - музика - - - game - гра - - - audiobook - аудіокнига - - - podcast - подкаст - - - book - книга - - - archive - архів - - - picture - зображення - - - software - програма - - - other - інше - - - Hide filter - Приховати фільтр - - - Show filter - Показати фільтр - - - Private - Приватний - - -
-