diff --git a/.github/workflows/linters.yml b/.github/workflows/linters.yml index 55af98cb4..1b9be3cfe 100644 --- a/.github/workflows/linters.yml +++ b/.github/workflows/linters.yml @@ -7,7 +7,6 @@ on: jobs: jshint: runs-on: ubuntu-latest - container: kanboard/tests:latest steps: - uses: actions/checkout@v2 - name: Install jshint diff --git a/.gitignore b/.gitignore index 225a8804c..29cfe64c2 100644 --- a/.gitignore +++ b/.gitignore @@ -21,4 +21,5 @@ data/config.php *.bak /config.php !docker/var/wwww/app/config.php -node_modules \ No newline at end of file +node_modules +.phpunit.result.cache \ No newline at end of file diff --git a/Dockerfile b/Dockerfile index 540f2e821..c0e338163 100644 --- a/Dockerfile +++ b/Dockerfile @@ -9,12 +9,12 @@ EXPOSE 80 443 ARG VERSION RUN apk --no-cache --update add \ - tzdata openssl unzip nginx bash ca-certificates s6 curl ssmtp mailx php7 php7-phar php7-curl \ - php7-fpm php7-json php7-zlib php7-xml php7-dom php7-ctype php7-opcache php7-zip php7-iconv \ - php7-pdo php7-pdo_mysql php7-pdo_sqlite php7-pdo_pgsql php7-mbstring php7-session php7-bcmath \ - php7-gd php7-mcrypt php7-openssl php7-sockets php7-posix php7-ldap php7-simplexml && \ + tzdata openssl unzip nginx bash ca-certificates s6 curl ssmtp mailx php8 php8-phar php8-curl \ + php8-fpm php8-json php8-zlib php8-xml php8-dom php8-ctype php8-opcache php8-zip php8-iconv \ + php8-pdo php8-pdo_mysql php8-pdo_sqlite php8-pdo_pgsql php8-mbstring php8-session php8-bcmath \ + php8-gd php8-openssl php8-sockets php8-posix php8-ldap php8-simplexml && \ rm -rf /var/www/localhost && \ - rm -f /etc/php7/php-fpm.d/www.conf + rm -f /etc/php8/php-fpm.d/www.conf ADD . /var/www/app ADD docker/ / diff --git a/LICENSE b/LICENSE index 6505a3666..045f1aecd 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ The MIT License (MIT) -Copyright (c) 2014-2021 Frédéric Guillot +Copyright (c) 2014-2022 Frédéric Guillot Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/app/Action/TaskEmail.php b/app/Action/TaskEmail.php index 8a18299af..13210a792 100644 --- a/app/Action/TaskEmail.php +++ b/app/Action/TaskEmail.php @@ -83,8 +83,10 @@ class TaskEmail extends Base $subject = $this->getParam('subject'); foreach ($data["task"] as $key => $value) { - $placeholder = sprintf('{{%s}}', $key); - $subject = str_replace($placeholder, $value, $subject); + if ($value !== null) { + $placeholder = sprintf('{{%s}}', $key); + $subject = str_replace($placeholder, $value, $subject); + } } if (! empty($user['email'])) { diff --git a/app/Controller/CommentListController.php b/app/Controller/CommentListController.php index 63d206634..f9e66dff0 100644 --- a/app/Controller/CommentListController.php +++ b/app/Controller/CommentListController.php @@ -14,12 +14,10 @@ class CommentListController extends BaseController { public function show() { - $project = $this->getProject(); $task = $this->getTask(); $commentSortingDirection = $this->userMetadataCacheDecorator->get(UserMetadataModel::KEY_COMMENT_SORTING_DIRECTION, 'ASC'); $this->response->html($this->template->render('comment_list/show', array( - 'project' => $project, 'task' => $task, 'comments' => $this->commentModel->getAll($task['id'], $commentSortingDirection), 'editable' => $this->helper->user->hasProjectAccess('CommentController', 'edit', $task['project_id']), diff --git a/app/Controller/TaskAjaxController.php b/app/Controller/TaskAjaxController.php index 96a0a27a0..5ab356620 100644 --- a/app/Controller/TaskAjaxController.php +++ b/app/Controller/TaskAjaxController.php @@ -38,7 +38,7 @@ class TaskAjaxController extends BaseController $filter->withFilter(new TaskIdExclusionFilter(array($exclude_task_id))); } - if (ctype_digit($search)) { + if (ctype_digit((string) $search)) { $filter->withFilter(new TaskIdFilter($search)); } else { $filter->withFilter(new TaskTitleFilter($search)); diff --git a/app/Core/DateParser.php b/app/Core/DateParser.php index 9d012d12b..31528a11a 100644 --- a/app/Core/DateParser.php +++ b/app/Core/DateParser.php @@ -175,7 +175,7 @@ class DateParser extends Base */ public function getTimestamp($value) { - if (ctype_digit($value)) { + if (ctype_digit((string) $value)) { return (int) $value; } @@ -263,7 +263,7 @@ class DateParser extends Base */ public function getTimestampFromIsoFormat($value) { - return $this->removeTimeFromTimestamp(ctype_digit($value) ? $value : strtotime($value)); + return $this->removeTimeFromTimestamp(ctype_digit((string) $value) ? $value : strtotime($value)); } /** @@ -291,7 +291,7 @@ class DateParser extends Base { foreach ($fields as $field) { if (! empty($values[$field])) { - if (ctype_digit($values[$field])) { + if (ctype_digit((string) $values[$field])) { $values[$field] = date($format, $values[$field]); } } else { diff --git a/app/Core/Http/RememberMeCookie.php b/app/Core/Http/RememberMeCookie.php index a32b35f3a..31e6df31e 100644 --- a/app/Core/Http/RememberMeCookie.php +++ b/app/Core/Http/RememberMeCookie.php @@ -112,7 +112,7 @@ class RememberMeCookie extends Base '', time() - 3600, $this->helper->url->dir(), - null, + '', $this->request->isHTTPS(), true ); diff --git a/app/Core/Http/Request.php b/app/Core/Http/Request.php index b9907d067..1de87b7c1 100644 --- a/app/Core/Http/Request.php +++ b/app/Core/Http/Request.php @@ -79,7 +79,7 @@ class Request extends Base */ public function getIntegerParam($name, $default_value = 0) { - return isset($this->get[$name]) && ctype_digit($this->get[$name]) ? (int) $this->get[$name] : $default_value; + return isset($this->get[$name]) && ctype_digit((string) $this->get[$name]) ? (int) $this->get[$name] : $default_value; } /** diff --git a/app/Core/Ldap/User.php b/app/Core/Ldap/User.php index 34019df0d..fd1e51f5b 100644 --- a/app/Core/Ldap/User.php +++ b/app/Core/Ldap/User.php @@ -318,7 +318,7 @@ class User * @access public * @return string */ - public function getGroupAdminDn() + public function getGroupAdminDn(): string { return strtolower(LDAP_GROUP_ADMIN_DN); } @@ -329,7 +329,7 @@ class User * @access public * @return string */ - public function getGroupManagerDn() + public function getGroupManagerDn(): string { return LDAP_GROUP_MANAGER_DN; } diff --git a/app/Core/Session/SessionHandler.php b/app/Core/Session/SessionHandler.php index df32a74ea..66c4aa0cb 100644 --- a/app/Core/Session/SessionHandler.php +++ b/app/Core/Session/SessionHandler.php @@ -24,32 +24,38 @@ class SessionHandler implements SessionHandlerInterface $this->db = $db; } + #[\ReturnTypeWillChange] public function close() { return true; } + #[\ReturnTypeWillChange] public function destroy($sessionID) { return $this->db->table(self::TABLE)->eq('id', $sessionID)->remove(); } + #[\ReturnTypeWillChange] public function gc($maxlifetime) { return $this->db->table(self::TABLE)->lt('expire_at', time())->remove(); } + #[\ReturnTypeWillChange] public function open($savePath, $name) { return true; } + #[\ReturnTypeWillChange] public function read($sessionID) { $result = $this->db->table(self::TABLE)->eq('id', $sessionID)->findOneColumn('data'); return $result ?: ''; } + #[\ReturnTypeWillChange] public function write($sessionID, $data) { $lifetime = time() + (ini_get('session.gc_maxlifetime') ?: 1440); diff --git a/app/Core/Translator.php b/app/Core/Translator.php index ac2e2aaea..f516271e6 100644 --- a/app/Core/Translator.php +++ b/app/Core/Translator.php @@ -61,7 +61,7 @@ class Translator array_unshift($args, $this->get($identifier, $identifier)); foreach ($args as &$arg) { - $arg = htmlspecialchars($arg, ENT_QUOTES, 'UTF-8', false); + $arg = htmlspecialchars((string) $arg, ENT_QUOTES, 'UTF-8', false); } return call_user_func_array( diff --git a/app/Event/GenericEvent.php b/app/Event/GenericEvent.php index e87d94816..b6e3dbdfb 100644 --- a/app/Event/GenericEvent.php +++ b/app/Event/GenericEvent.php @@ -41,6 +41,7 @@ class GenericEvent extends BaseEvent implements ArrayAccess return $this->container; } + #[\ReturnTypeWillChange] public function offsetSet($offset, $value) { if (is_null($offset)) { @@ -50,16 +51,19 @@ class GenericEvent extends BaseEvent implements ArrayAccess } } + #[\ReturnTypeWillChange] public function offsetExists($offset) { return isset($this->container[$offset]); } + #[\ReturnTypeWillChange] public function offsetUnset($offset) { unset($this->container[$offset]); } + #[\ReturnTypeWillChange] public function offsetGet($offset) { return isset($this->container[$offset]) ? $this->container[$offset] : null; diff --git a/app/EventBuilder/EventIteratorBuilder.php b/app/EventBuilder/EventIteratorBuilder.php index ba8217532..bfacc651f 100644 --- a/app/EventBuilder/EventIteratorBuilder.php +++ b/app/EventBuilder/EventIteratorBuilder.php @@ -27,6 +27,7 @@ class EventIteratorBuilder implements Iterator { return $this; } + #[\ReturnTypeWillChange] public function rewind() { $this->position = 0; } @@ -34,18 +35,22 @@ class EventIteratorBuilder implements Iterator { /** * @return BaseEventBuilder */ + #[\ReturnTypeWillChange] public function current() { return $this->builders[$this->position]; } + #[\ReturnTypeWillChange] public function key() { return $this->position; } + #[\ReturnTypeWillChange] public function next() { ++$this->position; } + #[\ReturnTypeWillChange] public function valid() { return isset($this->builders[$this->position]); } diff --git a/app/Filter/ProjectStatusFilter.php b/app/Filter/ProjectStatusFilter.php index c1a06eff3..5379f897d 100644 --- a/app/Filter/ProjectStatusFilter.php +++ b/app/Filter/ProjectStatusFilter.php @@ -32,7 +32,7 @@ class ProjectStatusFilter extends BaseFilter implements FilterInterface */ public function apply() { - if (is_int($this->value) || ctype_digit($this->value)) { + if (is_int($this->value) || ctype_digit((string) $this->value)) { $this->query->eq(ProjectModel::TABLE.'.is_active', $this->value); } elseif ($this->value === 'inactive' || $this->value === 'closed' || $this->value === 'disabled') { $this->query->eq(ProjectModel::TABLE.'.is_active', 0); diff --git a/app/Filter/ProjectTypeFilter.php b/app/Filter/ProjectTypeFilter.php index 6afcd2933..601d197be 100644 --- a/app/Filter/ProjectTypeFilter.php +++ b/app/Filter/ProjectTypeFilter.php @@ -32,7 +32,7 @@ class ProjectTypeFilter extends BaseFilter implements FilterInterface */ public function apply() { - if (is_int($this->value) || ctype_digit($this->value)) { + if (is_int($this->value) || ctype_digit((string) $this->value)) { $this->query->eq(ProjectModel::TABLE.'.is_private', $this->value); } elseif ($this->value === 'private') { $this->query->eq(ProjectModel::TABLE.'.is_private', ProjectModel::TYPE_PRIVATE); diff --git a/app/Filter/TaskAssigneeFilter.php b/app/Filter/TaskAssigneeFilter.php index d0e8a9fa8..93250a6bc 100644 --- a/app/Filter/TaskAssigneeFilter.php +++ b/app/Filter/TaskAssigneeFilter.php @@ -54,7 +54,7 @@ class TaskAssigneeFilter extends BaseFilter implements FilterInterface */ public function apply() { - if (is_int($this->value) || ctype_digit($this->value)) { + if (is_int($this->value) || ctype_digit((string) $this->value)) { $this->query->eq(TaskModel::TABLE.'.owner_id', $this->value); } else { switch ($this->value) { diff --git a/app/Filter/TaskCategoryFilter.php b/app/Filter/TaskCategoryFilter.php index 35c52f696..c8ca54ade 100644 --- a/app/Filter/TaskCategoryFilter.php +++ b/app/Filter/TaskCategoryFilter.php @@ -33,7 +33,7 @@ class TaskCategoryFilter extends BaseFilter implements FilterInterface */ public function apply() { - if (is_int($this->value) || ctype_digit($this->value)) { + if (is_int($this->value) || ctype_digit((string) $this->value)) { $this->query->eq(TaskModel::TABLE.'.category_id', $this->value); } elseif ($this->value === 'none') { $this->query->eq(TaskModel::TABLE.'.category_id', 0); diff --git a/app/Filter/TaskColumnFilter.php b/app/Filter/TaskColumnFilter.php index fa925b794..57db13332 100644 --- a/app/Filter/TaskColumnFilter.php +++ b/app/Filter/TaskColumnFilter.php @@ -33,7 +33,7 @@ class TaskColumnFilter extends BaseFilter implements FilterInterface */ public function apply() { - if (is_int($this->value) || ctype_digit($this->value)) { + if (is_int($this->value) || ctype_digit((string) $this->value)) { $this->query->eq(TaskModel::TABLE.'.column_id', $this->value); } else { $this->query->eq(ColumnModel::TABLE.'.title', $this->value); diff --git a/app/Filter/TaskCreatorFilter.php b/app/Filter/TaskCreatorFilter.php index 39bb8ff73..599031000 100644 --- a/app/Filter/TaskCreatorFilter.php +++ b/app/Filter/TaskCreatorFilter.php @@ -53,7 +53,7 @@ class TaskCreatorFilter extends BaseFilter implements FilterInterface */ public function apply() { - if (is_int($this->value) || ctype_digit($this->value)) { + if (is_int($this->value) || ctype_digit((string) $this->value)) { $this->query->eq(TaskModel::TABLE.'.creator_id', $this->value); } else { switch ($this->value) { diff --git a/app/Filter/TaskProjectFilter.php b/app/Filter/TaskProjectFilter.php index 0b5a336be..2b5082b2a 100644 --- a/app/Filter/TaskProjectFilter.php +++ b/app/Filter/TaskProjectFilter.php @@ -33,7 +33,7 @@ class TaskProjectFilter extends BaseFilter implements FilterInterface */ public function apply() { - if (is_int($this->value) || ctype_digit($this->value)) { + if (is_int($this->value) || ctype_digit((string) $this->value)) { $this->query->eq(TaskModel::TABLE.'.project_id', $this->value); } else { $this->query->ilike(ProjectModel::TABLE.'.name', $this->value); diff --git a/app/Filter/TaskStatusFilter.php b/app/Filter/TaskStatusFilter.php index 791ebce6a..b5d55f37b 100644 --- a/app/Filter/TaskStatusFilter.php +++ b/app/Filter/TaskStatusFilter.php @@ -34,7 +34,7 @@ class TaskStatusFilter extends BaseFilter implements FilterInterface { if ($this->value === 'open' || $this->value === 'closed') { $this->query->eq(TaskModel::TABLE.'.is_active', $this->value === 'open' ? TaskModel::STATUS_OPEN : TaskModel::STATUS_CLOSED); - } elseif (is_int($this->value) || ctype_digit($this->value)) { + } elseif (is_int($this->value) || ctype_digit((string) $this->value)) { $this->query->eq(TaskModel::TABLE.'.is_active', $this->value); } diff --git a/app/Filter/TaskSubtaskAssigneeFilter.php b/app/Filter/TaskSubtaskAssigneeFilter.php index 4c5e0f7b6..1e497bd7b 100644 --- a/app/Filter/TaskSubtaskAssigneeFilter.php +++ b/app/Filter/TaskSubtaskAssigneeFilter.php @@ -106,7 +106,7 @@ class TaskSubtaskAssigneeFilter extends BaseFilter implements FilterInterface */ protected function applySubQueryFilter(Table $subquery) { - if (is_int($this->value) || ctype_digit($this->value)) { + if (is_int($this->value) || ctype_digit((string) $this->value)) { $subquery->eq(SubtaskModel::TABLE.'.user_id', $this->value); } else { switch ($this->value) { diff --git a/app/Filter/TaskTitleFilter.php b/app/Filter/TaskTitleFilter.php index f255ac814..475ed604b 100644 --- a/app/Filter/TaskTitleFilter.php +++ b/app/Filter/TaskTitleFilter.php @@ -32,7 +32,7 @@ class TaskTitleFilter extends BaseFilter implements FilterInterface */ public function apply() { - if (ctype_digit($this->value) || (strlen($this->value) > 1 && $this->value[0] === '#' && ctype_digit(substr($this->value, 1)))) { + if (ctype_digit((string) $this->value) || (strlen($this->value) > 1 && $this->value[0] === '#' && ctype_digit(substr($this->value, 1)))) { $this->query->beginOr(); $this->query->eq(TaskModel::TABLE.'.id', str_replace('#', '', $this->value)); $this->query->ilike(TaskModel::TABLE.'.title', '%'.$this->value.'%'); diff --git a/app/Helper/DateHelper.php b/app/Helper/DateHelper.php index 14287db52..6eb73eefe 100644 --- a/app/Helper/DateHelper.php +++ b/app/Helper/DateHelper.php @@ -38,7 +38,7 @@ class DateHelper extends Base return ''; } - if (! ctype_digit($value)) { + if (! ctype_digit((string) $value)) { $value = strtotime($value); } diff --git a/app/Job/UserMentionJob.php b/app/Job/UserMentionJob.php index 355095bba..6b556e47a 100644 --- a/app/Job/UserMentionJob.php +++ b/app/Job/UserMentionJob.php @@ -58,7 +58,7 @@ class UserMentionJob extends BaseJob { $users = array(); - if (preg_match_all('/@([^\s,!:?]+)/', $text, $matches)) { + if ($text !== null && preg_match_all('/@([^\s,!:?]+)/', $text, $matches)) { array_walk($matches[1], function (&$username) { $username = rtrim($username, '.'); }); $users = $this->db->table(UserModel::TABLE) ->columns('id', 'username', 'name', 'email', 'language') diff --git a/app/Locale/bs_BA/translations.php b/app/Locale/bs_BA/translations.php index c803a508a..35ada3ada 100644 --- a/app/Locale/bs_BA/translations.php +++ b/app/Locale/bs_BA/translations.php @@ -1427,4 +1427,5 @@ return array( // 'XBT - Bitcoin' => '', // 'You must select a file to upload as your avatar!' => '', // 'The file you uploaded is not a valid image! (Only *.gif, *.jpg, *.jpeg and *.png are allowed!)' => '', + // 'Automatically set the due date when the task is moved away from a specific column' => '', ); diff --git a/app/Locale/ca_ES/translations.php b/app/Locale/ca_ES/translations.php index 4a367850d..76d965e90 100644 --- a/app/Locale/ca_ES/translations.php +++ b/app/Locale/ca_ES/translations.php @@ -1427,4 +1427,5 @@ return array( // 'XBT - Bitcoin' => '', // 'You must select a file to upload as your avatar!' => '', // 'The file you uploaded is not a valid image! (Only *.gif, *.jpg, *.jpeg and *.png are allowed!)' => '', + // 'Automatically set the due date when the task is moved away from a specific column' => '', ); diff --git a/app/Locale/cs_CZ/translations.php b/app/Locale/cs_CZ/translations.php index e95e908ea..4f1301009 100644 --- a/app/Locale/cs_CZ/translations.php +++ b/app/Locale/cs_CZ/translations.php @@ -1427,4 +1427,5 @@ return array( 'XBT - Bitcoin' => 'XBT - Bitcoin', // 'You must select a file to upload as your avatar!' => '', // 'The file you uploaded is not a valid image! (Only *.gif, *.jpg, *.jpeg and *.png are allowed!)' => '', + // 'Automatically set the due date when the task is moved away from a specific column' => '', ); diff --git a/app/Locale/da_DK/translations.php b/app/Locale/da_DK/translations.php index 365d220ec..f20c7ec63 100644 --- a/app/Locale/da_DK/translations.php +++ b/app/Locale/da_DK/translations.php @@ -1427,4 +1427,5 @@ return array( 'XBT - Bitcoin' => 'XBT - Bitcoin', 'You must select a file to upload as your avatar!' => 'Vælg fil som overføres som profil billede!', 'The file you uploaded is not a valid image! (Only *.gif, *.jpg, *.jpeg and *.png are allowed!)' => 'Overført fil er ikke et gyldigt billede! (*.gif, *.jpg, *.jpeg eller *.png)', + // 'Automatically set the due date when the task is moved away from a specific column' => '', ); diff --git a/app/Locale/de_DE/translations.php b/app/Locale/de_DE/translations.php index bff78728e..97ab7724e 100644 --- a/app/Locale/de_DE/translations.php +++ b/app/Locale/de_DE/translations.php @@ -1427,4 +1427,5 @@ return array( 'XBT - Bitcoin' => 'XBT - Bitcoin', 'You must select a file to upload as your avatar!' => 'Sie müssen eine Datei auswählen, die als Avatar hochgeladen werden soll!', 'The file you uploaded is not a valid image! (Only *.gif, *.jpg, *.jpeg and *.png are allowed!)' => 'Die hochgeladene Datei ist kein gültiges Bild! (Nur *.gif, *.jpg, *.jpeg and *.png sind erlaubt!)', + // 'Automatically set the due date when the task is moved away from a specific column' => '', ); diff --git a/app/Locale/de_DE_du/translations.php b/app/Locale/de_DE_du/translations.php index f644b4870..5ba8b8c10 100644 --- a/app/Locale/de_DE_du/translations.php +++ b/app/Locale/de_DE_du/translations.php @@ -1427,4 +1427,5 @@ return array( 'XBT - Bitcoin' => 'XBT - Bitcoin', 'You must select a file to upload as your avatar!' => 'Du musst eine Datei auswählen, die als Avatar hochgeladen werden soll!', 'The file you uploaded is not a valid image! (Only *.gif, *.jpg, *.jpeg and *.png are allowed!)' => 'Die hochgeladene Datei ist kein gültiges Bild! (Nur *.gif, *.jpg, *.jpeg and *.png sind erlaubt!)', + // 'Automatically set the due date when the task is moved away from a specific column' => '', ); diff --git a/app/Locale/el_GR/translations.php b/app/Locale/el_GR/translations.php index 9a5807021..63c701a11 100644 --- a/app/Locale/el_GR/translations.php +++ b/app/Locale/el_GR/translations.php @@ -1427,4 +1427,5 @@ return array( // 'XBT - Bitcoin' => '', // 'You must select a file to upload as your avatar!' => '', // 'The file you uploaded is not a valid image! (Only *.gif, *.jpg, *.jpeg and *.png are allowed!)' => '', + // 'Automatically set the due date when the task is moved away from a specific column' => '', ); diff --git a/app/Locale/es_ES/translations.php b/app/Locale/es_ES/translations.php index 22f1010a1..10c6155df 100644 --- a/app/Locale/es_ES/translations.php +++ b/app/Locale/es_ES/translations.php @@ -1427,4 +1427,5 @@ return array( 'XBT - Bitcoin' => 'XBT - Bitcoin', // 'You must select a file to upload as your avatar!' => '', // 'The file you uploaded is not a valid image! (Only *.gif, *.jpg, *.jpeg and *.png are allowed!)' => '', + // 'Automatically set the due date when the task is moved away from a specific column' => '', ); diff --git a/app/Locale/es_VE/translations.php b/app/Locale/es_VE/translations.php index d81df4214..7de945cef 100644 --- a/app/Locale/es_VE/translations.php +++ b/app/Locale/es_VE/translations.php @@ -1427,4 +1427,5 @@ return array( 'XBT - Bitcoin' => 'XBT - Bitcoin', // 'You must select a file to upload as your avatar!' => '', // 'The file you uploaded is not a valid image! (Only *.gif, *.jpg, *.jpeg and *.png are allowed!)' => '', + // 'Automatically set the due date when the task is moved away from a specific column' => '', ); diff --git a/app/Locale/fa_IR/translations.php b/app/Locale/fa_IR/translations.php index aa4153a78..75032f751 100644 --- a/app/Locale/fa_IR/translations.php +++ b/app/Locale/fa_IR/translations.php @@ -1427,4 +1427,5 @@ return array( 'XBT - Bitcoin' => 'XBT - بیت کوین', 'You must select a file to upload as your avatar!' => 'برای بارگذاری تصویر نمایه تان باید فایلی انتخاب کنید!', 'The file you uploaded is not a valid image! (Only *.gif, *.jpg, *.jpeg and *.png are allowed!)' => 'فایلی که بارگذاری کردید یک تصویر معتبر نیست! (فقط *.gif, *.jpg, *.jpeg و *.png مجاز هستند!)', + // 'Automatically set the due date when the task is moved away from a specific column' => '', ); diff --git a/app/Locale/fi_FI/translations.php b/app/Locale/fi_FI/translations.php index fe9cfd548..7f5a8a757 100644 --- a/app/Locale/fi_FI/translations.php +++ b/app/Locale/fi_FI/translations.php @@ -1427,4 +1427,5 @@ return array( // 'XBT - Bitcoin' => '', // 'You must select a file to upload as your avatar!' => '', // 'The file you uploaded is not a valid image! (Only *.gif, *.jpg, *.jpeg and *.png are allowed!)' => '', + // 'Automatically set the due date when the task is moved away from a specific column' => '', ); diff --git a/app/Locale/fr_FR/translations.php b/app/Locale/fr_FR/translations.php index 5b187a14a..2045f24fa 100644 --- a/app/Locale/fr_FR/translations.php +++ b/app/Locale/fr_FR/translations.php @@ -1427,4 +1427,5 @@ return array( 'XBT - Bitcoin' => 'XBT - Bitcoin', 'You must select a file to upload as your avatar!' => 'Vous devez sélectionner un fichier à télécharger pour votre avatar !', 'The file you uploaded is not a valid image! (Only *.gif, *.jpg, *.jpeg and *.png are allowed!)' => 'Le fichier que vous avez téléchargé n\'est pas une image valide ! (Seuls * .gif, * .jpg, * .jpeg et * .png sont autorisés !)', + 'Automatically set the due date when the task is moved away from a specific column' => 'Changer automatiquement la date d\'échéance lorsque la tâche est déplacée dans une colonne spécifique', ); diff --git a/app/Locale/hr_HR/translations.php b/app/Locale/hr_HR/translations.php index 0d511802c..3595b0ecc 100644 --- a/app/Locale/hr_HR/translations.php +++ b/app/Locale/hr_HR/translations.php @@ -1427,4 +1427,5 @@ return array( // 'XBT - Bitcoin' => '', // 'You must select a file to upload as your avatar!' => '', // 'The file you uploaded is not a valid image! (Only *.gif, *.jpg, *.jpeg and *.png are allowed!)' => '', + // 'Automatically set the due date when the task is moved away from a specific column' => '', ); diff --git a/app/Locale/hu_HU/translations.php b/app/Locale/hu_HU/translations.php index a009e4fd9..47b018558 100644 --- a/app/Locale/hu_HU/translations.php +++ b/app/Locale/hu_HU/translations.php @@ -1427,4 +1427,5 @@ return array( 'XBT - Bitcoin' => 'XBT – bitcoin', 'You must select a file to upload as your avatar!' => 'Ki kell választania egy fájlt a profilképként való feltöltéshez!', 'The file you uploaded is not a valid image! (Only *.gif, *.jpg, *.jpeg and *.png are allowed!)' => 'A feltöltött fájl nem érvényes kép! Csak *.gif, *.jpg, *.jpeg és *.png engedélyezett.', + // 'Automatically set the due date when the task is moved away from a specific column' => '', ); diff --git a/app/Locale/id_ID/translations.php b/app/Locale/id_ID/translations.php index ebace4a8d..9c00c4987 100644 --- a/app/Locale/id_ID/translations.php +++ b/app/Locale/id_ID/translations.php @@ -1427,4 +1427,5 @@ return array( 'XBT - Bitcoin' => 'XBT - Bitcoin', // 'You must select a file to upload as your avatar!' => '', // 'The file you uploaded is not a valid image! (Only *.gif, *.jpg, *.jpeg and *.png are allowed!)' => '', + // 'Automatically set the due date when the task is moved away from a specific column' => '', ); diff --git a/app/Locale/it_IT/translations.php b/app/Locale/it_IT/translations.php index 9c0c0d944..7876d4897 100644 --- a/app/Locale/it_IT/translations.php +++ b/app/Locale/it_IT/translations.php @@ -1427,4 +1427,5 @@ return array( // 'XBT - Bitcoin' => '', // 'You must select a file to upload as your avatar!' => '', // 'The file you uploaded is not a valid image! (Only *.gif, *.jpg, *.jpeg and *.png are allowed!)' => '', + // 'Automatically set the due date when the task is moved away from a specific column' => '', ); diff --git a/app/Locale/ja_JP/translations.php b/app/Locale/ja_JP/translations.php index a8db6d577..f88f30aa7 100644 --- a/app/Locale/ja_JP/translations.php +++ b/app/Locale/ja_JP/translations.php @@ -1427,4 +1427,5 @@ return array( 'XBT - Bitcoin' => 'XBT - Bitcoin', // 'You must select a file to upload as your avatar!' => '', // 'The file you uploaded is not a valid image! (Only *.gif, *.jpg, *.jpeg and *.png are allowed!)' => '', + // 'Automatically set the due date when the task is moved away from a specific column' => '', ); diff --git a/app/Locale/ko_KR/translations.php b/app/Locale/ko_KR/translations.php index c1eaf361a..aab0c941b 100644 --- a/app/Locale/ko_KR/translations.php +++ b/app/Locale/ko_KR/translations.php @@ -1427,4 +1427,5 @@ return array( // 'XBT - Bitcoin' => '', // 'You must select a file to upload as your avatar!' => '', // 'The file you uploaded is not a valid image! (Only *.gif, *.jpg, *.jpeg and *.png are allowed!)' => '', + // 'Automatically set the due date when the task is moved away from a specific column' => '', ); diff --git a/app/Locale/mk_MK/translations.php b/app/Locale/mk_MK/translations.php index e19603a90..5a9e7efa5 100644 --- a/app/Locale/mk_MK/translations.php +++ b/app/Locale/mk_MK/translations.php @@ -1427,4 +1427,5 @@ return array( 'XBT - Bitcoin' => 'XBT - биткоин', // 'You must select a file to upload as your avatar!' => '', // 'The file you uploaded is not a valid image! (Only *.gif, *.jpg, *.jpeg and *.png are allowed!)' => '', + // 'Automatically set the due date when the task is moved away from a specific column' => '', ); diff --git a/app/Locale/my_MY/translations.php b/app/Locale/my_MY/translations.php index 064ca5490..7a6da1578 100644 --- a/app/Locale/my_MY/translations.php +++ b/app/Locale/my_MY/translations.php @@ -1427,4 +1427,5 @@ return array( // 'XBT - Bitcoin' => '', // 'You must select a file to upload as your avatar!' => '', // 'The file you uploaded is not a valid image! (Only *.gif, *.jpg, *.jpeg and *.png are allowed!)' => '', + // 'Automatically set the due date when the task is moved away from a specific column' => '', ); diff --git a/app/Locale/nb_NO/translations.php b/app/Locale/nb_NO/translations.php index cc010b46b..970d3557b 100644 --- a/app/Locale/nb_NO/translations.php +++ b/app/Locale/nb_NO/translations.php @@ -1427,4 +1427,5 @@ return array( // 'XBT - Bitcoin' => '', // 'You must select a file to upload as your avatar!' => '', // 'The file you uploaded is not a valid image! (Only *.gif, *.jpg, *.jpeg and *.png are allowed!)' => '', + // 'Automatically set the due date when the task is moved away from a specific column' => '', ); diff --git a/app/Locale/nl_NL/translations.php b/app/Locale/nl_NL/translations.php index c40fe8d1a..f9a962cbe 100644 --- a/app/Locale/nl_NL/translations.php +++ b/app/Locale/nl_NL/translations.php @@ -1427,4 +1427,5 @@ return array( // 'XBT - Bitcoin' => '', // 'You must select a file to upload as your avatar!' => '', // 'The file you uploaded is not a valid image! (Only *.gif, *.jpg, *.jpeg and *.png are allowed!)' => '', + // 'Automatically set the due date when the task is moved away from a specific column' => '', ); diff --git a/app/Locale/pl_PL/translations.php b/app/Locale/pl_PL/translations.php index 6e15c51ec..5fede6f25 100644 --- a/app/Locale/pl_PL/translations.php +++ b/app/Locale/pl_PL/translations.php @@ -1427,4 +1427,5 @@ return array( 'XBT - Bitcoin' => 'XBT - Bitcoin', 'You must select a file to upload as your avatar!' => 'Musisz wybrać plik, który chcesz przesłać jako swój awatar!', 'The file you uploaded is not a valid image! (Only *.gif, *.jpg, *.jpeg and *.png are allowed!)' => 'Przesłany plik nie jest prawidłowym obrazem! (Tylko *.gif, *.jpg, *.jpeg i *.png są dozwolone!)', + // 'Automatically set the due date when the task is moved away from a specific column' => '', ); diff --git a/app/Locale/pt_BR/translations.php b/app/Locale/pt_BR/translations.php index bc08b5f12..b8323db89 100644 --- a/app/Locale/pt_BR/translations.php +++ b/app/Locale/pt_BR/translations.php @@ -1427,4 +1427,5 @@ return array( 'XBT - Bitcoin' => 'XBT - Bitcoin', // 'You must select a file to upload as your avatar!' => '', // 'The file you uploaded is not a valid image! (Only *.gif, *.jpg, *.jpeg and *.png are allowed!)' => '', + // 'Automatically set the due date when the task is moved away from a specific column' => '', ); diff --git a/app/Locale/pt_PT/translations.php b/app/Locale/pt_PT/translations.php index 9ae195713..70e6aa169 100644 --- a/app/Locale/pt_PT/translations.php +++ b/app/Locale/pt_PT/translations.php @@ -1427,4 +1427,5 @@ return array( 'XBT - Bitcoin' => 'XBT - Bitcoin', // 'You must select a file to upload as your avatar!' => '', // 'The file you uploaded is not a valid image! (Only *.gif, *.jpg, *.jpeg and *.png are allowed!)' => '', + // 'Automatically set the due date when the task is moved away from a specific column' => '', ); diff --git a/app/Locale/ro_RO/translations.php b/app/Locale/ro_RO/translations.php index 34d491f5a..cd56c2617 100644 --- a/app/Locale/ro_RO/translations.php +++ b/app/Locale/ro_RO/translations.php @@ -1427,4 +1427,5 @@ return array( // 'XBT - Bitcoin' => '', // 'You must select a file to upload as your avatar!' => '', // 'The file you uploaded is not a valid image! (Only *.gif, *.jpg, *.jpeg and *.png are allowed!)' => '', + // 'Automatically set the due date when the task is moved away from a specific column' => '', ); diff --git a/app/Locale/ru_RU/translations.php b/app/Locale/ru_RU/translations.php index a95d6bed7..d5e2c1ad7 100644 --- a/app/Locale/ru_RU/translations.php +++ b/app/Locale/ru_RU/translations.php @@ -1427,4 +1427,5 @@ return array( 'XBT - Bitcoin' => 'XBT - Биткоин', 'You must select a file to upload as your avatar!' => 'Вы должны выбрать файл для загрузки в качестве аватара!', 'The file you uploaded is not a valid image! (Only *.gif, *.jpg, *.jpeg and *.png are allowed!)' => 'Выбранный вами файл не является изображением! (Допустимые расширения: *.gif, *.jpg, *.jpeg, *.png)', + // 'Automatically set the due date when the task is moved away from a specific column' => '', ); diff --git a/app/Locale/sk_SK/translations.php b/app/Locale/sk_SK/translations.php index 555a178b2..999781a5c 100644 --- a/app/Locale/sk_SK/translations.php +++ b/app/Locale/sk_SK/translations.php @@ -1427,4 +1427,5 @@ return array( 'XBT - Bitcoin' => 'XBT – Bitcoin', 'You must select a file to upload as your avatar!' => 'Musíte zvoliť súbor na nahratie ako svoj avatar', 'The file you uploaded is not a valid image! (Only *.gif, *.jpg, *.jpeg and *.png are allowed!)' => 'nahraný súbor nie je paltný obrázok! (Povolené sú len *.gif, *.jpg, *.jpeg a *.png!)', + // 'Automatically set the due date when the task is moved away from a specific column' => '', ); diff --git a/app/Locale/sr_Latn_RS/translations.php b/app/Locale/sr_Latn_RS/translations.php index dcebb7df3..b7df306de 100644 --- a/app/Locale/sr_Latn_RS/translations.php +++ b/app/Locale/sr_Latn_RS/translations.php @@ -1427,4 +1427,5 @@ return array( 'XBT - Bitcoin' => 'XBT - Bitkoin', // 'You must select a file to upload as your avatar!' => '', // 'The file you uploaded is not a valid image! (Only *.gif, *.jpg, *.jpeg and *.png are allowed!)' => '', + // 'Automatically set the due date when the task is moved away from a specific column' => '', ); diff --git a/app/Locale/sv_SE/translations.php b/app/Locale/sv_SE/translations.php index a9d9be4b1..19e0150f1 100644 --- a/app/Locale/sv_SE/translations.php +++ b/app/Locale/sv_SE/translations.php @@ -1148,6 +1148,40 @@ return array( 'Remove this role' => 'Ta bort denna rollen', 'There is no restriction for this role.' => 'Det finns inga restriktioner för denna rollen', 'Only moving task between those columns is permitted' => 'Endast tillåtet att flytta uppgifter mellan dessa kolumner', + // 'Close a task in a specific column when not moved during a given period' => '', + // 'Edit columns' => '', + // 'The column restriction has been created successfully.' => '', + // 'Unable to create this column restriction.' => '', + // 'Column restriction removed successfully.' => '', + // 'Unable to remove this restriction.' => '', + // 'Your custom project role has been created successfully.' => '', + // 'Unable to create custom project role.' => '', + // 'Your custom project role has been updated successfully.' => '', + // 'Unable to update custom project role.' => '', + // 'Custom project role removed successfully.' => '', + // 'Unable to remove this project role.' => '', + // 'The project restriction has been created successfully.' => '', + // 'Unable to create this project restriction.' => '', + // 'Project restriction removed successfully.' => '', + // 'You cannot create tasks in this column.' => '', + // 'Task creation is permitted for this column' => '', + // 'Closing or opening a task is permitted for this column' => '', + // 'Task creation is blocked for this column' => '', + // 'Closing or opening a task is blocked for this column' => '', + // 'Task creation is not permitted' => '', + // 'Closing or opening a task is not permitted' => '', + // 'New drag and drop restriction for the role "%s"' => '', + // 'People belonging to this role will be able to move tasks only between the source and the destination column.' => '', + // 'Remove a column restriction' => '', + // 'Do you really want to remove this column restriction: "%s" to "%s"?' => '', + // 'New column restriction for the role "%s"' => '', + // 'Rule' => '', + // 'Do you really want to remove this column restriction?' => '', + // 'Custom roles' => '', + // 'New custom project role' => '', + // 'Edit custom project role' => '', + // 'Remove a custom role' => '', + // 'Do you really want to remove this custom role: "%s"? All people assigned to this role will become project member.' => '', 'There is no custom role for this project.' => 'Det finns ingen anpassad roll för detta projekt.', 'New project restriction for the role "%s"' => 'Ny projektrestriktion för roll "%s"', 'Restriction' => 'Restriktion', @@ -1390,7 +1424,8 @@ return array( 'MXN - Mexican Peso' => 'MXN - Mexikansk peso', 'Estimated vs actual time per column' => 'Uppskattad kontra faktisk tid per kolumn', 'HUF - Hungarian Forint' => 'HUF - Ungersk forint', - 'XBT - bitcoin' => 'XBT - bitcoin', + // 'XBT - Bitcoin' => '', 'You must select a file to upload as your avatar!' => 'Du måste välja en fil att uppladda som din avatar!', 'The file you uploaded is not a valid image! (Only *.gif, *.jpg, *.jpeg and *.png are allowed!)' => 'Filen du laddade upp är inte ett giltigt bildformat! (Endast *.gif *.jpg *.jpeg samt *.png är tillåtet!)', + // 'Automatically set the due date when the task is moved away from a specific column' => '', ); diff --git a/app/Locale/th_TH/translations.php b/app/Locale/th_TH/translations.php index 33de0bfc6..82fd8e58e 100644 --- a/app/Locale/th_TH/translations.php +++ b/app/Locale/th_TH/translations.php @@ -1427,4 +1427,5 @@ return array( // 'XBT - Bitcoin' => '', // 'You must select a file to upload as your avatar!' => '', // 'The file you uploaded is not a valid image! (Only *.gif, *.jpg, *.jpeg and *.png are allowed!)' => '', + // 'Automatically set the due date when the task is moved away from a specific column' => '', ); diff --git a/app/Locale/tr_TR/translations.php b/app/Locale/tr_TR/translations.php index 4f6d72c4c..f227884f1 100644 --- a/app/Locale/tr_TR/translations.php +++ b/app/Locale/tr_TR/translations.php @@ -1427,4 +1427,5 @@ return array( 'XBT - Bitcoin' => 'XBT - Bitcoin', // 'You must select a file to upload as your avatar!' => '', // 'The file you uploaded is not a valid image! (Only *.gif, *.jpg, *.jpeg and *.png are allowed!)' => '', + // 'Automatically set the due date when the task is moved away from a specific column' => '', ); diff --git a/app/Locale/uk_UA/translations.php b/app/Locale/uk_UA/translations.php index 6547d5de1..539ad3977 100644 --- a/app/Locale/uk_UA/translations.php +++ b/app/Locale/uk_UA/translations.php @@ -1427,4 +1427,5 @@ return array( 'XBT - Bitcoin' => 'XBT – Біткоїн', // 'You must select a file to upload as your avatar!' => '', // 'The file you uploaded is not a valid image! (Only *.gif, *.jpg, *.jpeg and *.png are allowed!)' => '', + // 'Automatically set the due date when the task is moved away from a specific column' => '', ); diff --git a/app/Locale/vi_VN/translations.php b/app/Locale/vi_VN/translations.php index e57adb5f7..f995233cc 100644 --- a/app/Locale/vi_VN/translations.php +++ b/app/Locale/vi_VN/translations.php @@ -1427,4 +1427,5 @@ return array( // 'XBT - Bitcoin' => '', // 'You must select a file to upload as your avatar!' => '', // 'The file you uploaded is not a valid image! (Only *.gif, *.jpg, *.jpeg and *.png are allowed!)' => '', + // 'Automatically set the due date when the task is moved away from a specific column' => '', ); diff --git a/app/Locale/zh_CN/translations.php b/app/Locale/zh_CN/translations.php index 53db1eee8..aa35b47eb 100644 --- a/app/Locale/zh_CN/translations.php +++ b/app/Locale/zh_CN/translations.php @@ -1427,4 +1427,5 @@ return array( 'XBT - Bitcoin' => 'XBT - 比特币', 'You must select a file to upload as your avatar!' => '你必须选择一张图片作为你的头像', 'The file you uploaded is not a valid image! (Only *.gif, *.jpg, *.jpeg and *.png are allowed!)' => '你所上传的文件不是有效图像!(只有*.gif, *.jpg, *.jpeg and *.png才被允许!)', + // 'Automatically set the due date when the task is moved away from a specific column' => '', ); diff --git a/app/Locale/zh_TW/translations.php b/app/Locale/zh_TW/translations.php index f549e7686..52db20ff7 100644 --- a/app/Locale/zh_TW/translations.php +++ b/app/Locale/zh_TW/translations.php @@ -1427,4 +1427,5 @@ return array( // 'XBT - Bitcoin' => '', // 'You must select a file to upload as your avatar!' => '', // 'The file you uploaded is not a valid image! (Only *.gif, *.jpg, *.jpeg and *.png are allowed!)' => '', + // 'Automatically set the due date when the task is moved away from a specific column' => '', ); diff --git a/app/Template/comment_list/show.php b/app/Template/comment_list/show.php index 5ebd7526c..a39891f45 100644 --- a/app/Template/comment_list/show.php +++ b/app/Template/comment_list/show.php @@ -18,7 +18,6 @@ render('comment/show', array( 'comment' => $comment, 'task' => $task, - 'project' => $project, 'editable' => $editable, 'is_public' => isset($is_public) && $is_public, )) ?> diff --git a/app/check_setup.php b/app/check_setup.php index 6d6baf667..a8984df30 100644 --- a/app/check_setup.php +++ b/app/check_setup.php @@ -34,8 +34,3 @@ foreach (array('gd', 'mbstring', 'hash', 'openssl', 'json', 'hash', 'ctype', 'fi if (ini_get('arg_separator.output') === '&') { ini_set('arg_separator.output', '&'); } - -// Make sure we can read files with "\r", "\r\n" and "\n" -if (ini_get('auto_detect_line_endings') != 1) { - ini_set("auto_detect_line_endings", 1); -} diff --git a/assets/css/app.min.css b/assets/css/app.min.css index 4c668351a..50e65f1fc 100644 --- a/assets/css/app.min.css +++ b/assets/css/app.min.css @@ -1 +1 @@ -:root{--color-primary:#333;--color-light:#999;--color-lighter:#dedede;--color-dark:#000;--color-medium:#555;--color-error:#b94a48;--link-color-primary:#36C;--link-color-focus:#DF5353;--link-color-hover:#333;--alert-color-default:#c09853;--alert-color-success:#468847;--alert-color-error:#b94a48;--alert-color-info:#3a87ad;--alert-color-normal:#333;--alert-background-color-default:#fcf8e3;--alert-background-color-success:#dff0d8;--alert-background-color-error:#f2dede;--alert-background-color-info:#d9edf7;--alert-background-color-normal:#f0f0f0;--alert-border-color-default:#fbeed5;--alert-border-color-success:#d6e9c6;--alert-border-color-error:#eed3d7;--alert-border-color-info:#bce8f1;--alert-border-color-normal:#ddd;--button-default-color:#333;--button-default-background-color:#f5f5f5;--button-default-border-color:#ddd;--button-default-color-focus:#000;--button-default-background-color-focus:#fafafa;--button-default-border-color-focus:#bbb;--button-primary-color:#fff;--button-primary-background-color:#4d90fe;--button-primary-border-color:#3079ed;--button-primary-color-focus:#fff;--button-primary-background-color-focus:#357ae8;--button-primary-border-color-focus:#3079ed;--button-danger-color:#fff;--button-danger-background-color:#d14836;--button-danger-border-color:#b0281a;--button-danger-color-focus:#fff;--button-danger-background-color-focus:#c53727;--button-danger-border-color-focus:#b0281a;--button-disabled-color:#ccc;--button-disabled-background-color:#f7f7f7;--button-disabled-border-color:#ccc;--avatar-color-letter:#fff;--activity-title-color:#000;--activity-title-border-color:#efefef;--activity-event-background-color:#fafafa;--activity-event-hover-color:#fff8dc;--user-mention-color:#000;--board-task-limit-color:#DF5353}h1,li,ul,ol,table,tr,td,th,p,blockquote,body{margin:0;padding:0}body{font-size:100%;padding-bottom:10px;color:var(--color-primary);font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;text-rendering:optimizeLegibility}small{font-size:.8em}hr{border:0;height:0;border-top:1px solid rgba(0,0,0,.1);border-bottom:1px solid rgba(255,255,255,.3)}.page{margin-left:10px;margin-right:10px}.margin-top{margin-top:20px}.margin-bottom{margin-bottom:20px}.pull-right{text-align:right}ul.no-bullet li{list-style-type:none;margin-left:0}#app-loading-icon{position:fixed;right:3px;bottom:3px}.assign-me{vertical-align:bottom}a{color:var(--link-color-primary);border:none}a:focus{color:var(--link-color-focus);outline:0;text-decoration:none}a:hover{color:var(--link-color-hover);text-decoration:none}a .fa{color:var(--color-primary);padding-right:3px;text-decoration:none}h1,h2,h3{font-weight:400;color:var(--color-primary)}h1{font-size:1.5em}h2{font-size:1.4em;margin-bottom:10px}h3{margin-top:10px;font-size:1.2em}table{width:100%;border-collapse:collapse;border-spacing:0;margin-bottom:20px}table.table-fixed{table-layout:fixed;white-space:nowrap}table.table-fixed th{overflow:hidden}table.table-fixed td{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}table.table-small{font-size:.8em}table.table-striped tr:nth-child(odd){background:#fefefe}@media (max-width:768px){table.table-scrolling{overflow-x:auto;display:inline-block;vertical-align:top;max-width:100%;white-space:nowrap}}table th{text-align:left;padding:.5em 3px;border:1px solid #eee;background:#fbfbfb}table th a{text-decoration:none;color:var(--color-primary)}table th a:focus,table th a:hover{text-decoration:underline}table td{border:1px solid #eee;padding:.5em 3px;vertical-align:top}table td li{margin-left:20px}.column-1{width:1%}.column-2{width:2%}.column-3{width:3%}.column-4{width:4%}.column-5{width:5%}.column-6{width:6%}.column-7{width:7%}.column-8{width:8%}.column-9{width:9%}.column-10{width:10%}.column-11{width:11%}.column-12{width:12%}.column-13{width:13%}.column-14{width:14%}.column-15{width:15%}.column-16{width:16%}.column-17{width:17%}.column-18{width:18%}.column-19{width:19%}.column-20{width:20%}.column-21{width:21%}.column-22{width:22%}.column-23{width:23%}.column-24{width:24%}.column-25{width:25%}.column-26{width:26%}.column-27{width:27%}.column-28{width:28%}.column-29{width:29%}.column-30{width:30%}.column-31{width:31%}.column-32{width:32%}.column-33{width:33%}.column-34{width:34%}.column-35{width:35%}.column-36{width:36%}.column-37{width:37%}.column-38{width:38%}.column-39{width:39%}.column-40{width:40%}.column-41{width:41%}.column-42{width:42%}.column-43{width:43%}.column-44{width:44%}.column-45{width:45%}.column-46{width:46%}.column-47{width:47%}.column-48{width:48%}.column-49{width:49%}.column-50{width:50%}.column-51{width:51%}.column-52{width:52%}.column-53{width:53%}.column-54{width:54%}.column-55{width:55%}.column-56{width:56%}.column-57{width:57%}.column-58{width:58%}.column-59{width:59%}.column-60{width:60%}.column-61{width:61%}.column-62{width:62%}.column-63{width:63%}.column-64{width:64%}.column-65{width:65%}.column-66{width:66%}.column-67{width:67%}.column-68{width:68%}.column-69{width:69%}.column-70{width:70%}.column-71{width:71%}.column-72{width:72%}.column-73{width:73%}.column-74{width:74%}.column-75{width:75%}.column-76{width:76%}.column-77{width:77%}.column-78{width:78%}.column-79{width:79%}.column-80{width:80%}.column-81{width:81%}.column-82{width:82%}.column-83{width:83%}.column-84{width:84%}.column-85{width:85%}.column-86{width:86%}.column-87{width:87%}.column-88{width:88%}.column-89{width:89%}.column-90{width:90%}.column-91{width:91%}.column-92{width:92%}.column-93{width:93%}.column-94{width:94%}.column-95{width:95%}.column-96{width:96%}.column-97{width:97%}.column-98{width:98%}.column-99{width:99%}.column-100{width:100%}.draggable-row-handle{cursor:move;color:#dedede}.draggable-row-handle:hover{color:var(--color-primary)}tr.draggable-item-selected{background:#fff;border:2px solid #666;box-shadow:4px 2px 10px -4px rgba(0,0,0,.55)}tr.draggable-item-selected td{border-top:none;border-bottom:none}tr.draggable-item-selected td:first-child{border-left:none}tr.draggable-item-selected td:last-child{border-right:none}.table-stripped tr.draggable-item-hover,.table-stripped tr.draggable-item-hover{background:#FEFFF2}.table-list{font-size:.85em;margin-bottom:20px}.table-list-header{background:#fbfbfb;border:1px solid #e5e5e5;border-radius:5px 5px 0 0;line-height:28px;padding-left:3px;padding-right:3px}.table-list-header a{color:#333;font-weight:500;text-decoration:none;margin-right:10px}.table-list-header a:hover,.table-list-header a:focus{color:#767676}.table-list-header .table-list-header-count{color:#767676;display:inline-block;float:left}.table-list-header .table-list-header-menu{text-align:right}.table-list-row{padding-left:3px;padding-right:3px;border-bottom:1px solid #e5e5e5;border-right:1px solid #e5e5e5}.table-list-row.table-border-left{border-left:1px solid #e5e5e5}.table-list-row:nth-child(odd){background:#fefefe}.table-list-row:last-child{border-radius:0 0 5px 5px}.table-list-row:hover{background:#fff8dc;border-bottom:1px solid #ffeb8e;border-right:1px solid #ffeb8e}.table-list-row .table-list-title{font-weight:500;line-height:23px}.table-list-row .table-list-title.status-closed{text-decoration:line-through;margin-right:10px}.table-list-row .table-list-title.status-closed a{font-style:italic}.table-list-row .table-list-title a{color:#333;text-decoration:none}.table-list-row .table-list-title a:hover,.table-list-row .table-list-title a:focus{text-decoration:underline}.table-list-row .table-list-details{color:#999;font-weight:300;line-height:20px}.table-list-row .table-list-details span{margin-left:5px}.table-list-row .table-list-details span:first-child{margin-left:0}.table-list-row .table-list-details li{display:inline;list-style-type:none}.table-list-row .table-list-details li:after{content:', '}.table-list-row .table-list-details li:last-child:after{content:''}.table-list-row .table-list-details strong{font-weight:400;color:#555}.table-list-row .table-list-details-with-icons{float:left}@media (max-width:768px){.table-list-row .table-list-details-with-icons{float:none}}.table-list-row .table-list-icons{font-size:.8em;text-align:right;line-height:30px}@media (max-width:768px){.table-list-row .table-list-icons{text-align:left;line-height:20px}}.table-list-row .table-list-icons span{margin-left:5px}.table-list-row .table-list-icons a{text-decoration:none}.table-list-row .table-list-icons a:hover{color:#333}.table-list-row .table-list-icons a:hover i{color:#333}.table-list-category{font-size:.9em;font-weight:500;color:#000;padding:1px 2px 1px 2px;border-radius:3px;background:#fcfcfc;border:1px solid #ccc}.table-list-category a{text-decoration:none;color:#000}.table-list-category a:hover{color:#36c}fieldset{border:1px solid #ddd;margin-top:10px}legend{font-weight:500;font-size:1.2em}label{cursor:pointer;display:block;margin-top:10px;font-weight:400}input[type="number"],input[type="date"],input[type="email"],input[type="password"],input[type="text"]:not(.input-addon-field){color:var(--color-light);border:1px solid #ccc;width:300px;max-width:95%;font-size:1em;height:25px;padding-bottom:0;padding-left:4px;font-family:sans-serif;-webkit-appearance:none;-moz-appearance:none}input[type="number"]::-webkit-input-placeholder,input[type="date"]::-webkit-input-placeholder,input[type="email"]::-webkit-input-placeholder,input[type="password"]::-webkit-input-placeholder,input[type="text"]:not(.input-addon-field)::-webkit-input-placeholder{color:#dedede}input[type="number"]::-moz-placeholder,input[type="date"]::-moz-placeholder,input[type="email"]::-moz-placeholder,input[type="password"]::-moz-placeholder,input[type="text"]:not(.input-addon-field)::-moz-placeholder{color:#dedede}input[type="number"]:-ms-input-placeholder,input[type="date"]:-ms-input-placeholder,input[type="email"]:-ms-input-placeholder,input[type="password"]:-ms-input-placeholder,input[type="text"]:not(.input-addon-field):-ms-input-placeholder{color:#dedede}input[type="number"]:focus,input[type="date"]:focus,input[type="email"]:focus,input[type="password"]:focus,input[type="text"]:focus{color:#000;border-color:rgba(82,168,236,.8);outline:0;box-shadow:0 0 8px rgba(82,168,236,.6)}input[type="number"]{width:70px}input[type="text"]:not(.input-addon-field).form-numeric{width:70px}input[type="text"]:not(.input-addon-field).form-datetime,input[type="text"]:not(.input-addon-field).form-date{width:150px}input[type="text"]:not(.input-addon-field).form-input-large{width:400px}input[type="text"]:not(.input-addon-field).form-input-small{width:150px}textarea:focus{color:#000;border-color:rgba(82,168,236,.8);outline:0;box-shadow:0 0 8px rgba(82,168,236,.6)}textarea{padding:4px;border:1px solid #ccc;width:400px;max-width:99%;height:200px;font-family:sans-serif;font-size:1em}textarea::-webkit-input-placeholder{color:#dedede}textarea::-moz-placeholder{color:#dedede}textarea:-ms-input-placeholder{color:#dedede}select{font-size:1em;max-width:95%}select:focus{outline:0}select[multiple]{width:300px}.tag-autocomplete{width:400px}span.select2-container{margin-top:2px}.form-actions{padding-top:20px;clear:both}.form-required{color:red;padding-left:5px;font-weight:700}@media (max-width:480px){.form-required{display:none}}input[type="text"].form-max-width{width:100%}input.form-error,textarea.form-error{border:2px solid #b94a48}input.form-error:focus,textarea.form-error:focus{box-shadow:none;border:2px solid #b94a48}.form-errors{color:#b94a48;list-style-type:none}ul.form-errors li{margin-left:0}.form-help{font-size:.8em;color:brown;margin-bottom:15px}.form-inline{padding:0;margin:0;border:none}.form-inline label{display:inline;padding-right:3px}.form-inline input,.form-inline select{margin:0 15px 0 0}.form-inline .form-required{display:none}.form-inline .form-actions{display:inline-block}.form-inline .js-submit-buttons-rendered{display:inline-block}.form-inline-group{display:inline}.form-columns{display:-webkit-flex;display:flex;-webkit-flex-direction:row;flex-direction:row;-webkit-flex-wrap:wrap;flex-wrap:wrap;-webkit-justify-content:flex-start;justify-content:flex-start}.form-columns .form-column{margin-right:25px;flex-grow:1}.form-columns fieldset{margin-top:0}.form-login{max-width:350px;margin:5% auto 0}@media (max-width:480px){.form-login{margin-left:5px}}.form-login li{margin-left:25px;line-height:25px}.form-login h2{margin-bottom:30px;font-weight:700}.reset-password{margin-top:20px;margin-bottom:20px}.reset-password a{color:var(--color-light)}.input-addon{display:flex}.input-addon-field{flex:1;font-size:1em;color:var(--color-light);margin:0;-webkit-appearance:none;-moz-appearance:none}.input-addon-field:first-child{border-radius:5px 0 0 5px}.input-addon-field:last-child{border-radius:0 5px 5px 0}.input-addon-item{background-color:rgba(147,128,108,.1);color:#666;font:inherit;font-weight:400}.input-addon-item:first-child{border-radius:5px 0 0 5px}.input-addon-item:last-child{border-radius:0 5px 5px 0}@media (max-width:480px){.input-addon-item .dropdown .fa-caret-down{display:none}}.input-addon-field,.input-addon-item{border:1px solid rgba(147,128,108,.25);padding:4px .75em}.input-addon-field:not(:first-child),.input-addon-item:not(:first-child){border-left:0}.project-header .filter-box-component .input-addon{min-width:280px}.input-addon .input-addon-field{flex:1 1 auto;width:1%!important}@media (max-width:400px){.input-addon-item{padding:3px}}.icon-success{color:#468847}.icon-error{color:#b94a48}.icon-fade-out{opacity:1;animation:icon-fadeout 5s linear forwards}@keyframes icon-fadeout{0%{opacity:1}100%{opacity:0}}.alert{padding:8px 35px 8px 14px;margin-top:5px;margin-bottom:5px;color:var(--alert-color-default);background-color:var(--alert-background-color-default);border:1px solid var(--alert-border-color-default);border-radius:4px}.alert-success{color:var(--alert-color-success);background-color:var(--alert-background-color-success);border-color:var(--alert-border-color-success)}.alert-error{color:var(--alert-color-error);background-color:var(--alert-background-color-error);border-color:var(--alert-border-color-error)}.alert-info{color:var(--alert-color-info);background-color:var(--alert-background-color-info);border-color:var(--alert-border-color-info)}.alert-normal{color:var(--alert-color-normal);background-color:var(--alert-background-color-normal);border-color:var(--alert-border-color-normal)}.alert ul{margin-top:10px;margin-bottom:10px}.alert li{margin-left:25px}.alert-fade-out{text-align:center;position:fixed;bottom:0;left:20%;width:60%;padding-top:5px;padding-bottom:5px;margin-bottom:0;border-width:1px 0 0;border-radius:4px 4px 0 0;z-index:9999;opacity:1;animation:fadeout 5s linear forwards}@keyframes fadeout{0%{opacity:1}100%{opacity:0;visibility:hidden}}a.btn{text-decoration:none}.btn{-webkit-appearance:none;-moz-appearance:none;font-size:1.2em;font-weight:400;cursor:pointer;display:inline-block;border-radius:2px;padding:3px 10px;margin:0;border:1px solid var(--button-default-border-color);background:var(--button-default-background-color);color:var(--button-default-color)}.btn:hover,.btn:focus{border-color:var(--button-default-border-color-focus);background:var(--button-default-background-color-focus);color:var(--button-default-color-focus)}.btn-red{border-color:var(--button-danger-border-color);background:var(--button-danger-background-color);color:var(--button-danger-color)}.btn-red:hover,.btn-red:focus{border-color:var(--button-danger-border-color-focus);background:var(--button-danger-background-color-focus);color:var(--button-danger-color-focus)}.btn-blue{border-color:var(--button-primary-border-color);background:var(--button-primary-background-color);color:var(--button-primary-color)}.btn-blue:hover,.btn-blue:focus{border-color:var(--button-primary-border-color-focus);background:var(--button-primary-background-color-focus);color:var(--button-primary-color-focus)}.btn:disabled{color:var(--button-disabled-color);border-color:var(--button-disabled-border-color);background:var(--button-disabled-background-color)}.buttons-header{font-size:.8em;margin-top:5px;margin-bottom:15px}.tooltip i.fa{cursor:pointer}.tooltip .fa-info-circle{color:var(--color-light)}#tooltip-container{padding:5px;background:#fff;border:1px solid #ddd;border-radius:4px;box-shadow:0 6px 12px #aaa;position:absolute;min-width:350px}#tooltip-container .markdown p:last-child{margin-bottom:0}#tooltip-container .tooltip-large{width:600px}h2 .dropdown ul{display:none}.dropdown{display:inline;position:relative}.dropdown ul{display:none}.dropdown-smaller{font-size:.85em}ul.dropdown-submenu-open{display:block;position:absolute;z-index:1000;min-width:285px;list-style:none;margin:3px 0 0 1px;padding:6px 0;background-color:#fff;border:1px solid #b2b2b2;border-radius:3px;box-shadow:0 1px 3px rgba(0,0,0,.15)}.dropdown-submenu-open li{display:block;margin:0;padding:8px 10px;font-size:.9em;border-bottom:1px solid #f8f8f8;cursor:pointer}.dropdown-submenu-open li.no-hover{cursor:default}.dropdown-submenu-open li:last-child{border:none}.dropdown-submenu-open li:not(.no-hover):hover{background:#4078C0;color:#fff}.dropdown-submenu-open li:hover a{color:#fff}.dropdown-submenu-open li:hover i{color:#fff}.dropdown-submenu-open a{text-decoration:none;color:#333}.dropdown-submenu-open a:focus{text-decoration:underline}.dropdown-menu-link-text,.dropdown-menu-link-icon{color:#333;text-decoration:none}.dropdown-menu-link-text:hover{text-decoration:underline}td a.dropdown-menu strong{color:#333}td a.dropdown-menu strong i{color:#333}td a.dropdown-menu i{color:#dedede}td a.dropdown-menu:hover strong{color:#555}td a.dropdown-menu:hover strong i{color:#555}td a.dropdown-menu:hover i{color:#333}.accordion-title{font-size:1.2em;cursor:pointer;margin-top:10px}.accordion-content{margin-top:15px;margin-bottom:25px}#select-dropdown-menu{position:absolute;display:block;z-index:1000;min-width:160px;padding:5px 0;background:#fff;list-style:none;border:1px solid #ccc;border-radius:3px;box-shadow:0 6px 12px rgba(0,0,0,.175);overflow:scroll}.select-dropdown-menu-item{white-space:nowrap;overflow:hidden;padding:3px 10px;color:var(--color-medium);cursor:pointer;border-bottom:1px solid #f8f8f8;line-height:1.5em;font-weight:400}.select-dropdown-menu-item.active{color:#fff;background:#428bca}.select-dropdown-menu-item:last-child{border:none}.select-dropdown-input-container{position:relative;border:1px solid #ccc;border-radius:5px;background-color:#fff;max-width:300px}.select-dropdown-input-container input.select-dropdown-input{margin:0 0 0 5px;border:none;height:23px;width:270px}.select-dropdown-input-container input.select-dropdown-input:focus{border:none;box-shadow:none}.select-dropdown-input-container .select-dropdown-chevron{color:var(--color-medium);position:absolute;top:4px;right:5px;cursor:pointer}.select-dropdown-input-container .select-loading-icon{color:var(--color-medium);position:absolute;top:4px;right:5px}#suggest-menu{position:absolute;display:block;z-index:1000;min-width:160px;padding:5px 0;background:#fff;list-style:none;border:1px solid #ccc;border-radius:3px;box-shadow:0 6px 12px rgba(0,0,0,.175)}.suggest-menu-item{white-space:nowrap;padding:3px 10px;color:var(--color-primary);font-weight:700;cursor:pointer}.suggest-menu-item.active{color:#fff;background:#428bca}.suggest-menu-item.active small{color:#fff}.suggest-menu-item small{color:var(--color-light);font-weight:400}#modal-overlay{position:fixed;top:0;left:0;width:100%;height:100%;background:rgba(0,0,0,.9);overflow:auto;z-index:100}#modal-box{position:fixed;max-height:calc(100% - 30px);top:2%;left:50%;transform:translateX(-50%);background:#fff;overflow:auto;border-radius:5px}#modal-content{padding:0 5px 5px}#modal-header{text-align:right;padding-right:5px}#modal-close-button{color:var(--color-primary)}#modal-close-button:hover{color:var(--color-error)}.pagination{text-align:center;font-size:.9em}.pagination-showing{margin-right:5px;padding-right:5px;border-right:1px solid #999}.pagination-next{margin-left:5px}.pagination-previous{margin-right:5px}header{display:flex;flex-wrap:wrap;padding:5px 10px;margin-bottom:5px;border-bottom:1px solid #dedede;background-color:#fbfbfb}header .title-container{flex:1;min-width:300px}@media (max-width:480px){header .title-container{order:3}}header .board-selector-container{min-width:320px;display:flex;align-items:center}@media (max-width:480px){header .board-selector-container{order:2;min-width:300px}header .board-selector-container input[type=text]{max-width:280px}}header .menus-container{min-width:120px;display:flex;align-items:center;justify-content:flex-end}@media (max-width:480px){header .menus-container{order:1;margin-bottom:5px;margin-left:auto}}header h1{font-size:1.5em}header h1 .tooltip{opacity:.3;font-size:.7em}a i.web-notification-icon{color:var(--link-color-primary)}a i.web-notification-icon:focus,a i.web-notification-icon:hover{color:#000}.logo a{opacity:.5;color:#d40000;text-decoration:none}.logo span{color:var(--color-primary)}.logo a:hover{opacity:.8;color:var(--color-primary)}.logo a:focus span,.logo a:hover span{color:#d40000}.page-header{margin-bottom:20px}.page-header .dropdown{padding-right:10px}.page-header h2{margin:0;padding:0;font-weight:700;border-bottom:1px dotted #ccc}.page-header h2 a{color:var(--color-primary);text-decoration:none}.page-header h2 a:focus,.page-header h2 a:hover{color:var(--color-light)}.page-header ul{text-align:left;margin-top:5px;display:inline-block}.page-header li{display:inline;padding-right:15px}@media (max-width:480px){.page-header li{display:block;line-height:1.5em}}.page-header li.active a{color:var(--color-primary);text-decoration:none;font-weight:700}.page-header li.active a:hover,.page-header li.active a:focus{text-decoration:underline}.menu-inline{margin-bottom:5px}.menu-inline li{display:inline;padding-right:15px}.menu-inline li .active a{font-weight:700;color:#000;text-decoration:none}.sidebar-container{height:100%;display:flex;flex-flow:row}@media (max-width:768px){.sidebar-container{flex-flow:wrap}}.sidebar-content{padding-left:10px;flex:1 100%;max-width:85%;overflow-wrap:break-word}@media (max-width:768px){.sidebar-content{padding-left:0;order:1;max-width:100%}}@media only screen and (min-device-width:768px) and (max-device-width:1024px) and (orientation:landscape) and (-webkit-min-device-pixel-ratio:1){.sidebar-content{max-width:75%}}.sidebar{max-width:25%;min-width:230px}@media (max-width:768px){.sidebar{flex:1 auto;order:2}}.sidebar h2{margin-top:0}.sidebar>ul a{text-decoration:none;color:var(--color-light);font-weight:300}.sidebar>ul a:hover{color:var(--color-primary)}.sidebar>ul li{list-style-type:none;line-height:35px;border-bottom:1px dotted #efefef;padding-left:13px}.sidebar>ul li:hover{border-left:5px solid #555;padding-left:8px}.sidebar>ul li.active{border-left:5px solid #333;padding-left:8px}.sidebar>ul li.active a{color:var(--color-primary);font-weight:700}.sidebar-icons>ul li{padding-left:0}.sidebar-icons>ul li:hover,.sidebar-icons>ul li.active{padding-left:0;border-left:none}.sidebar>ul li.active a:focus,.sidebar>ul li.active a:hover{color:var(--color-medium)}.sidebar>ul li:last-child{margin-bottom:15px}.avatar img{vertical-align:bottom}.avatar-left{float:left;margin-right:10px}.avatar-inline{display:inline-block;margin-right:3px}.avatar-48 img,.avatar-48 div{border-radius:30px}.avatar-48 .avatar-letter{line-height:48px;width:48px;font-size:25px}.avatar-20 img,.avatar-20 div{border-radius:10px}.avatar-20 .avatar-letter{line-height:20px;width:20px;font-size:11px}.avatar-letter{color:var(--avatar-color-letter);text-align:center}#file-dropzone,#screenshot-zone{position:relative;border:2px dashed #ccc;width:99%;height:250px;overflow:auto}#file-dropzone-inner,#screenshot-inner{position:absolute;left:0;bottom:48%;width:100%;text-align:center;color:#aaa}#screenshot-zone.screenshot-pasted{border:2px solid #333}#file-list{margin:20px}#file-list li{list-style-type:none;padding-top:8px;padding-bottom:8px;border-bottom:1px dotted #ddd;width:95%}#file-list li .file-error{font-weight:700;color:#b94a48}.file-thumbnails{display:-webkit-flex;display:flex;-webkit-flex-direction:row;flex-direction:row;-webkit-flex-wrap:wrap;flex-wrap:wrap;-webkit-justify-content:flex-start;justify-content:flex-start}.file-thumbnail{width:250px;border:1px solid #efefef;border-radius:5px;margin-bottom:20px;box-shadow:4px 2px 10px -6px rgba(0,0,0,.55);margin-right:15px}.file-thumbnail img{cursor:pointer;border-top-left-radius:5px;border-top-right-radius:5px}.file-thumbnail img:hover{opacity:.5}.file-thumbnail-content{padding-left:8px;padding-right:8px}.file-thumbnail-title{font-weight:700;font-size:.9em;color:var(--color-medium);overflow:hidden;text-overflow:ellipsis}.file-thumbnail-description{font-size:.8em;color:var(--color-light);margin-top:8px;margin-bottom:5px}.file-viewer{position:relative}.file-viewer img{max-width:95%;max-height:85%;margin-top:10px}.color-picker{width:220px}.color-picker-option{height:25px}.color-picker-square{display:inline-block;width:18px;height:18px;margin-right:5px;border:1px solid #000}.color-picker-label{display:inline-block;vertical-align:bottom;padding-bottom:3px}.filter-box{max-width:1024px}.action-menu{color:var(--color-primary);text-decoration:none}.action-menu:hover,.action-menu:focus{text-decoration:underline}.js-project-creation-options{max-width:500px;border-left:3px dotted #efefef;margin-top:20px;padding-left:15px;padding-bottom:5px;padding-top:5px}.project-overview-columns{display:-webkit-flex;display:flex;-webkit-flex-direction:row;flex-direction:row;-webkit-flex-wrap:wrap;flex-wrap:wrap;-webkit-align-items:center;align-items:center;-webkit-justify-content:center;justify-content:center;margin-bottom:20px;font-size:1.4em}@media (max-width:480px){.project-overview-columns{display:block}}.project-overview-column{text-align:center;margin-right:3%;margin-top:5px;padding:3px 15px 3px 15px;border:1px dashed #ddd}@media (max-width:480px){.project-overview-column{text-align:left}}.project-overview-column small{color:var(--color-light)}.project-overview-column strong{color:var(--color-medium);display:block}@media (max-width:480px){.project-overview-column strong{display:inline}}.project-header{margin-bottom:8px}.project-header .dropdown-component{margin-top:4px;margin-right:5px;float:left}@media (max-width:768px){.project-header .dropdown-component{float:none}}.project-header .views-switcher-component{margin-top:4px;float:left}@media (max-width:768px){.project-header .views-switcher-component{float:none;margin-bottom:10px}}.project-header .filter-box-component form{margin:0}.views{margin-right:10px;margin-top:1px;font-size:.9em}@media (max-width:560px){.views{width:100%}}@media (max-width:768px){.views{margin-top:10px;font-size:1em}}@media (max-width:480px){.views{margin-top:5px}}.views li{white-space:nowrap;background:#fafafa;border:1px solid #ddd;border-right:none;padding:4px 8px;display:inline}@media (max-width:560px){.views li{display:block;margin-top:5px;border-radius:5px;border:1px solid #ddd}}.views li.active a{font-weight:700;color:#000;text-decoration:none}.views li:first-child{border-top-left-radius:5px;border-bottom-left-radius:5px}.views li:last-child{border-right:1px solid #ddd;border-top-right-radius:5px;border-bottom-right-radius:5px}.views a{color:var(--color-medium);text-decoration:none}.views a:hover{color:var(--color-primary);text-decoration:underline}.dashboard-project-stats small{margin-right:10px;color:var(--color-light)}.dashboard-table-link{font-weight:700;color:#000;text-decoration:none}.dashboard-table-link:focus,.dashboard-table-link:hover{color:var(--color-light)}.public-board{margin-top:5px}.public-task{max-width:800px;margin:5px auto 0}#board-container{overflow-x:auto}#board{table-layout:fixed;margin-bottom:0}#board tr.board-swimlane-columns-first{visibility:hidden;padding:0}#board th.board-column-header{width:240px}#board th.board-column-header-first{visibility:hidden;padding:0}#board td{vertical-align:top}.board-container-compact{overflow-x:initial}@media all and (-ms-high-contrast:active),(-ms-high-contrast:none){.board-container-compact #board{table-layout:auto}}#board th.board-column-header.board-column-compact{width:initial}.board-column-collapsed{display:none}.board-column-expanded-header{display:flex;align-items:center}td.board-column-task-collapsed{font-weight:700;background-color:#fbfbfb}#board th.board-column-header-collapsed{width:28px;min-width:28px;text-align:center;overflow:hidden}.board-rotation-wrapper{position:relative;padding:8px 4px;min-height:150px;overflow:hidden}.board-rotation{white-space:nowrap;-webkit-backface-visibility:hidden;-webkit-transform:rotate(90deg);-moz-transform:rotate(90deg);-ms-transform:rotate(90deg);transform:rotate(90deg);-webkit-transform-origin:0 100%;-moz-transform-origin:0 100%;-ms-transform-origin:0 100%;transform-origin:0 100%}.board-column-title .dropdown-menu{text-decoration:none}.board-add-icon{float:left;padding:0 5px}.board-add-icon i{text-decoration:none;color:var(--link-color-primary);font-size:1.4em}.board-add-icon i:focus,.board-add-icon i:hover{text-decoration:none;color:red}.board-column-header-task-count{color:var(--color-light);font-weight:400}a.board-swimlane-toggle{text-decoration:none}a.board-swimlane-toggle:hover,a.board-swimlane-toggle:focus{color:#000;text-decoration:none;border:none}.board-task-list{min-height:60px}.board-task-list-compact{max-height:90vh;overflow-y:auto}.board-task-list .task-board:last-child{margin-bottom:0}.board-task-list-limit{background-color:var(--board-task-limit-color)}.draggable-item{cursor:pointer;user-select:none;-webkit-user-select:none;-moz-user-select:none}.draggable-placeholder{border:2px dashed #000;background:#fafafa;height:70px;margin-bottom:10px}div.draggable-item-selected{border:1px solid #000}.task-board-sort-handle{float:left;padding-right:5px}.task-board{position:relative;margin-bottom:4px;border:1px solid #000;padding:2px;word-wrap:break-word;font-size:.9em;border-radius:6px}div.task-board-recent{border-width:2px}div.task-board-status-closed{user-select:none;border:1px dotted #555}.task-board a{color:#000;text-decoration:none}.task-board-collapsed{overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.task-board-title{margin-top:5px;margin-bottom:8px}.task-board-title a:hover{text-decoration:underline}.task-board-saving-state{opacity:.3}.task-board-saving-icon{position:absolute;margin:auto;width:100%;text-align:center;color:#000}.task-board-avatars{text-align:right;float:right}.task-board-change-assignee{cursor:pointer}.task-board-change-assignee:hover{opacity:.6}.task-list-avatars{display:inline-block;float:left}@media (max-width:768px){.task-list-avatars{float:none;display:block}}.task-list-avatars .task-avatar-assignee{font-weight:300;color:#999}.task-list-avatars:hover .task-avatar-assignee{font-weight:400;color:#000}.task-board-icons,.task-list-icons{font-size:.8em;text-align:right}.task-board-icons a,.task-board-icons span.tooltip,.task-list-icons a,.task-list-icons span.tooltip{text-decoration:none}.task-board-icons a:hover,.task-board-icons span.tooltip:hover,.task-list-icons a:hover,.task-list-icons span.tooltip:hover{color:var(--color-primary)}.task-board-icons a:hover i,.task-board-icons span.tooltip:hover i,.task-list-icons a:hover i,.task-list-icons span.tooltip:hover i{color:var(--color-primary)}.task-board-icons .task-score,.task-list-icons .task-score{font-weight:700}.task-board-icons .flag-milestone,.task-list-icons .flag-milestone{color:green}.task-board-icons{margin-top:7px}.task-board-icons a{opacity:.5}.task-board-icons span{opacity:.5;margin-left:4px}.task-board-icons a:hover,.task-board-icons span.tooltip:hover{opacity:1;font-weight:700}.task-board-icons .task-board-icons-row{line-height:22px}.task-list-icons{line-height:22px}.task-list-icons a,.task-list-icons span,.task-list-icons i{color:#999;opacity:1}.task-list-icons span{margin-left:5px}@media (max-width:768px){.task-list-icons{text-align:left}}.task-icon-age{display:inline-block}span.task-icon-age-total{border:1px solid #e5e5e5;padding:1px 3px 1px 3px;border-top-left-radius:3px;border-bottom-left-radius:3px}span.task-icon-age-column{border:1px solid #e5e5e5;border-left:none;margin-left:-5px;padding:1px 3px 1px 3px;border-top-right-radius:3px;border-bottom-right-radius:3px}.task-board span.task-icon-age-total,.task-board span.task-icon-age-column{border-color:#666}.task-board-category-container{text-align:right;margin-top:8px;margin-bottom:8px}.task-board-category{border:1px solid #555;font-size:.9em;font-weight:500;color:#000;padding:1px 3px 1px 2px;border-radius:3px}.task-board-category a:hover{text-decoration:underline}.task-date{font-weight:500;color:#000}span.task-date-today{opacity:1;color:var(--link-color-primary)}span.task-date-overdue{opacity:1;color:#b94a48}.task-tags li{display:inline-block;margin:3px 3px 0 0;padding:1px 3px 1px 3px;color:var(--color-primary);border:1px solid #333;border-radius:4px}.task-summary-container .task-tags{margin-top:10px}#task-summary{margin-bottom:15px}#task-summary h2{color:var(--color-medium);font-size:1.6em;margin-top:0;padding-top:0}.task-summary-container{border:2px solid #000;border-radius:8px;padding:10px}.task-summary-columns{display:flex;flex-flow:row;justify-content:space-between}@media (max-width:768px){.task-summary-columns{flex-flow:column}}.task-summary-column{color:var(--color-primary)}.task-summary-column span{color:var(--color-medium)}.task-summary-column li{line-height:23px}#external-task-view{padding:10px;margin-top:10px;margin-bottom:10px;border:1px dotted #ccc}.task-form-container{box-sizing:border-box;display:flex;flex-wrap:wrap}.task-form-container>*{box-sizing:border-box}.task-form-container>*{width:1%}.task-form-main-column{width:60%}@media (max-width:1000px){.task-form-main-column{width:100%}}.task-form-main-column input[type="text"]{width:700px;max-width:99%}.task-form-secondary-column{max-width:250px;min-width:200px;max-height:600px;padding-left:10px;overflow:auto;width:20%}@media (max-width:1000px){.task-form-secondary-column{width:100%;max-width:99%;max-height:none}}@media (max-width:768px){.task-form-secondary-column{padding-left:0}}.task-form-secondary-column label:first-child{margin-top:0}@media (max-width:1000px){.task-form-secondary-column label:first-child{margin-top:10px}}.task-form-bottom{width:100%}.task-form-bottom label{display:inline-block}.comment-sorting{text-align:right}.comment-sorting a{color:var(--color-medium);font-weight:400;text-decoration:none}.comment-sorting a:hover{color:var(--color-light)}.comment{padding:5px;margin-bottom:15px}.comment-title{border-bottom:1px dotted #eee;margin-left:55px}.comment-date{color:var(--color-light);font-weight:200}.comment-actions{text-align:right}.comment-content{margin-left:55px}.comments .text-editor textarea{height:90px}.comments .text-editor .text-editor-preview-area{height:90px}.comments .comment-highlighted{background-color:#fff8dc;border:2px solid #ffeb8e}.comments .comment-highlighted:hover{background-color:#fff8dc}.comments .comment:hover{background:#fff8dc}.comments .comment:nth-child(even):not(.comment-highlighted){background:#fbfbfb}.comments .comment:nth-child(even):not(.comment-highlighted):hover{background:#fff8dc}.subtask-cell{padding:4px 10px;border-top:1px dotted #dedede;border-left:1px dotted #dedede;display:table-cell;vertical-align:middle}.subtask-cell a{color:var(--color-primary);text-decoration:none}.subtask-cell a:hover,.subtask-cell a:focus{color:var(--link-color-primary)}.subtask-cell:first-child{border-left:none}@media (max-width:768px){.subtask-cell{width:90%;display:block;border-left:none}}.subtasks-table .subtask-table-td{display:flex;white-space:normal;min-width:400px}.subtasks-table .subtask-submenu{display:flex}.js-subtask-toggle-status{display:flex;text-decoration:none}.task-list-subtasks{display:table;width:100%}@media (max-width:768px){.task-list-subtasks{display:block}}.task-list-subtask{display:table-row}@media (max-width:768px){.task-list-subtask{display:block}}@media (max-width:768px){.subtask-assignee,.subtask-time-tracking-cell{display:none}}.subtask-time-tracking{white-space:normal}.task-links-table td{vertical-align:middle}.task-links-task-count{color:var(--color-light);font-weight:400}.task-link-closed{text-decoration:line-through}.text-editor{margin-top:10px}.text-editor a{font-size:1em;color:var(--color-light);text-decoration:none;margin-right:10px}.text-editor a:hover{color:var(--link-color-primary)}.text-editor .text-editor-preview-area{border:1px solid #dedede;width:700px;max-width:99%;height:250px;overflow:auto;padding:2px}.text-editor textarea{width:700px;max-width:98%;height:250px}.markdown{line-height:1.4em}.markdown h1{margin-top:5px;margin-bottom:10px;font-weight:700}.markdown h2{font-weight:700}.markdown p{margin-bottom:10px}.markdown ol,.markdown ul{margin-left:25px;margin-top:10px;margin-bottom:10px}.markdown pre{background:#fbfbfb;padding:10px;border-radius:5px;border:1px solid #ddd;overflow:auto;overflow-wrap:initial;color:var(--color-medium)}.markdown blockquote{font-style:italic;border-left:3px solid #ddd;padding-left:10px;margin-bottom:10px;margin-left:20px}.markdown img{display:block;max-width:80%;margin-top:10px}.panel{border-radius:4px;padding:8px 35px 8px 10px;margin-top:10px;margin-bottom:15px;border:1px solid #ddd;color:var(--color-primary);background-color:#fcfcfc;overflow:auto}.panel li{list-style-type:square;margin-left:20px;line-height:1.35em}.activity-event{margin-bottom:15px;padding:10px}.activity-event:nth-child(even){background:var(--activity-event-background-color)}.activity-event:hover{background:var(--activity-event-hover-color)}.activity-date{margin-left:10px;font-weight:400;color:var(--color-light)}.activity-content{margin-left:55px}.activity-title{font-weight:700;color:var(--activity-title-color);border-bottom:1px dotted var(--activity-title-border-color)}.activity-description{color:var(--color-medium);margin-top:10px}@media (max-width:480px){.activity-description{overflow:auto}}.activity-description li{list-style-type:circle}.activity-description ul{margin-top:10px;margin-left:20px}.user-mention-link{font-weight:700;color:var(--user-mention-color);text-decoration:none}.user-mention-link:hover{color:var(--color-medium)}.image-slideshow-overlay{position:fixed;top:0;left:0;width:100%;height:100%;background:rgba(0,0,0,.95);overflow:auto;z-index:100}.image-slideshow-overlay img{display:block;margin:auto}.image-slideshow-overlay figcaption{color:#fff;opacity:.7;position:absolute;bottom:5px;right:15px}.slideshow-icon{color:#fff;position:absolute;font-size:2.5em;opacity:.6}.slideshow-icon:hover{opacity:.9;cursor:pointer}.slideshow-previous-icon{left:10px;top:45%}.slideshow-next-icon{right:10px;top:45%}.slideshow-close-icon{right:10px;top:10px;font-size:1.4em}.slideshow-download-icon{left:10px;bottom:10px;font-size:1.3em}.list-item-links,.list-item-actions{display:inline-block;float:left;margin-left:10px}.list-item-links a{margin:0}.list-item-action-hidden{display:none}.bulk-change-checkbox{float:left}.bulk-change-inputs{float:left;padding-left:10px}.bulk-change-inputs label{margin-top:0;margin-bottom:3px} +:root{--color-primary:#333;--color-light:#999;--color-lighter:#dedede;--color-dark:#000;--color-medium:#555;--color-error:#b94a48;--link-color-primary:#36C;--link-color-focus:#DF5353;--link-color-hover:#333;--alert-color-default:#c09853;--alert-color-success:#468847;--alert-color-error:#b94a48;--alert-color-info:#3a87ad;--alert-color-normal:#333;--alert-background-color-default:#fcf8e3;--alert-background-color-success:#dff0d8;--alert-background-color-error:#f2dede;--alert-background-color-info:#d9edf7;--alert-background-color-normal:#f0f0f0;--alert-border-color-default:#fbeed5;--alert-border-color-success:#d6e9c6;--alert-border-color-error:#eed3d7;--alert-border-color-info:#bce8f1;--alert-border-color-normal:#ddd;--button-default-color:#333;--button-default-background-color:#f5f5f5;--button-default-border-color:#ddd;--button-default-color-focus:#000;--button-default-background-color-focus:#fafafa;--button-default-border-color-focus:#bbb;--button-primary-color:#fff;--button-primary-background-color:#4d90fe;--button-primary-border-color:#3079ed;--button-primary-color-focus:#fff;--button-primary-background-color-focus:#357ae8;--button-primary-border-color-focus:#3079ed;--button-danger-color:#fff;--button-danger-background-color:#d14836;--button-danger-border-color:#b0281a;--button-danger-color-focus:#fff;--button-danger-background-color-focus:#c53727;--button-danger-border-color-focus:#b0281a;--button-disabled-color:#ccc;--button-disabled-background-color:#f7f7f7;--button-disabled-border-color:#ccc;--avatar-color-letter:#fff;--activity-title-color:#000;--activity-title-border-color:#efefef;--activity-event-background-color:#fafafa;--activity-event-hover-color:#fff8dc;--user-mention-color:#000;--board-task-limit-color:#DF5353}h1,li,ul,ol,table,tr,td,th,p,blockquote,body{margin:0;padding:0}body{font-size:100%;padding-bottom:10px;color:var(--color-primary);font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;text-rendering:optimizeLegibility}small{font-size:.8em}hr{border:0;height:0;border-top:1px solid rgba(0,0,0,.1);border-bottom:1px solid rgba(255,255,255,.3)}.page{margin-left:10px;margin-right:10px}.margin-top{margin-top:20px}.margin-bottom{margin-bottom:20px}.pull-right{text-align:right}ul.no-bullet li{list-style-type:none;margin-left:0}#app-loading-icon{position:fixed;right:3px;bottom:3px}.assign-me{vertical-align:bottom}a{color:var(--link-color-primary);border:none}a:focus{color:var(--link-color-focus);outline:0;text-decoration:none}a:hover{color:var(--link-color-hover);text-decoration:none}a .fa{color:var(--color-primary);padding-right:3px;text-decoration:none}h1,h2,h3{font-weight:400;color:var(--color-primary)}h1{font-size:1.5em}h2{font-size:1.4em;margin-bottom:10px}h3{margin-top:10px;font-size:1.2em}table{width:100%;border-collapse:collapse;border-spacing:0;margin-bottom:20px}table.table-fixed{table-layout:fixed;white-space:nowrap}table.table-fixed th{overflow:hidden}table.table-fixed td{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}table.table-small{font-size:.8em}table.table-striped tr:nth-child(odd){background:#fefefe}@media (max-width:768px){table.table-scrolling{overflow-x:auto;display:inline-block;vertical-align:top;max-width:100%;white-space:nowrap}}table th{text-align:left;padding:.5em 3px;border:1px solid #eee;background:#fbfbfb}table th a{text-decoration:none;color:var(--color-primary)}table th a:focus,table th a:hover{text-decoration:underline}table td{border:1px solid #eee;padding:.5em 3px;vertical-align:top}table td li{margin-left:20px}.column-1{width:1%}.column-2{width:2%}.column-3{width:3%}.column-4{width:4%}.column-5{width:5%}.column-6{width:6%}.column-7{width:7%}.column-8{width:8%}.column-9{width:9%}.column-10{width:10%}.column-11{width:11%}.column-12{width:12%}.column-13{width:13%}.column-14{width:14%}.column-15{width:15%}.column-16{width:16%}.column-17{width:17%}.column-18{width:18%}.column-19{width:19%}.column-20{width:20%}.column-21{width:21%}.column-22{width:22%}.column-23{width:23%}.column-24{width:24%}.column-25{width:25%}.column-26{width:26%}.column-27{width:27%}.column-28{width:28%}.column-29{width:29%}.column-30{width:30%}.column-31{width:31%}.column-32{width:32%}.column-33{width:33%}.column-34{width:34%}.column-35{width:35%}.column-36{width:36%}.column-37{width:37%}.column-38{width:38%}.column-39{width:39%}.column-40{width:40%}.column-41{width:41%}.column-42{width:42%}.column-43{width:43%}.column-44{width:44%}.column-45{width:45%}.column-46{width:46%}.column-47{width:47%}.column-48{width:48%}.column-49{width:49%}.column-50{width:50%}.column-51{width:51%}.column-52{width:52%}.column-53{width:53%}.column-54{width:54%}.column-55{width:55%}.column-56{width:56%}.column-57{width:57%}.column-58{width:58%}.column-59{width:59%}.column-60{width:60%}.column-61{width:61%}.column-62{width:62%}.column-63{width:63%}.column-64{width:64%}.column-65{width:65%}.column-66{width:66%}.column-67{width:67%}.column-68{width:68%}.column-69{width:69%}.column-70{width:70%}.column-71{width:71%}.column-72{width:72%}.column-73{width:73%}.column-74{width:74%}.column-75{width:75%}.column-76{width:76%}.column-77{width:77%}.column-78{width:78%}.column-79{width:79%}.column-80{width:80%}.column-81{width:81%}.column-82{width:82%}.column-83{width:83%}.column-84{width:84%}.column-85{width:85%}.column-86{width:86%}.column-87{width:87%}.column-88{width:88%}.column-89{width:89%}.column-90{width:90%}.column-91{width:91%}.column-92{width:92%}.column-93{width:93%}.column-94{width:94%}.column-95{width:95%}.column-96{width:96%}.column-97{width:97%}.column-98{width:98%}.column-99{width:99%}.column-100{width:100%}.draggable-row-handle{cursor:move;color:#dedede}.draggable-row-handle:hover{color:var(--color-primary)}tr.draggable-item-selected{background:#fff;border:2px solid #666;box-shadow:4px 2px 10px -4px rgba(0,0,0,.55)}tr.draggable-item-selected td{border-top:none;border-bottom:none}tr.draggable-item-selected td:first-child{border-left:none}tr.draggable-item-selected td:last-child{border-right:none}.table-stripped tr.draggable-item-hover,.table-stripped tr.draggable-item-hover{background:#FEFFF2}.table-list{font-size:.85em;margin-bottom:20px}.table-list-header{background:#fbfbfb;border:1px solid #e5e5e5;border-radius:5px 5px 0 0;line-height:28px;padding-left:3px;padding-right:3px}.table-list-header a{color:#333;font-weight:500;text-decoration:none;margin-right:10px}.table-list-header a:hover,.table-list-header a:focus{color:#767676}.table-list-header .table-list-header-count{color:#767676;display:inline-block;float:left}.table-list-header .table-list-header-menu{text-align:right}.table-list-row{padding-left:3px;padding-right:3px;border-bottom:1px solid #e5e5e5;border-right:1px solid #e5e5e5}.table-list-row.table-border-left{border-left:1px solid #e5e5e5}.table-list-row:nth-child(odd){background:#fefefe}.table-list-row:last-child{border-radius:0 0 5px 5px}.table-list-row:hover{background:#fff8dc;border-bottom:1px solid #ffeb8e;border-right:1px solid #ffeb8e}.table-list-row .table-list-title{font-weight:500;line-height:23px}.table-list-row .table-list-title.status-closed{text-decoration:line-through;margin-right:10px}.table-list-row .table-list-title.status-closed a{font-style:italic}.table-list-row .table-list-title a{color:#333;text-decoration:none}.table-list-row .table-list-title a:hover,.table-list-row .table-list-title a:focus{text-decoration:underline}.table-list-row .table-list-details{color:#999;font-weight:300;line-height:20px}.table-list-row .table-list-details span{margin-left:5px}.table-list-row .table-list-details span:first-child{margin-left:0}.table-list-row .table-list-details li{display:inline;list-style-type:none}.table-list-row .table-list-details li:after{content:', '}.table-list-row .table-list-details li:last-child:after{content:''}.table-list-row .table-list-details strong{font-weight:400;color:#555}.table-list-row .table-list-details-with-icons{float:left}@media (max-width:768px){.table-list-row .table-list-details-with-icons{float:none}}.table-list-row .table-list-icons{font-size:.8em;text-align:right;line-height:30px}@media (max-width:768px){.table-list-row .table-list-icons{text-align:left;line-height:20px}}.table-list-row .table-list-icons span{margin-left:5px}.table-list-row .table-list-icons a{text-decoration:none}.table-list-row .table-list-icons a:hover{color:#333}.table-list-row .table-list-icons a:hover i{color:#333}.table-list-category{font-size:.9em;font-weight:500;color:#000;padding:1px 2px 1px 2px;border-radius:3px;background:#fcfcfc;border:1px solid #ccc}.table-list-category a{text-decoration:none;color:#000}.table-list-category a:hover{color:#36c}fieldset{border:1px solid #ddd;margin-top:10px}legend{font-weight:500;font-size:1.2em}label{cursor:pointer;display:block;margin-top:10px;font-weight:400}input[type="number"],input[type="date"],input[type="email"],input[type="password"],input[type="text"]:not(.input-addon-field){color:var(--color-light);border:1px solid #ccc;width:300px;max-width:95%;font-size:1em;height:25px;padding-bottom:0;padding-left:4px;font-family:sans-serif;-webkit-appearance:none;-moz-appearance:none}input[type="number"]::-webkit-input-placeholder,input[type="date"]::-webkit-input-placeholder,input[type="email"]::-webkit-input-placeholder,input[type="password"]::-webkit-input-placeholder,input[type="text"]:not(.input-addon-field)::-webkit-input-placeholder{color:#dedede}input[type="number"]::-moz-placeholder,input[type="date"]::-moz-placeholder,input[type="email"]::-moz-placeholder,input[type="password"]::-moz-placeholder,input[type="text"]:not(.input-addon-field)::-moz-placeholder{color:#dedede}input[type="number"]:-ms-input-placeholder,input[type="date"]:-ms-input-placeholder,input[type="email"]:-ms-input-placeholder,input[type="password"]:-ms-input-placeholder,input[type="text"]:not(.input-addon-field):-ms-input-placeholder{color:#dedede}input[type="number"]:focus,input[type="date"]:focus,input[type="email"]:focus,input[type="password"]:focus,input[type="text"]:focus{color:#000;border-color:rgba(82,168,236,.8);outline:0;box-shadow:0 0 8px rgba(82,168,236,.6)}input[type="number"]{width:70px}input[type="text"]:not(.input-addon-field).form-numeric{width:70px}input[type="text"]:not(.input-addon-field).form-datetime,input[type="text"]:not(.input-addon-field).form-date{width:150px}input[type="text"]:not(.input-addon-field).form-input-large{width:400px}input[type="text"]:not(.input-addon-field).form-input-small{width:150px}textarea:focus{color:#000;border-color:rgba(82,168,236,.8);outline:0;box-shadow:0 0 8px rgba(82,168,236,.6)}textarea{padding:4px;border:1px solid #ccc;width:400px;max-width:99%;height:200px;font-family:sans-serif;font-size:1em}textarea::-webkit-input-placeholder{color:#dedede}textarea::-moz-placeholder{color:#dedede}textarea:-ms-input-placeholder{color:#dedede}select{font-size:1em;max-width:95%}select:focus{outline:0}select[multiple]{width:300px}.tag-autocomplete{width:400px}span.select2-container{margin-top:2px}.form-actions{padding-top:20px;clear:both}.form-required{color:red;padding-left:5px;font-weight:700}@media (max-width:480px){.form-required{display:none}}input[type="text"].form-max-width{width:100%}input.form-error,textarea.form-error{border:2px solid #b94a48}input.form-error:focus,textarea.form-error:focus{box-shadow:none;border:2px solid #b94a48}.form-errors{color:#b94a48;list-style-type:none}ul.form-errors li{margin-left:0}.form-help{font-size:.8em;color:brown;margin-bottom:15px}.form-inline{padding:0;margin:0;border:none}.form-inline label{display:inline;padding-right:3px}.form-inline input,.form-inline select{margin:0 15px 0 0}.form-inline .form-required{display:none}.form-inline .form-actions{display:inline-block}.form-inline .js-submit-buttons-rendered{display:inline-block}.form-inline-group{display:inline}.form-columns{display:-webkit-flex;display:flex;-webkit-flex-direction:row;flex-direction:row;-webkit-flex-wrap:wrap;flex-wrap:wrap;-webkit-justify-content:flex-start;justify-content:flex-start}.form-columns .form-column{margin-right:25px;flex-grow:1}.form-columns fieldset{margin-top:0}.form-login{max-width:350px;margin:5% auto 0}@media (max-width:480px){.form-login{margin-left:5px}}.form-login li{margin-left:25px;line-height:25px}.form-login h2{margin-bottom:30px;font-weight:700}.reset-password{margin-top:20px;margin-bottom:20px}.reset-password a{color:var(--color-light)}.input-addon{display:flex}.input-addon-field{flex:1;font-size:1em;color:var(--color-light);margin:0;-webkit-appearance:none;-moz-appearance:none}.input-addon-field:first-child{border-radius:5px 0 0 5px}.input-addon-field:last-child{border-radius:0 5px 5px 0}.input-addon-item{background-color:rgba(147,128,108,.1);color:#666;font:inherit;font-weight:400}.input-addon-item:first-child{border-radius:5px 0 0 5px}.input-addon-item:last-child{border-radius:0 5px 5px 0}@media (max-width:480px){.input-addon-item .dropdown .fa-caret-down{display:none}}.input-addon-field,.input-addon-item{border:1px solid rgba(147,128,108,.25);padding:4px .75em}.input-addon-field:not(:first-child),.input-addon-item:not(:first-child){border-left:0}.project-header .filter-box-component .input-addon{min-width:280px}.input-addon .input-addon-field{flex:1 1 auto;width:1%!important}@media (max-width:400px){.input-addon-item{padding:3px}}.icon-success{color:#468847}.icon-error{color:#b94a48}.icon-fade-out{opacity:1;animation:icon-fadeout 5s linear forwards}@keyframes icon-fadeout{0%{opacity:1}100%{opacity:0}}.alert{padding:8px 35px 8px 14px;margin-top:5px;margin-bottom:5px;color:var(--alert-color-default);background-color:var(--alert-background-color-default);border:1px solid var(--alert-border-color-default);border-radius:4px}.alert-success{color:var(--alert-color-success);background-color:var(--alert-background-color-success);border-color:var(--alert-border-color-success)}.alert-error{color:var(--alert-color-error);background-color:var(--alert-background-color-error);border-color:var(--alert-border-color-error)}.alert-info{color:var(--alert-color-info);background-color:var(--alert-background-color-info);border-color:var(--alert-border-color-info)}.alert-normal{color:var(--alert-color-normal);background-color:var(--alert-background-color-normal);border-color:var(--alert-border-color-normal)}.alert ul{margin-top:10px;margin-bottom:10px}.alert li{margin-left:25px}.alert-fade-out{text-align:center;position:fixed;bottom:0;left:20%;width:60%;padding-top:5px;padding-bottom:5px;margin-bottom:0;border-width:1px 0 0;border-radius:4px 4px 0 0;z-index:9999;opacity:1;animation:fadeout 5s linear forwards}@keyframes fadeout{0%{opacity:1}100%{opacity:0;visibility:hidden}}a.btn{text-decoration:none}.btn{-webkit-appearance:none;-moz-appearance:none;font-size:1.2em;font-weight:400;cursor:pointer;display:inline-block;border-radius:2px;padding:3px 10px;margin:0;border:1px solid var(--button-default-border-color);background:var(--button-default-background-color);color:var(--button-default-color)}.btn:hover,.btn:focus{border-color:var(--button-default-border-color-focus);background:var(--button-default-background-color-focus);color:var(--button-default-color-focus)}.btn-red{border-color:var(--button-danger-border-color);background:var(--button-danger-background-color);color:var(--button-danger-color)}.btn-red:hover,.btn-red:focus{border-color:var(--button-danger-border-color-focus);background:var(--button-danger-background-color-focus);color:var(--button-danger-color-focus)}.btn-blue{border-color:var(--button-primary-border-color);background:var(--button-primary-background-color);color:var(--button-primary-color)}.btn-blue:hover,.btn-blue:focus{border-color:var(--button-primary-border-color-focus);background:var(--button-primary-background-color-focus);color:var(--button-primary-color-focus)}.btn:disabled{color:var(--button-disabled-color);border-color:var(--button-disabled-border-color);background:var(--button-disabled-background-color)}.buttons-header{font-size:.8em;margin-top:5px;margin-bottom:15px}.tooltip i.fa{cursor:pointer}.tooltip .fa-info-circle{color:var(--color-light)}#tooltip-container{padding:5px;background:#fff;border:1px solid #ddd;border-radius:4px;box-shadow:0 6px 12px #aaa;position:absolute;min-width:350px}#tooltip-container .markdown p:last-child{margin-bottom:0}#tooltip-container .tooltip-large{width:600px}h2 .dropdown ul{display:none}.dropdown{display:inline;position:relative}.dropdown ul{display:none}.dropdown-smaller{font-size:.85em}ul.dropdown-submenu-open{display:block;position:absolute;z-index:1000;min-width:285px;list-style:none;margin:3px 0 0 1px;padding:6px 0;background-color:#fff;border:1px solid #b2b2b2;border-radius:3px;box-shadow:0 1px 3px rgba(0,0,0,.15)}.dropdown-submenu-open li{display:block;margin:0;padding:8px 10px;font-size:.9em;border-bottom:1px solid #f8f8f8;cursor:pointer}.dropdown-submenu-open li.no-hover{cursor:default}.dropdown-submenu-open li:last-child{border:none}.dropdown-submenu-open li:not(.no-hover):hover{background:#4078C0;color:#fff}.dropdown-submenu-open li:hover a{color:#fff}.dropdown-submenu-open li:hover i{color:#fff}.dropdown-submenu-open a{text-decoration:none;color:#333}.dropdown-submenu-open a:focus{text-decoration:underline}.dropdown-menu-link-text,.dropdown-menu-link-icon{color:#333;text-decoration:none}.dropdown-menu-link-text:hover{text-decoration:underline}td a.dropdown-menu strong{color:#333}td a.dropdown-menu strong i{color:#333}td a.dropdown-menu i{color:#dedede}td a.dropdown-menu:hover strong{color:#555}td a.dropdown-menu:hover strong i{color:#555}td a.dropdown-menu:hover i{color:#333}.accordion-title{font-size:1.2em;cursor:pointer;margin-top:10px}.accordion-content{margin-top:15px;margin-bottom:25px}#select-dropdown-menu{position:absolute;display:block;z-index:1000;min-width:160px;padding:5px 0;background:#fff;list-style:none;border:1px solid #ccc;border-radius:3px;box-shadow:0 6px 12px rgba(0,0,0,.175);overflow:scroll}.select-dropdown-menu-item{white-space:nowrap;overflow:hidden;padding:3px 10px;color:var(--color-medium);cursor:pointer;border-bottom:1px solid #f8f8f8;line-height:1.5em;font-weight:400}.select-dropdown-menu-item.active{color:#fff;background:#428bca}.select-dropdown-menu-item:last-child{border:none}.select-dropdown-input-container{position:relative;border:1px solid #ccc;border-radius:5px;background-color:#fff;max-width:300px}.select-dropdown-input-container input.select-dropdown-input{margin:0 0 0 5px;border:none;height:23px;width:270px}.select-dropdown-input-container input.select-dropdown-input:focus{border:none;box-shadow:none}.select-dropdown-input-container .select-dropdown-chevron{color:var(--color-medium);position:absolute;top:4px;right:5px;cursor:pointer}.select-dropdown-input-container .select-loading-icon{color:var(--color-medium);position:absolute;top:4px;right:5px}#suggest-menu{position:absolute;display:block;z-index:1000;min-width:160px;padding:5px 0;background:#fff;list-style:none;border:1px solid #ccc;border-radius:3px;box-shadow:0 6px 12px rgba(0,0,0,.175)}.suggest-menu-item{white-space:nowrap;padding:3px 10px;color:var(--color-primary);font-weight:700;cursor:pointer}.suggest-menu-item.active{color:#fff;background:#428bca}.suggest-menu-item.active small{color:#fff}.suggest-menu-item small{color:var(--color-light);font-weight:400}#modal-overlay{position:fixed;top:0;left:0;width:100%;height:100%;background:rgba(0,0,0,.9);overflow:auto;z-index:100}#modal-box{position:fixed;max-height:calc(100% - 30px);top:2%;left:50%;transform:translateX(-50%);background:#fff;overflow:auto;border-radius:5px}#modal-content{padding:0 5px 5px}#modal-header{text-align:right;padding-right:5px}#modal-close-button{color:var(--color-primary)}#modal-close-button:hover{color:var(--color-error)}.pagination{text-align:center;font-size:.9em}.pagination-showing{margin-right:5px;padding-right:5px;border-right:1px solid #999}.pagination-next{margin-left:5px}.pagination-previous{margin-right:5px}header{display:flex;flex-wrap:wrap;padding:5px 10px;margin-bottom:5px;border-bottom:1px solid #dedede;background-color:#fbfbfb}header .title-container{flex:1;min-width:300px}@media (max-width:480px){header .title-container{order:3}}header .board-selector-container{min-width:320px;display:flex;align-items:center}@media (max-width:480px){header .board-selector-container{order:2;min-width:300px}header .board-selector-container input[type=text]{max-width:280px}}header .menus-container{min-width:120px;display:flex;align-items:center;justify-content:flex-end}@media (max-width:480px){header .menus-container{order:1;margin-bottom:5px;margin-left:auto}}header h1{font-size:1.5em}header h1 .tooltip{opacity:.3;font-size:.7em}a i.web-notification-icon{color:var(--link-color-primary)}a i.web-notification-icon:focus,a i.web-notification-icon:hover{color:#000}.logo a{opacity:.5;color:#d40000;text-decoration:none}.logo span{color:var(--color-primary)}.logo a:hover{opacity:.8;color:var(--color-primary)}.logo a:focus span,.logo a:hover span{color:#d40000}.page-header{margin-bottom:20px}.page-header .dropdown{padding-right:10px}.page-header h2{margin:0;padding:0;font-weight:700;border-bottom:1px dotted #ccc}.page-header h2 a{color:var(--color-primary);text-decoration:none}.page-header h2 a:focus,.page-header h2 a:hover{color:var(--color-light)}.page-header ul{text-align:left;margin-top:5px;display:inline-block}.page-header li{display:inline;padding-right:15px}@media (max-width:480px){.page-header li{display:block;line-height:1.5em}}.page-header li.active a{color:var(--color-primary);text-decoration:none;font-weight:700}.page-header li.active a:hover,.page-header li.active a:focus{text-decoration:underline}.menu-inline{margin-bottom:5px}.menu-inline li{display:inline;padding-right:15px}.menu-inline li .active a{font-weight:700;color:#000;text-decoration:none}.sidebar-container{height:100%;display:flex;flex-flow:row}@media (max-width:768px){.sidebar-container{flex-flow:wrap}}.sidebar-content{padding-left:10px;flex:1 100%;max-width:85%;overflow-wrap:break-word}@media (max-width:768px){.sidebar-content{padding-left:0;order:1;max-width:100%}}@media only screen and (min-device-width:768px) and (max-device-width:1024px) and (orientation:landscape) and (-webkit-min-device-pixel-ratio:1){.sidebar-content{max-width:75%}}.sidebar{max-width:25%;min-width:230px}@media (max-width:768px){.sidebar{flex:1 auto;order:2}}.sidebar h2{margin-top:0}.sidebar>ul a{text-decoration:none;color:var(--color-light);font-weight:300}.sidebar>ul a:hover{color:var(--color-primary)}.sidebar>ul li{list-style-type:none;line-height:35px;border-bottom:1px dotted #efefef;padding-left:13px}.sidebar>ul li:hover{border-left:5px solid #555;padding-left:8px}.sidebar>ul li.active{border-left:5px solid #333;padding-left:8px}.sidebar>ul li.active a{color:var(--color-primary);font-weight:700}.sidebar-icons>ul li{padding-left:0}.sidebar-icons>ul li:hover,.sidebar-icons>ul li.active{padding-left:0;border-left:none}.sidebar>ul li.active a:focus,.sidebar>ul li.active a:hover{color:var(--color-medium)}.sidebar>ul li:last-child{margin-bottom:15px}.avatar img{vertical-align:bottom}.avatar-left{float:left;margin-right:10px}.avatar-inline{display:inline-block;margin-right:3px}.avatar-48 img,.avatar-48 div{border-radius:30px}.avatar-48 .avatar-letter{line-height:48px;width:48px;font-size:25px}.avatar-20 img,.avatar-20 div{border-radius:10px}.avatar-20 .avatar-letter{line-height:20px;width:20px;font-size:11px}.avatar-letter{color:var(--avatar-color-letter);text-align:center}#file-dropzone,#screenshot-zone{position:relative;border:2px dashed #ccc;width:99%;height:250px;overflow:auto}#file-dropzone-inner,#screenshot-inner{position:absolute;left:0;bottom:48%;width:100%;text-align:center;color:#aaa}#screenshot-zone.screenshot-pasted{border:2px solid #333}#file-list{margin:20px}#file-list li{list-style-type:none;padding-top:8px;padding-bottom:8px;border-bottom:1px dotted #ddd;width:95%}#file-list li .file-error{font-weight:700;color:#b94a48}.file-thumbnails{display:-webkit-flex;display:flex;-webkit-flex-direction:row;flex-direction:row;-webkit-flex-wrap:wrap;flex-wrap:wrap;-webkit-justify-content:flex-start;justify-content:flex-start}.file-thumbnail{width:250px;border:1px solid #efefef;border-radius:5px;margin-bottom:20px;box-shadow:4px 2px 10px -6px rgba(0,0,0,.55);margin-right:15px}.file-thumbnail img{cursor:pointer;border-top-left-radius:5px;border-top-right-radius:5px}.file-thumbnail img:hover{opacity:.5}.file-thumbnail-content{padding-left:8px;padding-right:8px}.file-thumbnail-title{font-weight:700;font-size:.9em;color:var(--color-medium);overflow:hidden;text-overflow:ellipsis}.file-thumbnail-description{font-size:.8em;color:var(--color-light);margin-top:8px;margin-bottom:5px}.file-viewer{position:relative}.file-viewer img{max-width:95%;max-height:85%;margin-top:10px}.color-picker{width:220px}.color-picker-option{height:25px}.color-picker-square{display:inline-block;width:18px;height:18px;margin-right:5px;border:1px solid #000}.color-picker-label{display:inline-block;vertical-align:bottom;padding-bottom:3px}.filter-box{max-width:1024px}.action-menu{color:var(--color-primary);text-decoration:none}.action-menu:hover,.action-menu:focus{text-decoration:underline}.js-project-creation-options{max-width:500px;border-left:3px dotted #efefef;margin-top:20px;padding-left:15px;padding-bottom:5px;padding-top:5px}.project-overview-columns{display:-webkit-flex;display:flex;-webkit-flex-direction:row;flex-direction:row;-webkit-flex-wrap:wrap;flex-wrap:wrap;-webkit-align-items:center;align-items:center;-webkit-justify-content:center;justify-content:center;margin-bottom:20px;font-size:1.4em}@media (max-width:480px){.project-overview-columns{display:block}}.project-overview-column{text-align:center;margin-right:3%;margin-top:5px;padding:3px 15px 3px 15px;border:1px dashed #ddd}@media (max-width:480px){.project-overview-column{text-align:left}}.project-overview-column small{color:var(--color-light)}.project-overview-column strong{color:var(--color-medium);display:block}@media (max-width:480px){.project-overview-column strong{display:inline}}.project-header{margin-bottom:8px}.project-header .dropdown-component{margin-top:4px;margin-right:5px;float:left}@media (max-width:768px){.project-header .dropdown-component{float:none}}.project-header .views-switcher-component{margin-top:4px;float:left}@media (max-width:768px){.project-header .views-switcher-component{float:none;margin-bottom:10px}}.project-header .filter-box-component form{margin:0}.views{margin-right:10px;margin-top:1px;font-size:.9em}@media (max-width:560px){.views{width:100%}}@media (max-width:768px){.views{margin-top:10px;font-size:1em}}@media (max-width:480px){.views{margin-top:5px}}.views li{white-space:nowrap;background:#fafafa;border:1px solid #ddd;border-right:none;padding:4px 8px;display:inline}@media (max-width:560px){.views li{display:block;margin-top:5px;border-radius:5px;border:1px solid #ddd}}.views li.active a{font-weight:700;color:#000;text-decoration:none}.views li:first-child{border-top-left-radius:5px;border-bottom-left-radius:5px}.views li:last-child{border-right:1px solid #ddd;border-top-right-radius:5px;border-bottom-right-radius:5px}.views a{color:var(--color-medium);text-decoration:none}.views a:hover{color:var(--color-primary);text-decoration:underline}.dashboard-project-stats small{margin-right:10px;color:var(--color-light)}.dashboard-table-link{font-weight:700;color:#000;text-decoration:none}.dashboard-table-link:focus,.dashboard-table-link:hover{color:var(--color-light)}.public-board{margin-top:5px}.public-task{max-width:800px;margin:5px auto 0}#board-container{overflow-x:auto}#board{table-layout:fixed;margin-bottom:0}#board tr.board-swimlane-columns-first{visibility:hidden;padding:0}#board th.board-column-header{width:240px}#board th.board-column-header-first{visibility:hidden;padding:0}#board td{vertical-align:top}.board-container-compact{overflow-x:initial}@media all and (-ms-high-contrast:active),(-ms-high-contrast:none){.board-container-compact #board{table-layout:auto}}#board th.board-column-header.board-column-compact{width:initial}.board-column-collapsed{display:none}.board-column-expanded-header{display:flex;align-items:center}td.board-column-task-collapsed{font-weight:700;background-color:#fbfbfb}#board th.board-column-header-collapsed{width:28px;min-width:28px;text-align:center;overflow:hidden}.board-rotation-wrapper{position:relative;padding:8px 4px;min-height:150px;overflow:hidden}.board-rotation{white-space:nowrap;-webkit-backface-visibility:hidden;-webkit-transform:rotate(90deg);-moz-transform:rotate(90deg);-ms-transform:rotate(90deg);transform:rotate(90deg);-webkit-transform-origin:0 100%;-moz-transform-origin:0 100%;-ms-transform-origin:0 100%;transform-origin:0 100%}.board-column-title .dropdown-menu{text-decoration:none}.board-add-icon{float:left;padding:0 5px}.board-add-icon i{text-decoration:none;color:var(--link-color-primary);font-size:1.4em}.board-add-icon i:focus,.board-add-icon i:hover{text-decoration:none;color:red}.board-column-header-task-count{color:var(--color-light);font-weight:400}a.board-swimlane-toggle{text-decoration:none}a.board-swimlane-toggle:hover,a.board-swimlane-toggle:focus{color:#000;text-decoration:none;border:none}.board-task-list{min-height:60px}.board-task-list-compact{max-height:90vh;overflow-y:auto}.board-task-list .task-board:last-child{margin-bottom:0}.board-task-list-limit{background-color:var(--board-task-limit-color)}.draggable-item{cursor:pointer;user-select:none;-webkit-user-select:none;-moz-user-select:none}.draggable-placeholder{border:2px dashed #000;background:#fafafa;height:70px;margin-bottom:10px}div.draggable-item-selected{border:1px solid #000}.task-board-sort-handle{float:left;padding-right:5px}.task-board{position:relative;margin-bottom:4px;border:1px solid #000;padding:2px;word-wrap:break-word;font-size:.9em;border-radius:6px}div.task-board-recent{border-width:2px}div.task-board-status-closed{user-select:none;border:1px dotted #555}.task-board a{color:#000;text-decoration:none}.task-board-collapsed{overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.task-board-title{margin-top:5px;margin-bottom:8px}.task-board-title a:hover{text-decoration:underline}.task-board-saving-state{opacity:.3}.task-board-saving-icon{position:absolute;margin:auto;width:100%;text-align:center;color:#000}.task-board-avatars{text-align:right;float:right}.task-board-change-assignee{cursor:pointer}.task-board-change-assignee:hover{opacity:.6}.task-list-avatars{display:inline-block;float:left}@media (max-width:768px){.task-list-avatars{float:none;display:block}}.task-list-avatars .task-avatar-assignee{font-weight:300;color:#999}.task-list-avatars:hover .task-avatar-assignee{font-weight:400;color:#000}.task-board-icons,.task-list-icons{font-size:.8em;text-align:right}.task-board-icons a,.task-board-icons span.tooltip,.task-list-icons a,.task-list-icons span.tooltip{text-decoration:none}.task-board-icons a:hover,.task-board-icons span.tooltip:hover,.task-list-icons a:hover,.task-list-icons span.tooltip:hover{color:var(--color-primary)}.task-board-icons a:hover i,.task-board-icons span.tooltip:hover i,.task-list-icons a:hover i,.task-list-icons span.tooltip:hover i{color:var(--color-primary)}.task-board-icons .task-score,.task-list-icons .task-score{font-weight:700}.task-board-icons .flag-milestone,.task-list-icons .flag-milestone{color:green}.task-board-icons{margin-top:7px}.task-board-icons a{opacity:.5}.task-board-icons span{opacity:.5;margin-left:4px}.task-board-icons a:hover,.task-board-icons span.tooltip:hover{opacity:1;font-weight:700}.task-board-icons .task-board-icons-row{line-height:22px}.task-list-icons{line-height:22px}.task-list-icons a,.task-list-icons span,.task-list-icons i{color:#999;opacity:1}.task-list-icons span{margin-left:5px}@media (max-width:768px){.task-list-icons{text-align:left}}.task-icon-age{display:inline-block}span.task-icon-age-total{border:1px solid #e5e5e5;padding:1px 3px 1px 3px;border-top-left-radius:3px;border-bottom-left-radius:3px}span.task-icon-age-column{border:1px solid #e5e5e5;border-left:none;margin-left:-5px;padding:1px 3px 1px 3px;border-top-right-radius:3px;border-bottom-right-radius:3px}.task-board span.task-icon-age-total,.task-board span.task-icon-age-column{border-color:#666}.task-board-category-container{text-align:right;margin-top:8px;margin-bottom:8px}.task-board-category{border:1px solid #555;font-size:.9em;font-weight:500;color:#000;padding:1px 3px 1px 2px;border-radius:3px}.task-board-category a:hover{text-decoration:underline}.task-date{font-weight:500;color:#000}span.task-date-today{opacity:1;color:var(--link-color-primary)}span.task-date-overdue{opacity:1;color:#b94a48}.task-tags li{display:inline-block;margin:3px 3px 0 0;padding:1px 3px 1px 3px;color:var(--color-primary);border:1px solid #333;border-radius:4px}.task-summary-container .task-tags{margin-top:10px}#task-summary{margin-bottom:15px}#task-summary h2{color:var(--color-medium);font-size:1.6em;margin-top:0;padding-top:0}.task-summary-container{border:2px solid #000;border-radius:8px;padding:10px}.task-summary-columns{display:flex;flex-flow:row;justify-content:space-between}@media (max-width:768px){.task-summary-columns{flex-flow:column}}.task-summary-column{color:var(--color-primary)}.task-summary-column span{color:var(--color-medium)}.task-summary-column li{line-height:23px}#external-task-view{padding:10px;margin-top:10px;margin-bottom:10px;border:1px dotted #ccc}.task-form-container{box-sizing:border-box;display:flex;flex-wrap:wrap}.task-form-container>*{box-sizing:border-box}.task-form-container>*{width:1%}.task-form-main-column{width:60%}@media (max-width:1000px){.task-form-main-column{width:100%}}.task-form-main-column input[type="text"]{width:700px;max-width:99%}.task-form-secondary-column{max-width:250px;min-width:200px;max-height:600px;padding-left:10px;overflow:auto;width:20%}@media (max-width:1000px){.task-form-secondary-column{width:100%;max-width:99%;max-height:none}}@media (max-width:768px){.task-form-secondary-column{padding-left:0}}.task-form-secondary-column label:first-child{margin-top:0}@media (max-width:1000px){.task-form-secondary-column label:first-child{margin-top:10px}}.task-form-bottom{width:100%}.task-form-bottom label{display:inline-block}.comment-sorting{text-align:right}.comment-sorting a{color:var(--color-medium);font-weight:400;text-decoration:none}.comment-sorting a:hover{color:var(--color-light)}.comment{padding:5px;margin-bottom:15px}.comment-title{border-bottom:1px dotted #eee;margin-left:55px}.comment-date{color:var(--color-light);font-weight:200}.comment-actions{text-align:right}.comment-content{margin-left:55px}.comments .text-editor textarea{height:90px}.comments .text-editor .text-editor-preview-area{height:90px}.comments .comment-highlighted{background-color:#fff8dc;border:2px solid #ffeb8e}.comments .comment-highlighted:hover{background-color:#fff8dc}.comments .comment:hover{background:#fff8dc}.comments .comment:nth-child(even):not(.comment-highlighted){background:#fbfbfb}.comments .comment:nth-child(even):not(.comment-highlighted):hover{background:#fff8dc}.subtask-cell{padding:4px 10px;border-top:1px dotted #dedede;border-left:1px dotted #dedede;display:table-cell;vertical-align:middle}.subtask-cell a{color:var(--color-primary);text-decoration:none}.subtask-cell a:hover,.subtask-cell a:focus{color:var(--link-color-primary)}.subtask-cell:first-child{border-left:none}@media (max-width:768px){.subtask-cell{width:90%;display:block;border-left:none}}.subtasks-table .subtask-table-td{display:flex;white-space:normal;min-width:400px}.subtasks-table .subtask-submenu{display:flex}.js-subtask-toggle-status{display:flex;text-decoration:none}.task-list-subtasks{display:table;width:100%}@media (max-width:768px){.task-list-subtasks{display:block}}.task-list-subtask{display:table-row}@media (max-width:768px){.task-list-subtask{display:block}}@media (max-width:768px){.subtask-assignee,.subtask-time-tracking-cell{display:none}}.subtask-time-tracking{white-space:normal}.task-links-table td{vertical-align:middle}.task-links-task-count{color:var(--color-light);font-weight:400}.task-link-closed{text-decoration:line-through}.text-editor{margin-top:10px}.text-editor a{font-size:1em;color:var(--color-light);text-decoration:none;margin-right:10px}.text-editor a:hover{color:var(--link-color-primary)}.text-editor .text-editor-preview-area{border:1px solid #dedede;width:700px;max-width:99%;height:250px;overflow:auto;padding:2px}.text-editor textarea{width:700px;max-width:98%;height:250px}.markdown{line-height:1.4em}.markdown h1{margin-top:5px;margin-bottom:10px;font-weight:700}.markdown h2{font-weight:700}.markdown p{margin-bottom:10px}.markdown ol,.markdown ul{margin-left:25px;margin-top:10px;margin-bottom:10px}.markdown pre{background:#fbfbfb;padding:10px;border-radius:5px;border:1px solid #ddd;overflow:auto;overflow-wrap:initial;color:var(--color-medium)}.markdown blockquote{font-style:italic;border-left:3px solid #ddd;padding-left:10px;margin-bottom:10px;margin-left:20px}.markdown img{display:block;max-width:80%;margin-top:10px}.panel{border-radius:4px;padding:8px 35px 8px 10px;margin-top:10px;margin-bottom:15px;border:1px solid #ddd;color:var(--color-primary);background-color:#fcfcfc;overflow:auto}.panel li{list-style-type:square;margin-left:20px;line-height:1.35em}.activity-event{margin-bottom:15px;padding:10px}.activity-event:nth-child(even){background:var(--activity-event-background-color)}.activity-event:hover{background:var(--activity-event-hover-color)}.activity-date{margin-left:10px;font-weight:400;color:var(--color-light)}.activity-content{margin-left:55px}.activity-title{font-weight:700;color:var(--activity-title-color);border-bottom:1px dotted var(--activity-title-border-color)}.activity-description{color:var(--color-medium);margin-top:10px}@media (max-width:480px){.activity-description{overflow:auto}}.activity-description li{list-style-type:circle}.activity-description ul{margin-top:10px;margin-left:20px}.user-mention-link{font-weight:700;color:var(--user-mention-color);text-decoration:none}.user-mention-link:hover{color:var(--color-medium)}.image-slideshow-overlay{position:fixed;top:0;left:0;width:100%;height:100%;background:rgba(0,0,0,.95);overflow:auto;z-index:100}.image-slideshow-overlay img{display:block;margin:auto}.image-slideshow-overlay figcaption{color:#fff;opacity:.7;position:absolute;bottom:5px;right:15px}.slideshow-icon{color:#fff;position:absolute;font-size:2.5em;opacity:.6}.slideshow-icon:hover{opacity:.9;cursor:pointer}.slideshow-previous-icon{left:10px;top:45%}.slideshow-next-icon{right:10px;top:45%}.slideshow-close-icon{right:10px;top:10px;font-size:1.4em}.slideshow-download-icon{left:10px;bottom:10px;font-size:1.3em}.list-item-links,.list-item-actions{display:inline-block;float:left;margin-left:10px}.list-item-links a{margin:0}.list-item-action-hidden{display:none}.bulk-change-checkbox{float:left}.bulk-change-inputs{float:left;padding-left:10px}.bulk-change-inputs label{margin-top:0;margin-bottom:3px} \ No newline at end of file diff --git a/composer.json b/composer.json index 80b8956f8..d18454bcc 100644 --- a/composer.json +++ b/composer.json @@ -28,13 +28,14 @@ "ext-session" : "*", "christian-riesen/otp" : "1.4.3", "eluceo/ical": "0.16.1", - "erusev/parsedown" : "^1.7", + "erusev/parsedown" : "1.7.4", "pimple/pimple" : "3.5.0", - "psr/log": "~1.0", + "psr/log": "1.1.4", "swiftmailer/swiftmailer" : "5.4.8", - "symfony/console" : "4.2.12", - "symfony/event-dispatcher" : "3.4.2", - "gregwar/captcha": "1.1.9" + "symfony/console" : "4.4.37", + "symfony/event-dispatcher" : "4.4.37", + "gregwar/captcha": "1.1.9", + "symfony/finder": "5.4.3" }, "autoload" : { "classmap" : ["app/"], @@ -56,7 +57,7 @@ }, "require-dev" : { "symfony/stopwatch" : "5.4.3", - "phpunit/phpunit" : "^7", + "phpunit/phpunit" : "9.5.13", "roave/security-advisories": "dev-master" } } diff --git a/composer.lock b/composer.lock index 71232568e..80655e221 100644 --- a/composer.lock +++ b/composer.lock @@ -4,34 +4,34 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "c1f5acf487f7a1384b50aba93a21b680", + "content-hash": "9ab66a7ff0a9f1719021900f5378ef39", "packages": [ { "name": "christian-riesen/base32", - "version": "1.3.2", + "version": "1.6.0", "source": { "type": "git", "url": "https://github.com/ChristianRiesen/base32.git", - "reference": "80ff0e3b2124e61b4b39e2535709452f70bff367" + "reference": "2e82dab3baa008e24a505649b0d583c31d31e894" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/ChristianRiesen/base32/zipball/80ff0e3b2124e61b4b39e2535709452f70bff367", - "reference": "80ff0e3b2124e61b4b39e2535709452f70bff367", + "url": "https://api.github.com/repos/ChristianRiesen/base32/zipball/2e82dab3baa008e24a505649b0d583c31d31e894", + "reference": "2e82dab3baa008e24a505649b0d583c31d31e894", "shasum": "" }, "require": { - "php": ">=5.3" + "php": "^7.2 || ^8.0" }, "require-dev": { - "php": ">=5.6", - "phpunit/phpunit": "^5.0", - "satooshi/php-coveralls": "^1.0" + "friendsofphp/php-cs-fixer": "^2.17", + "phpstan/phpstan": "^0.12", + "phpunit/phpunit": "^8.5.13 || ^9.5" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.1.x-dev" + "dev-master": "1.x-dev" } }, "autoload": { @@ -59,7 +59,11 @@ "encode", "rfc4648" ], - "time": "2018-11-02T09:03:50+00:00" + "support": { + "issues": "https://github.com/ChristianRiesen/base32/issues", + "source": "https://github.com/ChristianRiesen/base32/tree/1.6.0" + }, + "time": "2021-02-26T10:19:33+00:00" }, { "name": "christian-riesen/otp", @@ -110,6 +114,10 @@ "rfc6238", "totp" ], + "support": { + "issues": "https://github.com/ChristianRiesen/otp/issues", + "source": "https://github.com/ChristianRiesen/otp/tree/master" + }, "time": "2015-10-08T08:17:59+00:00" }, { @@ -161,6 +169,10 @@ "ics", "php calendar" ], + "support": { + "issues": "https://github.com/markuspoerschke/iCal/issues", + "source": "https://github.com/markuspoerschke/iCal" + }, "time": "2020-10-04T17:41:11+00:00" }, { @@ -207,6 +219,10 @@ "markdown", "parser" ], + "support": { + "issues": "https://github.com/erusev/parsedown/issues", + "source": "https://github.com/erusev/parsedown/tree/1.7.x" + }, "time": "2019-12-30T22:54:17+00:00" }, { @@ -260,6 +276,10 @@ "captcha", "spam" ], + "support": { + "issues": "https://github.com/Gregwar/Captcha/issues", + "source": "https://github.com/Gregwar/Captcha/tree/master" + }, "time": "2020-03-24T14:39:05+00:00" }, { @@ -310,31 +330,29 @@ "container", "dependency injection" ], + "support": { + "source": "https://github.com/silexphp/Pimple/tree/v3.5.0" + }, "time": "2021-10-28T11:13:42+00:00" }, { "name": "psr/container", - "version": "2.0.1", + "version": "1.1.2", "source": { "type": "git", "url": "https://github.com/php-fig/container.git", - "reference": "2ae37329ee82f91efadc282cc2d527fd6065a5ef" + "reference": "513e0666f7216c7459170d56df27dfcefe1689ea" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/container/zipball/2ae37329ee82f91efadc282cc2d527fd6065a5ef", - "reference": "2ae37329ee82f91efadc282cc2d527fd6065a5ef", + "url": "https://api.github.com/repos/php-fig/container/zipball/513e0666f7216c7459170d56df27dfcefe1689ea", + "reference": "513e0666f7216c7459170d56df27dfcefe1689ea", "shasum": "" }, "require": { - "php": ">=7.2.0" + "php": ">=7.4.0" }, "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.0.x-dev" - } - }, "autoload": { "psr-4": { "Psr\\Container\\": "src/" @@ -359,7 +377,11 @@ "container-interop", "psr" ], - "time": "2021-03-24T13:40:57+00:00" + "support": { + "issues": "https://github.com/php-fig/container/issues", + "source": "https://github.com/php-fig/container/tree/1.1.2" + }, + "time": "2021-11-05T16:50:12+00:00" }, { "name": "psr/log", @@ -406,6 +428,9 @@ "psr", "psr-3" ], + "support": { + "source": "https://github.com/php-fig/log/tree/1.1.4" + }, "time": "2021-05-03T11:20:27+00:00" }, { @@ -460,42 +485,52 @@ "mail", "mailer" ], + "support": { + "issues": "https://github.com/swiftmailer/swiftmailer/issues", + "source": "https://github.com/swiftmailer/swiftmailer/tree/v5.4.8" + }, "abandoned": "symfony/mailer", "time": "2017-05-01T15:54:03+00:00" }, { "name": "symfony/console", - "version": "v4.2.12", + "version": "v4.4.37", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "fc2e274aade6567a750551942094b2145ade9b6c" + "reference": "0259f01dbf9d77badddbbf4c2abb681f24c9cac6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/fc2e274aade6567a750551942094b2145ade9b6c", - "reference": "fc2e274aade6567a750551942094b2145ade9b6c", + "url": "https://api.github.com/repos/symfony/console/zipball/0259f01dbf9d77badddbbf4c2abb681f24c9cac6", + "reference": "0259f01dbf9d77badddbbf4c2abb681f24c9cac6", "shasum": "" }, "require": { - "php": "^7.1.3", - "symfony/contracts": "^1.0", - "symfony/polyfill-mbstring": "~1.0" + "php": ">=7.1.3", + "symfony/polyfill-mbstring": "~1.0", + "symfony/polyfill-php73": "^1.8", + "symfony/polyfill-php80": "^1.16", + "symfony/service-contracts": "^1.1|^2" }, "conflict": { + "psr/log": ">=3", "symfony/dependency-injection": "<3.4", + "symfony/event-dispatcher": "<4.3|>=5", + "symfony/lock": "<4.4", "symfony/process": "<3.3" }, "provide": { - "psr/log-implementation": "1.0" + "psr/log-implementation": "1.0|2.0" }, "require-dev": { - "psr/log": "~1.0", - "symfony/config": "~3.4|~4.0", - "symfony/dependency-injection": "~3.4|~4.0", - "symfony/event-dispatcher": "~3.4|~4.0", - "symfony/lock": "~3.4|~4.0", - "symfony/process": "~3.4|~4.0" + "psr/log": "^1|^2", + "symfony/config": "^3.4|^4.0|^5.0", + "symfony/dependency-injection": "^3.4|^4.0|^5.0", + "symfony/event-dispatcher": "^4.3", + "symfony/lock": "^4.4|^5.0", + "symfony/process": "^3.4|^4.0|^5.0", + "symfony/var-dumper": "^4.3|^5.0" }, "suggest": { "psr/log": "For using the console logger", @@ -504,11 +539,6 @@ "symfony/process": "" }, "type": "library", - "extra": { - "branch-alias": { - "dev-master": "4.2-dev" - } - }, "autoload": { "psr-4": { "Symfony\\Component\\Console\\": "" @@ -531,61 +561,57 @@ "homepage": "https://symfony.com/contributors" } ], - "description": "Symfony Console Component", + "description": "Eases the creation of beautiful and testable command line interfaces", "homepage": "https://symfony.com", - "time": "2019-07-24T17:13:20+00:00" + "support": { + "source": "https://github.com/symfony/console/tree/v4.4.37" + }, + "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": "2022-01-26T16:15:26+00:00" }, { - "name": "symfony/contracts", - "version": "v1.1.3", + "name": "symfony/deprecation-contracts", + "version": "v2.5.0", "source": { "type": "git", - "url": "https://github.com/symfony/contracts.git", - "reference": "2d19b12caccbd80cf0c85624dc87b7021a0df1d5" + "url": "https://github.com/symfony/deprecation-contracts.git", + "reference": "6f981ee24cf69ee7ce9736146d1c57c2780598a8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/contracts/zipball/2d19b12caccbd80cf0c85624dc87b7021a0df1d5", - "reference": "2d19b12caccbd80cf0c85624dc87b7021a0df1d5", + "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/6f981ee24cf69ee7ce9736146d1c57c2780598a8", + "reference": "6f981ee24cf69ee7ce9736146d1c57c2780598a8", "shasum": "" }, "require": { - "php": "^7.1.3" - }, - "replace": { - "symfony/cache-contracts": "self.version", - "symfony/event-dispatcher-contracts": "self.version", - "symfony/http-client-contracts": "self.version", - "symfony/service-contracts": "self.version", - "symfony/translation-contracts": "self.version" - }, - "require-dev": { - "psr/cache": "^1.0", - "psr/container": "^1.0", - "symfony/polyfill-intl-idn": "^1.10" - }, - "suggest": { - "psr/cache": "When using the Cache contracts", - "psr/container": "When using the Service contracts", - "psr/event-dispatcher": "When using the EventDispatcher contracts", - "symfony/cache-implementation": "", - "symfony/event-dispatcher-implementation": "", - "symfony/http-client-implementation": "", - "symfony/service-implementation": "", - "symfony/translation-implementation": "" + "php": ">=7.1" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.1-dev" + "dev-main": "2.5-dev" + }, + "thanks": { + "name": "symfony/contracts", + "url": "https://github.com/symfony/contracts" } }, "autoload": { - "psr-4": { - "Symfony\\Contracts\\": "" - }, - "exclude-from-classmap": [ - "**/Tests/" + "files": [ + "function.php" ] }, "notification-url": "https://packagist.org/downloads/", @@ -602,55 +628,68 @@ "homepage": "https://symfony.com/contributors" } ], - "description": "A set of abstractions extracted out of the Symfony components", + "description": "A generic function and convention to trigger deprecation notices", "homepage": "https://symfony.com", - "keywords": [ - "abstractions", - "contracts", - "decoupling", - "interfaces", - "interoperability", - "standards" + "support": { + "source": "https://github.com/symfony/deprecation-contracts/tree/v2.5.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": "2019-06-05T13:28:50+00:00" + "time": "2021-07-12T14:48:14+00:00" }, { "name": "symfony/event-dispatcher", - "version": "v3.4.2", + "version": "v4.4.37", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher.git", - "reference": "b869cbf8a15ca6261689de2c28a7d7f2d0706835" + "reference": "3ccfcfb96ecce1217d7b0875a0736976bc6e63dc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/b869cbf8a15ca6261689de2c28a7d7f2d0706835", - "reference": "b869cbf8a15ca6261689de2c28a7d7f2d0706835", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/3ccfcfb96ecce1217d7b0875a0736976bc6e63dc", + "reference": "3ccfcfb96ecce1217d7b0875a0736976bc6e63dc", "shasum": "" }, "require": { - "php": "^5.5.9|>=7.0.8" + "php": ">=7.1.3", + "symfony/event-dispatcher-contracts": "^1.1", + "symfony/polyfill-php80": "^1.16" }, "conflict": { - "symfony/dependency-injection": "<3.3" + "symfony/dependency-injection": "<3.4" + }, + "provide": { + "psr/event-dispatcher-implementation": "1.0", + "symfony/event-dispatcher-implementation": "1.1" }, "require-dev": { - "psr/log": "~1.0", - "symfony/config": "~2.8|~3.0|~4.0", - "symfony/dependency-injection": "~3.3|~4.0", - "symfony/expression-language": "~2.8|~3.0|~4.0", - "symfony/stopwatch": "~2.8|~3.0|~4.0" + "psr/log": "^1|^2|^3", + "symfony/config": "^3.4|^4.0|^5.0", + "symfony/dependency-injection": "^3.4|^4.0|^5.0", + "symfony/error-handler": "~3.4|~4.4", + "symfony/expression-language": "^3.4|^4.0|^5.0", + "symfony/http-foundation": "^3.4|^4.0|^5.0", + "symfony/service-contracts": "^1.1|^2", + "symfony/stopwatch": "^3.4|^4.0|^5.0" }, "suggest": { "symfony/dependency-injection": "", "symfony/http-kernel": "" }, "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.4-dev" - } - }, "autoload": { "psr-4": { "Symfony\\Component\\EventDispatcher\\": "" @@ -673,26 +712,124 @@ "homepage": "https://symfony.com/contributors" } ], - "description": "Symfony EventDispatcher Component", + "description": "Provides tools that allow your application components to communicate with each other by dispatching events and listening to them", "homepage": "https://symfony.com", - "time": "2017-12-14T19:40:10+00:00" + "support": { + "source": "https://github.com/symfony/event-dispatcher/tree/v4.4.37" + }, + "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": "2022-01-02T09:41:36+00:00" }, { - "name": "symfony/finder", - "version": "v5.2.1", + "name": "symfony/event-dispatcher-contracts", + "version": "v1.1.11", "source": { "type": "git", - "url": "https://github.com/symfony/finder.git", - "reference": "0b9231a5922fd7287ba5b411893c0ecd2733e5ba" + "url": "https://github.com/symfony/event-dispatcher-contracts.git", + "reference": "01e9a4efac0ee33a05dfdf93b346f62e7d0e998c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/0b9231a5922fd7287ba5b411893c0ecd2733e5ba", - "reference": "0b9231a5922fd7287ba5b411893c0ecd2733e5ba", + "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/01e9a4efac0ee33a05dfdf93b346f62e7d0e998c", + "reference": "01e9a4efac0ee33a05dfdf93b346f62e7d0e998c", "shasum": "" }, "require": { - "php": ">=7.2.5" + "php": ">=7.1.3" + }, + "suggest": { + "psr/event-dispatcher": "", + "symfony/event-dispatcher-implementation": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.1-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/v1.1.11" + }, + "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": "2021-03-23T15:25:38+00:00" + }, + { + "name": "symfony/finder", + "version": "v5.4.3", + "source": { + "type": "git", + "url": "https://github.com/symfony/finder.git", + "reference": "231313534dded84c7ecaa79d14bc5da4ccb69b7d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/finder/zipball/231313534dded84c7ecaa79d14bc5da4ccb69b7d", + "reference": "231313534dded84c7ecaa79d14bc5da4ccb69b7d", + "shasum": "" + }, + "require": { + "php": ">=7.2.5", + "symfony/deprecation-contracts": "^2.1|^3", + "symfony/polyfill-php80": "^1.16" }, "type": "library", "autoload": { @@ -717,8 +854,11 @@ "homepage": "https://symfony.com/contributors" } ], - "description": "Symfony Finder Component", + "description": "Finds files and directories via an intuitive fluent interface", "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/finder/tree/v5.4.3" + }, "funding": [ { "url": "https://symfony.com/sponsor", @@ -733,24 +873,27 @@ "type": "tidelift" } ], - "time": "2020-12-08T17:02:38+00:00" + "time": "2022-01-26T16:34:36+00:00" }, { "name": "symfony/polyfill-mbstring", - "version": "v1.18.1", + "version": "v1.24.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "a6977d63bf9a0ad4c65cd352709e230876f9904a" + "reference": "0abb51d2f102e00a4eefcf46ba7fec406d245825" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/a6977d63bf9a0ad4c65cd352709e230876f9904a", - "reference": "a6977d63bf9a0ad4c65cd352709e230876f9904a", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/0abb51d2f102e00a4eefcf46ba7fec406d245825", + "reference": "0abb51d2f102e00a4eefcf46ba7fec406d245825", "shasum": "" }, "require": { - "php": ">=5.3.3" + "php": ">=7.1" + }, + "provide": { + "ext-mbstring": "*" }, "suggest": { "ext-mbstring": "For best performance" @@ -758,7 +901,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.18-dev" + "dev-main": "1.23-dev" }, "thanks": { "name": "symfony/polyfill", @@ -796,6 +939,9 @@ "portable", "shim" ], + "support": { + "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.24.0" + }, "funding": [ { "url": "https://symfony.com/sponsor", @@ -810,42 +956,282 @@ "type": "tidelift" } ], - "time": "2020-07-14T12:35:20+00:00" + "time": "2021-11-30T18:21:41+00:00" + }, + { + "name": "symfony/polyfill-php73", + "version": "v1.24.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-php73.git", + "reference": "cc5db0e22b3cb4111010e48785a97f670b350ca5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-php73/zipball/cc5db0e22b3cb4111010e48785a97f670b350ca5", + "reference": "cc5db0e22b3cb4111010e48785a97f670b350ca5", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.23-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Polyfill\\Php73\\": "" + }, + "files": [ + "bootstrap.php" + ], + "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 7.3+ features to lower PHP versions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-php73/tree/v1.24.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": "2021-06-05T21:20:04+00:00" + }, + { + "name": "symfony/polyfill-php80", + "version": "v1.24.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-php80.git", + "reference": "57b712b08eddb97c762a8caa32c84e037892d2e9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/57b712b08eddb97c762a8caa32c84e037892d2e9", + "reference": "57b712b08eddb97c762a8caa32c84e037892d2e9", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.23-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Polyfill\\Php80\\": "" + }, + "files": [ + "bootstrap.php" + ], + "classmap": [ + "Resources/stubs" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Ion Bazan", + "email": "ion.bazan@gmail.com" + }, + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill backporting some PHP 8.0+ features to lower PHP versions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-php80/tree/v1.24.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": "2021-09-13T13:58:33+00:00" + }, + { + "name": "symfony/service-contracts", + "version": "v2.5.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/service-contracts.git", + "reference": "1ab11b933cd6bc5464b08e81e2c5b07dec58b0fc" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/service-contracts/zipball/1ab11b933cd6bc5464b08e81e2c5b07dec58b0fc", + "reference": "1ab11b933cd6bc5464b08e81e2c5b07dec58b0fc", + "shasum": "" + }, + "require": { + "php": ">=7.2.5", + "psr/container": "^1.1", + "symfony/deprecation-contracts": "^2.1" + }, + "conflict": { + "ext-psr": "<1.1|>=2" + }, + "suggest": { + "symfony/service-implementation": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "2.5-dev" + }, + "thanks": { + "name": "symfony/contracts", + "url": "https://github.com/symfony/contracts" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Contracts\\Service\\": "" + } + }, + "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/v2.5.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": "2021-11-04T16:48:04+00:00" } ], "packages-dev": [ { "name": "doctrine/instantiator", - "version": "1.3.1", + "version": "1.4.0", "source": { "type": "git", "url": "https://github.com/doctrine/instantiator.git", - "reference": "f350df0268e904597e3bd9c4685c53e0e333feea" + "reference": "d56bf6102915de5702778fe20f2de3b2fe570b5b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/instantiator/zipball/f350df0268e904597e3bd9c4685c53e0e333feea", - "reference": "f350df0268e904597e3bd9c4685c53e0e333feea", + "url": "https://api.github.com/repos/doctrine/instantiator/zipball/d56bf6102915de5702778fe20f2de3b2fe570b5b", + "reference": "d56bf6102915de5702778fe20f2de3b2fe570b5b", "shasum": "" }, "require": { "php": "^7.1 || ^8.0" }, "require-dev": { - "doctrine/coding-standard": "^6.0", + "doctrine/coding-standard": "^8.0", "ext-pdo": "*", "ext-phar": "*", - "phpbench/phpbench": "^0.13", - "phpstan/phpstan-phpunit": "^0.11", - "phpstan/phpstan-shim": "^0.11", - "phpunit/phpunit": "^7.0" + "phpbench/phpbench": "^0.13 || 1.0.0-alpha2", + "phpstan/phpstan": "^0.12", + "phpstan/phpstan-phpunit": "^0.12", + "phpunit/phpunit": "^7.0 || ^8.0 || ^9.0" }, "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.2.x-dev" - } - }, "autoload": { "psr-4": { "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/" @@ -859,7 +1245,7 @@ { "name": "Marco Pivetta", "email": "ocramius@gmail.com", - "homepage": "http://ocramius.github.com/" + "homepage": "https://ocramius.github.io/" } ], "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors", @@ -868,6 +1254,10 @@ "constructor", "instantiate" ], + "support": { + "issues": "https://github.com/doctrine/instantiator/issues", + "source": "https://github.com/doctrine/instantiator/tree/1.4.0" + }, "funding": [ { "url": "https://www.doctrine-project.org/sponsorship.html", @@ -882,20 +1272,20 @@ "type": "tidelift" } ], - "time": "2020-05-29T17:27:14+00:00" + "time": "2020-11-10T18:47:58+00:00" }, { "name": "myclabs/deep-copy", - "version": "1.10.1", + "version": "1.10.2", "source": { "type": "git", "url": "https://github.com/myclabs/DeepCopy.git", - "reference": "969b211f9a51aa1f6c01d1d2aef56d3bd91598e5" + "reference": "776f831124e9c62e1a2c601ecc52e776d8bb7220" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/969b211f9a51aa1f6c01d1d2aef56d3bd91598e5", - "reference": "969b211f9a51aa1f6c01d1d2aef56d3bd91598e5", + "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/776f831124e9c62e1a2c601ecc52e776d8bb7220", + "reference": "776f831124e9c62e1a2c601ecc52e776d8bb7220", "shasum": "" }, "require": { @@ -911,12 +1301,12 @@ }, "type": "library", "autoload": { - "psr-4": { - "DeepCopy\\": "src/DeepCopy/" - }, "files": [ "src/DeepCopy/deep_copy.php" - ] + ], + "psr-4": { + "DeepCopy\\": "src/DeepCopy/" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -930,38 +1320,99 @@ "object", "object graph" ], + "support": { + "issues": "https://github.com/myclabs/DeepCopy/issues", + "source": "https://github.com/myclabs/DeepCopy/tree/1.10.2" + }, "funding": [ { "url": "https://tidelift.com/funding/github/packagist/myclabs/deep-copy", "type": "tidelift" } ], - "time": "2020-06-29T13:22:24+00:00" + "time": "2020-11-13T09:40:50+00:00" }, { - "name": "phar-io/manifest", - "version": "1.0.3", + "name": "nikic/php-parser", + "version": "v4.13.2", "source": { "type": "git", - "url": "https://github.com/phar-io/manifest.git", - "reference": "7761fcacf03b4d4f16e7ccb606d4879ca431fcf4" + "url": "https://github.com/nikic/PHP-Parser.git", + "reference": "210577fe3cf7badcc5814d99455df46564f3c077" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phar-io/manifest/zipball/7761fcacf03b4d4f16e7ccb606d4879ca431fcf4", - "reference": "7761fcacf03b4d4f16e7ccb606d4879ca431fcf4", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/210577fe3cf7badcc5814d99455df46564f3c077", + "reference": "210577fe3cf7badcc5814d99455df46564f3c077", + "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.13.2" + }, + "time": "2021-11-30T19:35:32+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": "*", - "phar-io/version": "^2.0", - "php": "^5.6 || ^7.0" + "ext-xmlwriter": "*", + "phar-io/version": "^3.0.1", + "php": "^7.2 || ^8.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0.x-dev" + "dev-master": "2.0.x-dev" } }, "autoload": { @@ -991,24 +1442,28 @@ } ], "description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)", - "time": "2018-07-08T19:23:20+00:00" + "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": "2.0.1", + "version": "3.1.0", "source": { "type": "git", "url": "https://github.com/phar-io/version.git", - "reference": "45a2ec53a73c70ce41d55cedef9063630abaf1b6" + "reference": "bae7c545bef187884426f042434e561ab1ddb182" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phar-io/version/zipball/45a2ec53a73c70ce41d55cedef9063630abaf1b6", - "reference": "45a2ec53a73c70ce41d55cedef9063630abaf1b6", + "url": "https://api.github.com/repos/phar-io/version/zipball/bae7c545bef187884426f042434e561ab1ddb182", + "reference": "bae7c545bef187884426f042434e561ab1ddb182", "shasum": "" }, "require": { - "php": "^5.6 || ^7.0" + "php": "^7.2 || ^8.0" }, "type": "library", "autoload": { @@ -1038,7 +1493,11 @@ } ], "description": "Library for handling version information and constraints", - "time": "2018-07-08T19:19:57+00:00" + "support": { + "issues": "https://github.com/phar-io/version/issues", + "source": "https://github.com/phar-io/version/tree/3.1.0" + }, + "time": "2021-02-23T14:00:09+00:00" }, { "name": "phpdocumentor/reflection-common", @@ -1087,20 +1546,24 @@ "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.2.2", + "version": "5.3.0", "source": { "type": "git", "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", - "reference": "069a785b2141f5bcf49f3e353548dc1cce6df556" + "reference": "622548b623e81ca6d78b721c5e029f4ce664f170" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/069a785b2141f5bcf49f3e353548dc1cce6df556", - "reference": "069a785b2141f5bcf49f3e353548dc1cce6df556", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/622548b623e81ca6d78b721c5e029f4ce664f170", + "reference": "622548b623e81ca6d78b721c5e029f4ce664f170", "shasum": "" }, "require": { @@ -1111,7 +1574,8 @@ "webmozart/assert": "^1.9.1" }, "require-dev": { - "mockery/mockery": "~1.3.2" + "mockery/mockery": "~1.3.2", + "psalm/phar": "^4.8" }, "type": "library", "extra": { @@ -1139,20 +1603,24 @@ } ], "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.", - "time": "2020-09-03T19:13:55+00:00" + "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.4.0", + "version": "1.6.0", "source": { "type": "git", "url": "https://github.com/phpDocumentor/TypeResolver.git", - "reference": "6a467b8989322d92aa1c8bf2bebcc6e5c2ba55c0" + "reference": "93ebd0014cab80c4ea9f5e297ea48672f1b87706" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/6a467b8989322d92aa1c8bf2bebcc6e5c2ba55c0", - "reference": "6a467b8989322d92aa1c8bf2bebcc6e5c2ba55c0", + "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/93ebd0014cab80c4ea9f5e297ea48672f1b87706", + "reference": "93ebd0014cab80c4ea9f5e297ea48672f1b87706", "shasum": "" }, "require": { @@ -1160,7 +1628,8 @@ "phpdocumentor/reflection-common": "^2.0" }, "require-dev": { - "ext-tokenizer": "*" + "ext-tokenizer": "*", + "psalm/phar": "^4.8" }, "type": "library", "extra": { @@ -1184,37 +1653,41 @@ } ], "description": "A PSR-5 based resolver of Class names, Types and Structural Element Names", - "time": "2020-09-17T18:55:26+00:00" + "support": { + "issues": "https://github.com/phpDocumentor/TypeResolver/issues", + "source": "https://github.com/phpDocumentor/TypeResolver/tree/1.6.0" + }, + "time": "2022-01-04T19:58:01+00:00" }, { "name": "phpspec/prophecy", - "version": "1.12.1", + "version": "v1.15.0", "source": { "type": "git", "url": "https://github.com/phpspec/prophecy.git", - "reference": "8ce87516be71aae9b956f81906aaf0338e0d8a2d" + "reference": "bbcd7380b0ebf3961ee21409db7b38bc31d69a13" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpspec/prophecy/zipball/8ce87516be71aae9b956f81906aaf0338e0d8a2d", - "reference": "8ce87516be71aae9b956f81906aaf0338e0d8a2d", + "url": "https://api.github.com/repos/phpspec/prophecy/zipball/bbcd7380b0ebf3961ee21409db7b38bc31d69a13", + "reference": "bbcd7380b0ebf3961ee21409db7b38bc31d69a13", "shasum": "" }, "require": { "doctrine/instantiator": "^1.2", - "php": "^7.2 || ~8.0, <8.1", + "php": "^7.2 || ~8.0, <8.2", "phpdocumentor/reflection-docblock": "^5.2", "sebastian/comparator": "^3.0 || ^4.0", "sebastian/recursion-context": "^3.0 || ^4.0" }, "require-dev": { - "phpspec/phpspec": "^6.0", - "phpunit/phpunit": "^8.0 || ^9.0 <9.3" + "phpspec/phpspec": "^6.0 || ^7.0", + "phpunit/phpunit": "^8.0 || ^9.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.11.x-dev" + "dev-master": "1.x-dev" } }, "autoload": { @@ -1247,44 +1720,52 @@ "spy", "stub" ], - "time": "2020-09-29T09:10:42+00:00" + "support": { + "issues": "https://github.com/phpspec/prophecy/issues", + "source": "https://github.com/phpspec/prophecy/tree/v1.15.0" + }, + "time": "2021-12-08T12:19:24+00:00" }, { "name": "phpunit/php-code-coverage", - "version": "6.1.4", + "version": "9.2.10", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "807e6013b00af69b6c5d9ceb4282d0393dbb9d8d" + "reference": "d5850aaf931743067f4bfc1ae4cbd06468400687" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/807e6013b00af69b6c5d9ceb4282d0393dbb9d8d", - "reference": "807e6013b00af69b6c5d9ceb4282d0393dbb9d8d", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/d5850aaf931743067f4bfc1ae4cbd06468400687", + "reference": "d5850aaf931743067f4bfc1ae4cbd06468400687", "shasum": "" }, "require": { "ext-dom": "*", + "ext-libxml": "*", "ext-xmlwriter": "*", - "php": "^7.1", - "phpunit/php-file-iterator": "^2.0", - "phpunit/php-text-template": "^1.2.1", - "phpunit/php-token-stream": "^3.0", - "sebastian/code-unit-reverse-lookup": "^1.0.1", - "sebastian/environment": "^3.1 || ^4.0", - "sebastian/version": "^2.0.1", - "theseer/tokenizer": "^1.1" + "nikic/php-parser": "^4.13.0", + "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": "^7.0" + "phpunit/phpunit": "^9.3" }, "suggest": { - "ext-xdebug": "^2.6.0" + "ext-pcov": "*", + "ext-xdebug": "*" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "6.1-dev" + "dev-master": "9.2-dev" } }, "autoload": { @@ -1310,32 +1791,42 @@ "testing", "xunit" ], - "time": "2018-10-31T16:06:48+00:00" + "support": { + "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", + "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.10" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2021-12-05T09:12:13+00:00" }, { "name": "phpunit/php-file-iterator", - "version": "2.0.2", + "version": "3.0.6", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-file-iterator.git", - "reference": "050bedf145a257b1ff02746c31894800e5122946" + "reference": "cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/050bedf145a257b1ff02746c31894800e5122946", - "reference": "050bedf145a257b1ff02746c31894800e5122946", + "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf", + "reference": "cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf", "shasum": "" }, "require": { - "php": "^7.1" + "php": ">=7.3" }, "require-dev": { - "phpunit/phpunit": "^7.1" + "phpunit/phpunit": "^9.3" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.0.x-dev" + "dev-master": "3.0-dev" } }, "autoload": { @@ -1360,26 +1851,107 @@ "filesystem", "iterator" ], - "time": "2018-09-13T20:33:42+00:00" + "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-text-template", - "version": "1.2.1", + "name": "phpunit/php-invoker", + "version": "3.1.1", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/php-text-template.git", - "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686" + "url": "https://github.com/sebastianbergmann/php-invoker.git", + "reference": "5a10147d0aaf65b58940a0b72f71c9ac0423cc67" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/31f8b717e51d9a2afca6c9f046f5d69fc27c8686", - "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686", + "url": "https://api.github.com/repos/sebastianbergmann/php-invoker/zipball/5a10147d0aaf65b58940a0b72f71c9ac0423cc67", + "reference": "5a10147d0aaf65b58940a0b72f71c9ac0423cc67", "shasum": "" }, "require": { - "php": ">=5.3.3" + "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/" @@ -1401,32 +1973,42 @@ "keywords": [ "template" ], - "time": "2015-06-21T13:50:34+00:00" + "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": "2.1.2", + "version": "5.0.3", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-timer.git", - "reference": "1038454804406b0b5f5f520358e78c1c2f71501e" + "reference": "5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/1038454804406b0b5f5f520358e78c1c2f71501e", - "reference": "1038454804406b0b5f5f520358e78c1c2f71501e", + "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2", + "reference": "5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2", "shasum": "" }, "require": { - "php": "^7.1" + "php": ">=7.3" }, "require-dev": { - "phpunit/phpunit": "^7.0" + "phpunit/phpunit": "^9.3" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.1-dev" + "dev-master": "5.0-dev" } }, "autoload": { @@ -1450,107 +2032,69 @@ "keywords": [ "timer" ], - "time": "2019-06-07T04:22:29+00:00" - }, - { - "name": "phpunit/php-token-stream", - "version": "3.1.1", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-token-stream.git", - "reference": "995192df77f63a59e47f025390d2d1fdf8f425ff" + "support": { + "issues": "https://github.com/sebastianbergmann/php-timer/issues", + "source": "https://github.com/sebastianbergmann/php-timer/tree/5.0.3" }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/995192df77f63a59e47f025390d2d1fdf8f425ff", - "reference": "995192df77f63a59e47f025390d2d1fdf8f425ff", - "shasum": "" - }, - "require": { - "ext-tokenizer": "*", - "php": "^7.1" - }, - "require-dev": { - "phpunit/phpunit": "^7.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.1-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ + "funding": [ { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" + "url": "https://github.com/sebastianbergmann", + "type": "github" } ], - "description": "Wrapper around PHP's tokenizer extension.", - "homepage": "https://github.com/sebastianbergmann/php-token-stream/", - "keywords": [ - "tokenizer" - ], - "abandoned": true, - "time": "2019-09-17T06:23:10+00:00" + "time": "2020-10-26T13:16:10+00:00" }, { "name": "phpunit/phpunit", - "version": "7.5.20", + "version": "9.5.13", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "9467db479d1b0487c99733bb1e7944d32deded2c" + "reference": "597cb647654ede35e43b137926dfdfef0fb11743" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/9467db479d1b0487c99733bb1e7944d32deded2c", - "reference": "9467db479d1b0487c99733bb1e7944d32deded2c", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/597cb647654ede35e43b137926dfdfef0fb11743", + "reference": "597cb647654ede35e43b137926dfdfef0fb11743", "shasum": "" }, "require": { - "doctrine/instantiator": "^1.1", + "doctrine/instantiator": "^1.3.1", "ext-dom": "*", "ext-json": "*", "ext-libxml": "*", "ext-mbstring": "*", "ext-xml": "*", - "myclabs/deep-copy": "^1.7", - "phar-io/manifest": "^1.0.2", - "phar-io/version": "^2.0", - "php": "^7.1", - "phpspec/prophecy": "^1.7", - "phpunit/php-code-coverage": "^6.0.7", - "phpunit/php-file-iterator": "^2.0.1", - "phpunit/php-text-template": "^1.2.1", - "phpunit/php-timer": "^2.1", - "sebastian/comparator": "^3.0", - "sebastian/diff": "^3.0", - "sebastian/environment": "^4.0", - "sebastian/exporter": "^3.1", - "sebastian/global-state": "^2.0", - "sebastian/object-enumerator": "^3.0.3", - "sebastian/resource-operations": "^2.0", - "sebastian/version": "^2.0.1" - }, - "conflict": { - "phpunit/phpunit-mock-objects": "*" + "ext-xmlwriter": "*", + "myclabs/deep-copy": "^1.10.1", + "phar-io/manifest": "^2.0.3", + "phar-io/version": "^3.0.2", + "php": ">=7.3", + "phpspec/prophecy": "^1.12.1", + "phpunit/php-code-coverage": "^9.2.7", + "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.5", + "sebastian/diff": "^4.0.3", + "sebastian/environment": "^5.1.3", + "sebastian/exporter": "^4.0.3", + "sebastian/global-state": "^5.0.1", + "sebastian/object-enumerator": "^4.0.3", + "sebastian/resource-operations": "^3.0.3", + "sebastian/type": "^2.3.4", + "sebastian/version": "^3.0.2" }, "require-dev": { - "ext-pdo": "*" + "ext-pdo": "*", + "phpspec/prophecy-phpunit": "^2.0.1" }, "suggest": { "ext-soap": "*", - "ext-xdebug": "*", - "phpunit/php-invoker": "^2.0" + "ext-xdebug": "*" }, "bin": [ "phpunit" @@ -1558,12 +2102,15 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "7.5-dev" + "dev-master": "9.5-dev" } }, "autoload": { "classmap": [ "src/" + ], + "files": [ + "src/Framework/Assert/Functions.php" ] }, "notification-url": "https://packagist.org/downloads/", @@ -1584,7 +2131,21 @@ "testing", "xunit" ], - "time": "2020-01-08T08:45:45+00:00" + "support": { + "issues": "https://github.com/sebastianbergmann/phpunit/issues", + "source": "https://github.com/sebastianbergmann/phpunit/tree/9.5.13" + }, + "funding": [ + { + "url": "https://phpunit.de/sponsors.html", + "type": "custom" + }, + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2022-01-24T07:33:35+00:00" }, { "name": "roave/security-advisories", @@ -1592,12 +2153,12 @@ "source": { "type": "git", "url": "https://github.com/Roave/SecurityAdvisories.git", - "reference": "f2fdb4f34a593f9435ff6f994a4ca47600f285d9" + "reference": "2ec9ad634c459ee60c42d99390be37c8a3c6e8e5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Roave/SecurityAdvisories/zipball/f2fdb4f34a593f9435ff6f994a4ca47600f285d9", - "reference": "f2fdb4f34a593f9435ff6f994a4ca47600f285d9", + "url": "https://api.github.com/repos/Roave/SecurityAdvisories/zipball/2ec9ad634c459ee60c42d99390be37c8a3c6e8e5", + "reference": "2ec9ad634c459ee60c42d99390be37c8a3c6e8e5", "shasum": "" }, "conflict": { @@ -1743,7 +2304,7 @@ "klaviyo/magento2-extension": ">=1,<3", "kreait/firebase-php": ">=3.2,<3.8.1", "la-haute-societe/tcpdf": "<6.2.22", - "laminas/laminas-form": "<3.1.1", + "laminas/laminas-form": "<2.17.1|>=3,<3.0.2|>=3.1,<3.1.1", "laminas/laminas-http": "<2.14.2", "laravel/framework": "<6.20.42|>=7,<7.30.6|>=8,<8.75", "laravel/socialite": ">=1,<1.0.99|>=2,<2.0.10", @@ -1850,7 +2411,7 @@ "shopware/platform": "<=6.4.6", "shopware/production": "<=6.3.5.2", "shopware/shopware": "<5.7.7", - "showdoc/showdoc": "<2.10", + "showdoc/showdoc": "<2.10.2", "silverstripe/admin": ">=1,<1.8.1", "silverstripe/assets": ">=1,<1.4.7|>=1.5,<1.5.2", "silverstripe/cms": "<4.3.6|>=4.4,<4.4.4", @@ -1896,7 +2457,7 @@ "symfony/dependency-injection": ">=2,<2.0.17|>=2.7,<2.7.51|>=2.8,<2.8.50|>=3,<3.4.26|>=4,<4.1.12|>=4.2,<4.2.7", "symfony/error-handler": ">=4.4,<4.4.4|>=5,<5.0.4", "symfony/form": ">=2.3,<2.3.35|>=2.4,<2.6.12|>=2.7,<2.7.50|>=2.8,<2.8.49|>=3,<3.4.20|>=4,<4.0.15|>=4.1,<4.1.9|>=4.2,<4.2.1", - "symfony/framework-bundle": ">=2,<2.3.18|>=2.4,<2.4.8|>=2.5,<2.5.2|>=2.7,<2.7.51|>=2.8,<2.8.50|>=3,<3.4.26|>=4,<4.1.12|>=4.2,<4.2.7|>=5.3.14,<=5.3.14|>=5.4.3,<=5.4.3|>=6.0.3,<=6.0.3", + "symfony/framework-bundle": ">=2,<2.3.18|>=2.4,<2.4.8|>=2.5,<2.5.2|>=2.7,<2.7.51|>=2.8,<2.8.50|>=3,<3.4.26|>=4,<4.1.12|>=4.2,<4.2.7|>=5.3.14,<=5.3.14|>=5.4.3,<=5.4.3|>=6.0.3,<=6.0.3|= 6.0.3|= 5.4.3|= 5.3.14", "symfony/http-foundation": ">=2,<2.8.52|>=3,<3.4.35|>=4,<4.2.12|>=4.3,<4.3.8|>=4.4,<4.4.7|>=5,<5.0.7", "symfony/http-kernel": ">=2,<2.8.52|>=3,<3.4.35|>=4,<4.2.12|>=4.3,<4.4.13|>=5,<5.1.5|>=5.2,<5.3.12", "symfony/intl": ">=2.7,<2.7.38|>=2.8,<2.8.31|>=3,<3.2.14|>=3.3,<3.3.13", @@ -1923,6 +2484,7 @@ "t3/dce": ">=2.2,<2.6.2", "t3g/svg-sanitizer": "<1.0.3", "tecnickcom/tcpdf": "<6.2.22", + "terminal42/contao-tablelookupwizard": ">=1,<3.3.5", "thelia/backoffice-default-template": ">=2.1,<2.1.2", "thelia/thelia": ">=2.1-beta.1,<2.1.3", "theonedemon/phpwhois": "<=4.2.5", @@ -2016,6 +2578,10 @@ } ], "description": "Prevents installation of composer packages with known security vulnerabilities: no API, simply require it", + "support": { + "issues": "https://github.com/Roave/SecurityAdvisories/issues", + "source": "https://github.com/Roave/SecurityAdvisories/tree/latest" + }, "funding": [ { "url": "https://github.com/Ocramius", @@ -2026,32 +2592,144 @@ "type": "tidelift" } ], - "time": "2022-01-29T19:13:00+00:00" + "time": "2022-02-05T03:12:57+00:00" }, { - "name": "sebastian/code-unit-reverse-lookup", + "name": "sebastian/cli-parser", "version": "1.0.1", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git", - "reference": "4419fcdb5eabb9caa61a27c7a1db532a6b55dd18" + "url": "https://github.com/sebastianbergmann/cli-parser.git", + "reference": "442e7c7e687e42adc03470c7b668bc4b2402c0b2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/4419fcdb5eabb9caa61a27c7a1db532a6b55dd18", - "reference": "4419fcdb5eabb9caa61a27c7a1db532a6b55dd18", + "url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/442e7c7e687e42adc03470c7b668bc4b2402c0b2", + "reference": "442e7c7e687e42adc03470c7b668bc4b2402c0b2", "shasum": "" }, "require": { - "php": "^5.6 || ^7.0" + "php": ">=7.3" }, "require-dev": { - "phpunit/phpunit": "^5.7 || ^6.0" + "phpunit/phpunit": "^9.3" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0.x-dev" + "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": { @@ -2071,34 +2749,44 @@ ], "description": "Looks up which function or method a line of code belongs to", "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/", - "time": "2017-03-04T06:30:41+00:00" + "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": "3.0.2", + "version": "4.0.6", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/comparator.git", - "reference": "5de4fc177adf9bce8df98d8d141a7559d7ccf6da" + "reference": "55f4261989e546dc112258c7a75935a81a7ce382" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/5de4fc177adf9bce8df98d8d141a7559d7ccf6da", - "reference": "5de4fc177adf9bce8df98d8d141a7559d7ccf6da", + "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/55f4261989e546dc112258c7a75935a81a7ce382", + "reference": "55f4261989e546dc112258c7a75935a81a7ce382", "shasum": "" }, "require": { - "php": "^7.1", - "sebastian/diff": "^3.0", - "sebastian/exporter": "^3.1" + "php": ">=7.3", + "sebastian/diff": "^4.0", + "sebastian/exporter": "^4.0" }, "require-dev": { - "phpunit/phpunit": "^7.1" + "phpunit/phpunit": "^9.3" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "3.0-dev" + "dev-master": "4.0-dev" } }, "autoload": { @@ -2111,6 +2799,10 @@ "BSD-3-Clause" ], "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, { "name": "Jeff Welch", "email": "whatthejeff@gmail.com" @@ -2122,10 +2814,6 @@ { "name": "Bernhard Schussek", "email": "bschussek@2bepublished.at" - }, - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" } ], "description": "Provides the functionality to compare PHP values for equality", @@ -2135,33 +2823,43 @@ "compare", "equality" ], - "time": "2018-07-12T15:12:46+00:00" + "support": { + "issues": "https://github.com/sebastianbergmann/comparator/issues", + "source": "https://github.com/sebastianbergmann/comparator/tree/4.0.6" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-10-26T15:49:45+00:00" }, { - "name": "sebastian/diff", - "version": "3.0.2", + "name": "sebastian/complexity", + "version": "2.0.2", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/diff.git", - "reference": "720fcc7e9b5cf384ea68d9d930d480907a0c1a29" + "url": "https://github.com/sebastianbergmann/complexity.git", + "reference": "739b35e53379900cc9ac327b2147867b8b6efd88" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/720fcc7e9b5cf384ea68d9d930d480907a0c1a29", - "reference": "720fcc7e9b5cf384ea68d9d930d480907a0c1a29", + "url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/739b35e53379900cc9ac327b2147867b8b6efd88", + "reference": "739b35e53379900cc9ac327b2147867b8b6efd88", "shasum": "" }, "require": { - "php": "^7.1" + "nikic/php-parser": "^4.7", + "php": ">=7.3" }, "require-dev": { - "phpunit/phpunit": "^7.5 || ^8.0", - "symfony/process": "^2 || ^3.3 || ^4" + "phpunit/phpunit": "^9.3" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "3.0-dev" + "dev-master": "2.0-dev" } }, "autoload": { @@ -2175,12 +2873,69 @@ ], "authors": [ { - "name": "Kore Nordmann", - "email": "mail@kore-nordmann.de" - }, + "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.4", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/diff.git", + "reference": "3461e3fccc7cfdfc2720be910d3bd73c69be590d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/3461e3fccc7cfdfc2720be910d3bd73c69be590d", + "reference": "3461e3fccc7cfdfc2720be910d3bd73c69be590d", + "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", @@ -2191,27 +2946,37 @@ "unidiff", "unified diff" ], - "time": "2019-02-04T06:01:07+00:00" + "support": { + "issues": "https://github.com/sebastianbergmann/diff/issues", + "source": "https://github.com/sebastianbergmann/diff/tree/4.0.4" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-10-26T13:10:38+00:00" }, { "name": "sebastian/environment", - "version": "4.2.3", + "version": "5.1.3", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/environment.git", - "reference": "464c90d7bdf5ad4e8a6aea15c091fec0603d4368" + "reference": "388b6ced16caa751030f6a69e588299fa09200ac" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/464c90d7bdf5ad4e8a6aea15c091fec0603d4368", - "reference": "464c90d7bdf5ad4e8a6aea15c091fec0603d4368", + "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/388b6ced16caa751030f6a69e588299fa09200ac", + "reference": "388b6ced16caa751030f6a69e588299fa09200ac", "shasum": "" }, "require": { - "php": "^7.1" + "php": ">=7.3" }, "require-dev": { - "phpunit/phpunit": "^7.5" + "phpunit/phpunit": "^9.3" }, "suggest": { "ext-posix": "*" @@ -2219,7 +2984,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "4.2-dev" + "dev-master": "5.1-dev" } }, "autoload": { @@ -2244,34 +3009,44 @@ "environment", "hhvm" ], - "time": "2019-11-20T08:46:58+00:00" + "support": { + "issues": "https://github.com/sebastianbergmann/environment/issues", + "source": "https://github.com/sebastianbergmann/environment/tree/5.1.3" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-09-28T05:52:38+00:00" }, { "name": "sebastian/exporter", - "version": "3.1.2", + "version": "4.0.4", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/exporter.git", - "reference": "68609e1261d215ea5b21b7987539cbfbe156ec3e" + "reference": "65e8b7db476c5dd267e65eea9cab77584d3cfff9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/68609e1261d215ea5b21b7987539cbfbe156ec3e", - "reference": "68609e1261d215ea5b21b7987539cbfbe156ec3e", + "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/65e8b7db476c5dd267e65eea9cab77584d3cfff9", + "reference": "65e8b7db476c5dd267e65eea9cab77584d3cfff9", "shasum": "" }, "require": { - "php": "^7.0", - "sebastian/recursion-context": "^3.0" + "php": ">=7.3", + "sebastian/recursion-context": "^4.0" }, "require-dev": { "ext-mbstring": "*", - "phpunit/phpunit": "^6.0" + "phpunit/phpunit": "^9.3" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "3.1.x-dev" + "dev-master": "4.0-dev" } }, "autoload": { @@ -2306,32 +3081,45 @@ } ], "description": "Provides the functionality to export PHP variables for visualization", - "homepage": "http://www.github.com/sebastianbergmann/exporter", + "homepage": "https://www.github.com/sebastianbergmann/exporter", "keywords": [ "export", "exporter" ], - "time": "2019-09-14T09:02:43+00:00" + "support": { + "issues": "https://github.com/sebastianbergmann/exporter/issues", + "source": "https://github.com/sebastianbergmann/exporter/tree/4.0.4" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2021-11-11T14:18:36+00:00" }, { "name": "sebastian/global-state", - "version": "2.0.0", + "version": "5.0.3", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/global-state.git", - "reference": "e8ba02eed7bbbb9e59e43dedd3dddeff4a56b0c4" + "reference": "23bd5951f7ff26f12d4e3242864df3e08dec4e49" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/e8ba02eed7bbbb9e59e43dedd3dddeff4a56b0c4", - "reference": "e8ba02eed7bbbb9e59e43dedd3dddeff4a56b0c4", + "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/23bd5951f7ff26f12d4e3242864df3e08dec4e49", + "reference": "23bd5951f7ff26f12d4e3242864df3e08dec4e49", "shasum": "" }, "require": { - "php": "^7.0" + "php": ">=7.3", + "sebastian/object-reflector": "^2.0", + "sebastian/recursion-context": "^4.0" }, "require-dev": { - "phpunit/phpunit": "^6.0" + "ext-dom": "*", + "phpunit/phpunit": "^9.3" }, "suggest": { "ext-uopz": "*" @@ -2339,7 +3127,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "2.0-dev" + "dev-master": "5.0-dev" } }, "autoload": { @@ -2362,34 +3150,101 @@ "keywords": [ "global state" ], - "time": "2017-04-27T15:39:26+00:00" + "support": { + "issues": "https://github.com/sebastianbergmann/global-state/issues", + "source": "https://github.com/sebastianbergmann/global-state/tree/5.0.3" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2021-06-11T13:31:12+00:00" }, { - "name": "sebastian/object-enumerator", - "version": "3.0.3", + "name": "sebastian/lines-of-code", + "version": "1.0.3", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/object-enumerator.git", - "reference": "7cfd9e65d11ffb5af41198476395774d4c8a84c5" + "url": "https://github.com/sebastianbergmann/lines-of-code.git", + "reference": "c1c2e997aa3146983ed888ad08b15470a2e22ecc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/7cfd9e65d11ffb5af41198476395774d4c8a84c5", - "reference": "7cfd9e65d11ffb5af41198476395774d4c8a84c5", + "url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/c1c2e997aa3146983ed888ad08b15470a2e22ecc", + "reference": "c1c2e997aa3146983ed888ad08b15470a2e22ecc", "shasum": "" }, "require": { - "php": "^7.0", - "sebastian/object-reflector": "^1.1.1", - "sebastian/recursion-context": "^3.0" + "nikic/php-parser": "^4.6", + "php": ">=7.3" }, "require-dev": { - "phpunit/phpunit": "^6.0" + "phpunit/phpunit": "^9.3" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "3.0.x-dev" + "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": { @@ -2409,122 +3264,37 @@ ], "description": "Traverses array structures and object graphs to enumerate all referenced objects", "homepage": "https://github.com/sebastianbergmann/object-enumerator/", - "time": "2017-08-03T12:35:26+00:00" + "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": "1.1.1", + "version": "2.0.4", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/object-reflector.git", - "reference": "773f97c67f28de00d397be301821b06708fca0be" + "reference": "b4f479ebdbf63ac605d183ece17d8d7fe49c15c7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/773f97c67f28de00d397be301821b06708fca0be", - "reference": "773f97c67f28de00d397be301821b06708fca0be", + "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/b4f479ebdbf63ac605d183ece17d8d7fe49c15c7", + "reference": "b4f479ebdbf63ac605d183ece17d8d7fe49c15c7", "shasum": "" }, "require": { - "php": "^7.0" + "php": ">=7.3" }, "require-dev": { - "phpunit/phpunit": "^6.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.1-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Allows reflection of object attributes, including inherited and non-public ones", - "homepage": "https://github.com/sebastianbergmann/object-reflector/", - "time": "2017-03-29T09:07:27+00:00" - }, - { - "name": "sebastian/recursion-context", - "version": "3.0.0", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/recursion-context.git", - "reference": "5b0cd723502bac3b006cbf3dbf7a1e3fcefe4fa8" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/5b0cd723502bac3b006cbf3dbf7a1e3fcefe4fa8", - "reference": "5b0cd723502bac3b006cbf3dbf7a1e3fcefe4fa8", - "shasum": "" - }, - "require": { - "php": "^7.0" - }, - "require-dev": { - "phpunit/phpunit": "^6.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.0.x-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Jeff Welch", - "email": "whatthejeff@gmail.com" - }, - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - }, - { - "name": "Adam Harvey", - "email": "aharvey@php.net" - } - ], - "description": "Provides functionality to recursively process PHP variables", - "homepage": "http://www.github.com/sebastianbergmann/recursion-context", - "time": "2017-03-03T06:23:57+00:00" - }, - { - "name": "sebastian/resource-operations", - "version": "2.0.1", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/resource-operations.git", - "reference": "4d7a795d35b889bf80a0cc04e08d77cedfa917a9" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/4d7a795d35b889bf80a0cc04e08d77cedfa917a9", - "reference": "4d7a795d35b889bf80a0cc04e08d77cedfa917a9", - "shasum": "" - }, - "require": { - "php": "^7.1" + "phpunit/phpunit": "^9.3" }, "type": "library", "extra": { @@ -2547,31 +3317,215 @@ "email": "sebastian@phpunit.de" } ], - "description": "Provides a list of PHP built-in functions that operate on resources", - "homepage": "https://www.github.com/sebastianbergmann/resource-operations", - "time": "2018-10-04T04:07:39+00:00" + "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/version", - "version": "2.0.1", + "name": "sebastian/recursion-context", + "version": "4.0.4", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/version.git", - "reference": "99732be0ddb3361e16ad77b68ba41efc8e979019" + "url": "https://github.com/sebastianbergmann/recursion-context.git", + "reference": "cd9d8cf3c5804de4341c283ed787f099f5506172" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/99732be0ddb3361e16ad77b68ba41efc8e979019", - "reference": "99732be0ddb3361e16ad77b68ba41efc8e979019", + "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/cd9d8cf3c5804de4341c283ed787f099f5506172", + "reference": "cd9d8cf3c5804de4341c283ed787f099f5506172", "shasum": "" }, "require": { - "php": ">=5.6" + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.0.x-dev" + "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": "http://www.github.com/sebastianbergmann/recursion-context", + "support": { + "issues": "https://github.com/sebastianbergmann/recursion-context/issues", + "source": "https://github.com/sebastianbergmann/recursion-context/tree/4.0.4" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-10-26T13:17:30+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": "2.3.4", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/type.git", + "reference": "b8cd8a1c753c90bc1a0f5372170e3e489136f914" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/b8cd8a1c753c90bc1a0f5372170e3e489136f914", + "reference": "b8cd8a1c753c90bc1a0f5372170e3e489136f914", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.3-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/2.3.4" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2021-06-15T12:49:02+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": { @@ -2592,24 +3546,37 @@ ], "description": "Library that helps with managing the version number of Git-hosted PHP projects", "homepage": "https://github.com/sebastianbergmann/version", - "time": "2016-10-03T07:35:21+00:00" + "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/polyfill-ctype", - "version": "v1.18.1", + "version": "v1.24.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-ctype.git", - "reference": "1c302646f6efc070cd46856e600e5e0684d6b454" + "reference": "30885182c981ab175d4d034db0f6f469898070ab" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/1c302646f6efc070cd46856e600e5e0684d6b454", - "reference": "1c302646f6efc070cd46856e600e5e0684d6b454", + "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/30885182c981ab175d4d034db0f6f469898070ab", + "reference": "30885182c981ab175d4d034db0f6f469898070ab", "shasum": "" }, "require": { - "php": ">=5.3.3" + "php": ">=7.1" + }, + "provide": { + "ext-ctype": "*" }, "suggest": { "ext-ctype": "For best performance" @@ -2617,7 +3584,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.18-dev" + "dev-main": "1.23-dev" }, "thanks": { "name": "symfony/polyfill", @@ -2654,6 +3621,9 @@ "polyfill", "portable" ], + "support": { + "source": "https://github.com/symfony/polyfill-ctype/tree/v1.24.0" + }, "funding": [ { "url": "https://symfony.com/sponsor", @@ -2668,7 +3638,7 @@ "type": "tidelift" } ], - "time": "2020-07-14T12:35:20+00:00" + "time": "2021-10-20T20:35:02+00:00" }, { "name": "symfony/stopwatch", @@ -2713,6 +3683,9 @@ ], "description": "Provides a way to profile code", "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/stopwatch/tree/v5.4.3" + }, "funding": [ { "url": "https://symfony.com/sponsor", @@ -2731,16 +3704,16 @@ }, { "name": "theseer/tokenizer", - "version": "1.2.0", + "version": "1.2.1", "source": { "type": "git", "url": "https://github.com/theseer/tokenizer.git", - "reference": "75a63c33a8577608444246075ea0af0d052e452a" + "reference": "34a41e998c2183e22995f158c581e7b5e755ab9e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/theseer/tokenizer/zipball/75a63c33a8577608444246075ea0af0d052e452a", - "reference": "75a63c33a8577608444246075ea0af0d052e452a", + "url": "https://api.github.com/repos/theseer/tokenizer/zipball/34a41e998c2183e22995f158c581e7b5e755ab9e", + "reference": "34a41e998c2183e22995f158c581e7b5e755ab9e", "shasum": "" }, "require": { @@ -2767,40 +3740,49 @@ } ], "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.1" + }, "funding": [ { "url": "https://github.com/theseer", "type": "github" } ], - "time": "2020-07-12T23:59:07+00:00" + "time": "2021-07-28T10:34:58+00:00" }, { "name": "webmozart/assert", - "version": "1.9.1", + "version": "1.10.0", "source": { "type": "git", "url": "https://github.com/webmozarts/assert.git", - "reference": "bafc69caeb4d49c39fd0779086c03a3738cbb389" + "reference": "6964c76c7804814a842473e0c8fd15bab0f18e25" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/webmozarts/assert/zipball/bafc69caeb4d49c39fd0779086c03a3738cbb389", - "reference": "bafc69caeb4d49c39fd0779086c03a3738cbb389", + "url": "https://api.github.com/repos/webmozarts/assert/zipball/6964c76c7804814a842473e0c8fd15bab0f18e25", + "reference": "6964c76c7804814a842473e0c8fd15bab0f18e25", "shasum": "" }, "require": { - "php": "^5.3.3 || ^7.0 || ^8.0", + "php": "^7.2 || ^8.0", "symfony/polyfill-ctype": "^1.8" }, "conflict": { "phpstan/phpstan": "<0.12.20", - "vimeo/psalm": "<3.9.1" + "vimeo/psalm": "<4.6.1 || 4.6.2" }, "require-dev": { - "phpunit/phpunit": "^4.8.36 || ^7.5.13" + "phpunit/phpunit": "^8.5.13" }, "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.10-dev" + } + }, "autoload": { "psr-4": { "Webmozart\\Assert\\": "src/" @@ -2822,7 +3804,11 @@ "check", "validate" ], - "time": "2020-07-08T17:02:28+00:00" + "support": { + "issues": "https://github.com/webmozarts/assert/issues", + "source": "https://github.com/webmozarts/assert/tree/1.10.0" + }, + "time": "2021-03-09T10:59:23+00:00" } ], "aliases": [], @@ -2847,5 +3833,5 @@ "ext-session": "*" }, "platform-dev": [], - "plugin-api-version": "1.1.0" + "plugin-api-version": "2.1.0" } diff --git a/docker/etc/php7/conf.d/local.ini b/docker/etc/php8/conf.d/local.ini similarity index 100% rename from docker/etc/php7/conf.d/local.ini rename to docker/etc/php8/conf.d/local.ini diff --git a/docker/etc/php7/php-fpm.conf b/docker/etc/php8/php-fpm.conf similarity index 89% rename from docker/etc/php7/php-fpm.conf rename to docker/etc/php8/php-fpm.conf index ea2275297..33b0f176a 100644 --- a/docker/etc/php7/php-fpm.conf +++ b/docker/etc/php8/php-fpm.conf @@ -16,4 +16,4 @@ pm.start_servers = 1 pm.min_spare_servers = 1 pm.max_spare_servers = 3 pm.max_requests = 2048 -include = /etc/php7/php-fpm.d/env.conf \ No newline at end of file +include = /etc/php8/php-fpm.d/env.conf \ No newline at end of file diff --git a/docker/etc/php7/php-fpm.d/env.conf b/docker/etc/php8/php-fpm.d/env.conf similarity index 100% rename from docker/etc/php7/php-fpm.d/env.conf rename to docker/etc/php8/php-fpm.d/env.conf diff --git a/docker/etc/services.d/php/run b/docker/etc/services.d/php/run index 6b093238f..4a29e084a 100755 --- a/docker/etc/services.d/php/run +++ b/docker/etc/services.d/php/run @@ -1,2 +1,2 @@ #!/bin/execlineb -P -php-fpm7 -F \ No newline at end of file +php-fpm8 -F \ No newline at end of file diff --git a/libs/SimpleValidator/Validators/Integer.php b/libs/SimpleValidator/Validators/Integer.php index 5afdc1e0f..17e0f9561 100644 --- a/libs/SimpleValidator/Validators/Integer.php +++ b/libs/SimpleValidator/Validators/Integer.php @@ -13,7 +13,7 @@ class Integer extends Base return ctype_digit(substr($data[$this->field], 1)); } - return ctype_digit($data[$this->field]); + return ctype_digit((string) $data[$this->field]); } else { return is_int($data[$this->field]); diff --git a/tests/integration/ActionProcedureTest.php b/tests/integration/ActionProcedureTest.php index 432de3d32..43e77c618 100644 --- a/tests/integration/ActionProcedureTest.php +++ b/tests/integration/ActionProcedureTest.php @@ -10,7 +10,7 @@ class ActionProcedureTest extends BaseProcedureTest { $actions = $this->app->getAvailableActions(); $this->assertNotEmpty($actions); - $this->assertInternalType('array', $actions); + $this->assertIsArray($actions); $this->assertArrayHasKey('\Kanboard\Action\TaskCloseColumn', $actions); } @@ -18,7 +18,7 @@ class ActionProcedureTest extends BaseProcedureTest { $events = $this->app->getAvailableActionEvents(); $this->assertNotEmpty($events); - $this->assertInternalType('array', $events); + $this->assertIsArray($events); $this->assertArrayHasKey('task.move.column', $events); } @@ -26,7 +26,7 @@ class ActionProcedureTest extends BaseProcedureTest { $events = $this->app->getCompatibleActionEvents('\Kanboard\Action\TaskCloseColumn'); $this->assertNotEmpty($events); - $this->assertInternalType('array', $events); + $this->assertIsArray($events); $this->assertArrayHasKey('task.move.column', $events); } @@ -49,7 +49,7 @@ class ActionProcedureTest extends BaseProcedureTest { $actions = $this->app->getActions($this->projectId); $this->assertNotEmpty($actions); - $this->assertInternalType('array', $actions); + $this->assertIsArray($actions); $this->assertArrayHasKey('id', $actions[0]); $this->assertArrayHasKey('project_id', $actions[0]); $this->assertArrayHasKey('event_name', $actions[0]); diff --git a/tests/integration/BaseProcedureTest.php b/tests/integration/BaseProcedureTest.php index d0bc81380..d4cbf0b10 100644 --- a/tests/integration/BaseProcedureTest.php +++ b/tests/integration/BaseProcedureTest.php @@ -27,7 +27,7 @@ abstract class BaseProcedureTest extends PHPUnit\Framework\TestCase protected $username = 'test-user'; protected $userId; - public function setUp() + protected function setUp(): void { $this->setUpAppClient(); $this->setUpAdminUser(); diff --git a/tests/integration/CategoryProcedureTest.php b/tests/integration/CategoryProcedureTest.php index 2f5294bab..0ee403af9 100644 --- a/tests/integration/CategoryProcedureTest.php +++ b/tests/integration/CategoryProcedureTest.php @@ -40,7 +40,7 @@ class CategoryProcedureTest extends BaseProcedureTest { $category = $this->app->getCategory($this->categoryId); - $this->assertInternalType('array', $category); + $this->assertIsArray($category); $this->assertEquals($this->categoryId, $category['id']); $this->assertEquals('Category', $category['name']); $this->assertEquals($this->projectId, $category['project_id']); diff --git a/tests/integration/LinkProcedureTest.php b/tests/integration/LinkProcedureTest.php index fb07e6941..ee6cfb150 100644 --- a/tests/integration/LinkProcedureTest.php +++ b/tests/integration/LinkProcedureTest.php @@ -43,11 +43,11 @@ class LinkProcedureTest extends BaseProcedureTest { $link_id = $this->app->createLink(array('label' => 'test')); $this->assertNotFalse($link_id); - $this->assertInternalType('int', $link_id); + $this->assertIsInt($link_id); $link_id = $this->app->createLink(array('label' => 'foo', 'opposite_label' => 'bar')); $this->assertNotFalse($link_id); - $this->assertInternalType('int', $link_id); + $this->assertIsInt($link_id); } public function testUpdateLink() diff --git a/tests/integration/ProjectProcedureTest.php b/tests/integration/ProjectProcedureTest.php index 12bb6d04f..68c9e58b8 100644 --- a/tests/integration/ProjectProcedureTest.php +++ b/tests/integration/ProjectProcedureTest.php @@ -46,7 +46,7 @@ class ProjectProcedureTest extends BaseProcedureTest { $projects = $this->app->getAllProjects(); $this->assertNotEmpty($projects); - $this->assertInternalType('array', $projects); + $this->assertIsArray($projects); $this->assertArrayHasKey('board', $projects[0]['url']); $this->assertArrayHasKey('list', $projects[0]['url']); } @@ -54,14 +54,14 @@ class ProjectProcedureTest extends BaseProcedureTest public function assertGetProjectActivity() { $activities = $this->app->getProjectActivity($this->projectId); - $this->assertInternalType('array', $activities); + $this->assertIsArray($activities); $this->assertCount(0, $activities); } public function assertGetProjectsActivity() { $activities = $this->app->getProjectActivities(array('project_ids' => array($this->projectId))); - $this->assertInternalType('array', $activities); + $this->assertIsArray($activities); $this->assertCount(0, $activities); } diff --git a/tests/integration/SwimlaneProcedureTest.php b/tests/integration/SwimlaneProcedureTest.php index a3c2397a7..cc143c5b7 100644 --- a/tests/integration/SwimlaneProcedureTest.php +++ b/tests/integration/SwimlaneProcedureTest.php @@ -31,7 +31,7 @@ class SwimlaneProcedureTest extends BaseProcedureTest public function assertGetSwimlane() { $swimlane = $this->app->getSwimlane($this->swimlaneId); - $this->assertInternalType('array', $swimlane); + $this->assertIsArray($swimlane); $this->assertEquals('Swimlane 1', $swimlane['name']); } diff --git a/tests/integration/TaskProcedureTest.php b/tests/integration/TaskProcedureTest.php index 54527939e..d2bbdf7ab 100644 --- a/tests/integration/TaskProcedureTest.php +++ b/tests/integration/TaskProcedureTest.php @@ -44,7 +44,7 @@ class TaskProcedureTest extends BaseProcedureTest public function assertGetAllTasks() { $tasks = $this->app->getAllTasks($this->projectId); - $this->assertInternalType('array', $tasks); + $this->assertIsArray($tasks); $this->assertNotEmpty($tasks); $this->assertArrayHasKey('url', $tasks[0]); } diff --git a/tests/integration/UserProcedureTest.php b/tests/integration/UserProcedureTest.php index 290f87fbe..709900b08 100644 --- a/tests/integration/UserProcedureTest.php +++ b/tests/integration/UserProcedureTest.php @@ -32,7 +32,7 @@ class UserProcedureTest extends BaseProcedureTest public function assertGetAllUsers() { $users = $this->app->getAllUsers(); - $this->assertInternalType('array', $users); + $this->assertIsArray($users); $this->assertNotEmpty($users); } diff --git a/tests/units/Analytic/AverageLeadCycleTimeAnalyticTest.php b/tests/units/Analytic/AverageLeadCycleTimeAnalyticTest.php index 831ec9608..a556eaa47 100644 --- a/tests/units/Analytic/AverageLeadCycleTimeAnalyticTest.php +++ b/tests/units/Analytic/AverageLeadCycleTimeAnalyticTest.php @@ -43,7 +43,7 @@ class AverageLeadCycleTimeAnalyticTest extends Base $stats = $averageLeadCycleTimeAnalytic->build(1); $this->assertEquals(5, $stats['count']); - $this->assertEquals(3600 + 1800 + 3600 + 2*3600, $stats['total_lead_time'], '', 5); + $this->assertEquals(3600 + 1800 + 3600 + 2*3600, $stats['total_lead_time'], '', 10); $this->assertEquals(1800 + 900, $stats['total_cycle_time'], '', 5); $this->assertEquals((3600 + 1800 + 3600 + 2*3600) / 5, $stats['avg_lead_time'], '', 5); $this->assertEquals((1800 + 900) / 5, $stats['avg_cycle_time'], '', 5); diff --git a/tests/units/Auth/ReverseProxyAuthTest.php b/tests/units/Auth/ReverseProxyAuthTest.php index 10d0841ed..75fa72521 100644 --- a/tests/units/Auth/ReverseProxyAuthTest.php +++ b/tests/units/Auth/ReverseProxyAuthTest.php @@ -8,7 +8,7 @@ require_once __DIR__.'/../Base.php'; class ReverseProxyAuthTest extends Base { - public function setUp() + protected function setUp(): void { parent::setUp(); diff --git a/tests/units/Base.php b/tests/units/Base.php index e746d45f0..be05b5ecd 100644 --- a/tests/units/Base.php +++ b/tests/units/Base.php @@ -20,7 +20,7 @@ abstract class Base extends PHPUnit\Framework\TestCase */ protected $dispatcher; - public function setUp() + protected function setUp(): void { date_default_timezone_set('UTC'); $_SESSION = array(); @@ -98,7 +98,7 @@ abstract class Base extends PHPUnit\Framework\TestCase $loader->register(); } - public function tearDown() + protected function tearDown(): void { $this->container['db']->closeConnection(); unset ($this->container); diff --git a/tests/units/Core/Cache/FileCacheTest.php b/tests/units/Core/Cache/FileCacheTest.php index b6336581f..b6d1ece23 100644 --- a/tests/units/Core/Cache/FileCacheTest.php +++ b/tests/units/Core/Cache/FileCacheTest.php @@ -41,7 +41,7 @@ class FileCacheTest extends \Base */ public static $functions; - public function setUp() + protected function setUp(): void { parent::setup(); @@ -58,7 +58,7 @@ class FileCacheTest extends \Base ->getMock(); } - public function tearDown() + protected function tearDown(): void { parent::tearDown(); self::$functions = null; @@ -71,7 +71,7 @@ class FileCacheTest extends \Base $cache = new FileCache(); self::$functions - ->expects($this->at(0)) + ->expects($this->once()) ->method('is_dir') ->with( $this->equalTo(CACHE_DIR) @@ -79,7 +79,7 @@ class FileCacheTest extends \Base ->will($this->returnValue(false)); self::$functions - ->expects($this->at(1)) + ->expects($this->once()) ->method('mkdir') ->with( $this->equalTo(CACHE_DIR), @@ -88,7 +88,7 @@ class FileCacheTest extends \Base ->will($this->returnValue(true)); self::$functions - ->expects($this->at(2)) + ->expects($this->once()) ->method('file_put_contents') ->with( $this->equalTo(CACHE_DIR.DIRECTORY_SEPARATOR.$key), @@ -106,7 +106,7 @@ class FileCacheTest extends \Base $cache = new FileCache(); self::$functions - ->expects($this->at(0)) + ->expects($this->once()) ->method('file_exists') ->with( $this->equalTo(CACHE_DIR.DIRECTORY_SEPARATOR.$key) @@ -114,7 +114,7 @@ class FileCacheTest extends \Base ->will($this->returnValue(true)); self::$functions - ->expects($this->at(1)) + ->expects($this->once()) ->method('file_get_contents') ->with( $this->equalTo(CACHE_DIR.DIRECTORY_SEPARATOR.$key) @@ -130,7 +130,7 @@ class FileCacheTest extends \Base $cache = new FileCache(); self::$functions - ->expects($this->at(0)) + ->expects($this->once()) ->method('file_exists') ->with( $this->equalTo(CACHE_DIR.DIRECTORY_SEPARATOR.$key) @@ -146,7 +146,7 @@ class FileCacheTest extends \Base $cache = new FileCache(); self::$functions - ->expects($this->at(0)) + ->expects($this->once()) ->method('file_exists') ->with( $this->equalTo(CACHE_DIR.DIRECTORY_SEPARATOR.$key) @@ -166,7 +166,7 @@ class FileCacheTest extends \Base $cache = new FileCache(); self::$functions - ->expects($this->at(0)) + ->expects($this->once()) ->method('file_exists') ->with( $this->equalTo(CACHE_DIR.DIRECTORY_SEPARATOR.$key) @@ -174,7 +174,7 @@ class FileCacheTest extends \Base ->will($this->returnValue(true)); self::$functions - ->expects($this->at(1)) + ->expects($this->once()) ->method('unlink') ->with( $this->equalTo(CACHE_DIR.DIRECTORY_SEPARATOR.$key) diff --git a/tests/units/Core/Http/RememberMeCookieTest.php b/tests/units/Core/Http/RememberMeCookieTest.php index ae5606acd..7aa910ef5 100644 --- a/tests/units/Core/Http/RememberMeCookieTest.php +++ b/tests/units/Core/Http/RememberMeCookieTest.php @@ -13,7 +13,7 @@ class RememberMeCookieTest extends \Base { public static $functions; - public function setUp() + protected function setUp(): void { parent::setup(); @@ -25,7 +25,7 @@ class RememberMeCookieTest extends \Base ->getMock(); } - public function tearDown() + protected function tearDown(): void { parent::tearDown(); self::$functions = null; diff --git a/tests/units/Core/Ldap/ClientTest.php b/tests/units/Core/Ldap/ClientTest.php index 761ec0d70..833cf98c0 100644 --- a/tests/units/Core/Ldap/ClientTest.php +++ b/tests/units/Core/Ldap/ClientTest.php @@ -42,7 +42,7 @@ class ClientTest extends \Base { public static $functions; - public function setUp() + protected function setUp(): void { parent::setup(); @@ -60,7 +60,7 @@ class ClientTest extends \Base ->getMock(); } - public function tearDown() + protected function tearDown(): void { parent::tearDown(); self::$functions = null; diff --git a/tests/units/Core/Ldap/LdapGroupTest.php b/tests/units/Core/Ldap/LdapGroupTest.php index a5d26763a..80b650eda 100644 --- a/tests/units/Core/Ldap/LdapGroupTest.php +++ b/tests/units/Core/Ldap/LdapGroupTest.php @@ -11,7 +11,7 @@ class LdapGroupTest extends Base private $client; private $group; - public function setUp() + protected function setUp(): void { parent::setUp(); diff --git a/tests/units/Core/Ldap/LdapUserTest.php b/tests/units/Core/Ldap/LdapUserTest.php index 6f476da3a..fd2fa6a74 100644 --- a/tests/units/Core/Ldap/LdapUserTest.php +++ b/tests/units/Core/Ldap/LdapUserTest.php @@ -15,7 +15,7 @@ class LdapUserTest extends Base private $user; private $group; - public function setUp() + protected function setUp(): void { parent::setUp(); diff --git a/tests/units/Core/Ldap/QueryTest.php b/tests/units/Core/Ldap/QueryTest.php index b3987df04..6c97c1151 100644 --- a/tests/units/Core/Ldap/QueryTest.php +++ b/tests/units/Core/Ldap/QueryTest.php @@ -19,7 +19,7 @@ class QueryTest extends \Base public static $functions; private $client; - public function setUp() + protected function setUp(): void { parent::setup(); @@ -39,7 +39,7 @@ class QueryTest extends \Base ->getMock(); } - public function tearDown() + protected function tearDown(): void { parent::tearDown(); self::$functions = null; diff --git a/tests/units/Core/ObjectStorage/FileStorageTest.php b/tests/units/Core/ObjectStorage/FileStorageTest.php index ed77dedd5..2c2930a61 100644 --- a/tests/units/Core/ObjectStorage/FileStorageTest.php +++ b/tests/units/Core/ObjectStorage/FileStorageTest.php @@ -53,7 +53,7 @@ class FileStorageTest extends \Base { public static $functions; - public function setUp() + protected function setUp(): void { parent::setup(); @@ -73,7 +73,7 @@ class FileStorageTest extends \Base ->getMock(); } - public function tearDown() + protected function tearDown(): void { parent::tearDown(); self::$functions = null; @@ -85,7 +85,7 @@ class FileStorageTest extends \Base $storage = new FileStorage('somewhere'); self::$functions - ->expects($this->at(0)) + ->expects($this->once()) ->method('is_dir') ->with( $this->equalTo('somewhere') @@ -93,7 +93,7 @@ class FileStorageTest extends \Base ->will($this->returnValue(false)); self::$functions - ->expects($this->at(1)) + ->expects($this->once()) ->method('mkdir') ->with( $this->equalTo('somewhere') @@ -101,7 +101,7 @@ class FileStorageTest extends \Base ->will($this->returnValue(true)); self::$functions - ->expects($this->at(2)) + ->expects($this->once()) ->method('file_put_contents') ->with( $this->equalTo('somewhere'.DIRECTORY_SEPARATOR.'mykey'), @@ -118,7 +118,7 @@ class FileStorageTest extends \Base $storage = new FileStorage('somewhere'); self::$functions - ->expects($this->at(0)) + ->expects($this->once()) ->method('is_dir') ->with( $this->equalTo('somewhere'.DIRECTORY_SEPARATOR.'my') @@ -126,7 +126,7 @@ class FileStorageTest extends \Base ->will($this->returnValue(false)); self::$functions - ->expects($this->at(1)) + ->expects($this->once()) ->method('mkdir') ->with( $this->equalTo('somewhere'.DIRECTORY_SEPARATOR.'my') @@ -134,7 +134,7 @@ class FileStorageTest extends \Base ->will($this->returnValue(true)); self::$functions - ->expects($this->at(2)) + ->expects($this->once()) ->method('file_put_contents') ->with( $this->equalTo('somewhere'.DIRECTORY_SEPARATOR.'my'.DIRECTORY_SEPARATOR.'key'), @@ -150,11 +150,13 @@ class FileStorageTest extends \Base */ public function testPutWhenNotAbleToCreateFolder() { + $this->expectException(\Kanboard\Core\ObjectStorage\ObjectStorageException::class); + $data = 'data'; $storage = new FileStorage('somewhere'); self::$functions - ->expects($this->at(0)) + ->expects($this->once()) ->method('is_dir') ->with( $this->equalTo('somewhere') @@ -162,7 +164,7 @@ class FileStorageTest extends \Base ->will($this->returnValue(false)); self::$functions - ->expects($this->at(1)) + ->expects($this->once()) ->method('mkdir') ->with( $this->equalTo('somewhere') @@ -177,7 +179,7 @@ class FileStorageTest extends \Base $storage = new FileStorage('somewhere'); self::$functions - ->expects($this->at(0)) + ->expects($this->once()) ->method('file_exists') ->with( $this->equalTo('somewhere'.DIRECTORY_SEPARATOR.'mykey') @@ -185,7 +187,7 @@ class FileStorageTest extends \Base ->will($this->returnValue(true)); self::$functions - ->expects($this->at(1)) + ->expects($this->once()) ->method('file_get_contents') ->with( $this->equalTo('somewhere'.DIRECTORY_SEPARATOR.'mykey') @@ -202,8 +204,10 @@ class FileStorageTest extends \Base { $storage = new FileStorage('somewhere'); + $this->expectException(\Kanboard\Core\ObjectStorage\ObjectStorageException::class); + self::$functions - ->expects($this->at(0)) + ->expects($this->once()) ->method('file_exists') ->with( $this->equalTo('somewhere'.DIRECTORY_SEPARATOR.'mykey') @@ -218,7 +222,7 @@ class FileStorageTest extends \Base $storage = new FileStorage('somewhere'); self::$functions - ->expects($this->at(0)) + ->expects($this->once()) ->method('file_exists') ->with( $this->equalTo('somewhere'.DIRECTORY_SEPARATOR.'mykey') @@ -226,7 +230,7 @@ class FileStorageTest extends \Base ->will($this->returnValue(true)); self::$functions - ->expects($this->at(1)) + ->expects($this->once()) ->method('readfile') ->with( $this->equalTo('somewhere'.DIRECTORY_SEPARATOR.'mykey') @@ -242,7 +246,7 @@ class FileStorageTest extends \Base $storage = new FileStorage('somewhere'); self::$functions - ->expects($this->at(0)) + ->expects($this->once()) ->method('file_exists') ->with( $this->equalTo('somewhere'.DIRECTORY_SEPARATOR.'mykey') @@ -250,7 +254,7 @@ class FileStorageTest extends \Base ->will($this->returnValue(true)); self::$functions - ->expects($this->at(1)) + ->expects($this->once()) ->method('unlink') ->with( $this->equalTo('somewhere'.DIRECTORY_SEPARATOR.'mykey') @@ -265,7 +269,7 @@ class FileStorageTest extends \Base $storage = new FileStorage('somewhere'); self::$functions - ->expects($this->at(0)) + ->expects($this->once()) ->method('is_dir') ->with( $this->equalTo('somewhere') @@ -273,7 +277,7 @@ class FileStorageTest extends \Base ->will($this->returnValue(true)); self::$functions - ->expects($this->at(1)) + ->expects($this->once()) ->method('rename') ->with( $this->equalTo('src_file'), @@ -289,7 +293,7 @@ class FileStorageTest extends \Base $storage = new FileStorage('somewhere'); self::$functions - ->expects($this->at(0)) + ->expects($this->once()) ->method('is_dir') ->with( $this->equalTo('somewhere') @@ -297,7 +301,7 @@ class FileStorageTest extends \Base ->will($this->returnValue(true)); self::$functions - ->expects($this->at(1)) + ->expects($this->once()) ->method('move_uploaded_file') ->with( $this->equalTo('src_file'), diff --git a/tests/units/Core/Plugin/HookTest.php b/tests/units/Core/Plugin/HookTest.php index acadede0a..98df32422 100644 --- a/tests/units/Core/Plugin/HookTest.php +++ b/tests/units/Core/Plugin/HookTest.php @@ -46,7 +46,7 @@ class HookTest extends Base return array($p); }); - $hook->on('myhook', function () { + $hook->on('myhook', function ($p) { return array('D'); }); diff --git a/tests/units/Core/Security/AuthenticationManagerTest.php b/tests/units/Core/Security/AuthenticationManagerTest.php index 3869a87f0..7d21ba927 100644 --- a/tests/units/Core/Security/AuthenticationManagerTest.php +++ b/tests/units/Core/Security/AuthenticationManagerTest.php @@ -86,8 +86,8 @@ class AuthenticationManagerTest extends Base $this->assertTrue($authManager->preAuthentication()); $called = $this->container['dispatcher']->getCalledListeners(); - $this->assertArrayHasKey(AuthenticationManager::EVENT_SUCCESS.'.AuthenticationManagerTest::onSuccess', $called); - $this->assertArrayNotHasKey(AuthenticationManager::EVENT_FAILURE.'.AuthenticationManagerTest::onFailure', $called); + $this->assertCount(1, $called); + $this->assertEquals('auth.success', $called[0]['event']); } public function testPreAuthenticationFailed() @@ -102,8 +102,7 @@ class AuthenticationManagerTest extends Base $this->assertFalse($authManager->preAuthentication()); $called = $this->container['dispatcher']->getCalledListeners(); - $this->assertArrayNotHasKey(AuthenticationManager::EVENT_SUCCESS.'.AuthenticationManagerTest::onSuccess', $called); - $this->assertArrayNotHasKey(AuthenticationManager::EVENT_FAILURE.'.AuthenticationManagerTest::onFailure', $called); + $this->assertCount(0, $called); } public function testPasswordAuthenticationSuccessful() @@ -117,8 +116,8 @@ class AuthenticationManagerTest extends Base $this->assertTrue($authManager->passwordAuthentication('admin', 'admin')); $called = $this->container['dispatcher']->getCalledListeners(); - $this->assertArrayHasKey(AuthenticationManager::EVENT_SUCCESS.'.AuthenticationManagerTest::onSuccess', $called); - $this->assertArrayNotHasKey(AuthenticationManager::EVENT_FAILURE.'.AuthenticationManagerTest::onFailure', $called); + $this->assertCount(1, $called); + $this->assertEquals('auth.success', $called[0]['event']); } public function testPasswordAuthenticationFailed() @@ -132,8 +131,8 @@ class AuthenticationManagerTest extends Base $this->assertFalse($authManager->passwordAuthentication('admin', 'wrong password')); $called = $this->container['dispatcher']->getCalledListeners(); - $this->assertArrayNotHasKey(AuthenticationManager::EVENT_SUCCESS.'.AuthenticationManagerTest::onSuccess', $called); - $this->assertArrayHasKey(AuthenticationManager::EVENT_FAILURE.'.AuthenticationManagerTest::onFailure', $called); + $this->assertCount(1, $called); + $this->assertEquals('auth.failure', $called[0]['event']); } public function onSuccess($event) diff --git a/tests/units/Core/TranslatorTest.php b/tests/units/Core/TranslatorTest.php index 6aa480e12..861fe9d8c 100644 --- a/tests/units/Core/TranslatorTest.php +++ b/tests/units/Core/TranslatorTest.php @@ -6,7 +6,7 @@ use Kanboard\Core\Translator; class TranslatorTest extends Base { - public function setUp() + protected function setUp(): void { parent::setUp(); Translator::unload(); diff --git a/tests/units/Core/User/UserSyncTest.php b/tests/units/Core/User/UserSyncTest.php index e7ce42b2a..9b63591af 100644 --- a/tests/units/Core/User/UserSyncTest.php +++ b/tests/units/Core/User/UserSyncTest.php @@ -12,7 +12,7 @@ class UserSyncTest extends Base { $user = new LdapUserProvider('ldapId', 'bob', 'Bob', '', Role::APP_MANAGER, array()); $userSync = new UserSync($this->container); - + $result = $userSync->synchronize($user); $profile = array( 'id' => 2, 'username' => 'bob', @@ -22,7 +22,9 @@ class UserSyncTest extends Base 'is_ldap_user' => 1, ); - $this->assertArraySubset($profile, $userSync->synchronize($user)); + foreach ($profile as $key => $value) { + $this->assertEquals($value, $result[$key]); + } } public function testSynchronizeExistingUser() @@ -38,7 +40,10 @@ class UserSyncTest extends Base 'role' => Role::APP_MANAGER, ); - $this->assertArraySubset($profile, $userSync->synchronize($user)); + $result = $userSync->synchronize($user); + foreach ($profile as $key => $value) { + $this->assertEquals($value, $result[$key]); + } $user = new LdapUserProvider('ldapId', 'admin', '', '', Role::APP_ADMIN, array()); @@ -50,6 +55,9 @@ class UserSyncTest extends Base 'role' => Role::APP_ADMIN, ); - $this->assertArraySubset($profile, $userSync->synchronize($user)); + $result = $userSync->synchronize($user); + foreach ($profile as $key => $value) { + $this->assertEquals($value, $result[$key]); + } } } diff --git a/tests/units/Decorator/MetadataCacheDecoratorTest.php b/tests/units/Decorator/MetadataCacheDecoratorTest.php index 3e4dd3203..61db8b424 100644 --- a/tests/units/Decorator/MetadataCacheDecoratorTest.php +++ b/tests/units/Decorator/MetadataCacheDecoratorTest.php @@ -24,7 +24,7 @@ class MetadataCacheDecoratorTest extends Base */ protected $metadataCacheDecorator; - public function setUp() + protected function setUp(): void { parent::setUp(); @@ -61,11 +61,11 @@ class MetadataCacheDecoratorTest extends Base ->method('set'); $this->metadataModelMock - ->expects($this->at(0)) + ->expects($this->once()) ->method('save'); $this->metadataModelMock - ->expects($this->at(1)) + ->expects($this->once()) ->method('getAll') ->with($this->entityId) ; @@ -100,14 +100,14 @@ class MetadataCacheDecoratorTest extends Base public function testGetWithoutCache() { $this->cacheMock - ->expects($this->at(0)) + ->expects($this->once()) ->method('get') ->with($this->cachePrefix.$this->entityId) ->will($this->returnValue(null)) ; $this->cacheMock - ->expects($this->at(1)) + ->expects($this->once()) ->method('set') ->with( $this->cachePrefix.$this->entityId, diff --git a/tests/units/Helper/HookHelperTest.php b/tests/units/Helper/HookHelperTest.php index a67eaed9b..95a1cfde2 100644 --- a/tests/units/Helper/HookHelperTest.php +++ b/tests/units/Helper/HookHelperTest.php @@ -121,7 +121,7 @@ class HookHelperTest extends Base $this->container['helper'] ->asset - ->expects($this->at(0)) + ->expects($this->once()) ->method('css') ->with( $this->equalTo('skin.css') @@ -130,7 +130,7 @@ class HookHelperTest extends Base $this->container['helper'] ->asset - ->expects($this->at(1)) + ->expects($this->once()) ->method('js') ->with( $this->equalTo('skin.js') @@ -141,7 +141,7 @@ class HookHelperTest extends Base $hookHelper->attach('test1', 'skin.css'); $hookHelper->attach('test2', 'skin.js'); - $this->assertContains('', $hookHelper->asset('css', 'test1')); - $this->assertContains('', $hookHelper->asset('js', 'test2')); + $this->assertStringContainsString('', $hookHelper->asset('css', 'test1')); + $this->assertStringContainsString('', $hookHelper->asset('js', 'test2')); } } diff --git a/tests/units/Helper/ProjectActivityHelperTest.php b/tests/units/Helper/ProjectActivityHelperTest.php index 1ad956998..0a747e636 100644 --- a/tests/units/Helper/ProjectActivityHelperTest.php +++ b/tests/units/Helper/ProjectActivityHelperTest.php @@ -36,7 +36,7 @@ class ProjectActivityHelperTest extends Base $this->assertNotEmpty($events[0]['event_content']); $this->assertNotEmpty($events[0]['event_title']); $this->assertNotEmpty($events[0]['author']); - $this->assertInternalType('array', $events[0]['task']); + $this->assertIsArray($events[0]['task']); } public function testGetProjectsEvents() @@ -66,7 +66,7 @@ class ProjectActivityHelperTest extends Base $this->assertNotEmpty($events[0]['event_content']); $this->assertNotEmpty($events[0]['event_title']); $this->assertNotEmpty($events[0]['author']); - $this->assertInternalType('array', $events[0]['task']); + $this->assertIsArray($events[0]['task']); } public function testGetTaskEvents() @@ -92,6 +92,6 @@ class ProjectActivityHelperTest extends Base $this->assertNotEmpty($events[0]['event_content']); $this->assertNotEmpty($events[0]['event_title']); $this->assertNotEmpty($events[0]['author']); - $this->assertInternalType('array', $events[0]['task']); + $this->assertIsArray($events[0]['task']); } } diff --git a/tests/units/Job/CommentEventJobTest.php b/tests/units/Job/CommentEventJobTest.php index b830b2b83..05626edb7 100644 --- a/tests/units/Job/CommentEventJobTest.php +++ b/tests/units/Job/CommentEventJobTest.php @@ -45,9 +45,10 @@ class CommentEventJobTest extends Base $this->assertTrue($commentModel->remove(1)); $called = $this->container['dispatcher']->getCalledListeners(); - $this->assertArrayHasKey(CommentModel::EVENT_CREATE.'.closure', $called); - $this->assertArrayHasKey(CommentModel::EVENT_UPDATE.'.closure', $called); - $this->assertArrayHasKey(CommentModel::EVENT_DELETE.'.closure', $called); + $this->assertCount(3, $called); + $this->assertEquals(CommentModel::EVENT_CREATE, $called[0]['event']); + $this->assertEquals(CommentModel::EVENT_UPDATE, $called[1]['event']); + $this->assertEquals(CommentModel::EVENT_DELETE, $called[2]['event']); } public function testThatUserMentionJobIsCalled() diff --git a/tests/units/Job/ProjectFileEventJobTest.php b/tests/units/Job/ProjectFileEventJobTest.php index f266d2936..737cf85de 100644 --- a/tests/units/Job/ProjectFileEventJobTest.php +++ b/tests/units/Job/ProjectFileEventJobTest.php @@ -38,6 +38,7 @@ class ProjectFileEventJobTest extends Base $this->assertEquals(1, $projectFileModel->create(1, 'Test', '/tmp/test', 123)); $called = $this->container['dispatcher']->getCalledListeners(); - $this->assertArrayHasKey(ProjectFileModel::EVENT_CREATE.'.closure', $called); + $this->assertCount(1, $called); + $this->assertEquals(ProjectFileModel::EVENT_CREATE, $called[0]['event']); } } diff --git a/tests/units/Job/SubtaskEventJobTest.php b/tests/units/Job/SubtaskEventJobTest.php index 32bcd3720..a2bb7ace7 100644 --- a/tests/units/Job/SubtaskEventJobTest.php +++ b/tests/units/Job/SubtaskEventJobTest.php @@ -46,9 +46,6 @@ class SubtaskEventJobTest extends Base $this->assertTrue($subtaskModel->remove(1)); $called = $this->container['dispatcher']->getCalledListeners(); - $this->assertArrayHasKey(SubtaskModel::EVENT_CREATE.'.closure', $called); - $this->assertArrayHasKey(SubtaskModel::EVENT_UPDATE.'.closure', $called); - $this->assertArrayHasKey(SubtaskModel::EVENT_DELETE.'.closure', $called); - $this->assertArrayHasKey(SubtaskModel::EVENT_CREATE_UPDATE.'.closure', $called); + $this->assertCount(5, $called); } } diff --git a/tests/units/Job/TaskEventJobTest.php b/tests/units/Job/TaskEventJobTest.php index d8c4bb8bd..d2fce5d0f 100644 --- a/tests/units/Job/TaskEventJobTest.php +++ b/tests/units/Job/TaskEventJobTest.php @@ -48,8 +48,7 @@ class TaskEventJobTest extends Base $this->assertEquals(1, $taskCreationModel->create(array('title' => 'test', 'project_id' => 1))); $called = $this->container['dispatcher']->getCalledListeners(); - $this->assertArrayHasKey(TaskModel::EVENT_CREATE.'.closure', $called); - $this->assertArrayHasKey(TaskModel::EVENT_CREATE_UPDATE.'.closure', $called); + $this->assertCount(2, $called); } public function testTriggerUpdateEvent() @@ -66,8 +65,7 @@ class TaskEventJobTest extends Base $this->assertTrue($taskModificationModel->update(array('id' => 1, 'title' => 'new title'))); $called = $this->container['dispatcher']->getCalledListeners(); - $this->assertArrayHasKey(TaskModel::EVENT_UPDATE.'.closure', $called); - $this->assertArrayHasKey(TaskModel::EVENT_CREATE_UPDATE.'.closure', $called); + $this->assertCount(3, $called); } public function testTriggerAssigneeChangeEvent() @@ -83,7 +81,7 @@ class TaskEventJobTest extends Base $this->assertTrue($taskModificationModel->update(array('id' => 1, 'owner_id' => 1))); $called = $this->container['dispatcher']->getCalledListeners(); - $this->assertArrayHasKey(TaskModel::EVENT_ASSIGNEE_CHANGE.'.closure', $called); + $this->assertCount(1, $called); } public function testTriggerCloseEvent() @@ -99,7 +97,7 @@ class TaskEventJobTest extends Base $this->assertTrue($taskStatusModel->close(1)); $called = $this->container['dispatcher']->getCalledListeners(); - $this->assertArrayHasKey(TaskModel::EVENT_CLOSE.'.closure', $called); + $this->assertCount(1, $called); } public function testTriggerOpenEvent() @@ -116,7 +114,7 @@ class TaskEventJobTest extends Base $this->assertTrue($taskStatusModel->open(1)); $called = $this->container['dispatcher']->getCalledListeners(); - $this->assertArrayHasKey(TaskModel::EVENT_OPEN.'.closure', $called); + $this->assertCount(1, $called); } public function testTriggerMovePositionEvent() @@ -133,7 +131,7 @@ class TaskEventJobTest extends Base $this->assertTrue($taskPositionModel->movePosition(1, 1, 1, 2)); $called = $this->container['dispatcher']->getCalledListeners(); - $this->assertArrayHasKey(TaskModel::EVENT_MOVE_POSITION.'.closure', $called); + $this->assertCount(1, $called); } public function testTriggerMoveColumnEvent() @@ -149,7 +147,7 @@ class TaskEventJobTest extends Base $this->assertTrue($taskPositionModel->movePosition(1, 1, 2, 2)); $called = $this->container['dispatcher']->getCalledListeners(); - $this->assertArrayHasKey(TaskModel::EVENT_MOVE_COLUMN.'.closure', $called); + $this->assertCount(1, $called); } public function testTriggerMoveSwimlaneEvent() @@ -167,7 +165,7 @@ class TaskEventJobTest extends Base $this->assertTrue($taskPositionModel->movePosition(1, 1, 1, 1, 2)); $called = $this->container['dispatcher']->getCalledListeners(); - $this->assertArrayHasKey(TaskModel::EVENT_MOVE_SWIMLANE.'.closure', $called); + $this->assertCount(1, $called); } public function testTriggerMoveProjectEvent() @@ -184,7 +182,7 @@ class TaskEventJobTest extends Base $this->assertTrue($taskProjectMoveModel->moveToProject(1, 1)); $called = $this->container['dispatcher']->getCalledListeners(); - $this->assertArrayHasKey(TaskModel::EVENT_MOVE_PROJECT.'.closure', $called); + $this->assertCount(1, $called); } public function testThatUserMentionJobIsCalled() diff --git a/tests/units/Job/TaskFileEventJobTest.php b/tests/units/Job/TaskFileEventJobTest.php index 921fe8019..00136379e 100644 --- a/tests/units/Job/TaskFileEventJobTest.php +++ b/tests/units/Job/TaskFileEventJobTest.php @@ -41,6 +41,6 @@ class TaskFileEventJobTest extends Base $this->assertEquals(1, $taskFileModel->create(1, 'Test', '/tmp/test', 123)); $called = $this->container['dispatcher']->getCalledListeners(); - $this->assertArrayHasKey(TaskFileModel::EVENT_CREATE.'.closure', $called); + $this->assertCount(1, $called); } } diff --git a/tests/units/Job/TaskLinkEventJobTest.php b/tests/units/Job/TaskLinkEventJobTest.php index 1949316a1..661e3c0b1 100644 --- a/tests/units/Job/TaskLinkEventJobTest.php +++ b/tests/units/Job/TaskLinkEventJobTest.php @@ -42,7 +42,7 @@ class TaskLinkEventJobTest extends Base $this->assertEquals(1, $taskLinkModel->create(1, 2, 1)); $called = $this->container['dispatcher']->getCalledListeners(); - $this->assertArrayHasKey(TaskLinkModel::EVENT_CREATE_UPDATE.'.closure', $called); + $this->assertCount(2, $called); } public function testTriggerDeleteEvents() @@ -60,6 +60,6 @@ class TaskLinkEventJobTest extends Base $this->assertTrue($taskLinkModel->remove(1)); $called = $this->container['dispatcher']->getCalledListeners(); - $this->assertArrayHasKey(TaskLinkModel::EVENT_DELETE.'.closure', $called); + $this->assertCount(1, $called); } } diff --git a/tests/units/Job/UserMentionJobTest.php b/tests/units/Job/UserMentionJobTest.php index b2bfe41c7..b88bf9adf 100644 --- a/tests/units/Job/UserMentionJobTest.php +++ b/tests/units/Job/UserMentionJobTest.php @@ -99,7 +99,7 @@ class UserMentionJobTest extends Base $userMentionJob->execute('test @user1 @user2', TaskModel::EVENT_USER_MENTION, $event->getAll()); $called = $this->container['dispatcher']->getCalledListeners(); - $this->assertArrayHasKey(TaskModel::EVENT_USER_MENTION.'.UserMentionJobTest::onUserMention', $called); + $this->assertCount(1, $called); } public function onUserMention($event) diff --git a/tests/units/Middleware/ApplicationAuthorizationMiddlewareTest.php b/tests/units/Middleware/ApplicationAuthorizationMiddlewareTest.php index 482fbc2ac..f05e4044e 100644 --- a/tests/units/Middleware/ApplicationAuthorizationMiddlewareTest.php +++ b/tests/units/Middleware/ApplicationAuthorizationMiddlewareTest.php @@ -12,7 +12,7 @@ class ApplicationAuthorizationMiddlewareMiddlewareTest extends Base private $middleware; private $nextMiddleware; - public function setUp() + protected function setUp(): void { parent::setUp(); diff --git a/tests/units/Middleware/AuthenticationMiddlewareTest.php b/tests/units/Middleware/AuthenticationMiddlewareTest.php index 2cbcc123d..592626c3a 100644 --- a/tests/units/Middleware/AuthenticationMiddlewareTest.php +++ b/tests/units/Middleware/AuthenticationMiddlewareTest.php @@ -12,7 +12,7 @@ class AuthenticationMiddlewareTest extends Base private $middleware; private $nextMiddleware; - public function setUp() + protected function setUp(): void { parent::setUp(); diff --git a/tests/units/Middleware/ProjectAuthorizationMiddlewareTest.php b/tests/units/Middleware/ProjectAuthorizationMiddlewareTest.php index 089bba895..e9f3d02ad 100644 --- a/tests/units/Middleware/ProjectAuthorizationMiddlewareTest.php +++ b/tests/units/Middleware/ProjectAuthorizationMiddlewareTest.php @@ -12,7 +12,7 @@ class ProjectAuthorizationMiddlewareMiddlewareTest extends Base private $middleware; private $nextMiddleware; - public function setUp() + protected function setUp(): void { parent::setUp(); diff --git a/tests/units/Model/ProjectDailyStatsTest.php b/tests/units/Model/ProjectDailyStatsTest.php index 851af9851..53e941ba2 100644 --- a/tests/units/Model/ProjectDailyStatsTest.php +++ b/tests/units/Model/ProjectDailyStatsTest.php @@ -45,10 +45,10 @@ class ProjectDailyStatsTest extends Base $this->assertEquals($expected[0]['day'], $metrics[0]['day']); $this->assertEquals($expected[1]['day'], $metrics[1]['day']); - $this->assertEquals($expected[0]['avg_lead_time'], $metrics[0]['avg_lead_time'], '', 2); - $this->assertEquals($expected[1]['avg_lead_time'], $metrics[1]['avg_lead_time'], '', 2); + $this->assertEquals($expected[0]['avg_lead_time'], $metrics[0]['avg_lead_time'], '', 5); + $this->assertEquals($expected[1]['avg_lead_time'], $metrics[1]['avg_lead_time'], '', 5); - $this->assertEquals($expected[0]['avg_cycle_time'], $metrics[0]['avg_cycle_time'], '', 2); - $this->assertEquals($expected[1]['avg_cycle_time'], $metrics[1]['avg_cycle_time'], '', 2); + $this->assertEquals($expected[0]['avg_cycle_time'], $metrics[0]['avg_cycle_time'], '', 5); + $this->assertEquals($expected[1]['avg_cycle_time'], $metrics[1]['avg_cycle_time'], '', 5); } } diff --git a/tests/units/Model/ProjectModelTest.php b/tests/units/Model/ProjectModelTest.php index 372a5e0b5..6d15ed09d 100644 --- a/tests/units/Model/ProjectModelTest.php +++ b/tests/units/Model/ProjectModelTest.php @@ -281,7 +281,8 @@ class ProjectModelTest extends Base $this->assertEquals(1, $taskCreationModel->create(array('title' => 'Task #1', 'project_id' => 1))); $called = $this->container['dispatcher']->getCalledListeners(); - $this->assertArrayHasKey(TaskModel::EVENT_CREATE_UPDATE.'.Kanboard\Subscriber\ProjectModificationDateSubscriber::execute', $called); + $this->assertCount(1, $called); + $this->assertEquals(TaskModel::EVENT_CREATE_UPDATE, $called[0]['event']); $project = $projectModel->getById(1); $this->assertNotEmpty($project); diff --git a/tests/units/Model/TaskCreationModelTest.php b/tests/units/Model/TaskCreationModelTest.php index 4b04ac3b9..d06035fdb 100644 --- a/tests/units/Model/TaskCreationModelTest.php +++ b/tests/units/Model/TaskCreationModelTest.php @@ -33,8 +33,7 @@ class TaskCreationModelTest extends Base $this->assertEquals(1, $taskCreationModel->create(array('project_id' => 1))); $called = $this->container['dispatcher']->getCalledListeners(); - $this->assertArrayHasKey(TaskModel::EVENT_CREATE_UPDATE.'.closure', $called); - $this->assertArrayHasKey(TaskModel::EVENT_CREATE.'.closure', $called); + $this->assertCount(2, $called); $task = $taskFinderModel->getById(1); $this->assertNotEmpty($task); @@ -56,8 +55,7 @@ class TaskCreationModelTest extends Base $this->assertEquals(1, $taskCreationModel->create(array('project_id' => 1, 'title' => 'test'))); $called = $this->container['dispatcher']->getCalledListeners(); - $this->assertArrayHasKey(TaskModel::EVENT_CREATE_UPDATE.'.closure', $called); - $this->assertArrayHasKey(TaskModel::EVENT_CREATE.'.TaskCreationModelTest::onCreate', $called); + $this->assertCount(2, $called); $task = $finderModel->getById(1); $this->assertNotEmpty($task); diff --git a/tests/units/Model/TaskDuplicationModelTest.php b/tests/units/Model/TaskDuplicationModelTest.php index 1295cd37e..495d95728 100644 --- a/tests/units/Model/TaskDuplicationModelTest.php +++ b/tests/units/Model/TaskDuplicationModelTest.php @@ -80,8 +80,7 @@ class TaskDuplicationModelTest extends Base $this->assertEquals(2, $taskDuplicationModel->duplicate(1)); $called = $this->container['dispatcher']->getCalledListeners(); - $this->assertArrayHasKey(TaskModel::EVENT_CREATE_UPDATE.'.closure', $called); - $this->assertArrayHasKey(TaskModel::EVENT_CREATE.'.closure', $called); + $this->assertCount(2, $called); // Check the values of the duplicated task $task = $taskFinderModel->getById(2); diff --git a/tests/units/Model/TaskModificationModelTest.php b/tests/units/Model/TaskModificationModelTest.php index a716cf3d9..a58f34b17 100644 --- a/tests/units/Model/TaskModificationModelTest.php +++ b/tests/units/Model/TaskModificationModelTest.php @@ -75,8 +75,7 @@ class TaskModificationModelTest extends Base $this->assertTrue($taskModificationModel->update(array('id' => 1, 'title' => 'After'))); $called = $this->container['dispatcher']->getCalledListeners(); - $this->assertArrayHasKey(TaskModel::EVENT_CREATE_UPDATE.'.TaskModificationModelTest::onCreateUpdate', $called); - $this->assertArrayHasKey(TaskModel::EVENT_UPDATE.'.TaskModificationModelTest::onUpdate', $called); + $this->assertCount(2, $called); $task = $taskFinderModel->getById(1); $this->assertEquals('After', $task['title']); @@ -100,7 +99,7 @@ class TaskModificationModelTest extends Base $this->assertTrue($taskModificationModel->update(array('id' => 1, 'owner_id' => 1))); $called = $this->container['dispatcher']->getCalledListeners(); - $this->assertArrayHasKey(TaskModel::EVENT_ASSIGNEE_CHANGE.'.TaskModificationModelTest::onAssigneeChange', $called); + $this->assertCount(1, $called); $task = $taskFinderModel->getById(1); $this->assertEquals(1, $task['owner_id']); diff --git a/tests/units/Model/TaskPositionModelTest.php b/tests/units/Model/TaskPositionModelTest.php index 99154a4f5..76d66898d 100644 --- a/tests/units/Model/TaskPositionModelTest.php +++ b/tests/units/Model/TaskPositionModelTest.php @@ -552,8 +552,7 @@ class TaskPositionModelTest extends Base $this->assertEquals(2, $task['position']); $called = $this->container['dispatcher']->getCalledListeners(); - $this->assertArrayHasKey(TaskModel::EVENT_MOVE_COLUMN.'.TaskPositionModelTest::onMoveColumn', $called); - $this->assertEquals(1, count($called)); + $this->assertCount(1, $called); // We move the task 1 to the position 2 $this->assertTrue($taskPositionModel->movePosition(1, 1, 2, 2)); @@ -569,8 +568,7 @@ class TaskPositionModelTest extends Base $this->assertEquals(1, $task['position']); $called = $this->container['dispatcher']->getCalledListeners(); - $this->assertArrayHasKey(TaskModel::EVENT_MOVE_POSITION.'.TaskPositionModelTest::onMovePosition', $called); - $this->assertEquals(2, count($called)); + $this->assertCount(2, $called); // Move to another swimlane $this->assertTrue($taskPositionModel->movePosition(1, 1, 3, 1, 2)); @@ -588,8 +586,7 @@ class TaskPositionModelTest extends Base $this->assertEquals(1, $task['swimlane_id']); $called = $this->container['dispatcher']->getCalledListeners(); - $this->assertArrayHasKey(TaskModel::EVENT_MOVE_SWIMLANE.'.TaskPositionModelTest::onMoveSwimlane', $called); - $this->assertEquals(3, count($called)); + $this->assertCount(3, $called); } public function onMoveColumn($event) diff --git a/tests/units/Model/TaskProjectDuplicationModelTest.php b/tests/units/Model/TaskProjectDuplicationModelTest.php index 5ca91718a..8c4a0d473 100644 --- a/tests/units/Model/TaskProjectDuplicationModelTest.php +++ b/tests/units/Model/TaskProjectDuplicationModelTest.php @@ -47,8 +47,7 @@ class TaskProjectDuplicationModelTest extends Base $this->assertEquals(2, $taskProjectDuplicationModel->duplicateToProject(1, 2)); $called = $this->container['dispatcher']->getCalledListeners(); - $this->assertArrayHasKey(TaskModel::EVENT_CREATE_UPDATE.'.closure', $called); - $this->assertArrayHasKey(TaskModel::EVENT_CREATE.'.closure', $called); + $this->assertCount(2, $called); // Check the values of the duplicated task $task = $taskFinderModel->getById(2); diff --git a/tests/units/Model/TaskProjectMoveModelTest.php b/tests/units/Model/TaskProjectMoveModelTest.php index 9782cd100..f91348e50 100644 --- a/tests/units/Model/TaskProjectMoveModelTest.php +++ b/tests/units/Model/TaskProjectMoveModelTest.php @@ -54,7 +54,7 @@ class TaskProjectMoveModelTest extends Base $this->assertTrue($taskProjectMoveModel->moveToProject(1, 2)); $called = $this->container['dispatcher']->getCalledListeners(); - $this->assertArrayHasKey(TaskModel::EVENT_MOVE_PROJECT.'.TaskProjectMoveModelTest::onMoveProject', $called); + $this->assertCount(1, $called); // Check the values of the moved task $task = $taskFinderModel->getById(1); diff --git a/tests/units/Model/TaskStatusModelTest.php b/tests/units/Model/TaskStatusModelTest.php index 157ed3e2a..ef0fc399d 100644 --- a/tests/units/Model/TaskStatusModelTest.php +++ b/tests/units/Model/TaskStatusModelTest.php @@ -100,8 +100,7 @@ class TaskStatusModelTest extends Base $this->assertEquals(time(), $task['date_modification'], '', 1); $called = $this->container['dispatcher']->getCalledListeners(); - $this->assertArrayHasKey('task.close.TaskStatusModelTest::onTaskClose', $called); - $this->assertArrayHasKey('task.open.TaskStatusModelTest::onTaskOpen', $called); + $this->assertCount(2, $called); } public function onTaskOpen($event) diff --git a/vendor/christian-riesen/base32/README.md b/vendor/christian-riesen/base32/README.md index 56915f1cb..74343b8d7 100644 --- a/vendor/christian-riesen/base32/README.md +++ b/vendor/christian-riesen/base32/README.md @@ -3,14 +3,19 @@ base32 Base32 Encoder/Decoder for PHP according to [RFC 4648](https://tools.ietf.org/html/rfc4648). -[![Build Status](https://secure.travis-ci.org/ChristianRiesen/base32.png)](http://travis-ci.org/ChristianRiesen/base32) -[![HHVM Status](http://hhvm.h4cc.de/badge/christian-riesen/base32.png)](http://hhvm.h4cc.de/package/christian-riesen/base32) +![CI](https://github.com/ChristianRiesen/base32/workflows/CI/badge.svg) [![Latest Stable Version](https://poser.pugx.org/christian-riesen/base32/v/stable.png)](https://packagist.org/packages/christian-riesen/base32) [![Total Downloads](https://poser.pugx.org/christian-riesen/base32/downloads.png)](https://packagist.org/packages/christian-riesen/base32) [![Latest Unstable Version](https://poser.pugx.org/christian-riesen/base32/v/unstable.png)](https://packagist.org/packages/christian-riesen/base32) [![License](https://poser.pugx.org/christian-riesen/base32/license.png)](https://packagist.org/packages/christian-riesen/base32) -Do you like this? Flattr it: -[![Flattr base32](http://api.flattr.com/button/flattr-badge-large.png)](http://flattr.com/thing/720563/ChristianRiesenbase32-on-GitHub) +Installation +----- + +Use composer: + +```bash +composer require christian-riesen/base32 +``` Usage ----- @@ -23,20 +28,19 @@ use Base32\Base32; $string = 'fooba'; -$encoded = Base32::encode($string); // $encoded contains now 'MZXW6YTB' +$encoded = Base32::encode($string); -$decoded = Base32::decode($encoded); // $decoded is again 'fooba' +$decoded = Base32::decode($encoded); ``` +You can also use the extended hex alphabet by using the `Base32Hex` class instead. + About ===== -Use ---- - -Initially created to work with the [one time password project](https://github.com/ChristianRiesen/otp), yet it can stand alone just as well as [Jordi Boggiano](http://seld.be/) kindly pointed out. It's the only Base32 implementation I could make work that passes the test vectors (and contains unit tests). +Initially created to work with the [one time password project](https://github.com/ChristianRiesen/otp), yet it can stand alone just as well as [Jordi Boggiano](http://seld.be/) kindly pointed out. It's the only Base32 implementation that passes the test vectors and contains unit tests as well. Goal ---- @@ -45,9 +49,9 @@ Have a RFC compliant Base32 encoder and decoder. The implementation could be imp Requirements ------------ -PHP 5.3 to 5.6 or 7.0+ +Works on PHP 7.2 and later, including PHP 8.0. -If you want to run the tests, PHPUnit 5.0+ or up is required. Tests require PHP 5.6 or 7.0+. +Tests run on PHPUnit 9.5, with PHP 7.3 and later. For PHP 7.2, tests use an older PHPUnit version. Author ------ diff --git a/vendor/christian-riesen/base32/src/Base32.php b/vendor/christian-riesen/base32/src/Base32.php index bf7901826..d71f1350f 100644 --- a/vendor/christian-riesen/base32/src/Base32.php +++ b/vendor/christian-riesen/base32/src/Base32.php @@ -1,146 +1,168 @@ - * @link http://christianriesen.com + * @author Christian Riesen + * @author Sam Williams + * + * @see http://christianriesen.com + * * @license MIT License see LICENSE file */ class Base32 { /** - * Alphabet for encoding and decoding base32 + * Alphabet for encoding and decoding base32. * - * @var array + * @var string */ - private static $alphabet = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ234567='; + protected const ALPHABET = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ234567='; + + protected const BASE32HEX_PATTERN = '/[^A-Z2-7]/'; /** - * Creates an array from a binary string into a given chunk size - * - * @param string $binaryString String to chunk - * @param integer $bits Number of bits per chunk - * @return array + * Maps the Base32 character to its corresponding bit value. */ - private static function chunk($binaryString, $bits) - { - $binaryString = chunk_split($binaryString, $bits, ' '); - - if (substr($binaryString, (strlen($binaryString)) - 1) == ' ') { - $binaryString = substr($binaryString, 0, strlen($binaryString)-1); - } - - return explode(' ', $binaryString); - } + protected const MAPPING = [ + '=' => 0b00000, + 'A' => 0b00000, + 'B' => 0b00001, + 'C' => 0b00010, + 'D' => 0b00011, + 'E' => 0b00100, + 'F' => 0b00101, + 'G' => 0b00110, + 'H' => 0b00111, + 'I' => 0b01000, + 'J' => 0b01001, + 'K' => 0b01010, + 'L' => 0b01011, + 'M' => 0b01100, + 'N' => 0b01101, + 'O' => 0b01110, + 'P' => 0b01111, + 'Q' => 0b10000, + 'R' => 0b10001, + 'S' => 0b10010, + 'T' => 0b10011, + 'U' => 0b10100, + 'V' => 0b10101, + 'W' => 0b10110, + 'X' => 0b10111, + 'Y' => 0b11000, + 'Z' => 0b11001, + '2' => 0b11010, + '3' => 0b11011, + '4' => 0b11100, + '5' => 0b11101, + '6' => 0b11110, + '7' => 0b11111, + ]; /** - * Encodes into base32 + * Encodes into base32. * * @param string $string Clear text string + * * @return string Base32 encoded string */ - public static function encode($string) + public static function encode(string $string): string { - if (strlen($string) == 0) { - // Gives an empty string - + // Empty string results in empty string + if ('' === $string) { return ''; } - // Convert string to binary - $binaryString = ''; + $encoded = ''; - foreach (str_split($string) as $s) { - // Return each character as an 8-bit binary string - $binaryString .= sprintf('%08b', ord($s)); - } + //Set the initial values + $n = $bitLen = $val = 0; + $len = \strlen($string); - // Break into 5-bit chunks, then break that into an array - $binaryArray = self::chunk($binaryString, 5); + //Pad the end of the string - this ensures that there are enough zeros + $string .= \str_repeat(\chr(0), 4); - // Pad array to be divisible by 8 - while (count($binaryArray) % 8 !== 0) { - $binaryArray[] = null; - } + //Explode string into integers + $chars = (array) \unpack('C*', $string, 0); - $base32String = ''; - - // Encode in base32 - foreach ($binaryArray as $bin) { - $char = 32; - - if (!is_null($bin)) { - // Pad the binary strings - $bin = str_pad($bin, 5, 0, STR_PAD_RIGHT); - $char = bindec($bin); + while ($n < $len || 0 !== $bitLen) { + //If the bit length has fallen below 5, shift left 8 and add the next character. + if ($bitLen < 5) { + $val = $val << 8; + $bitLen += 8; + $n++; + $val += $chars[$n]; } - - // Base32 character - $base32String .= self::$alphabet[$char]; + $shift = $bitLen - 5; + $encoded .= ($n - (int)($bitLen > 8) > $len && 0 == $val) ? '=' : static::ALPHABET[$val >> $shift]; + $val = $val & ((1 << $shift) - 1); + $bitLen -= 5; } - return $base32String; + return $encoded; } /** - * Decodes base32 + * Decodes base32. * * @param string $base32String Base32 encoded string + * * @return string Clear text string */ - public static function decode($base32String) + public static function decode(string $base32String): string { // Only work in upper cases - $base32String = strtoupper($base32String); + $base32String = \strtoupper($base32String); // Remove anything that is not base32 alphabet - $pattern = '/[^A-Z2-7]/'; + $base32String = \preg_replace(static::BASE32HEX_PATTERN, '', $base32String); - $base32String = preg_replace($pattern, '', $base32String); - - if (strlen($base32String) == 0) { - // Gives an empty string + // Empty string results in empty string + if ('' === $base32String || null === $base32String) { return ''; } - $base32Array = str_split($base32String); + $decoded = ''; - $string = ''; + //Set the initial values + $len = \strlen($base32String); + $n = 0; + $bitLen = 5; + $val = static::MAPPING[$base32String[0]]; - foreach ($base32Array as $str) { - $char = strpos(self::$alphabet, $str); + while ($n < $len) { + //If the bit length has fallen below 8, shift left 5 and add the next pentet. + if ($bitLen < 8) { + $val = $val << 5; + $bitLen += 5; + $n++; + $pentet = $base32String[$n] ?? '='; - // Ignore the padding character - if ($char !== 32) { - $string .= sprintf('%05b', $char); + //If the new pentet is padding, make this the last iteration. + if ('=' === $pentet) { + $n = $len; + } + $val += static::MAPPING[$pentet]; + continue; } + $shift = $bitLen - 8; + + $decoded .= \chr($val >> $shift); + $val = $val & ((1 << $shift) - 1); + $bitLen -= 8; } - while (strlen($string) %8 !== 0) { - $string = substr($string, 0, strlen($string)-1); - } - - $binaryArray = self::chunk($string, 8); - - $realString = ''; - - foreach ($binaryArray as $bin) { - // Pad each value to 8 bits - $bin = str_pad($bin, 8, 0, STR_PAD_RIGHT); - // Convert binary strings to ASCII - $realString .= chr(bindec($bin)); - } - - return $realString; + return $decoded; } } diff --git a/vendor/christian-riesen/base32/src/Base32Hex.php b/vendor/christian-riesen/base32/src/Base32Hex.php new file mode 100644 index 000000000..083091010 --- /dev/null +++ b/vendor/christian-riesen/base32/src/Base32Hex.php @@ -0,0 +1,68 @@ + + * + * @see http://christianriesen.com + * + * @license MIT License see LICENSE file + */ +class Base32Hex extends Base32 +{ + /** + * Alphabet for encoding and decoding base32 extended hex. + * + * @var string + */ + protected const ALPHABET = '0123456789ABCDEFGHIJKLMNOPQRSTUV='; + + protected const BASE32HEX_PATTERN = '/[^0-9A-V]/'; + + /** + * Maps the Base32 character to its corresponding bit value. + */ + protected const MAPPING = [ + '=' => 0b00000, + '0' => 0b00000, + '1' => 0b00001, + '2' => 0b00010, + '3' => 0b00011, + '4' => 0b00100, + '5' => 0b00101, + '6' => 0b00110, + '7' => 0b00111, + '8' => 0b01000, + '9' => 0b01001, + 'A' => 0b01010, + 'B' => 0b01011, + 'C' => 0b01100, + 'D' => 0b01101, + 'E' => 0b01110, + 'F' => 0b01111, + 'G' => 0b10000, + 'H' => 0b10001, + 'I' => 0b10010, + 'J' => 0b10011, + 'K' => 0b10100, + 'L' => 0b10101, + 'M' => 0b10110, + 'N' => 0b10111, + 'O' => 0b11000, + 'P' => 0b11001, + 'Q' => 0b11010, + 'R' => 0b11011, + 'S' => 0b11100, + 'T' => 0b11101, + 'U' => 0b11110, + 'V' => 0b11111, + ]; +} diff --git a/vendor/composer/autoload_classmap.php b/vendor/composer/autoload_classmap.php index 88096f071..e50a879a6 100644 --- a/vendor/composer/autoload_classmap.php +++ b/vendor/composer/autoload_classmap.php @@ -6,7 +6,9 @@ $vendorDir = dirname(dirname(__FILE__)); $baseDir = dirname($vendorDir); return array( + 'Attribute' => $vendorDir . '/symfony/polyfill-php80/Resources/stubs/Attribute.php', 'Base32\\Base32' => $vendorDir . '/christian-riesen/base32/src/Base32.php', + 'Base32\\Base32Hex' => $vendorDir . '/christian-riesen/base32/src/Base32Hex.php', 'Composer\\InstalledVersions' => $vendorDir . '/composer/InstalledVersions.php', 'Eluceo\\iCal\\Component' => $vendorDir . '/eluceo/ical/src/Component.php', 'Eluceo\\iCal\\Component\\Alarm' => $vendorDir . '/eluceo/ical/src/Component/Alarm.php', @@ -36,6 +38,7 @@ return array( 'Gregwar\\Captcha\\ImageFileHandler' => $vendorDir . '/gregwar/captcha/src/Gregwar/Captcha/ImageFileHandler.php', 'Gregwar\\Captcha\\PhraseBuilder' => $vendorDir . '/gregwar/captcha/src/Gregwar/Captcha/PhraseBuilder.php', 'Gregwar\\Captcha\\PhraseBuilderInterface' => $vendorDir . '/gregwar/captcha/src/Gregwar/Captcha/PhraseBuilderInterface.php', + 'JsonException' => $vendorDir . '/symfony/polyfill-php73/Resources/stubs/JsonException.php', 'JsonRPC\\Client' => $baseDir . '/libs/jsonrpc/src/JsonRPC/Client.php', 'JsonRPC\\Exception\\AccessDeniedException' => $baseDir . '/libs/jsonrpc/src/JsonRPC/Exception/AccessDeniedException.php', 'JsonRPC\\Exception\\AuthenticationFailureException' => $baseDir . '/libs/jsonrpc/src/JsonRPC/Exception/AuthenticationFailureException.php', @@ -82,6 +85,7 @@ return array( 'Kanboard\\Action\\TaskAssignCurrentUser' => $baseDir . '/app/Action/TaskAssignCurrentUser.php', 'Kanboard\\Action\\TaskAssignCurrentUserColumn' => $baseDir . '/app/Action/TaskAssignCurrentUserColumn.php', 'Kanboard\\Action\\TaskAssignDueDateOnCreation' => $baseDir . '/app/Action/TaskAssignDueDateOnCreation.php', + 'Kanboard\\Action\\TaskAssignDueDateOnMoveColumn' => $baseDir . '/app/Action/TaskAssignDueDateOnMoveColumn.php', 'Kanboard\\Action\\TaskAssignPrioritySwimlane' => $baseDir . '/app/Action/TaskAssignPrioritySwimlane.php', 'Kanboard\\Action\\TaskAssignSpecificUser' => $baseDir . '/app/Action/TaskAssignSpecificUser.php', 'Kanboard\\Action\\TaskAssignUser' => $baseDir . '/app/Action/TaskAssignUser.php', @@ -802,6 +806,7 @@ return array( 'SimpleValidator\\Validators\\Range' => $baseDir . '/libs/SimpleValidator/Validators/Range.php', 'SimpleValidator\\Validators\\Required' => $baseDir . '/libs/SimpleValidator/Validators/Required.php', 'SimpleValidator\\Validators\\Unique' => $baseDir . '/libs/SimpleValidator/Validators/Unique.php', + 'Stringable' => $vendorDir . '/symfony/polyfill-php80/Resources/stubs/Stringable.php', 'Symfony\\Component\\Console\\Application' => $vendorDir . '/symfony/console/Application.php', 'Symfony\\Component\\Console\\CommandLoader\\CommandLoaderInterface' => $vendorDir . '/symfony/console/CommandLoader/CommandLoaderInterface.php', 'Symfony\\Component\\Console\\CommandLoader\\ContainerCommandLoader' => $vendorDir . '/symfony/console/CommandLoader/ContainerCommandLoader.php', @@ -829,6 +834,7 @@ return array( 'Symfony\\Component\\Console\\Exception\\InvalidArgumentException' => $vendorDir . '/symfony/console/Exception/InvalidArgumentException.php', 'Symfony\\Component\\Console\\Exception\\InvalidOptionException' => $vendorDir . '/symfony/console/Exception/InvalidOptionException.php', 'Symfony\\Component\\Console\\Exception\\LogicException' => $vendorDir . '/symfony/console/Exception/LogicException.php', + 'Symfony\\Component\\Console\\Exception\\MissingInputException' => $vendorDir . '/symfony/console/Exception/MissingInputException.php', 'Symfony\\Component\\Console\\Exception\\NamespaceNotFoundException' => $vendorDir . '/symfony/console/Exception/NamespaceNotFoundException.php', 'Symfony\\Component\\Console\\Exception\\RuntimeException' => $vendorDir . '/symfony/console/Exception/RuntimeException.php', 'Symfony\\Component\\Console\\Formatter\\OutputFormatter' => $vendorDir . '/symfony/console/Formatter/OutputFormatter.php', @@ -839,6 +845,7 @@ return array( 'Symfony\\Component\\Console\\Formatter\\WrappableOutputFormatterInterface' => $vendorDir . '/symfony/console/Formatter/WrappableOutputFormatterInterface.php', 'Symfony\\Component\\Console\\Helper\\DebugFormatterHelper' => $vendorDir . '/symfony/console/Helper/DebugFormatterHelper.php', 'Symfony\\Component\\Console\\Helper\\DescriptorHelper' => $vendorDir . '/symfony/console/Helper/DescriptorHelper.php', + 'Symfony\\Component\\Console\\Helper\\Dumper' => $vendorDir . '/symfony/console/Helper/Dumper.php', 'Symfony\\Component\\Console\\Helper\\FormatterHelper' => $vendorDir . '/symfony/console/Helper/FormatterHelper.php', 'Symfony\\Component\\Console\\Helper\\Helper' => $vendorDir . '/symfony/console/Helper/Helper.php', 'Symfony\\Component\\Console\\Helper\\HelperInterface' => $vendorDir . '/symfony/console/Helper/HelperInterface.php', @@ -873,6 +880,7 @@ return array( 'Symfony\\Component\\Console\\Output\\Output' => $vendorDir . '/symfony/console/Output/Output.php', 'Symfony\\Component\\Console\\Output\\OutputInterface' => $vendorDir . '/symfony/console/Output/OutputInterface.php', 'Symfony\\Component\\Console\\Output\\StreamOutput' => $vendorDir . '/symfony/console/Output/StreamOutput.php', + 'Symfony\\Component\\Console\\Output\\TrimmedBufferOutput' => $vendorDir . '/symfony/console/Output/TrimmedBufferOutput.php', 'Symfony\\Component\\Console\\Question\\ChoiceQuestion' => $vendorDir . '/symfony/console/Question/ChoiceQuestion.php', 'Symfony\\Component\\Console\\Question\\ConfirmationQuestion' => $vendorDir . '/symfony/console/Question/ConfirmationQuestion.php', 'Symfony\\Component\\Console\\Question\\Question' => $vendorDir . '/symfony/console/Question/Question.php', @@ -883,10 +891,10 @@ return array( 'Symfony\\Component\\Console\\Tester\\ApplicationTester' => $vendorDir . '/symfony/console/Tester/ApplicationTester.php', 'Symfony\\Component\\Console\\Tester\\CommandTester' => $vendorDir . '/symfony/console/Tester/CommandTester.php', 'Symfony\\Component\\Console\\Tester\\TesterTrait' => $vendorDir . '/symfony/console/Tester/TesterTrait.php', - 'Symfony\\Component\\EventDispatcher\\ContainerAwareEventDispatcher' => $vendorDir . '/symfony/event-dispatcher/ContainerAwareEventDispatcher.php', 'Symfony\\Component\\EventDispatcher\\Debug\\TraceableEventDispatcher' => $vendorDir . '/symfony/event-dispatcher/Debug/TraceableEventDispatcher.php', 'Symfony\\Component\\EventDispatcher\\Debug\\TraceableEventDispatcherInterface' => $vendorDir . '/symfony/event-dispatcher/Debug/TraceableEventDispatcherInterface.php', 'Symfony\\Component\\EventDispatcher\\Debug\\WrappedListener' => $vendorDir . '/symfony/event-dispatcher/Debug/WrappedListener.php', + 'Symfony\\Component\\EventDispatcher\\DependencyInjection\\AddEventAliasesPass' => $vendorDir . '/symfony/event-dispatcher/DependencyInjection/AddEventAliasesPass.php', 'Symfony\\Component\\EventDispatcher\\DependencyInjection\\RegisterListenersPass' => $vendorDir . '/symfony/event-dispatcher/DependencyInjection/RegisterListenersPass.php', 'Symfony\\Component\\EventDispatcher\\Event' => $vendorDir . '/symfony/event-dispatcher/Event.php', 'Symfony\\Component\\EventDispatcher\\EventDispatcher' => $vendorDir . '/symfony/event-dispatcher/EventDispatcher.php', @@ -894,6 +902,8 @@ return array( 'Symfony\\Component\\EventDispatcher\\EventSubscriberInterface' => $vendorDir . '/symfony/event-dispatcher/EventSubscriberInterface.php', 'Symfony\\Component\\EventDispatcher\\GenericEvent' => $vendorDir . '/symfony/event-dispatcher/GenericEvent.php', 'Symfony\\Component\\EventDispatcher\\ImmutableEventDispatcher' => $vendorDir . '/symfony/event-dispatcher/ImmutableEventDispatcher.php', + 'Symfony\\Component\\EventDispatcher\\LegacyEventDispatcherProxy' => $vendorDir . '/symfony/event-dispatcher/LegacyEventDispatcherProxy.php', + 'Symfony\\Component\\EventDispatcher\\LegacyEventProxy' => $vendorDir . '/symfony/event-dispatcher/LegacyEventProxy.php', 'Symfony\\Component\\Finder\\Comparator\\Comparator' => $vendorDir . '/symfony/finder/Comparator/Comparator.php', 'Symfony\\Component\\Finder\\Comparator\\DateComparator' => $vendorDir . '/symfony/finder/Comparator/DateComparator.php', 'Symfony\\Component\\Finder\\Comparator\\NumberComparator' => $vendorDir . '/symfony/finder/Comparator/NumberComparator.php', @@ -909,42 +919,27 @@ return array( 'Symfony\\Component\\Finder\\Iterator\\FileTypeFilterIterator' => $vendorDir . '/symfony/finder/Iterator/FileTypeFilterIterator.php', 'Symfony\\Component\\Finder\\Iterator\\FilecontentFilterIterator' => $vendorDir . '/symfony/finder/Iterator/FilecontentFilterIterator.php', 'Symfony\\Component\\Finder\\Iterator\\FilenameFilterIterator' => $vendorDir . '/symfony/finder/Iterator/FilenameFilterIterator.php', + 'Symfony\\Component\\Finder\\Iterator\\LazyIterator' => $vendorDir . '/symfony/finder/Iterator/LazyIterator.php', 'Symfony\\Component\\Finder\\Iterator\\MultiplePcreFilterIterator' => $vendorDir . '/symfony/finder/Iterator/MultiplePcreFilterIterator.php', 'Symfony\\Component\\Finder\\Iterator\\PathFilterIterator' => $vendorDir . '/symfony/finder/Iterator/PathFilterIterator.php', 'Symfony\\Component\\Finder\\Iterator\\RecursiveDirectoryIterator' => $vendorDir . '/symfony/finder/Iterator/RecursiveDirectoryIterator.php', 'Symfony\\Component\\Finder\\Iterator\\SizeRangeFilterIterator' => $vendorDir . '/symfony/finder/Iterator/SizeRangeFilterIterator.php', 'Symfony\\Component\\Finder\\Iterator\\SortableIterator' => $vendorDir . '/symfony/finder/Iterator/SortableIterator.php', + 'Symfony\\Component\\Finder\\Iterator\\VcsIgnoredFilterIterator' => $vendorDir . '/symfony/finder/Iterator/VcsIgnoredFilterIterator.php', 'Symfony\\Component\\Finder\\SplFileInfo' => $vendorDir . '/symfony/finder/SplFileInfo.php', - 'Symfony\\Contracts\\Cache\\CacheInterface' => $vendorDir . '/symfony/contracts/Cache/CacheInterface.php', - 'Symfony\\Contracts\\Cache\\CacheTrait' => $vendorDir . '/symfony/contracts/Cache/CacheTrait.php', - 'Symfony\\Contracts\\Cache\\CallbackInterface' => $vendorDir . '/symfony/contracts/Cache/CallbackInterface.php', - 'Symfony\\Contracts\\Cache\\ItemInterface' => $vendorDir . '/symfony/contracts/Cache/ItemInterface.php', - 'Symfony\\Contracts\\Cache\\TagAwareCacheInterface' => $vendorDir . '/symfony/contracts/Cache/TagAwareCacheInterface.php', - 'Symfony\\Contracts\\EventDispatcher\\Event' => $vendorDir . '/symfony/contracts/EventDispatcher/Event.php', - 'Symfony\\Contracts\\EventDispatcher\\EventDispatcherInterface' => $vendorDir . '/symfony/contracts/EventDispatcher/EventDispatcherInterface.php', - 'Symfony\\Contracts\\HttpClient\\ChunkInterface' => $vendorDir . '/symfony/contracts/HttpClient/ChunkInterface.php', - 'Symfony\\Contracts\\HttpClient\\Exception\\ClientExceptionInterface' => $vendorDir . '/symfony/contracts/HttpClient/Exception/ClientExceptionInterface.php', - 'Symfony\\Contracts\\HttpClient\\Exception\\ExceptionInterface' => $vendorDir . '/symfony/contracts/HttpClient/Exception/ExceptionInterface.php', - 'Symfony\\Contracts\\HttpClient\\Exception\\HttpExceptionInterface' => $vendorDir . '/symfony/contracts/HttpClient/Exception/HttpExceptionInterface.php', - 'Symfony\\Contracts\\HttpClient\\Exception\\RedirectionExceptionInterface' => $vendorDir . '/symfony/contracts/HttpClient/Exception/RedirectionExceptionInterface.php', - 'Symfony\\Contracts\\HttpClient\\Exception\\ServerExceptionInterface' => $vendorDir . '/symfony/contracts/HttpClient/Exception/ServerExceptionInterface.php', - 'Symfony\\Contracts\\HttpClient\\Exception\\TransportExceptionInterface' => $vendorDir . '/symfony/contracts/HttpClient/Exception/TransportExceptionInterface.php', - 'Symfony\\Contracts\\HttpClient\\HttpClientInterface' => $vendorDir . '/symfony/contracts/HttpClient/HttpClientInterface.php', - 'Symfony\\Contracts\\HttpClient\\ResponseInterface' => $vendorDir . '/symfony/contracts/HttpClient/ResponseInterface.php', - 'Symfony\\Contracts\\HttpClient\\ResponseStreamInterface' => $vendorDir . '/symfony/contracts/HttpClient/ResponseStreamInterface.php', - 'Symfony\\Contracts\\HttpClient\\Test\\HttpClientTestCase' => $vendorDir . '/symfony/contracts/HttpClient/Test/HttpClientTestCase.php', - 'Symfony\\Contracts\\HttpClient\\Test\\TestHttpServer' => $vendorDir . '/symfony/contracts/HttpClient/Test/TestHttpServer.php', - 'Symfony\\Contracts\\Service\\ResetInterface' => $vendorDir . '/symfony/contracts/Service/ResetInterface.php', - 'Symfony\\Contracts\\Service\\ServiceLocatorTrait' => $vendorDir . '/symfony/contracts/Service/ServiceLocatorTrait.php', - 'Symfony\\Contracts\\Service\\ServiceProviderInterface' => $vendorDir . '/symfony/contracts/Service/ServiceProviderInterface.php', - 'Symfony\\Contracts\\Service\\ServiceSubscriberInterface' => $vendorDir . '/symfony/contracts/Service/ServiceSubscriberInterface.php', - 'Symfony\\Contracts\\Service\\ServiceSubscriberTrait' => $vendorDir . '/symfony/contracts/Service/ServiceSubscriberTrait.php', - 'Symfony\\Contracts\\Service\\Test\\ServiceLocatorTest' => $vendorDir . '/symfony/contracts/Service/Test/ServiceLocatorTest.php', - 'Symfony\\Contracts\\Tests\\Cache\\CacheTraitTest' => $vendorDir . '/symfony/contracts/Tests/Cache/CacheTraitTest.php', - 'Symfony\\Contracts\\Tests\\Service\\ServiceSubscriberTraitTest' => $vendorDir . '/symfony/contracts/Tests/Service/ServiceSubscriberTraitTest.php', - 'Symfony\\Contracts\\Translation\\LocaleAwareInterface' => $vendorDir . '/symfony/contracts/Translation/LocaleAwareInterface.php', - 'Symfony\\Contracts\\Translation\\Test\\TranslatorTest' => $vendorDir . '/symfony/contracts/Translation/Test/TranslatorTest.php', - 'Symfony\\Contracts\\Translation\\TranslatorInterface' => $vendorDir . '/symfony/contracts/Translation/TranslatorInterface.php', - 'Symfony\\Contracts\\Translation\\TranslatorTrait' => $vendorDir . '/symfony/contracts/Translation/TranslatorTrait.php', + 'Symfony\\Contracts\\EventDispatcher\\Event' => $vendorDir . '/symfony/event-dispatcher-contracts/Event.php', + 'Symfony\\Contracts\\EventDispatcher\\EventDispatcherInterface' => $vendorDir . '/symfony/event-dispatcher-contracts/EventDispatcherInterface.php', + 'Symfony\\Contracts\\Service\\Attribute\\Required' => $vendorDir . '/symfony/service-contracts/Attribute/Required.php', + 'Symfony\\Contracts\\Service\\Attribute\\SubscribedService' => $vendorDir . '/symfony/service-contracts/Attribute/SubscribedService.php', + 'Symfony\\Contracts\\Service\\ResetInterface' => $vendorDir . '/symfony/service-contracts/ResetInterface.php', + 'Symfony\\Contracts\\Service\\ServiceLocatorTrait' => $vendorDir . '/symfony/service-contracts/ServiceLocatorTrait.php', + 'Symfony\\Contracts\\Service\\ServiceProviderInterface' => $vendorDir . '/symfony/service-contracts/ServiceProviderInterface.php', + 'Symfony\\Contracts\\Service\\ServiceSubscriberInterface' => $vendorDir . '/symfony/service-contracts/ServiceSubscriberInterface.php', + 'Symfony\\Contracts\\Service\\ServiceSubscriberTrait' => $vendorDir . '/symfony/service-contracts/ServiceSubscriberTrait.php', + 'Symfony\\Contracts\\Service\\Test\\ServiceLocatorTest' => $vendorDir . '/symfony/service-contracts/Test/ServiceLocatorTest.php', 'Symfony\\Polyfill\\Mbstring\\Mbstring' => $vendorDir . '/symfony/polyfill-mbstring/Mbstring.php', + 'Symfony\\Polyfill\\Php73\\Php73' => $vendorDir . '/symfony/polyfill-php73/Php73.php', + 'Symfony\\Polyfill\\Php80\\Php80' => $vendorDir . '/symfony/polyfill-php80/Php80.php', + 'UnhandledMatchError' => $vendorDir . '/symfony/polyfill-php80/Resources/stubs/UnhandledMatchError.php', + 'ValueError' => $vendorDir . '/symfony/polyfill-php80/Resources/stubs/ValueError.php', ); diff --git a/vendor/composer/autoload_files.php b/vendor/composer/autoload_files.php index d30d852fd..85cbec2f6 100644 --- a/vendor/composer/autoload_files.php +++ b/vendor/composer/autoload_files.php @@ -6,7 +6,10 @@ $vendorDir = dirname(dirname(__FILE__)); $baseDir = dirname($vendorDir); return array( + '6e3fae29631ef280660b3cdad06f25a8' => $vendorDir . '/symfony/deprecation-contracts/function.php', + 'a4a119a56e50fbb293281d9a48007e0e' => $vendorDir . '/symfony/polyfill-php80/bootstrap.php', '0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => $vendorDir . '/symfony/polyfill-mbstring/bootstrap.php', + '0d59ee240a4cd96ddbb4ff164fccea4d' => $vendorDir . '/symfony/polyfill-php73/bootstrap.php', '2c102faa651ef8ea5874edb585946bce' => $vendorDir . '/swiftmailer/swiftmailer/lib/swift_required.php', '8a67f3044590529ed0a5e02f9cc9c90b' => $baseDir . '/app/functions.php', ); diff --git a/vendor/composer/autoload_psr4.php b/vendor/composer/autoload_psr4.php index 15309737b..dfa26651d 100644 --- a/vendor/composer/autoload_psr4.php +++ b/vendor/composer/autoload_psr4.php @@ -6,8 +6,11 @@ $vendorDir = dirname(dirname(__FILE__)); $baseDir = dirname($vendorDir); return array( + 'Symfony\\Polyfill\\Php80\\' => array($vendorDir . '/symfony/polyfill-php80'), + 'Symfony\\Polyfill\\Php73\\' => array($vendorDir . '/symfony/polyfill-php73'), 'Symfony\\Polyfill\\Mbstring\\' => array($vendorDir . '/symfony/polyfill-mbstring'), - 'Symfony\\Contracts\\' => array($vendorDir . '/symfony/contracts'), + 'Symfony\\Contracts\\Service\\' => array($vendorDir . '/symfony/service-contracts'), + 'Symfony\\Contracts\\EventDispatcher\\' => array($vendorDir . '/symfony/event-dispatcher-contracts'), 'Symfony\\Component\\Finder\\' => array($vendorDir . '/symfony/finder'), 'Symfony\\Component\\EventDispatcher\\' => array($vendorDir . '/symfony/event-dispatcher'), 'Symfony\\Component\\Console\\' => array($vendorDir . '/symfony/console'), diff --git a/vendor/composer/autoload_static.php b/vendor/composer/autoload_static.php index edf9bc540..170fea16b 100644 --- a/vendor/composer/autoload_static.php +++ b/vendor/composer/autoload_static.php @@ -7,7 +7,10 @@ namespace Composer\Autoload; class ComposerStaticInit80f59a55e693f3d5493bcaaa968d1851 { public static $files = array ( + '6e3fae29631ef280660b3cdad06f25a8' => __DIR__ . '/..' . '/symfony/deprecation-contracts/function.php', + 'a4a119a56e50fbb293281d9a48007e0e' => __DIR__ . '/..' . '/symfony/polyfill-php80/bootstrap.php', '0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => __DIR__ . '/..' . '/symfony/polyfill-mbstring/bootstrap.php', + '0d59ee240a4cd96ddbb4ff164fccea4d' => __DIR__ . '/..' . '/symfony/polyfill-php73/bootstrap.php', '2c102faa651ef8ea5874edb585946bce' => __DIR__ . '/..' . '/swiftmailer/swiftmailer/lib/swift_required.php', '8a67f3044590529ed0a5e02f9cc9c90b' => __DIR__ . '/../..' . '/app/functions.php', ); @@ -15,8 +18,11 @@ class ComposerStaticInit80f59a55e693f3d5493bcaaa968d1851 public static $prefixLengthsPsr4 = array ( 'S' => array ( + 'Symfony\\Polyfill\\Php80\\' => 23, + 'Symfony\\Polyfill\\Php73\\' => 23, 'Symfony\\Polyfill\\Mbstring\\' => 26, - 'Symfony\\Contracts\\' => 18, + 'Symfony\\Contracts\\Service\\' => 26, + 'Symfony\\Contracts\\EventDispatcher\\' => 34, 'Symfony\\Component\\Finder\\' => 25, 'Symfony\\Component\\EventDispatcher\\' => 34, 'Symfony\\Component\\Console\\' => 26, @@ -50,13 +56,25 @@ class ComposerStaticInit80f59a55e693f3d5493bcaaa968d1851 ); public static $prefixDirsPsr4 = array ( + 'Symfony\\Polyfill\\Php80\\' => + array ( + 0 => __DIR__ . '/..' . '/symfony/polyfill-php80', + ), + 'Symfony\\Polyfill\\Php73\\' => + array ( + 0 => __DIR__ . '/..' . '/symfony/polyfill-php73', + ), 'Symfony\\Polyfill\\Mbstring\\' => array ( 0 => __DIR__ . '/..' . '/symfony/polyfill-mbstring', ), - 'Symfony\\Contracts\\' => + 'Symfony\\Contracts\\Service\\' => array ( - 0 => __DIR__ . '/..' . '/symfony/contracts', + 0 => __DIR__ . '/..' . '/symfony/service-contracts', + ), + 'Symfony\\Contracts\\EventDispatcher\\' => + array ( + 0 => __DIR__ . '/..' . '/symfony/event-dispatcher-contracts', ), 'Symfony\\Component\\Finder\\' => array ( @@ -152,7 +170,9 @@ class ComposerStaticInit80f59a55e693f3d5493bcaaa968d1851 ); public static $classMap = array ( + 'Attribute' => __DIR__ . '/..' . '/symfony/polyfill-php80/Resources/stubs/Attribute.php', 'Base32\\Base32' => __DIR__ . '/..' . '/christian-riesen/base32/src/Base32.php', + 'Base32\\Base32Hex' => __DIR__ . '/..' . '/christian-riesen/base32/src/Base32Hex.php', 'Composer\\InstalledVersions' => __DIR__ . '/..' . '/composer/InstalledVersions.php', 'Eluceo\\iCal\\Component' => __DIR__ . '/..' . '/eluceo/ical/src/Component.php', 'Eluceo\\iCal\\Component\\Alarm' => __DIR__ . '/..' . '/eluceo/ical/src/Component/Alarm.php', @@ -182,6 +202,7 @@ class ComposerStaticInit80f59a55e693f3d5493bcaaa968d1851 'Gregwar\\Captcha\\ImageFileHandler' => __DIR__ . '/..' . '/gregwar/captcha/src/Gregwar/Captcha/ImageFileHandler.php', 'Gregwar\\Captcha\\PhraseBuilder' => __DIR__ . '/..' . '/gregwar/captcha/src/Gregwar/Captcha/PhraseBuilder.php', 'Gregwar\\Captcha\\PhraseBuilderInterface' => __DIR__ . '/..' . '/gregwar/captcha/src/Gregwar/Captcha/PhraseBuilderInterface.php', + 'JsonException' => __DIR__ . '/..' . '/symfony/polyfill-php73/Resources/stubs/JsonException.php', 'JsonRPC\\Client' => __DIR__ . '/../..' . '/libs/jsonrpc/src/JsonRPC/Client.php', 'JsonRPC\\Exception\\AccessDeniedException' => __DIR__ . '/../..' . '/libs/jsonrpc/src/JsonRPC/Exception/AccessDeniedException.php', 'JsonRPC\\Exception\\AuthenticationFailureException' => __DIR__ . '/../..' . '/libs/jsonrpc/src/JsonRPC/Exception/AuthenticationFailureException.php', @@ -228,6 +249,7 @@ class ComposerStaticInit80f59a55e693f3d5493bcaaa968d1851 'Kanboard\\Action\\TaskAssignCurrentUser' => __DIR__ . '/../..' . '/app/Action/TaskAssignCurrentUser.php', 'Kanboard\\Action\\TaskAssignCurrentUserColumn' => __DIR__ . '/../..' . '/app/Action/TaskAssignCurrentUserColumn.php', 'Kanboard\\Action\\TaskAssignDueDateOnCreation' => __DIR__ . '/../..' . '/app/Action/TaskAssignDueDateOnCreation.php', + 'Kanboard\\Action\\TaskAssignDueDateOnMoveColumn' => __DIR__ . '/../..' . '/app/Action/TaskAssignDueDateOnMoveColumn.php', 'Kanboard\\Action\\TaskAssignPrioritySwimlane' => __DIR__ . '/../..' . '/app/Action/TaskAssignPrioritySwimlane.php', 'Kanboard\\Action\\TaskAssignSpecificUser' => __DIR__ . '/../..' . '/app/Action/TaskAssignSpecificUser.php', 'Kanboard\\Action\\TaskAssignUser' => __DIR__ . '/../..' . '/app/Action/TaskAssignUser.php', @@ -948,6 +970,7 @@ class ComposerStaticInit80f59a55e693f3d5493bcaaa968d1851 'SimpleValidator\\Validators\\Range' => __DIR__ . '/../..' . '/libs/SimpleValidator/Validators/Range.php', 'SimpleValidator\\Validators\\Required' => __DIR__ . '/../..' . '/libs/SimpleValidator/Validators/Required.php', 'SimpleValidator\\Validators\\Unique' => __DIR__ . '/../..' . '/libs/SimpleValidator/Validators/Unique.php', + 'Stringable' => __DIR__ . '/..' . '/symfony/polyfill-php80/Resources/stubs/Stringable.php', 'Symfony\\Component\\Console\\Application' => __DIR__ . '/..' . '/symfony/console/Application.php', 'Symfony\\Component\\Console\\CommandLoader\\CommandLoaderInterface' => __DIR__ . '/..' . '/symfony/console/CommandLoader/CommandLoaderInterface.php', 'Symfony\\Component\\Console\\CommandLoader\\ContainerCommandLoader' => __DIR__ . '/..' . '/symfony/console/CommandLoader/ContainerCommandLoader.php', @@ -975,6 +998,7 @@ class ComposerStaticInit80f59a55e693f3d5493bcaaa968d1851 'Symfony\\Component\\Console\\Exception\\InvalidArgumentException' => __DIR__ . '/..' . '/symfony/console/Exception/InvalidArgumentException.php', 'Symfony\\Component\\Console\\Exception\\InvalidOptionException' => __DIR__ . '/..' . '/symfony/console/Exception/InvalidOptionException.php', 'Symfony\\Component\\Console\\Exception\\LogicException' => __DIR__ . '/..' . '/symfony/console/Exception/LogicException.php', + 'Symfony\\Component\\Console\\Exception\\MissingInputException' => __DIR__ . '/..' . '/symfony/console/Exception/MissingInputException.php', 'Symfony\\Component\\Console\\Exception\\NamespaceNotFoundException' => __DIR__ . '/..' . '/symfony/console/Exception/NamespaceNotFoundException.php', 'Symfony\\Component\\Console\\Exception\\RuntimeException' => __DIR__ . '/..' . '/symfony/console/Exception/RuntimeException.php', 'Symfony\\Component\\Console\\Formatter\\OutputFormatter' => __DIR__ . '/..' . '/symfony/console/Formatter/OutputFormatter.php', @@ -985,6 +1009,7 @@ class ComposerStaticInit80f59a55e693f3d5493bcaaa968d1851 'Symfony\\Component\\Console\\Formatter\\WrappableOutputFormatterInterface' => __DIR__ . '/..' . '/symfony/console/Formatter/WrappableOutputFormatterInterface.php', 'Symfony\\Component\\Console\\Helper\\DebugFormatterHelper' => __DIR__ . '/..' . '/symfony/console/Helper/DebugFormatterHelper.php', 'Symfony\\Component\\Console\\Helper\\DescriptorHelper' => __DIR__ . '/..' . '/symfony/console/Helper/DescriptorHelper.php', + 'Symfony\\Component\\Console\\Helper\\Dumper' => __DIR__ . '/..' . '/symfony/console/Helper/Dumper.php', 'Symfony\\Component\\Console\\Helper\\FormatterHelper' => __DIR__ . '/..' . '/symfony/console/Helper/FormatterHelper.php', 'Symfony\\Component\\Console\\Helper\\Helper' => __DIR__ . '/..' . '/symfony/console/Helper/Helper.php', 'Symfony\\Component\\Console\\Helper\\HelperInterface' => __DIR__ . '/..' . '/symfony/console/Helper/HelperInterface.php', @@ -1019,6 +1044,7 @@ class ComposerStaticInit80f59a55e693f3d5493bcaaa968d1851 'Symfony\\Component\\Console\\Output\\Output' => __DIR__ . '/..' . '/symfony/console/Output/Output.php', 'Symfony\\Component\\Console\\Output\\OutputInterface' => __DIR__ . '/..' . '/symfony/console/Output/OutputInterface.php', 'Symfony\\Component\\Console\\Output\\StreamOutput' => __DIR__ . '/..' . '/symfony/console/Output/StreamOutput.php', + 'Symfony\\Component\\Console\\Output\\TrimmedBufferOutput' => __DIR__ . '/..' . '/symfony/console/Output/TrimmedBufferOutput.php', 'Symfony\\Component\\Console\\Question\\ChoiceQuestion' => __DIR__ . '/..' . '/symfony/console/Question/ChoiceQuestion.php', 'Symfony\\Component\\Console\\Question\\ConfirmationQuestion' => __DIR__ . '/..' . '/symfony/console/Question/ConfirmationQuestion.php', 'Symfony\\Component\\Console\\Question\\Question' => __DIR__ . '/..' . '/symfony/console/Question/Question.php', @@ -1029,10 +1055,10 @@ class ComposerStaticInit80f59a55e693f3d5493bcaaa968d1851 'Symfony\\Component\\Console\\Tester\\ApplicationTester' => __DIR__ . '/..' . '/symfony/console/Tester/ApplicationTester.php', 'Symfony\\Component\\Console\\Tester\\CommandTester' => __DIR__ . '/..' . '/symfony/console/Tester/CommandTester.php', 'Symfony\\Component\\Console\\Tester\\TesterTrait' => __DIR__ . '/..' . '/symfony/console/Tester/TesterTrait.php', - 'Symfony\\Component\\EventDispatcher\\ContainerAwareEventDispatcher' => __DIR__ . '/..' . '/symfony/event-dispatcher/ContainerAwareEventDispatcher.php', 'Symfony\\Component\\EventDispatcher\\Debug\\TraceableEventDispatcher' => __DIR__ . '/..' . '/symfony/event-dispatcher/Debug/TraceableEventDispatcher.php', 'Symfony\\Component\\EventDispatcher\\Debug\\TraceableEventDispatcherInterface' => __DIR__ . '/..' . '/symfony/event-dispatcher/Debug/TraceableEventDispatcherInterface.php', 'Symfony\\Component\\EventDispatcher\\Debug\\WrappedListener' => __DIR__ . '/..' . '/symfony/event-dispatcher/Debug/WrappedListener.php', + 'Symfony\\Component\\EventDispatcher\\DependencyInjection\\AddEventAliasesPass' => __DIR__ . '/..' . '/symfony/event-dispatcher/DependencyInjection/AddEventAliasesPass.php', 'Symfony\\Component\\EventDispatcher\\DependencyInjection\\RegisterListenersPass' => __DIR__ . '/..' . '/symfony/event-dispatcher/DependencyInjection/RegisterListenersPass.php', 'Symfony\\Component\\EventDispatcher\\Event' => __DIR__ . '/..' . '/symfony/event-dispatcher/Event.php', 'Symfony\\Component\\EventDispatcher\\EventDispatcher' => __DIR__ . '/..' . '/symfony/event-dispatcher/EventDispatcher.php', @@ -1040,6 +1066,8 @@ class ComposerStaticInit80f59a55e693f3d5493bcaaa968d1851 'Symfony\\Component\\EventDispatcher\\EventSubscriberInterface' => __DIR__ . '/..' . '/symfony/event-dispatcher/EventSubscriberInterface.php', 'Symfony\\Component\\EventDispatcher\\GenericEvent' => __DIR__ . '/..' . '/symfony/event-dispatcher/GenericEvent.php', 'Symfony\\Component\\EventDispatcher\\ImmutableEventDispatcher' => __DIR__ . '/..' . '/symfony/event-dispatcher/ImmutableEventDispatcher.php', + 'Symfony\\Component\\EventDispatcher\\LegacyEventDispatcherProxy' => __DIR__ . '/..' . '/symfony/event-dispatcher/LegacyEventDispatcherProxy.php', + 'Symfony\\Component\\EventDispatcher\\LegacyEventProxy' => __DIR__ . '/..' . '/symfony/event-dispatcher/LegacyEventProxy.php', 'Symfony\\Component\\Finder\\Comparator\\Comparator' => __DIR__ . '/..' . '/symfony/finder/Comparator/Comparator.php', 'Symfony\\Component\\Finder\\Comparator\\DateComparator' => __DIR__ . '/..' . '/symfony/finder/Comparator/DateComparator.php', 'Symfony\\Component\\Finder\\Comparator\\NumberComparator' => __DIR__ . '/..' . '/symfony/finder/Comparator/NumberComparator.php', @@ -1055,44 +1083,29 @@ class ComposerStaticInit80f59a55e693f3d5493bcaaa968d1851 'Symfony\\Component\\Finder\\Iterator\\FileTypeFilterIterator' => __DIR__ . '/..' . '/symfony/finder/Iterator/FileTypeFilterIterator.php', 'Symfony\\Component\\Finder\\Iterator\\FilecontentFilterIterator' => __DIR__ . '/..' . '/symfony/finder/Iterator/FilecontentFilterIterator.php', 'Symfony\\Component\\Finder\\Iterator\\FilenameFilterIterator' => __DIR__ . '/..' . '/symfony/finder/Iterator/FilenameFilterIterator.php', + 'Symfony\\Component\\Finder\\Iterator\\LazyIterator' => __DIR__ . '/..' . '/symfony/finder/Iterator/LazyIterator.php', 'Symfony\\Component\\Finder\\Iterator\\MultiplePcreFilterIterator' => __DIR__ . '/..' . '/symfony/finder/Iterator/MultiplePcreFilterIterator.php', 'Symfony\\Component\\Finder\\Iterator\\PathFilterIterator' => __DIR__ . '/..' . '/symfony/finder/Iterator/PathFilterIterator.php', 'Symfony\\Component\\Finder\\Iterator\\RecursiveDirectoryIterator' => __DIR__ . '/..' . '/symfony/finder/Iterator/RecursiveDirectoryIterator.php', 'Symfony\\Component\\Finder\\Iterator\\SizeRangeFilterIterator' => __DIR__ . '/..' . '/symfony/finder/Iterator/SizeRangeFilterIterator.php', 'Symfony\\Component\\Finder\\Iterator\\SortableIterator' => __DIR__ . '/..' . '/symfony/finder/Iterator/SortableIterator.php', + 'Symfony\\Component\\Finder\\Iterator\\VcsIgnoredFilterIterator' => __DIR__ . '/..' . '/symfony/finder/Iterator/VcsIgnoredFilterIterator.php', 'Symfony\\Component\\Finder\\SplFileInfo' => __DIR__ . '/..' . '/symfony/finder/SplFileInfo.php', - 'Symfony\\Contracts\\Cache\\CacheInterface' => __DIR__ . '/..' . '/symfony/contracts/Cache/CacheInterface.php', - 'Symfony\\Contracts\\Cache\\CacheTrait' => __DIR__ . '/..' . '/symfony/contracts/Cache/CacheTrait.php', - 'Symfony\\Contracts\\Cache\\CallbackInterface' => __DIR__ . '/..' . '/symfony/contracts/Cache/CallbackInterface.php', - 'Symfony\\Contracts\\Cache\\ItemInterface' => __DIR__ . '/..' . '/symfony/contracts/Cache/ItemInterface.php', - 'Symfony\\Contracts\\Cache\\TagAwareCacheInterface' => __DIR__ . '/..' . '/symfony/contracts/Cache/TagAwareCacheInterface.php', - 'Symfony\\Contracts\\EventDispatcher\\Event' => __DIR__ . '/..' . '/symfony/contracts/EventDispatcher/Event.php', - 'Symfony\\Contracts\\EventDispatcher\\EventDispatcherInterface' => __DIR__ . '/..' . '/symfony/contracts/EventDispatcher/EventDispatcherInterface.php', - 'Symfony\\Contracts\\HttpClient\\ChunkInterface' => __DIR__ . '/..' . '/symfony/contracts/HttpClient/ChunkInterface.php', - 'Symfony\\Contracts\\HttpClient\\Exception\\ClientExceptionInterface' => __DIR__ . '/..' . '/symfony/contracts/HttpClient/Exception/ClientExceptionInterface.php', - 'Symfony\\Contracts\\HttpClient\\Exception\\ExceptionInterface' => __DIR__ . '/..' . '/symfony/contracts/HttpClient/Exception/ExceptionInterface.php', - 'Symfony\\Contracts\\HttpClient\\Exception\\HttpExceptionInterface' => __DIR__ . '/..' . '/symfony/contracts/HttpClient/Exception/HttpExceptionInterface.php', - 'Symfony\\Contracts\\HttpClient\\Exception\\RedirectionExceptionInterface' => __DIR__ . '/..' . '/symfony/contracts/HttpClient/Exception/RedirectionExceptionInterface.php', - 'Symfony\\Contracts\\HttpClient\\Exception\\ServerExceptionInterface' => __DIR__ . '/..' . '/symfony/contracts/HttpClient/Exception/ServerExceptionInterface.php', - 'Symfony\\Contracts\\HttpClient\\Exception\\TransportExceptionInterface' => __DIR__ . '/..' . '/symfony/contracts/HttpClient/Exception/TransportExceptionInterface.php', - 'Symfony\\Contracts\\HttpClient\\HttpClientInterface' => __DIR__ . '/..' . '/symfony/contracts/HttpClient/HttpClientInterface.php', - 'Symfony\\Contracts\\HttpClient\\ResponseInterface' => __DIR__ . '/..' . '/symfony/contracts/HttpClient/ResponseInterface.php', - 'Symfony\\Contracts\\HttpClient\\ResponseStreamInterface' => __DIR__ . '/..' . '/symfony/contracts/HttpClient/ResponseStreamInterface.php', - 'Symfony\\Contracts\\HttpClient\\Test\\HttpClientTestCase' => __DIR__ . '/..' . '/symfony/contracts/HttpClient/Test/HttpClientTestCase.php', - 'Symfony\\Contracts\\HttpClient\\Test\\TestHttpServer' => __DIR__ . '/..' . '/symfony/contracts/HttpClient/Test/TestHttpServer.php', - 'Symfony\\Contracts\\Service\\ResetInterface' => __DIR__ . '/..' . '/symfony/contracts/Service/ResetInterface.php', - 'Symfony\\Contracts\\Service\\ServiceLocatorTrait' => __DIR__ . '/..' . '/symfony/contracts/Service/ServiceLocatorTrait.php', - 'Symfony\\Contracts\\Service\\ServiceProviderInterface' => __DIR__ . '/..' . '/symfony/contracts/Service/ServiceProviderInterface.php', - 'Symfony\\Contracts\\Service\\ServiceSubscriberInterface' => __DIR__ . '/..' . '/symfony/contracts/Service/ServiceSubscriberInterface.php', - 'Symfony\\Contracts\\Service\\ServiceSubscriberTrait' => __DIR__ . '/..' . '/symfony/contracts/Service/ServiceSubscriberTrait.php', - 'Symfony\\Contracts\\Service\\Test\\ServiceLocatorTest' => __DIR__ . '/..' . '/symfony/contracts/Service/Test/ServiceLocatorTest.php', - 'Symfony\\Contracts\\Tests\\Cache\\CacheTraitTest' => __DIR__ . '/..' . '/symfony/contracts/Tests/Cache/CacheTraitTest.php', - 'Symfony\\Contracts\\Tests\\Service\\ServiceSubscriberTraitTest' => __DIR__ . '/..' . '/symfony/contracts/Tests/Service/ServiceSubscriberTraitTest.php', - 'Symfony\\Contracts\\Translation\\LocaleAwareInterface' => __DIR__ . '/..' . '/symfony/contracts/Translation/LocaleAwareInterface.php', - 'Symfony\\Contracts\\Translation\\Test\\TranslatorTest' => __DIR__ . '/..' . '/symfony/contracts/Translation/Test/TranslatorTest.php', - 'Symfony\\Contracts\\Translation\\TranslatorInterface' => __DIR__ . '/..' . '/symfony/contracts/Translation/TranslatorInterface.php', - 'Symfony\\Contracts\\Translation\\TranslatorTrait' => __DIR__ . '/..' . '/symfony/contracts/Translation/TranslatorTrait.php', + 'Symfony\\Contracts\\EventDispatcher\\Event' => __DIR__ . '/..' . '/symfony/event-dispatcher-contracts/Event.php', + 'Symfony\\Contracts\\EventDispatcher\\EventDispatcherInterface' => __DIR__ . '/..' . '/symfony/event-dispatcher-contracts/EventDispatcherInterface.php', + 'Symfony\\Contracts\\Service\\Attribute\\Required' => __DIR__ . '/..' . '/symfony/service-contracts/Attribute/Required.php', + 'Symfony\\Contracts\\Service\\Attribute\\SubscribedService' => __DIR__ . '/..' . '/symfony/service-contracts/Attribute/SubscribedService.php', + 'Symfony\\Contracts\\Service\\ResetInterface' => __DIR__ . '/..' . '/symfony/service-contracts/ResetInterface.php', + 'Symfony\\Contracts\\Service\\ServiceLocatorTrait' => __DIR__ . '/..' . '/symfony/service-contracts/ServiceLocatorTrait.php', + 'Symfony\\Contracts\\Service\\ServiceProviderInterface' => __DIR__ . '/..' . '/symfony/service-contracts/ServiceProviderInterface.php', + 'Symfony\\Contracts\\Service\\ServiceSubscriberInterface' => __DIR__ . '/..' . '/symfony/service-contracts/ServiceSubscriberInterface.php', + 'Symfony\\Contracts\\Service\\ServiceSubscriberTrait' => __DIR__ . '/..' . '/symfony/service-contracts/ServiceSubscriberTrait.php', + 'Symfony\\Contracts\\Service\\Test\\ServiceLocatorTest' => __DIR__ . '/..' . '/symfony/service-contracts/Test/ServiceLocatorTest.php', 'Symfony\\Polyfill\\Mbstring\\Mbstring' => __DIR__ . '/..' . '/symfony/polyfill-mbstring/Mbstring.php', + 'Symfony\\Polyfill\\Php73\\Php73' => __DIR__ . '/..' . '/symfony/polyfill-php73/Php73.php', + 'Symfony\\Polyfill\\Php80\\Php80' => __DIR__ . '/..' . '/symfony/polyfill-php80/Php80.php', + 'UnhandledMatchError' => __DIR__ . '/..' . '/symfony/polyfill-php80/Resources/stubs/UnhandledMatchError.php', + 'ValueError' => __DIR__ . '/..' . '/symfony/polyfill-php80/Resources/stubs/ValueError.php', ); public static function getInitializer(ClassLoader $loader) diff --git a/vendor/composer/installed.json b/vendor/composer/installed.json index 4534fa72a..d7a87e922 100644 --- a/vendor/composer/installed.json +++ b/vendor/composer/installed.json @@ -2,32 +2,32 @@ "packages": [ { "name": "christian-riesen/base32", - "version": "1.3.2", - "version_normalized": "1.3.2.0", + "version": "1.6.0", + "version_normalized": "1.6.0.0", "source": { "type": "git", "url": "https://github.com/ChristianRiesen/base32.git", - "reference": "80ff0e3b2124e61b4b39e2535709452f70bff367" + "reference": "2e82dab3baa008e24a505649b0d583c31d31e894" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/ChristianRiesen/base32/zipball/80ff0e3b2124e61b4b39e2535709452f70bff367", - "reference": "80ff0e3b2124e61b4b39e2535709452f70bff367", + "url": "https://api.github.com/repos/ChristianRiesen/base32/zipball/2e82dab3baa008e24a505649b0d583c31d31e894", + "reference": "2e82dab3baa008e24a505649b0d583c31d31e894", "shasum": "" }, "require": { - "php": ">=5.3" + "php": "^7.2 || ^8.0" }, "require-dev": { - "php": ">=5.6", - "phpunit/phpunit": "^5.0", - "satooshi/php-coveralls": "^1.0" + "friendsofphp/php-cs-fixer": "^2.17", + "phpstan/phpstan": "^0.12", + "phpunit/phpunit": "^8.5.13 || ^9.5" }, - "time": "2018-11-02T09:03:50+00:00", + "time": "2021-02-26T10:19:33+00:00", "type": "library", "extra": { "branch-alias": { - "dev-master": "1.1.x-dev" + "dev-master": "1.x-dev" } }, "installation-source": "dist", @@ -56,6 +56,10 @@ "encode", "rfc4648" ], + "support": { + "issues": "https://github.com/ChristianRiesen/base32/issues", + "source": "https://github.com/ChristianRiesen/base32/tree/1.6.0" + }, "install-path": "../christian-riesen/base32" }, { @@ -326,29 +330,24 @@ }, { "name": "psr/container", - "version": "2.0.1", - "version_normalized": "2.0.1.0", + "version": "1.1.2", + "version_normalized": "1.1.2.0", "source": { "type": "git", "url": "https://github.com/php-fig/container.git", - "reference": "2ae37329ee82f91efadc282cc2d527fd6065a5ef" + "reference": "513e0666f7216c7459170d56df27dfcefe1689ea" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/container/zipball/2ae37329ee82f91efadc282cc2d527fd6065a5ef", - "reference": "2ae37329ee82f91efadc282cc2d527fd6065a5ef", + "url": "https://api.github.com/repos/php-fig/container/zipball/513e0666f7216c7459170d56df27dfcefe1689ea", + "reference": "513e0666f7216c7459170d56df27dfcefe1689ea", "shasum": "" }, "require": { - "php": ">=7.2.0" + "php": ">=7.4.0" }, - "time": "2021-03-24T13:40:57+00:00", + "time": "2021-11-05T16:50:12+00:00", "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.0.x-dev" - } - }, "installation-source": "dist", "autoload": { "psr-4": { @@ -374,6 +373,10 @@ "container-interop", "psr" ], + "support": { + "issues": "https://github.com/php-fig/container/issues", + "source": "https://github.com/php-fig/container/tree/1.1.2" + }, "install-path": "../psr/container" }, { @@ -481,42 +484,53 @@ "mail", "mailer" ], + "support": { + "issues": "https://github.com/swiftmailer/swiftmailer/issues", + "source": "https://github.com/swiftmailer/swiftmailer/tree/v5.4.8" + }, + "abandoned": "symfony/mailer", "install-path": "../swiftmailer/swiftmailer" }, { "name": "symfony/console", - "version": "v4.2.12", - "version_normalized": "4.2.12.0", + "version": "v4.4.37", + "version_normalized": "4.4.37.0", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "fc2e274aade6567a750551942094b2145ade9b6c" + "reference": "0259f01dbf9d77badddbbf4c2abb681f24c9cac6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/fc2e274aade6567a750551942094b2145ade9b6c", - "reference": "fc2e274aade6567a750551942094b2145ade9b6c", + "url": "https://api.github.com/repos/symfony/console/zipball/0259f01dbf9d77badddbbf4c2abb681f24c9cac6", + "reference": "0259f01dbf9d77badddbbf4c2abb681f24c9cac6", "shasum": "" }, "require": { - "php": "^7.1.3", - "symfony/contracts": "^1.0", - "symfony/polyfill-mbstring": "~1.0" + "php": ">=7.1.3", + "symfony/polyfill-mbstring": "~1.0", + "symfony/polyfill-php73": "^1.8", + "symfony/polyfill-php80": "^1.16", + "symfony/service-contracts": "^1.1|^2" }, "conflict": { + "psr/log": ">=3", "symfony/dependency-injection": "<3.4", + "symfony/event-dispatcher": "<4.3|>=5", + "symfony/lock": "<4.4", "symfony/process": "<3.3" }, "provide": { - "psr/log-implementation": "1.0" + "psr/log-implementation": "1.0|2.0" }, "require-dev": { - "psr/log": "~1.0", - "symfony/config": "~3.4|~4.0", - "symfony/dependency-injection": "~3.4|~4.0", - "symfony/event-dispatcher": "~3.4|~4.0", - "symfony/lock": "~3.4|~4.0", - "symfony/process": "~3.4|~4.0" + "psr/log": "^1|^2", + "symfony/config": "^3.4|^4.0|^5.0", + "symfony/dependency-injection": "^3.4|^4.0|^5.0", + "symfony/event-dispatcher": "^4.3", + "symfony/lock": "^4.4|^5.0", + "symfony/process": "^3.4|^4.0|^5.0", + "symfony/var-dumper": "^4.3|^5.0" }, "suggest": { "psr/log": "For using the console logger", @@ -524,13 +538,8 @@ "symfony/lock": "", "symfony/process": "" }, - "time": "2019-07-24T17:13:20+00:00", + "time": "2022-01-26T16:15:26+00:00", "type": "library", - "extra": { - "branch-alias": { - "dev-master": "4.2-dev" - } - }, "installation-source": "dist", "autoload": { "psr-4": { @@ -554,64 +563,60 @@ "homepage": "https://symfony.com/contributors" } ], - "description": "Symfony Console Component", + "description": "Eases the creation of beautiful and testable command line interfaces", "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/console/tree/v4.4.37" + }, + "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" + } + ], "install-path": "../symfony/console" }, { - "name": "symfony/contracts", - "version": "v1.1.3", - "version_normalized": "1.1.3.0", + "name": "symfony/deprecation-contracts", + "version": "v2.5.0", + "version_normalized": "2.5.0.0", "source": { "type": "git", - "url": "https://github.com/symfony/contracts.git", - "reference": "2d19b12caccbd80cf0c85624dc87b7021a0df1d5" + "url": "https://github.com/symfony/deprecation-contracts.git", + "reference": "6f981ee24cf69ee7ce9736146d1c57c2780598a8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/contracts/zipball/2d19b12caccbd80cf0c85624dc87b7021a0df1d5", - "reference": "2d19b12caccbd80cf0c85624dc87b7021a0df1d5", + "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/6f981ee24cf69ee7ce9736146d1c57c2780598a8", + "reference": "6f981ee24cf69ee7ce9736146d1c57c2780598a8", "shasum": "" }, "require": { - "php": "^7.1.3" + "php": ">=7.1" }, - "replace": { - "symfony/cache-contracts": "self.version", - "symfony/event-dispatcher-contracts": "self.version", - "symfony/http-client-contracts": "self.version", - "symfony/service-contracts": "self.version", - "symfony/translation-contracts": "self.version" - }, - "require-dev": { - "psr/cache": "^1.0", - "psr/container": "^1.0", - "symfony/polyfill-intl-idn": "^1.10" - }, - "suggest": { - "psr/cache": "When using the Cache contracts", - "psr/container": "When using the Service contracts", - "psr/event-dispatcher": "When using the EventDispatcher contracts", - "symfony/cache-implementation": "", - "symfony/event-dispatcher-implementation": "", - "symfony/http-client-implementation": "", - "symfony/service-implementation": "", - "symfony/translation-implementation": "" - }, - "time": "2019-06-05T13:28:50+00:00", + "time": "2021-07-12T14:48:14+00:00", "type": "library", "extra": { "branch-alias": { - "dev-master": "1.1-dev" + "dev-main": "2.5-dev" + }, + "thanks": { + "name": "symfony/contracts", + "url": "https://github.com/symfony/contracts" } }, "installation-source": "dist", "autoload": { - "psr-4": { - "Symfony\\Contracts\\": "" - }, - "exclude-from-classmap": [ - "**/Tests/" + "files": [ + "function.php" ] }, "notification-url": "https://packagist.org/downloads/", @@ -628,57 +633,70 @@ "homepage": "https://symfony.com/contributors" } ], - "description": "A set of abstractions extracted out of the Symfony components", + "description": "A generic function and convention to trigger deprecation notices", "homepage": "https://symfony.com", - "keywords": [ - "abstractions", - "contracts", - "decoupling", - "interfaces", - "interoperability", - "standards" + "support": { + "source": "https://github.com/symfony/deprecation-contracts/tree/v2.5.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" + } ], - "install-path": "../symfony/contracts" + "install-path": "../symfony/deprecation-contracts" }, { "name": "symfony/event-dispatcher", - "version": "v3.4.2", - "version_normalized": "3.4.2.0", + "version": "v4.4.37", + "version_normalized": "4.4.37.0", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher.git", - "reference": "b869cbf8a15ca6261689de2c28a7d7f2d0706835" + "reference": "3ccfcfb96ecce1217d7b0875a0736976bc6e63dc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/b869cbf8a15ca6261689de2c28a7d7f2d0706835", - "reference": "b869cbf8a15ca6261689de2c28a7d7f2d0706835", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/3ccfcfb96ecce1217d7b0875a0736976bc6e63dc", + "reference": "3ccfcfb96ecce1217d7b0875a0736976bc6e63dc", "shasum": "" }, "require": { - "php": "^5.5.9|>=7.0.8" + "php": ">=7.1.3", + "symfony/event-dispatcher-contracts": "^1.1", + "symfony/polyfill-php80": "^1.16" }, "conflict": { - "symfony/dependency-injection": "<3.3" + "symfony/dependency-injection": "<3.4" + }, + "provide": { + "psr/event-dispatcher-implementation": "1.0", + "symfony/event-dispatcher-implementation": "1.1" }, "require-dev": { - "psr/log": "~1.0", - "symfony/config": "~2.8|~3.0|~4.0", - "symfony/dependency-injection": "~3.3|~4.0", - "symfony/expression-language": "~2.8|~3.0|~4.0", - "symfony/stopwatch": "~2.8|~3.0|~4.0" + "psr/log": "^1|^2|^3", + "symfony/config": "^3.4|^4.0|^5.0", + "symfony/dependency-injection": "^3.4|^4.0|^5.0", + "symfony/error-handler": "~3.4|~4.4", + "symfony/expression-language": "^3.4|^4.0|^5.0", + "symfony/http-foundation": "^3.4|^4.0|^5.0", + "symfony/service-contracts": "^1.1|^2", + "symfony/stopwatch": "^3.4|^4.0|^5.0" }, "suggest": { "symfony/dependency-injection": "", "symfony/http-kernel": "" }, - "time": "2017-12-14T19:40:10+00:00", + "time": "2022-01-02T09:41:36+00:00", "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.4-dev" - } - }, "installation-source": "dist", "autoload": { "psr-4": { @@ -702,29 +720,130 @@ "homepage": "https://symfony.com/contributors" } ], - "description": "Symfony EventDispatcher Component", + "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/v4.4.37" + }, + "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" + } + ], "install-path": "../symfony/event-dispatcher" }, { - "name": "symfony/finder", - "version": "v5.2.1", - "version_normalized": "5.2.1.0", + "name": "symfony/event-dispatcher-contracts", + "version": "v1.1.11", + "version_normalized": "1.1.11.0", "source": { "type": "git", - "url": "https://github.com/symfony/finder.git", - "reference": "0b9231a5922fd7287ba5b411893c0ecd2733e5ba" + "url": "https://github.com/symfony/event-dispatcher-contracts.git", + "reference": "01e9a4efac0ee33a05dfdf93b346f62e7d0e998c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/0b9231a5922fd7287ba5b411893c0ecd2733e5ba", - "reference": "0b9231a5922fd7287ba5b411893c0ecd2733e5ba", + "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/01e9a4efac0ee33a05dfdf93b346f62e7d0e998c", + "reference": "01e9a4efac0ee33a05dfdf93b346f62e7d0e998c", "shasum": "" }, "require": { - "php": ">=7.2.5" + "php": ">=7.1.3" }, - "time": "2020-12-08T17:02:38+00:00", + "suggest": { + "psr/event-dispatcher": "", + "symfony/event-dispatcher-implementation": "" + }, + "time": "2021-03-23T15:25:38+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.1-dev" + }, + "thanks": { + "name": "symfony/contracts", + "url": "https://github.com/symfony/contracts" + } + }, + "installation-source": "dist", + "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/v1.1.11" + }, + "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" + } + ], + "install-path": "../symfony/event-dispatcher-contracts" + }, + { + "name": "symfony/finder", + "version": "v5.4.3", + "version_normalized": "5.4.3.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/finder.git", + "reference": "231313534dded84c7ecaa79d14bc5da4ccb69b7d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/finder/zipball/231313534dded84c7ecaa79d14bc5da4ccb69b7d", + "reference": "231313534dded84c7ecaa79d14bc5da4ccb69b7d", + "shasum": "" + }, + "require": { + "php": ">=7.2.5", + "symfony/deprecation-contracts": "^2.1|^3", + "symfony/polyfill-php80": "^1.16" + }, + "time": "2022-01-26T16:34:36+00:00", "type": "library", "installation-source": "dist", "autoload": { @@ -749,8 +868,11 @@ "homepage": "https://symfony.com/contributors" } ], - "description": "Symfony Finder Component", + "description": "Finds files and directories via an intuitive fluent interface", "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/finder/tree/v5.4.3" + }, "funding": [ { "url": "https://symfony.com/sponsor", @@ -769,30 +891,33 @@ }, { "name": "symfony/polyfill-mbstring", - "version": "v1.18.1", - "version_normalized": "1.18.1.0", + "version": "v1.24.0", + "version_normalized": "1.24.0.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "a6977d63bf9a0ad4c65cd352709e230876f9904a" + "reference": "0abb51d2f102e00a4eefcf46ba7fec406d245825" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/a6977d63bf9a0ad4c65cd352709e230876f9904a", - "reference": "a6977d63bf9a0ad4c65cd352709e230876f9904a", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/0abb51d2f102e00a4eefcf46ba7fec406d245825", + "reference": "0abb51d2f102e00a4eefcf46ba7fec406d245825", "shasum": "" }, "require": { - "php": ">=5.3.3" + "php": ">=7.1" + }, + "provide": { + "ext-mbstring": "*" }, "suggest": { "ext-mbstring": "For best performance" }, - "time": "2020-07-14T12:35:20+00:00", + "time": "2021-11-30T18:21:41+00:00", "type": "library", "extra": { "branch-alias": { - "dev-master": "1.18-dev" + "dev-main": "1.23-dev" }, "thanks": { "name": "symfony/polyfill", @@ -831,7 +956,278 @@ "portable", "shim" ], + "support": { + "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.24.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" + } + ], "install-path": "../symfony/polyfill-mbstring" + }, + { + "name": "symfony/polyfill-php73", + "version": "v1.24.0", + "version_normalized": "1.24.0.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-php73.git", + "reference": "cc5db0e22b3cb4111010e48785a97f670b350ca5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-php73/zipball/cc5db0e22b3cb4111010e48785a97f670b350ca5", + "reference": "cc5db0e22b3cb4111010e48785a97f670b350ca5", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "time": "2021-06-05T21:20:04+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.23-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "Symfony\\Polyfill\\Php73\\": "" + }, + "files": [ + "bootstrap.php" + ], + "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 7.3+ features to lower PHP versions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-php73/tree/v1.24.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" + } + ], + "install-path": "../symfony/polyfill-php73" + }, + { + "name": "symfony/polyfill-php80", + "version": "v1.24.0", + "version_normalized": "1.24.0.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-php80.git", + "reference": "57b712b08eddb97c762a8caa32c84e037892d2e9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/57b712b08eddb97c762a8caa32c84e037892d2e9", + "reference": "57b712b08eddb97c762a8caa32c84e037892d2e9", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "time": "2021-09-13T13:58:33+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.23-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "Symfony\\Polyfill\\Php80\\": "" + }, + "files": [ + "bootstrap.php" + ], + "classmap": [ + "Resources/stubs" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Ion Bazan", + "email": "ion.bazan@gmail.com" + }, + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill backporting some PHP 8.0+ features to lower PHP versions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-php80/tree/v1.24.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" + } + ], + "install-path": "../symfony/polyfill-php80" + }, + { + "name": "symfony/service-contracts", + "version": "v2.5.0", + "version_normalized": "2.5.0.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/service-contracts.git", + "reference": "1ab11b933cd6bc5464b08e81e2c5b07dec58b0fc" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/service-contracts/zipball/1ab11b933cd6bc5464b08e81e2c5b07dec58b0fc", + "reference": "1ab11b933cd6bc5464b08e81e2c5b07dec58b0fc", + "shasum": "" + }, + "require": { + "php": ">=7.2.5", + "psr/container": "^1.1", + "symfony/deprecation-contracts": "^2.1" + }, + "conflict": { + "ext-psr": "<1.1|>=2" + }, + "suggest": { + "symfony/service-implementation": "" + }, + "time": "2021-11-04T16:48:04+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "2.5-dev" + }, + "thanks": { + "name": "symfony/contracts", + "url": "https://github.com/symfony/contracts" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "Symfony\\Contracts\\Service\\": "" + } + }, + "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/v2.5.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" + } + ], + "install-path": "../symfony/service-contracts" } ], "dev": false, diff --git a/vendor/composer/installed.php b/vendor/composer/installed.php index 5e1329301..87f1b3e37 100644 --- a/vendor/composer/installed.php +++ b/vendor/composer/installed.php @@ -5,18 +5,18 @@ 'type' => 'project', 'install_path' => __DIR__ . '/../../', 'aliases' => array(), - 'reference' => '3e139ab6f4989ebd3963229be37166123c528b3a', + 'reference' => '14cdaa07bd0dad30903e4136e85124e1435c1f93', 'name' => 'kanboard/kanboard', 'dev' => false, ), 'versions' => array( 'christian-riesen/base32' => array( - 'pretty_version' => '1.3.2', - 'version' => '1.3.2.0', + 'pretty_version' => '1.6.0', + 'version' => '1.6.0.0', 'type' => 'library', 'install_path' => __DIR__ . '/../christian-riesen/base32', 'aliases' => array(), - 'reference' => '80ff0e3b2124e61b4b39e2535709452f70bff367', + 'reference' => '2e82dab3baa008e24a505649b0d583c31d31e894', 'dev_requirement' => false, ), 'christian-riesen/otp' => array( @@ -61,7 +61,7 @@ 'type' => 'project', 'install_path' => __DIR__ . '/../../', 'aliases' => array(), - 'reference' => '3e139ab6f4989ebd3963229be37166123c528b3a', + 'reference' => '14cdaa07bd0dad30903e4136e85124e1435c1f93', 'dev_requirement' => false, ), 'pimple/pimple' => array( @@ -74,14 +74,20 @@ 'dev_requirement' => false, ), 'psr/container' => array( - 'pretty_version' => '2.0.1', - 'version' => '2.0.1.0', + 'pretty_version' => '1.1.2', + 'version' => '1.1.2.0', 'type' => 'library', 'install_path' => __DIR__ . '/../psr/container', 'aliases' => array(), - 'reference' => '2ae37329ee82f91efadc282cc2d527fd6065a5ef', + 'reference' => '513e0666f7216c7459170d56df27dfcefe1689ea', 'dev_requirement' => false, ), + 'psr/event-dispatcher-implementation' => array( + 'dev_requirement' => false, + 'provided' => array( + 0 => '1.0', + ), + ), 'psr/log' => array( 'pretty_version' => '1.1.4', 'version' => '1.1.4.0', @@ -94,7 +100,7 @@ 'psr/log-implementation' => array( 'dev_requirement' => false, 'provided' => array( - 0 => '1.0', + 0 => '1.0|2.0', ), ), 'swiftmailer/swiftmailer' => array( @@ -106,80 +112,92 @@ 'reference' => '9a06dc570a0367850280eefd3f1dc2da45aef517', 'dev_requirement' => false, ), - 'symfony/cache-contracts' => array( - 'dev_requirement' => false, - 'replaced' => array( - 0 => 'v1.1.3', - ), - ), 'symfony/console' => array( - 'pretty_version' => 'v4.2.12', - 'version' => '4.2.12.0', + 'pretty_version' => 'v4.4.37', + 'version' => '4.4.37.0', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/console', 'aliases' => array(), - 'reference' => 'fc2e274aade6567a750551942094b2145ade9b6c', + 'reference' => '0259f01dbf9d77badddbbf4c2abb681f24c9cac6', 'dev_requirement' => false, ), - 'symfony/contracts' => array( - 'pretty_version' => 'v1.1.3', - 'version' => '1.1.3.0', + 'symfony/deprecation-contracts' => array( + 'pretty_version' => 'v2.5.0', + 'version' => '2.5.0.0', 'type' => 'library', - 'install_path' => __DIR__ . '/../symfony/contracts', + 'install_path' => __DIR__ . '/../symfony/deprecation-contracts', 'aliases' => array(), - 'reference' => '2d19b12caccbd80cf0c85624dc87b7021a0df1d5', + 'reference' => '6f981ee24cf69ee7ce9736146d1c57c2780598a8', 'dev_requirement' => false, ), 'symfony/event-dispatcher' => array( - 'pretty_version' => 'v3.4.2', - 'version' => '3.4.2.0', + 'pretty_version' => 'v4.4.37', + 'version' => '4.4.37.0', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/event-dispatcher', 'aliases' => array(), - 'reference' => 'b869cbf8a15ca6261689de2c28a7d7f2d0706835', + 'reference' => '3ccfcfb96ecce1217d7b0875a0736976bc6e63dc', 'dev_requirement' => false, ), 'symfony/event-dispatcher-contracts' => array( + 'pretty_version' => 'v1.1.11', + 'version' => '1.1.11.0', + 'type' => 'library', + 'install_path' => __DIR__ . '/../symfony/event-dispatcher-contracts', + 'aliases' => array(), + 'reference' => '01e9a4efac0ee33a05dfdf93b346f62e7d0e998c', 'dev_requirement' => false, - 'replaced' => array( - 0 => 'v1.1.3', + ), + 'symfony/event-dispatcher-implementation' => array( + 'dev_requirement' => false, + 'provided' => array( + 0 => '1.1', ), ), 'symfony/finder' => array( - 'pretty_version' => 'v5.2.1', - 'version' => '5.2.1.0', + 'pretty_version' => 'v5.4.3', + 'version' => '5.4.3.0', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/finder', 'aliases' => array(), - 'reference' => '0b9231a5922fd7287ba5b411893c0ecd2733e5ba', + 'reference' => '231313534dded84c7ecaa79d14bc5da4ccb69b7d', 'dev_requirement' => false, ), - 'symfony/http-client-contracts' => array( - 'dev_requirement' => false, - 'replaced' => array( - 0 => 'v1.1.3', - ), - ), 'symfony/polyfill-mbstring' => array( - 'pretty_version' => 'v1.18.1', - 'version' => '1.18.1.0', + 'pretty_version' => 'v1.24.0', + 'version' => '1.24.0.0', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/polyfill-mbstring', 'aliases' => array(), - 'reference' => 'a6977d63bf9a0ad4c65cd352709e230876f9904a', + 'reference' => '0abb51d2f102e00a4eefcf46ba7fec406d245825', + 'dev_requirement' => false, + ), + 'symfony/polyfill-php73' => array( + 'pretty_version' => 'v1.24.0', + 'version' => '1.24.0.0', + 'type' => 'library', + 'install_path' => __DIR__ . '/../symfony/polyfill-php73', + 'aliases' => array(), + 'reference' => 'cc5db0e22b3cb4111010e48785a97f670b350ca5', + 'dev_requirement' => false, + ), + 'symfony/polyfill-php80' => array( + 'pretty_version' => 'v1.24.0', + 'version' => '1.24.0.0', + 'type' => 'library', + 'install_path' => __DIR__ . '/../symfony/polyfill-php80', + 'aliases' => array(), + 'reference' => '57b712b08eddb97c762a8caa32c84e037892d2e9', 'dev_requirement' => false, ), 'symfony/service-contracts' => array( + 'pretty_version' => 'v2.5.0', + 'version' => '2.5.0.0', + 'type' => 'library', + 'install_path' => __DIR__ . '/../symfony/service-contracts', + 'aliases' => array(), + 'reference' => '1ab11b933cd6bc5464b08e81e2c5b07dec58b0fc', 'dev_requirement' => false, - 'replaced' => array( - 0 => 'v1.1.3', - ), - ), - 'symfony/translation-contracts' => array( - 'dev_requirement' => false, - 'replaced' => array( - 0 => 'v1.1.3', - ), ), ), ); diff --git a/vendor/composer/platform_check.php b/vendor/composer/platform_check.php index a8b98d5ce..580fa9609 100644 --- a/vendor/composer/platform_check.php +++ b/vendor/composer/platform_check.php @@ -4,8 +4,8 @@ $issues = array(); -if (!(PHP_VERSION_ID >= 70205)) { - $issues[] = 'Your Composer dependencies require a PHP version ">= 7.2.5". You are running ' . PHP_VERSION . '.'; +if (!(PHP_VERSION_ID >= 70400)) { + $issues[] = 'Your Composer dependencies require a PHP version ">= 7.4.0". You are running ' . PHP_VERSION . '.'; } if ($issues) { diff --git a/vendor/psr/container/composer.json b/vendor/psr/container/composer.json index 4bc837ac0..017f41ea6 100644 --- a/vendor/psr/container/composer.json +++ b/vendor/psr/container/composer.json @@ -12,16 +12,11 @@ } ], "require": { - "php": ">=7.2.0" + "php": ">=7.4.0" }, "autoload": { "psr-4": { "Psr\\Container\\": "src/" } - }, - "extra": { - "branch-alias": { - "dev-master": "2.0.x-dev" - } } } diff --git a/vendor/psr/container/src/ContainerExceptionInterface.php b/vendor/psr/container/src/ContainerExceptionInterface.php index cf10b8b4f..0f213f2fe 100644 --- a/vendor/psr/container/src/ContainerExceptionInterface.php +++ b/vendor/psr/container/src/ContainerExceptionInterface.php @@ -2,9 +2,11 @@ namespace Psr\Container; +use Throwable; + /** * Base interface representing a generic exception in a container. */ -interface ContainerExceptionInterface +interface ContainerExceptionInterface extends Throwable { } diff --git a/vendor/psr/container/src/ContainerInterface.php b/vendor/psr/container/src/ContainerInterface.php index b2cad4015..cf8e7fd33 100644 --- a/vendor/psr/container/src/ContainerInterface.php +++ b/vendor/psr/container/src/ContainerInterface.php @@ -32,5 +32,5 @@ interface ContainerInterface * * @return bool */ - public function has(string $id): bool; + public function has(string $id); } diff --git a/vendor/symfony/console/Application.php b/vendor/symfony/console/Application.php index 5c0faa5fe..15d537dac 100644 --- a/vendor/symfony/console/Application.php +++ b/vendor/symfony/console/Application.php @@ -36,14 +36,16 @@ use Symfony\Component\Console\Input\InputAwareInterface; use Symfony\Component\Console\Input\InputDefinition; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; -use Symfony\Component\Console\Input\StreamableInputInterface; use Symfony\Component\Console\Output\ConsoleOutput; use Symfony\Component\Console\Output\ConsoleOutputInterface; use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Style\SymfonyStyle; -use Symfony\Component\Debug\ErrorHandler; +use Symfony\Component\Debug\ErrorHandler as LegacyErrorHandler; use Symfony\Component\Debug\Exception\FatalThrowableError; +use Symfony\Component\ErrorHandler\ErrorHandler; use Symfony\Component\EventDispatcher\EventDispatcherInterface; +use Symfony\Component\EventDispatcher\LegacyEventDispatcherProxy; +use Symfony\Contracts\Service\ResetInterface; /** * An Application is the container for a collection of commands. @@ -60,7 +62,7 @@ use Symfony\Component\EventDispatcher\EventDispatcherInterface; * * @author Fabien Potencier */ -class Application +class Application implements ResetInterface { private $commands = []; private $wantHelps = false; @@ -90,9 +92,12 @@ class Application $this->defaultCommand = 'list'; } + /** + * @final since Symfony 4.3, the type-hint will be updated to the interface from symfony/contracts in 5.0 + */ public function setDispatcher(EventDispatcherInterface $dispatcher) { - $this->dispatcher = $dispatcher; + $this->dispatcher = LegacyEventDispatcherProxy::decorate($dispatcher); } public function setCommandLoader(CommandLoaderInterface $commandLoader) @@ -109,8 +114,10 @@ class Application */ public function run(InputInterface $input = null, OutputInterface $output = null) { - putenv('LINES='.$this->terminal->getHeight()); - putenv('COLUMNS='.$this->terminal->getWidth()); + if (\function_exists('putenv')) { + @putenv('LINES='.$this->terminal->getHeight()); + @putenv('COLUMNS='.$this->terminal->getWidth()); + } if (null === $input) { $input = new ArgvInput(); @@ -120,22 +127,19 @@ class Application $output = new ConsoleOutput(); } - $renderException = function ($e) use ($output) { - if (!$e instanceof \Exception) { - $e = class_exists(FatalThrowableError::class) ? new FatalThrowableError($e) : new \ErrorException($e->getMessage(), $e->getCode(), E_ERROR, $e->getFile(), $e->getLine()); - } + $renderException = function (\Throwable $e) use ($output) { if ($output instanceof ConsoleOutputInterface) { - $this->renderException($e, $output->getErrorOutput()); + $this->renderThrowable($e, $output->getErrorOutput()); } else { - $this->renderException($e, $output); + $this->renderThrowable($e, $output); } }; if ($phpHandler = set_exception_handler($renderException)) { restore_exception_handler(); - if (!\is_array($phpHandler) || !$phpHandler[0] instanceof ErrorHandler) { - $debugHandler = true; - } elseif ($debugHandler = $phpHandler[0]->setExceptionHandler($renderException)) { - $phpHandler[0]->setExceptionHandler($debugHandler); + if (!\is_array($phpHandler) || (!$phpHandler[0] instanceof ErrorHandler && !$phpHandler[0] instanceof LegacyErrorHandler)) { + $errorHandler = true; + } elseif ($errorHandler = $phpHandler[0]->setExceptionHandler($renderException)) { + $phpHandler[0]->setExceptionHandler($errorHandler); } } @@ -167,7 +171,7 @@ class Application restore_exception_handler(); } restore_exception_handler(); - } elseif (!$debugHandler) { + } elseif (!$errorHandler) { $finalHandler = $phpHandler[0]->setExceptionHandler(null); if ($finalHandler !== $renderException) { $phpHandler[0]->setExceptionHandler($finalHandler); @@ -235,7 +239,7 @@ class Application if (!($e instanceof CommandNotFoundException && !$e instanceof NamespaceNotFoundException) || 1 !== \count($alternatives = $e->getAlternatives()) || !$input->isInteractive()) { if (null !== $this->dispatcher) { $event = new ConsoleErrorEvent($input, $output, $e); - $this->dispatcher->dispatch(ConsoleEvents::ERROR, $event); + $this->dispatcher->dispatch($event, ConsoleEvents::ERROR); if (0 === $event->getExitCode()) { return 0; @@ -254,7 +258,7 @@ class Application if (!$style->confirm(sprintf('Do you want to run "%s" instead? ', $alternative), false)) { if (null !== $this->dispatcher) { $event = new ConsoleErrorEvent($input, $output, $e); - $this->dispatcher->dispatch(ConsoleEvents::ERROR, $event); + $this->dispatcher->dispatch($event, ConsoleEvents::ERROR); return $event->getExitCode(); } @@ -272,6 +276,13 @@ class Application return $exitCode; } + /** + * {@inheritdoc} + */ + public function reset() + { + } + public function setHelperSet(HelperSet $helperSet) { $this->helperSet = $helperSet; @@ -468,12 +479,11 @@ class Application if (!$command->isEnabled()) { $command->setApplication(null); - return; + return null; } - if (null === $command->getDefinition()) { - throw new LogicException(sprintf('Command class "%s" is not correctly initialized. You probably forgot to call the parent constructor.', \get_class($command))); - } + // Will throw if the command is not correctly initialized. + $command->getDefinition(); if (!$command->getName()) { throw new LogicException(sprintf('The command defined in "%s" cannot have an empty name.', \get_class($command))); @@ -505,6 +515,11 @@ class Application throw new CommandNotFoundException(sprintf('The command "%s" does not exist.', $name)); } + // When the command has a different name than the one used at the command loader level + if (!isset($this->commands[$name])) { + throw new CommandNotFoundException(sprintf('The "%s" command cannot be found because it is registered under multiple names. Make sure you don\'t set a different name via constructor or "setName()".', $name)); + } + $command = $this->commands[$name]; if ($this->wantHelps) { @@ -544,6 +559,10 @@ class Application { $namespaces = []; foreach ($this->all() as $command) { + if ($command->isHidden()) { + continue; + } + $namespaces = array_merge($namespaces, $this->extractAllNamespaces($command->getName())); foreach ($command->getAliases() as $alias) { @@ -587,7 +606,7 @@ class Application $exact = \in_array($namespace, $namespaces, true); if (\count($namespaces) > 1 && !$exact) { - throw new NamespaceNotFoundException(sprintf("The namespace \"%s\" is ambiguous.\nDid you mean one of these?\n%s", $namespace, $this->getAbbreviationSuggestions(array_values($namespaces))), array_values($namespaces)); + throw new NamespaceNotFoundException(sprintf("The namespace \"%s\" is ambiguous.\nDid you mean one of these?\n%s.", $namespace, $this->getAbbreviationSuggestions(array_values($namespaces))), array_values($namespaces)); } return $exact ? $namespace : reset($namespaces); @@ -619,6 +638,10 @@ class Application } } + if ($this->has($name)) { + return $this->get($name); + } + $allCommands = $this->commandLoader ? array_merge($this->commandLoader->getNames(), array_keys($this->commands)) : array_keys($this->commands); $expr = preg_replace_callback('{([^:]+|)}', function ($matches) { return preg_quote($matches[1]).'[^:]*'; }, $name); $commands = preg_grep('{^'.$expr.'}', $allCommands); @@ -637,6 +660,11 @@ class Application $message = sprintf('Command "%s" is not defined.', $name); if ($alternatives = $this->findAlternatives($name, $allCommands)) { + // remove hidden commands + $alternatives = array_filter($alternatives, function ($name) { + return !$this->get($name)->isHidden(); + }); + if (1 == \count($alternatives)) { $message .= "\n\nDid you mean this?\n "; } else { @@ -645,42 +673,58 @@ class Application $message .= implode("\n ", $alternatives); } - throw new CommandNotFoundException($message, $alternatives); + throw new CommandNotFoundException($message, array_values($alternatives)); } // filter out aliases for commands which are already on the list if (\count($commands) > 1) { $commandList = $this->commandLoader ? array_merge(array_flip($this->commandLoader->getNames()), $this->commands) : $this->commands; - $commands = array_unique(array_filter($commands, function ($nameOrAlias) use ($commandList, $commands, &$aliases) { - $commandName = $commandList[$nameOrAlias] instanceof Command ? $commandList[$nameOrAlias]->getName() : $nameOrAlias; + $commands = array_unique(array_filter($commands, function ($nameOrAlias) use (&$commandList, $commands, &$aliases) { + if (!$commandList[$nameOrAlias] instanceof Command) { + $commandList[$nameOrAlias] = $this->commandLoader->get($nameOrAlias); + } + + $commandName = $commandList[$nameOrAlias]->getName(); + $aliases[$nameOrAlias] = $commandName; return $commandName === $nameOrAlias || !\in_array($commandName, $commands); })); } - $exact = \in_array($name, $commands, true) || isset($aliases[$name]); - if (\count($commands) > 1 && !$exact) { + if (\count($commands) > 1) { $usableWidth = $this->terminal->getWidth() - 10; $abbrevs = array_values($commands); $maxLen = 0; foreach ($abbrevs as $abbrev) { $maxLen = max(Helper::strlen($abbrev), $maxLen); } - $abbrevs = array_map(function ($cmd) use ($commandList, $usableWidth, $maxLen) { - if (!$commandList[$cmd] instanceof Command) { - return $cmd; + $abbrevs = array_map(function ($cmd) use ($commandList, $usableWidth, $maxLen, &$commands) { + if ($commandList[$cmd]->isHidden()) { + unset($commands[array_search($cmd, $commands)]); + + return false; } + $abbrev = str_pad($cmd, $maxLen, ' ').' '.$commandList[$cmd]->getDescription(); return Helper::strlen($abbrev) > $usableWidth ? Helper::substr($abbrev, 0, $usableWidth - 3).'...' : $abbrev; }, array_values($commands)); - $suggestions = $this->getAbbreviationSuggestions($abbrevs); - throw new CommandNotFoundException(sprintf("Command \"%s\" is ambiguous.\nDid you mean one of these?\n%s", $name, $suggestions), array_values($commands)); + if (\count($commands) > 1) { + $suggestions = $this->getAbbreviationSuggestions(array_filter($abbrevs)); + + throw new CommandNotFoundException(sprintf("Command \"%s\" is ambiguous.\nDid you mean one of these?\n%s.", $name, $suggestions), array_values($commands)); + } } - return $this->get($exact ? $name : reset($commands)); + $command = $this->get(reset($commands)); + + if ($command->isHidden()) { + @trigger_error(sprintf('Command "%s" is hidden, finding it using an abbreviation is deprecated since Symfony 4.4, use its full name instead.', $command->getName()), \E_USER_DEPRECATED); + } + + return $command; } /** @@ -751,39 +795,95 @@ class Application /** * Renders a caught exception. + * + * @deprecated since Symfony 4.4, use "renderThrowable()" instead */ public function renderException(\Exception $e, OutputInterface $output) { + @trigger_error(sprintf('The "%s::renderException()" method is deprecated since Symfony 4.4, use "renderThrowable()" instead.', __CLASS__), \E_USER_DEPRECATED); + $output->writeln('', OutputInterface::VERBOSITY_QUIET); $this->doRenderException($e, $output); + $this->finishRenderThrowableOrException($output); + } + + public function renderThrowable(\Throwable $e, OutputInterface $output): void + { + if (__CLASS__ !== static::class && __CLASS__ === (new \ReflectionMethod($this, 'renderThrowable'))->getDeclaringClass()->getName() && __CLASS__ !== (new \ReflectionMethod($this, 'renderException'))->getDeclaringClass()->getName()) { + @trigger_error(sprintf('The "%s::renderException()" method is deprecated since Symfony 4.4, use "renderThrowable()" instead.', __CLASS__), \E_USER_DEPRECATED); + + if (!$e instanceof \Exception) { + $e = class_exists(FatalThrowableError::class) ? new FatalThrowableError($e) : new \ErrorException($e->getMessage(), $e->getCode(), \E_ERROR, $e->getFile(), $e->getLine()); + } + + $this->renderException($e, $output); + + return; + } + + $output->writeln('', OutputInterface::VERBOSITY_QUIET); + + $this->doRenderThrowable($e, $output); + + $this->finishRenderThrowableOrException($output); + } + + private function finishRenderThrowableOrException(OutputInterface $output): void + { if (null !== $this->runningCommand) { - $output->writeln(sprintf('%s', sprintf($this->runningCommand->getSynopsis(), $this->getName())), OutputInterface::VERBOSITY_QUIET); + $output->writeln(sprintf('%s', OutputFormatter::escape(sprintf($this->runningCommand->getSynopsis(), $this->getName()))), OutputInterface::VERBOSITY_QUIET); $output->writeln('', OutputInterface::VERBOSITY_QUIET); } } + /** + * @deprecated since Symfony 4.4, use "doRenderThrowable()" instead + */ protected function doRenderException(\Exception $e, OutputInterface $output) + { + @trigger_error(sprintf('The "%s::doRenderException()" method is deprecated since Symfony 4.4, use "doRenderThrowable()" instead.', __CLASS__), \E_USER_DEPRECATED); + + $this->doActuallyRenderThrowable($e, $output); + } + + protected function doRenderThrowable(\Throwable $e, OutputInterface $output): void + { + if (__CLASS__ !== static::class && __CLASS__ === (new \ReflectionMethod($this, 'doRenderThrowable'))->getDeclaringClass()->getName() && __CLASS__ !== (new \ReflectionMethod($this, 'doRenderException'))->getDeclaringClass()->getName()) { + @trigger_error(sprintf('The "%s::doRenderException()" method is deprecated since Symfony 4.4, use "doRenderThrowable()" instead.', __CLASS__), \E_USER_DEPRECATED); + + if (!$e instanceof \Exception) { + $e = class_exists(FatalThrowableError::class) ? new FatalThrowableError($e) : new \ErrorException($e->getMessage(), $e->getCode(), \E_ERROR, $e->getFile(), $e->getLine()); + } + + $this->doRenderException($e, $output); + + return; + } + + $this->doActuallyRenderThrowable($e, $output); + } + + private function doActuallyRenderThrowable(\Throwable $e, OutputInterface $output): void { do { $message = trim($e->getMessage()); if ('' === $message || OutputInterface::VERBOSITY_VERBOSE <= $output->getVerbosity()) { - $class = \get_class($e); - $class = 'c' === $class[0] && 0 === strpos($class, "class@anonymous\0") ? get_parent_class($class).'@anonymous' : $class; + $class = get_debug_type($e); $title = sprintf(' [%s%s] ', $class, 0 !== ($code = $e->getCode()) ? ' ('.$code.')' : ''); $len = Helper::strlen($title); } else { $len = 0; } - if (false !== strpos($message, "class@anonymous\0")) { - $message = preg_replace_callback('/class@anonymous\x00.*?\.php0x?[0-9a-fA-F]++/', function ($m) { - return class_exists($m[0], false) ? get_parent_class($m[0]).'@anonymous' : $m[0]; + if (str_contains($message, "@anonymous\0")) { + $message = preg_replace_callback('/[a-zA-Z_\x7f-\xff][\\\\a-zA-Z0-9_\x7f-\xff]*+@anonymous\x00.*?\.php(?:0x?|:[0-9]++\$)[0-9a-fA-F]++/', function ($m) { + return class_exists($m[0], false) ? (get_parent_class($m[0]) ?: key(class_implements($m[0])) ?: 'class').'@anonymous' : $m[0]; }, $message); } - $width = $this->terminal->getWidth() ? $this->terminal->getWidth() - 1 : PHP_INT_MAX; + $width = $this->terminal->getWidth() ? $this->terminal->getWidth() - 1 : \PHP_INT_MAX; $lines = []; foreach ('' !== $message ? preg_split('/\r?\n/', $message) : [] as $line) { foreach ($this->splitStringByWidth($line, $width - 4) as $line) { @@ -825,13 +925,13 @@ class Application ]); for ($i = 0, $count = \count($trace); $i < $count; ++$i) { - $class = isset($trace[$i]['class']) ? $trace[$i]['class'] : ''; - $type = isset($trace[$i]['type']) ? $trace[$i]['type'] : ''; - $function = $trace[$i]['function']; - $file = isset($trace[$i]['file']) ? $trace[$i]['file'] : 'n/a'; - $line = isset($trace[$i]['line']) ? $trace[$i]['line'] : 'n/a'; + $class = $trace[$i]['class'] ?? ''; + $type = $trace[$i]['type'] ?? ''; + $function = $trace[$i]['function'] ?? ''; + $file = $trace[$i]['file'] ?? 'n/a'; + $line = $trace[$i]['line'] ?? 'n/a'; - $output->writeln(sprintf(' %s%s%s() at %s:%s', $class, $type, $function, $file, $line), OutputInterface::VERBOSITY_QUIET); + $output->writeln(sprintf(' %s%s at %s:%s', $class, $function ? $type.$function.'()' : '', $file, $line), OutputInterface::VERBOSITY_QUIET); } $output->writeln('', OutputInterface::VERBOSITY_QUIET); @@ -852,16 +952,6 @@ class Application if (true === $input->hasParameterOption(['--no-interaction', '-n'], true)) { $input->setInteractive(false); - } elseif (\function_exists('posix_isatty')) { - $inputStream = null; - - if ($input instanceof StreamableInputInterface) { - $inputStream = $input->getStream(); - } - - if (!@posix_isatty($inputStream) && false === getenv('SHELL_INTERACTIVE')) { - $input->setInteractive(false); - } } switch ($shellVerbosity = (int) getenv('SHELL_VERBOSITY')) { @@ -892,7 +982,9 @@ class Application $input->setInteractive(false); } - putenv('SHELL_VERBOSITY='.$shellVerbosity); + if (\function_exists('putenv')) { + @putenv('SHELL_VERBOSITY='.$shellVerbosity); + } $_ENV['SHELL_VERBOSITY'] = $shellVerbosity; $_SERVER['SHELL_VERBOSITY'] = $shellVerbosity; } @@ -929,7 +1021,7 @@ class Application $e = null; try { - $this->dispatcher->dispatch(ConsoleEvents::COMMAND, $event); + $this->dispatcher->dispatch($event, ConsoleEvents::COMMAND); if ($event->commandShouldRun()) { $exitCode = $command->run($input, $output); @@ -938,7 +1030,7 @@ class Application } } catch (\Throwable $e) { $event = new ConsoleErrorEvent($input, $output, $e, $command); - $this->dispatcher->dispatch(ConsoleEvents::ERROR, $event); + $this->dispatcher->dispatch($event, ConsoleEvents::ERROR); $e = $event->getError(); if (0 === $exitCode = $event->getExitCode()) { @@ -947,7 +1039,7 @@ class Application } $event = new ConsoleTerminateEvent($command, $input, $output, $exitCode); - $this->dispatcher->dispatch(ConsoleEvents::TERMINATE, $event); + $this->dispatcher->dispatch($event, ConsoleEvents::TERMINATE); if (null !== $e) { throw $e; @@ -959,7 +1051,7 @@ class Application /** * Gets the name of the command based on input. * - * @return string The command name + * @return string|null */ protected function getCommandName(InputInterface $input) { @@ -1013,12 +1105,8 @@ class Application /** * Returns abbreviated suggestions in string format. - * - * @param array $abbrevs Abbreviated suggestions to convert - * - * @return string A formatted string of abbreviated suggestions */ - private function getAbbreviationSuggestions($abbrevs) + private function getAbbreviationSuggestions(array $abbrevs): string { return ' '.implode("\n ", $abbrevs); } @@ -1035,8 +1123,7 @@ class Application */ public function extractNamespace($name, $limit = null) { - $parts = explode(':', $name); - array_pop($parts); + $parts = explode(':', $name, -1); return implode(':', null === $limit ? $parts : \array_slice($parts, 0, $limit)); } @@ -1045,12 +1132,9 @@ class Application * Finds alternative of $name among $collection, * if nothing is found in $collection, try in $abbrevs. * - * @param string $name The string - * @param iterable $collection The collection - * * @return string[] A sorted array of similar string */ - private function findAlternatives($name, $collection) + private function findAlternatives(string $name, iterable $collection): array { $threshold = 1e3; $alternatives = []; @@ -1071,7 +1155,7 @@ class Application } $lev = levenshtein($subname, $parts[$i]); - if ($lev <= \strlen($subname) / 3 || '' !== $subname && false !== strpos($parts[$i], $subname)) { + if ($lev <= \strlen($subname) / 3 || '' !== $subname && str_contains($parts[$i], $subname)) { $alternatives[$collectionName] = $exists ? $alternatives[$collectionName] + $lev : $lev; } elseif ($exists) { $alternatives[$collectionName] += $threshold; @@ -1081,13 +1165,13 @@ class Application foreach ($collection as $item) { $lev = levenshtein($name, $item); - if ($lev <= \strlen($name) / 3 || false !== strpos($item, $name)) { + if ($lev <= \strlen($name) / 3 || str_contains($item, $name)) { $alternatives[$item] = isset($alternatives[$item]) ? $alternatives[$item] - $lev : $lev; } } $alternatives = array_filter($alternatives, function ($lev) use ($threshold) { return $lev < 2 * $threshold; }); - ksort($alternatives, SORT_NATURAL | SORT_FLAG_CASE); + ksort($alternatives, \SORT_NATURAL | \SORT_FLAG_CASE); return array_keys($alternatives); } @@ -1117,12 +1201,12 @@ class Application /** * @internal */ - public function isSingleCommand() + public function isSingleCommand(): bool { return $this->singleCommand; } - private function splitStringByWidth($string, $width) + private function splitStringByWidth(string $string, int $width): array { // str_split is not suitable for multi-byte characters, we should use preg_split to get char array properly. // additionally, array_slice() is not enough as some character has doubled width. @@ -1134,15 +1218,21 @@ class Application $utf8String = mb_convert_encoding($string, 'utf8', $encoding); $lines = []; $line = ''; - foreach (preg_split('//u', $utf8String) as $char) { - // test if $char could be appended to current line - if (mb_strwidth($line.$char, 'utf8') <= $width) { - $line .= $char; - continue; + + $offset = 0; + while (preg_match('/.{1,10000}/u', $utf8String, $m, 0, $offset)) { + $offset += \strlen($m[0]); + + foreach (preg_split('//u', $m[0]) as $char) { + // test if $char could be appended to current line + if (mb_strwidth($line.$char, 'utf8') <= $width) { + $line .= $char; + continue; + } + // if not, push current line to array and make new line + $lines[] = str_pad($line, $width); + $line = $char; } - // if not, push current line to array and make new line - $lines[] = str_pad($line, $width); - $line = $char; } $lines[] = \count($lines) ? str_pad($line, $width) : $line; @@ -1155,11 +1245,9 @@ class Application /** * Returns all namespaces of the command name. * - * @param string $name The full name of the command - * * @return string[] The namespaces of the command */ - private function extractAllNamespaces($name) + private function extractAllNamespaces(string $name): array { // -1 as third argument is needed to skip the command short name when exploding $parts = explode(':', $name, -1); diff --git a/vendor/symfony/console/CHANGELOG.md b/vendor/symfony/console/CHANGELOG.md index 399bbc221..515924455 100644 --- a/vendor/symfony/console/CHANGELOG.md +++ b/vendor/symfony/console/CHANGELOG.md @@ -1,6 +1,28 @@ CHANGELOG ========= +4.4.0 +----- + + * deprecated finding hidden commands using an abbreviation, use the full name instead + * added `Question::setTrimmable` default to true to allow the answer to be trimmed + * added method `minSecondsBetweenRedraws()` and `maxSecondsBetweenRedraws()` on `ProgressBar` + * `Application` implements `ResetInterface` + * marked all dispatched event classes as `@final` + * added support for displaying table horizontally + * deprecated returning `null` from `Command::execute()`, return `0` instead + * Deprecated the `Application::renderException()` and `Application::doRenderException()` methods, + use `renderThrowable()` and `doRenderThrowable()` instead. + * added support for the `NO_COLOR` env var (https://no-color.org/) + +4.3.0 +----- + + * added support for hyperlinks + * added `ProgressBar::iterate()` method that simplify updating the progress bar when iterating + * added `Question::setAutocompleterCallback()` to provide a callback function + that dynamically generates suggestions as the user types + 4.2.0 ----- @@ -24,10 +46,10 @@ CHANGELOG * `OutputFormatter` throws an exception when unknown options are used * removed `QuestionHelper::setInputStream()/getInputStream()` - * removed `Application::getTerminalWidth()/getTerminalHeight()` and - `Application::setTerminalDimensions()/getTerminalDimensions()` -* removed `ConsoleExceptionEvent` -* removed `ConsoleEvents::EXCEPTION` + * removed `Application::getTerminalWidth()/getTerminalHeight()` and + `Application::setTerminalDimensions()/getTerminalDimensions()` + * removed `ConsoleExceptionEvent` + * removed `ConsoleEvents::EXCEPTION` 3.4.0 ----- @@ -44,29 +66,29 @@ CHANGELOG 3.3.0 ----- -* added `ExceptionListener` -* added `AddConsoleCommandPass` (originally in FrameworkBundle) -* [BC BREAK] `Input::getOption()` no longer returns the default value for options - with value optional explicitly passed empty -* added console.error event to catch exceptions thrown by other listeners -* deprecated console.exception event in favor of console.error -* added ability to handle `CommandNotFoundException` through the - `console.error` event -* deprecated default validation in `SymfonyQuestionHelper::ask` + * added `ExceptionListener` + * added `AddConsoleCommandPass` (originally in FrameworkBundle) + * [BC BREAK] `Input::getOption()` no longer returns the default value for options + with value optional explicitly passed empty + * added console.error event to catch exceptions thrown by other listeners + * deprecated console.exception event in favor of console.error + * added ability to handle `CommandNotFoundException` through the + `console.error` event + * deprecated default validation in `SymfonyQuestionHelper::ask` 3.2.0 ------ -* added `setInputs()` method to CommandTester for ease testing of commands expecting inputs -* added `setStream()` and `getStream()` methods to Input (implement StreamableInputInterface) -* added StreamableInputInterface -* added LockableTrait + * added `setInputs()` method to CommandTester for ease testing of commands expecting inputs + * added `setStream()` and `getStream()` methods to Input (implement StreamableInputInterface) + * added StreamableInputInterface + * added LockableTrait 3.1.0 ----- * added truncate method to FormatterHelper - * added setColumnWidth(s) method to Table + * added setColumnWidth(s) method to Table 2.8.3 ----- diff --git a/vendor/symfony/console/Command/Command.php b/vendor/symfony/console/Command/Command.php index 18d683de9..da9b9f6af 100644 --- a/vendor/symfony/console/Command/Command.php +++ b/vendor/symfony/console/Command/Command.php @@ -40,8 +40,8 @@ class Command private $aliases = []; private $definition; private $hidden = false; - private $help; - private $description; + private $help = ''; + private $description = ''; private $ignoreValidationErrors = false; private $applicationDefinitionMerged = false; private $applicationDefinitionMergedWithArgs = false; @@ -55,7 +55,7 @@ class Command */ public static function getDefaultName() { - $class = \get_called_class(); + $class = static::class; $r = new \ReflectionProperty($class, 'defaultName'); return $class === $r->class ? static::$defaultName : null; @@ -105,7 +105,7 @@ class Command /** * Gets the helper set. * - * @return HelperSet A HelperSet instance + * @return HelperSet|null A HelperSet instance */ public function getHelperSet() { @@ -115,7 +115,7 @@ class Command /** * Gets the application instance for this command. * - * @return Application An Application instance + * @return Application|null An Application instance */ public function getApplication() { @@ -150,7 +150,7 @@ class Command * execute() method, you set the code to execute by passing * a Closure to the setCode() method. * - * @return int|null null or 0 if everything went fine, or an error code + * @return int 0 if everything went fine, or an exit code * * @throws LogicException When this abstract method is not implemented * @@ -223,7 +223,7 @@ class Command if (null !== $this->processTitle) { if (\function_exists('cli_set_process_title')) { if (!@cli_set_process_title($this->processTitle)) { - if ('Darwin' === PHP_OS) { + if ('Darwin' === \PHP_OS) { $output->writeln('Running "cli_set_process_title" as an unprivileged user is not supported on MacOS.', OutputInterface::VERBOSITY_VERY_VERBOSE); } else { cli_set_process_title($this->processTitle); @@ -253,6 +253,10 @@ class Command $statusCode = ($this->code)($input, $output); } else { $statusCode = $this->execute($input, $output); + + if (!\is_int($statusCode)) { + @trigger_error(sprintf('Return value of "%s::execute()" should always be of the type int since Symfony 4.4, %s returned.', static::class, \gettype($statusCode)), \E_USER_DEPRECATED); + } } return is_numeric($statusCode) ? (int) $statusCode : 0; @@ -277,7 +281,14 @@ class Command if ($code instanceof \Closure) { $r = new \ReflectionFunction($code); if (null === $r->getClosureThis()) { - $code = \Closure::bind($code, $this); + set_error_handler(static function () {}); + try { + if ($c = \Closure::bind($code, $this)) { + $code = $c; + } + } finally { + restore_error_handler(); + } } } @@ -339,6 +350,10 @@ class Command */ public function getDefinition() { + if (null === $this->definition) { + throw new LogicException(sprintf('Command class "%s" is not correctly initialized. You probably forgot to call the parent constructor.', static::class)); + } + return $this->definition; } @@ -360,10 +375,10 @@ class Command /** * Adds an argument. * - * @param string $name The argument name - * @param int|null $mode The argument mode: InputArgument::REQUIRED or InputArgument::OPTIONAL - * @param string $description A description text - * @param string|string[]|null $default The default value (for InputArgument::OPTIONAL mode only) + * @param string $name The argument name + * @param int|null $mode The argument mode: InputArgument::REQUIRED or InputArgument::OPTIONAL + * @param string $description A description text + * @param mixed $default The default value (for InputArgument::OPTIONAL mode only) * * @throws InvalidArgumentException When argument mode is not valid * @@ -379,11 +394,11 @@ class Command /** * Adds an option. * - * @param string $name The option name - * @param string|array|null $shortcut The shortcuts, can be null, a string of shortcuts delimited by | or an array of shortcuts - * @param int|null $mode The option mode: One of the InputOption::VALUE_* constants - * @param string $description A description text - * @param string|string[]|int|bool|null $default The default value (must be null for InputOption::VALUE_NONE) + * @param string $name The option name + * @param string|array|null $shortcut The shortcuts, can be null, a string of shortcuts delimited by | or an array of shortcuts + * @param int|null $mode The option mode: One of the InputOption::VALUE_* constants + * @param string $description A description text + * @param mixed $default The default value (must be null for InputOption::VALUE_NONE) * * @throws InvalidArgumentException If option mode is invalid or incompatible * @@ -425,8 +440,6 @@ class Command * This feature should be used only when creating a long process command, * like a daemon. * - * PHP 5.5+ or the proctitle PECL library is required - * * @param string $title The process title * * @return $this @@ -441,7 +454,7 @@ class Command /** * Returns the command name. * - * @return string The command name + * @return string|null */ public function getName() { @@ -451,7 +464,7 @@ class Command /** * @param bool $hidden Whether or not the command should be hidden from the list of commands * - * @return Command The current instance + * @return $this */ public function setHidden($hidden) { @@ -551,7 +564,7 @@ class Command public function setAliases($aliases) { if (!\is_array($aliases) && !$aliases instanceof \Traversable) { - throw new InvalidArgumentException('$aliases must be an array or an instance of \Traversable'); + throw new InvalidArgumentException('$aliases must be an array or an instance of \Traversable.'); } foreach ($aliases as $alias) { @@ -600,7 +613,7 @@ class Command */ public function addUsage($usage) { - if (0 !== strpos($usage, $this->name)) { + if (!str_starts_with($usage, $this->name)) { $usage = sprintf('%s %s', $this->name, $usage); } diff --git a/vendor/symfony/console/Command/HelpCommand.php b/vendor/symfony/console/Command/HelpCommand.php index 23847766b..cece78299 100644 --- a/vendor/symfony/console/Command/HelpCommand.php +++ b/vendor/symfony/console/Command/HelpCommand.php @@ -40,7 +40,7 @@ class HelpCommand extends Command new InputOption('format', null, InputOption::VALUE_REQUIRED, 'The output format (txt, xml, json, or md)', 'txt'), new InputOption('raw', null, InputOption::VALUE_NONE, 'To output raw command help'), ]) - ->setDescription('Displays help for a command') + ->setDescription('Display help for a command') ->setHelp(<<<'EOF' The %command.name% command displays help for a given command: @@ -77,5 +77,7 @@ EOF ]); $this->command = null; + + return 0; } } diff --git a/vendor/symfony/console/Command/ListCommand.php b/vendor/symfony/console/Command/ListCommand.php index 7259b1263..44324a5e7 100644 --- a/vendor/symfony/console/Command/ListCommand.php +++ b/vendor/symfony/console/Command/ListCommand.php @@ -33,7 +33,7 @@ class ListCommand extends Command $this ->setName('list') ->setDefinition($this->createDefinition()) - ->setDescription('Lists commands') + ->setDescription('List commands') ->setHelp(<<<'EOF' The %command.name% command lists all commands: @@ -74,12 +74,11 @@ EOF 'raw_text' => $input->getOption('raw'), 'namespace' => $input->getArgument('namespace'), ]); + + return 0; } - /** - * {@inheritdoc} - */ - private function createDefinition() + private function createDefinition(): InputDefinition { return new InputDefinition([ new InputArgument('namespace', InputArgument::OPTIONAL, 'The namespace name'), diff --git a/vendor/symfony/console/Command/LockableTrait.php b/vendor/symfony/console/Command/LockableTrait.php index f4ebe45bf..60cfe360f 100644 --- a/vendor/symfony/console/Command/LockableTrait.php +++ b/vendor/symfony/console/Command/LockableTrait.php @@ -12,8 +12,8 @@ namespace Symfony\Component\Console\Command; use Symfony\Component\Console\Exception\LogicException; -use Symfony\Component\Lock\Factory; use Symfony\Component\Lock\Lock; +use Symfony\Component\Lock\LockFactory; use Symfony\Component\Lock\Store\FlockStore; use Symfony\Component\Lock\Store\SemaphoreStore; @@ -29,10 +29,8 @@ trait LockableTrait /** * Locks a command. - * - * @return bool */ - private function lock($name = null, $blocking = false) + private function lock(string $name = null, bool $blocking = false): bool { if (!class_exists(SemaphoreStore::class)) { throw new LogicException('To enable the locking feature you must install the symfony/lock component.'); @@ -48,7 +46,7 @@ trait LockableTrait $store = new FlockStore(); } - $this->lock = (new Factory($store))->createLock($name ?: $this->getName()); + $this->lock = (new LockFactory($store))->createLock($name ?: $this->getName()); if (!$this->lock->acquire($blocking)) { $this->lock = null; diff --git a/vendor/symfony/console/CommandLoader/ContainerCommandLoader.php b/vendor/symfony/console/CommandLoader/ContainerCommandLoader.php index 8000c7d5e..50e5950a4 100644 --- a/vendor/symfony/console/CommandLoader/ContainerCommandLoader.php +++ b/vendor/symfony/console/CommandLoader/ContainerCommandLoader.php @@ -25,8 +25,7 @@ class ContainerCommandLoader implements CommandLoaderInterface private $commandMap; /** - * @param ContainerInterface $container A container from which to load command services - * @param array $commandMap An array with command names as keys and service ids as values + * @param array $commandMap An array with command names as keys and service ids as values */ public function __construct(ContainerInterface $container, array $commandMap) { diff --git a/vendor/symfony/console/ConsoleEvents.php b/vendor/symfony/console/ConsoleEvents.php index 4975643ae..99b423c83 100644 --- a/vendor/symfony/console/ConsoleEvents.php +++ b/vendor/symfony/console/ConsoleEvents.php @@ -21,11 +21,11 @@ final class ConsoleEvents /** * The COMMAND event allows you to attach listeners before any command is * executed by the console. It also allows you to modify the command, input and output - * before they are handled to the command. + * before they are handed to the command. * * @Event("Symfony\Component\Console\Event\ConsoleCommandEvent") */ - const COMMAND = 'console.command'; + public const COMMAND = 'console.command'; /** * The TERMINATE event allows you to attach listeners after a command is @@ -33,7 +33,7 @@ final class ConsoleEvents * * @Event("Symfony\Component\Console\Event\ConsoleTerminateEvent") */ - const TERMINATE = 'console.terminate'; + public const TERMINATE = 'console.terminate'; /** * The ERROR event occurs when an uncaught exception or error appears. @@ -43,5 +43,5 @@ final class ConsoleEvents * * @Event("Symfony\Component\Console\Event\ConsoleErrorEvent") */ - const ERROR = 'console.error'; + public const ERROR = 'console.error'; } diff --git a/vendor/symfony/console/Descriptor/ApplicationDescription.php b/vendor/symfony/console/Descriptor/ApplicationDescription.php index 03bfcfcda..3970b9000 100644 --- a/vendor/symfony/console/Descriptor/ApplicationDescription.php +++ b/vendor/symfony/console/Descriptor/ApplicationDescription.php @@ -22,7 +22,7 @@ use Symfony\Component\Console\Exception\CommandNotFoundException; */ class ApplicationDescription { - const GLOBAL_NAMESPACE = '_global'; + public const GLOBAL_NAMESPACE = '_global'; private $application; private $namespace; @@ -50,10 +50,7 @@ class ApplicationDescription $this->showHidden = $showHidden; } - /** - * @return array - */ - public function getNamespaces() + public function getNamespaces(): array { if (null === $this->namespaces) { $this->inspectApplication(); @@ -65,7 +62,7 @@ class ApplicationDescription /** * @return Command[] */ - public function getCommands() + public function getCommands(): array { if (null === $this->commands) { $this->inspectApplication(); @@ -75,19 +72,15 @@ class ApplicationDescription } /** - * @param string $name - * - * @return Command - * * @throws CommandNotFoundException */ - public function getCommand($name) + public function getCommand(string $name): Command { if (!isset($this->commands[$name]) && !isset($this->aliases[$name])) { - throw new CommandNotFoundException(sprintf('Command %s does not exist.', $name)); + throw new CommandNotFoundException(sprintf('Command "%s" does not exist.', $name)); } - return isset($this->commands[$name]) ? $this->commands[$name] : $this->aliases[$name]; + return $this->commands[$name] ?? $this->aliases[$name]; } private function inspectApplication() @@ -122,23 +115,29 @@ class ApplicationDescription { $namespacedCommands = []; $globalCommands = []; + $sortedCommands = []; foreach ($commands as $name => $command) { $key = $this->application->extractNamespace($name, 1); - if (!$key) { - $globalCommands['_global'][$name] = $command; + if (\in_array($key, ['', self::GLOBAL_NAMESPACE], true)) { + $globalCommands[$name] = $command; } else { $namespacedCommands[$key][$name] = $command; } } - ksort($namespacedCommands); - $namespacedCommands = array_merge($globalCommands, $namespacedCommands); - foreach ($namespacedCommands as &$commandsSet) { - ksort($commandsSet); + if ($globalCommands) { + ksort($globalCommands); + $sortedCommands[self::GLOBAL_NAMESPACE] = $globalCommands; } - // unset reference to keep scope clear - unset($commandsSet); - return $namespacedCommands; + if ($namespacedCommands) { + ksort($namespacedCommands); + foreach ($namespacedCommands as $key => $commandsSet) { + ksort($commandsSet); + $sortedCommands[$key] = $commandsSet; + } + } + + return $sortedCommands; } } diff --git a/vendor/symfony/console/Descriptor/Descriptor.php b/vendor/symfony/console/Descriptor/Descriptor.php index d25a708e4..9c3878d1e 100644 --- a/vendor/symfony/console/Descriptor/Descriptor.php +++ b/vendor/symfony/console/Descriptor/Descriptor.php @@ -72,36 +72,26 @@ abstract class Descriptor implements DescriptorInterface /** * Describes an InputArgument instance. - * - * @return string|mixed */ abstract protected function describeInputArgument(InputArgument $argument, array $options = []); /** * Describes an InputOption instance. - * - * @return string|mixed */ abstract protected function describeInputOption(InputOption $option, array $options = []); /** * Describes an InputDefinition instance. - * - * @return string|mixed */ abstract protected function describeInputDefinition(InputDefinition $definition, array $options = []); /** * Describes a Command instance. - * - * @return string|mixed */ abstract protected function describeCommand(Command $command, array $options = []); /** * Describes an Application instance. - * - * @return string|mixed */ abstract protected function describeApplication(Application $application, array $options = []); } diff --git a/vendor/symfony/console/Descriptor/DescriptorInterface.php b/vendor/symfony/console/Descriptor/DescriptorInterface.php index fbc07df87..e3184a6a5 100644 --- a/vendor/symfony/console/Descriptor/DescriptorInterface.php +++ b/vendor/symfony/console/Descriptor/DescriptorInterface.php @@ -23,9 +23,7 @@ interface DescriptorInterface /** * Describes an object if supported. * - * @param OutputInterface $output - * @param object $object - * @param array $options + * @param object $object */ public function describe(OutputInterface $output, $object, array $options = []); } diff --git a/vendor/symfony/console/Descriptor/JsonDescriptor.php b/vendor/symfony/console/Descriptor/JsonDescriptor.php index f5a143800..4c09e1267 100644 --- a/vendor/symfony/console/Descriptor/JsonDescriptor.php +++ b/vendor/symfony/console/Descriptor/JsonDescriptor.php @@ -63,7 +63,7 @@ class JsonDescriptor extends Descriptor */ protected function describeApplication(Application $application, array $options = []) { - $describedNamespace = isset($options['namespace']) ? $options['namespace'] : null; + $describedNamespace = $options['namespace'] ?? null; $description = new ApplicationDescription($application, $describedNamespace, true); $commands = []; @@ -92,34 +92,26 @@ class JsonDescriptor extends Descriptor /** * Writes data as json. - * - * @return array|string */ private function writeData(array $data, array $options) { - $flags = isset($options['json_encoding']) ? $options['json_encoding'] : 0; + $flags = $options['json_encoding'] ?? 0; $this->write(json_encode($data, $flags)); } - /** - * @return array - */ - private function getInputArgumentData(InputArgument $argument) + private function getInputArgumentData(InputArgument $argument): array { return [ 'name' => $argument->getName(), 'is_required' => $argument->isRequired(), 'is_array' => $argument->isArray(), 'description' => preg_replace('/\s*[\r\n]\s*/', ' ', $argument->getDescription()), - 'default' => INF === $argument->getDefault() ? 'INF' : $argument->getDefault(), + 'default' => \INF === $argument->getDefault() ? 'INF' : $argument->getDefault(), ]; } - /** - * @return array - */ - private function getInputOptionData(InputOption $option) + private function getInputOptionData(InputOption $option): array { return [ 'name' => '--'.$option->getName(), @@ -128,14 +120,11 @@ class JsonDescriptor extends Descriptor 'is_value_required' => $option->isValueRequired(), 'is_multiple' => $option->isArray(), 'description' => preg_replace('/\s*[\r\n]\s*/', ' ', $option->getDescription()), - 'default' => INF === $option->getDefault() ? 'INF' : $option->getDefault(), + 'default' => \INF === $option->getDefault() ? 'INF' : $option->getDefault(), ]; } - /** - * @return array - */ - private function getInputDefinitionData(InputDefinition $definition) + private function getInputDefinitionData(InputDefinition $definition): array { $inputArguments = []; foreach ($definition->getArguments() as $name => $argument) { @@ -150,10 +139,7 @@ class JsonDescriptor extends Descriptor return ['arguments' => $inputArguments, 'options' => $inputOptions]; } - /** - * @return array - */ - private function getCommandData(Command $command) + private function getCommandData(Command $command): array { $command->getSynopsis(); $command->mergeApplicationDefinition(false); diff --git a/vendor/symfony/console/Descriptor/MarkdownDescriptor.php b/vendor/symfony/console/Descriptor/MarkdownDescriptor.php index e6245778f..9a9d28075 100644 --- a/vendor/symfony/console/Descriptor/MarkdownDescriptor.php +++ b/vendor/symfony/console/Descriptor/MarkdownDescriptor.php @@ -143,7 +143,7 @@ class MarkdownDescriptor extends Descriptor */ protected function describeApplication(Application $application, array $options = []) { - $describedNamespace = isset($options['namespace']) ? $options['namespace'] : null; + $describedNamespace = $options['namespace'] ?? null; $description = new ApplicationDescription($application, $describedNamespace); $title = $this->getApplicationTitle($application); @@ -167,7 +167,7 @@ class MarkdownDescriptor extends Descriptor } } - private function getApplicationTitle(Application $application) + private function getApplicationTitle(Application $application): string { if ('UNKNOWN' !== $application->getName()) { if ('UNKNOWN' !== $application->getVersion()) { diff --git a/vendor/symfony/console/Descriptor/TextDescriptor.php b/vendor/symfony/console/Descriptor/TextDescriptor.php index 24fcf00a1..7d4d5f0bb 100644 --- a/vendor/symfony/console/Descriptor/TextDescriptor.php +++ b/vendor/symfony/console/Descriptor/TextDescriptor.php @@ -39,7 +39,7 @@ class TextDescriptor extends Descriptor $default = ''; } - $totalWidth = isset($options['total_width']) ? $options['total_width'] : Helper::strlen($argument->getName()); + $totalWidth = $options['total_width'] ?? Helper::strlen($argument->getName()); $spacingWidth = $totalWidth - \strlen($argument->getName()); $this->writeText(sprintf(' %s %s%s%s', @@ -71,7 +71,7 @@ class TextDescriptor extends Descriptor } } - $totalWidth = isset($options['total_width']) ? $options['total_width'] : $this->calculateTotalWidthForOptions([$option]); + $totalWidth = $options['total_width'] ?? $this->calculateTotalWidthForOptions([$option]); $synopsis = sprintf('%s%s', $option->getShortcut() ? sprintf('-%s, ', $option->getShortcut()) : ' ', sprintf('--%s%s', $option->getName(), $value) @@ -117,7 +117,7 @@ class TextDescriptor extends Descriptor $this->writeText('Options:', $options); foreach ($definition->getOptions() as $option) { - if (\strlen($option->getShortcut()) > 1) { + if (\strlen($option->getShortcut() ?? '') > 1) { $laterOptions[] = $option; continue; } @@ -176,7 +176,7 @@ class TextDescriptor extends Descriptor */ protected function describeApplication(Application $application, array $options = []) { - $describedNamespace = isset($options['namespace']) ? $options['namespace'] : null; + $describedNamespace = $options['namespace'] ?? null; $description = new ApplicationDescription($application, $describedNamespace); if (isset($options['raw_text']) && $options['raw_text']) { @@ -212,7 +212,7 @@ class TextDescriptor extends Descriptor // calculate max. width based on available commands per namespace $width = $this->getColumnWidth(array_merge(...array_values(array_map(function ($namespace) use ($commands) { return array_intersect($namespace['commands'], array_keys($commands)); - }, $namespaces)))); + }, array_values($namespaces))))); if ($describedNamespace) { $this->writeText(sprintf('Available commands for the "%s" namespace:', $describedNamespace), $options); @@ -250,7 +250,7 @@ class TextDescriptor extends Descriptor /** * {@inheritdoc} */ - private function writeText($content, array $options = []) + private function writeText(string $content, array $options = []) { $this->write( isset($options['raw_text']) && $options['raw_text'] ? strip_tags($content) : $content, @@ -280,7 +280,7 @@ class TextDescriptor extends Descriptor */ private function formatDefaultValue($default): string { - if (INF === $default) { + if (\INF === $default) { return 'INF'; } @@ -294,11 +294,11 @@ class TextDescriptor extends Descriptor } } - return str_replace('\\\\', '\\', json_encode($default, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE)); + return str_replace('\\\\', '\\', json_encode($default, \JSON_UNESCAPED_SLASHES | \JSON_UNESCAPED_UNICODE)); } /** - * @param (Command|string)[] $commands + * @param array $commands */ private function getColumnWidth(array $commands): int { diff --git a/vendor/symfony/console/Descriptor/XmlDescriptor.php b/vendor/symfony/console/Descriptor/XmlDescriptor.php index f5202a330..e0ed53a38 100644 --- a/vendor/symfony/console/Descriptor/XmlDescriptor.php +++ b/vendor/symfony/console/Descriptor/XmlDescriptor.php @@ -26,10 +26,7 @@ use Symfony\Component\Console\Input\InputOption; */ class XmlDescriptor extends Descriptor { - /** - * @return \DOMDocument - */ - public function getInputDefinitionDocument(InputDefinition $definition) + public function getInputDefinitionDocument(InputDefinition $definition): \DOMDocument { $dom = new \DOMDocument('1.0', 'UTF-8'); $dom->appendChild($definitionXML = $dom->createElement('definition')); @@ -47,10 +44,7 @@ class XmlDescriptor extends Descriptor return $dom; } - /** - * @return \DOMDocument - */ - public function getCommandDocument(Command $command) + public function getCommandDocument(Command $command): \DOMDocument { $dom = new \DOMDocument('1.0', 'UTF-8'); $dom->appendChild($commandXML = $dom->createElement('command')); @@ -80,13 +74,7 @@ class XmlDescriptor extends Descriptor return $dom; } - /** - * @param Application $application - * @param string|null $namespace - * - * @return \DOMDocument - */ - public function getApplicationDocument(Application $application, $namespace = null) + public function getApplicationDocument(Application $application, string $namespace = null): \DOMDocument { $dom = new \DOMDocument('1.0', 'UTF-8'); $dom->appendChild($rootXml = $dom->createElement('symfony')); @@ -164,7 +152,7 @@ class XmlDescriptor extends Descriptor */ protected function describeApplication(Application $application, array $options = []) { - $this->writeDocument($this->getApplicationDocument($application, isset($options['namespace']) ? $options['namespace'] : null)); + $this->writeDocument($this->getApplicationDocument($application, $options['namespace'] ?? null)); } /** @@ -179,8 +167,6 @@ class XmlDescriptor extends Descriptor /** * Writes DOM document. - * - * @return \DOMDocument|string */ private function writeDocument(\DOMDocument $dom) { @@ -215,7 +201,7 @@ class XmlDescriptor extends Descriptor $dom->appendChild($objectXML = $dom->createElement('option')); $objectXML->setAttribute('name', '--'.$option->getName()); - $pos = strpos($option->getShortcut(), '|'); + $pos = strpos($option->getShortcut() ?? '', '|'); if (false !== $pos) { $objectXML->setAttribute('shortcut', '-'.substr($option->getShortcut(), 0, $pos)); $objectXML->setAttribute('shortcuts', '-'.str_replace('|', '|-', $option->getShortcut())); diff --git a/vendor/symfony/console/Event/ConsoleCommandEvent.php b/vendor/symfony/console/Event/ConsoleCommandEvent.php index 2f517c1db..9691db636 100644 --- a/vendor/symfony/console/Event/ConsoleCommandEvent.php +++ b/vendor/symfony/console/Event/ConsoleCommandEvent.php @@ -15,13 +15,15 @@ namespace Symfony\Component\Console\Event; * Allows to do things before the command is executed, like skipping the command or changing the input. * * @author Fabien Potencier + * + * @final since Symfony 4.4 */ class ConsoleCommandEvent extends ConsoleEvent { /** * The return code for skipped commands, this will also be passed into the terminate event. */ - const RETURN_CODE_DISABLED = 113; + public const RETURN_CODE_DISABLED = 113; /** * Indicates if the command should be run or skipped. diff --git a/vendor/symfony/console/Event/ConsoleErrorEvent.php b/vendor/symfony/console/Event/ConsoleErrorEvent.php index 25d9b8812..57d9b38ba 100644 --- a/vendor/symfony/console/Event/ConsoleErrorEvent.php +++ b/vendor/symfony/console/Event/ConsoleErrorEvent.php @@ -53,6 +53,6 @@ final class ConsoleErrorEvent extends ConsoleEvent public function getExitCode(): int { - return null !== $this->exitCode ? $this->exitCode : (\is_int($this->error->getCode()) && 0 !== $this->error->getCode() ? $this->error->getCode() : 1); + return $this->exitCode ?? (\is_int($this->error->getCode()) && 0 !== $this->error->getCode() ? $this->error->getCode() : 1); } } diff --git a/vendor/symfony/console/Event/ConsoleEvent.php b/vendor/symfony/console/Event/ConsoleEvent.php index 5440da216..400eb5731 100644 --- a/vendor/symfony/console/Event/ConsoleEvent.php +++ b/vendor/symfony/console/Event/ConsoleEvent.php @@ -28,7 +28,7 @@ class ConsoleEvent extends Event private $input; private $output; - public function __construct(Command $command = null, InputInterface $input, OutputInterface $output) + public function __construct(?Command $command, InputInterface $input, OutputInterface $output) { $this->command = $command; $this->input = $input; diff --git a/vendor/symfony/console/Event/ConsoleTerminateEvent.php b/vendor/symfony/console/Event/ConsoleTerminateEvent.php index ff0c749d1..43d0f8ab1 100644 --- a/vendor/symfony/console/Event/ConsoleTerminateEvent.php +++ b/vendor/symfony/console/Event/ConsoleTerminateEvent.php @@ -19,6 +19,8 @@ use Symfony\Component\Console\Output\OutputInterface; * Allows to manipulate the exit code of a command after its execution. * * @author Francesco Levorato + * + * @final since Symfony 4.4 */ class ConsoleTerminateEvent extends ConsoleEvent { diff --git a/vendor/symfony/console/EventListener/ErrorListener.php b/vendor/symfony/console/EventListener/ErrorListener.php index 212ad1d96..897d9853f 100644 --- a/vendor/symfony/console/EventListener/ErrorListener.php +++ b/vendor/symfony/console/EventListener/ErrorListener.php @@ -40,10 +40,12 @@ class ErrorListener implements EventSubscriberInterface $error = $event->getError(); if (!$inputString = $this->getInputString($event)) { - return $this->logger->error('An error occurred while using the console. Message: "{message}"', ['exception' => $error, 'message' => $error->getMessage()]); + $this->logger->critical('An error occurred while using the console. Message: "{message}"', ['exception' => $error, 'message' => $error->getMessage()]); + + return; } - $this->logger->error('Error thrown while running command "{command}". Message: "{message}"', ['exception' => $error, 'command' => $inputString, 'message' => $error->getMessage()]); + $this->logger->critical('Error thrown while running command "{command}". Message: "{message}"', ['exception' => $error, 'command' => $inputString, 'message' => $error->getMessage()]); } public function onConsoleTerminate(ConsoleTerminateEvent $event) @@ -59,7 +61,9 @@ class ErrorListener implements EventSubscriberInterface } if (!$inputString = $this->getInputString($event)) { - return $this->logger->debug('The console exited with code "{code}"', ['code' => $exitCode]); + $this->logger->debug('The console exited with code "{code}"', ['code' => $exitCode]); + + return; } $this->logger->debug('Command "{command}" exited with code "{code}"', ['command' => $inputString, 'code' => $exitCode]); @@ -73,7 +77,7 @@ class ErrorListener implements EventSubscriberInterface ]; } - private static function getInputString(ConsoleEvent $event) + private static function getInputString(ConsoleEvent $event): ?string { $commandName = $event->getCommand() ? $event->getCommand()->getName() : null; $input = $event->getInput(); diff --git a/vendor/symfony/console/Exception/CommandNotFoundException.php b/vendor/symfony/console/Exception/CommandNotFoundException.php index 15ac522c6..590a71c77 100644 --- a/vendor/symfony/console/Exception/CommandNotFoundException.php +++ b/vendor/symfony/console/Exception/CommandNotFoundException.php @@ -21,12 +21,12 @@ class CommandNotFoundException extends \InvalidArgumentException implements Exce private $alternatives; /** - * @param string $message Exception message to throw - * @param array $alternatives List of similar defined names - * @param int $code Exception code - * @param \Exception $previous Previous exception used for the exception chaining + * @param string $message Exception message to throw + * @param string[] $alternatives List of similar defined names + * @param int $code Exception code + * @param \Throwable|null $previous Previous exception used for the exception chaining */ - public function __construct(string $message, array $alternatives = [], int $code = 0, \Exception $previous = null) + public function __construct(string $message, array $alternatives = [], int $code = 0, \Throwable $previous = null) { parent::__construct($message, $code, $previous); @@ -34,7 +34,7 @@ class CommandNotFoundException extends \InvalidArgumentException implements Exce } /** - * @return array A list of similar defined names + * @return string[] A list of similar defined names */ public function getAlternatives() { diff --git a/vendor/symfony/contracts/HttpClient/Exception/ExceptionInterface.php b/vendor/symfony/console/Exception/MissingInputException.php similarity index 51% rename from vendor/symfony/contracts/HttpClient/Exception/ExceptionInterface.php rename to vendor/symfony/console/Exception/MissingInputException.php index 6d59715f7..04f02ade4 100644 --- a/vendor/symfony/contracts/HttpClient/Exception/ExceptionInterface.php +++ b/vendor/symfony/console/Exception/MissingInputException.php @@ -9,15 +9,13 @@ * file that was distributed with this source code. */ -namespace Symfony\Contracts\HttpClient\Exception; +namespace Symfony\Component\Console\Exception; /** - * The base interface for all exceptions in the contract. + * Represents failure to read input from stdin. * - * @author Nicolas Grekas - * - * @experimental in 1.1 + * @author Gabriel Ostrolucký */ -interface ExceptionInterface extends \Throwable +class MissingInputException extends RuntimeException implements ExceptionInterface { } diff --git a/vendor/symfony/console/Formatter/OutputFormatter.php b/vendor/symfony/console/Formatter/OutputFormatter.php index 2b6db373d..e8c10e700 100644 --- a/vendor/symfony/console/Formatter/OutputFormatter.php +++ b/vendor/symfony/console/Formatter/OutputFormatter.php @@ -25,8 +25,16 @@ class OutputFormatter implements WrappableOutputFormatterInterface private $styles = []; private $styleStack; + public function __clone() + { + $this->styleStack = clone $this->styleStack; + foreach ($this->styles as $key => $value) { + $this->styles[$key] = clone $value; + } + } + /** - * Escapes "<" special char in given text. + * Escapes "<" and ">" special chars in given text. * * @param string $text Text to escape * @@ -34,7 +42,7 @@ class OutputFormatter implements WrappableOutputFormatterInterface */ public static function escape($text) { - $text = preg_replace('/([^\\\\]?)])/', '$1\\\\$2', $text); return self::escapeTrailingBackslash($text); } @@ -42,15 +50,11 @@ class OutputFormatter implements WrappableOutputFormatterInterface /** * Escapes trailing "\" in given text. * - * @param string $text Text to escape - * - * @return string Escaped text - * * @internal */ - public static function escapeTrailingBackslash($text) + public static function escapeTrailingBackslash(string $text): string { - if ('\\' === substr($text, -1)) { + if (str_ends_with($text, '\\')) { $len = \strlen($text); $text = rtrim($text, '\\'); $text = str_replace("\0", '', $text); @@ -63,8 +67,7 @@ class OutputFormatter implements WrappableOutputFormatterInterface /** * Initializes console output formatter. * - * @param bool $decorated Whether this formatter should actually decorate strings - * @param OutputFormatterStyleInterface[] $styles Array of "name => FormatterStyle" instances + * @param OutputFormatterStyleInterface[] $styles Array of "name => FormatterStyle" instances */ public function __construct(bool $decorated = false, array $styles = []) { @@ -120,7 +123,7 @@ class OutputFormatter implements WrappableOutputFormatterInterface public function getStyle($name) { if (!$this->hasStyle($name)) { - throw new InvalidArgumentException(sprintf('Undefined style: %s', $name)); + throw new InvalidArgumentException(sprintf('Undefined style: "%s".', $name)); } return $this->styles[strtolower($name)]; @@ -141,9 +144,10 @@ class OutputFormatter implements WrappableOutputFormatterInterface { $offset = 0; $output = ''; - $tagRegex = '[a-z][a-z0-9,_=;-]*+'; + $openTagRegex = '[a-z](?:[^\\\\<>]*+ | \\\\.)*'; + $closeTagRegex = '[a-z][^<>]*+'; $currentLineLength = 0; - preg_match_all("#<(($tagRegex) | /($tagRegex)?)>#ix", $message, $matches, PREG_OFFSET_CAPTURE); + preg_match_all("#<(($openTagRegex) | /($closeTagRegex)?)>#ix", $message, $matches, \PREG_OFFSET_CAPTURE); foreach ($matches[0] as $i => $match) { $pos = $match[1]; $text = $match[0]; @@ -160,13 +164,13 @@ class OutputFormatter implements WrappableOutputFormatterInterface if ($open = '/' != $text[1]) { $tag = $matches[1][$i][0]; } else { - $tag = isset($matches[3][$i][0]) ? $matches[3][$i][0] : ''; + $tag = $matches[3][$i][0] ?? ''; } if (!$open && !$tag) { // $this->styleStack->pop(); - } elseif (false === $style = $this->createStyleFromString($tag)) { + } elseif (null === $style = $this->createStyleFromString($tag)) { $output .= $this->applyCurrentStyle($text, $output, $width, $currentLineLength); } elseif ($open) { $this->styleStack->push($style); @@ -177,11 +181,7 @@ class OutputFormatter implements WrappableOutputFormatterInterface $output .= $this->applyCurrentStyle(substr($message, $offset), $output, $width, $currentLineLength); - if (false !== strpos($output, "\0")) { - return strtr($output, ["\0" => '\\', '\\<' => '<']); - } - - return str_replace('\\<', '<', $output); + return strtr($output, ["\0" => '\\', '\\<' => '<', '\\>' => '>']); } /** @@ -194,17 +194,15 @@ class OutputFormatter implements WrappableOutputFormatterInterface /** * Tries to create new style instance from string. - * - * @return OutputFormatterStyle|false False if string is not format string */ - private function createStyleFromString(string $string) + private function createStyleFromString(string $string): ?OutputFormatterStyleInterface { if (isset($this->styles[$string])) { return $this->styles[$string]; } - if (!preg_match_all('/([^=]+)=([^;]+)(;|$)/', $string, $matches, PREG_SET_ORDER)) { - return false; + if (!preg_match_all('/([^=]+)=([^;]+)(;|$)/', $string, $matches, \PREG_SET_ORDER)) { + return null; } $style = new OutputFormatterStyle(); @@ -216,6 +214,9 @@ class OutputFormatter implements WrappableOutputFormatterInterface $style->setForeground(strtolower($match[1])); } elseif ('bg' == $match[0]) { $style->setBackground(strtolower($match[1])); + } elseif ('href' === $match[0]) { + $url = preg_replace('{\\\\([<>])}', '$1', $match[1]); + $style->setHref($url); } elseif ('options' === $match[0]) { preg_match_all('([^,;]+)', strtolower($match[1]), $options); $options = array_shift($options); @@ -223,7 +224,7 @@ class OutputFormatter implements WrappableOutputFormatterInterface $style->setOption($option); } } else { - return false; + return null; } } diff --git a/vendor/symfony/console/Formatter/OutputFormatterInterface.php b/vendor/symfony/console/Formatter/OutputFormatterInterface.php index 281e240c5..22f40a34e 100644 --- a/vendor/symfony/console/Formatter/OutputFormatterInterface.php +++ b/vendor/symfony/console/Formatter/OutputFormatterInterface.php @@ -35,8 +35,7 @@ interface OutputFormatterInterface /** * Sets a new style. * - * @param string $name The style name - * @param OutputFormatterStyleInterface $style The style instance + * @param string $name The style name */ public function setStyle($name, OutputFormatterStyleInterface $style); diff --git a/vendor/symfony/console/Formatter/OutputFormatterStyle.php b/vendor/symfony/console/Formatter/OutputFormatterStyle.php index d1d33ca2e..7cb6116b4 100644 --- a/vendor/symfony/console/Formatter/OutputFormatterStyle.php +++ b/vendor/symfony/console/Formatter/OutputFormatterStyle.php @@ -52,14 +52,15 @@ class OutputFormatterStyle implements OutputFormatterStyleInterface private $foreground; private $background; + private $href; private $options = []; + private $handlesHrefGracefully; /** * Initializes output formatter style. * * @param string|null $foreground The style foreground color name * @param string|null $background The style background color name - * @param array $options The style options */ public function __construct(string $foreground = null, string $background = null, array $options = []) { @@ -86,7 +87,7 @@ class OutputFormatterStyle implements OutputFormatterStyleInterface } if (!isset(static::$availableForegroundColors[$color])) { - throw new InvalidArgumentException(sprintf('Invalid foreground color specified: "%s". Expected one of (%s)', $color, implode(', ', array_keys(static::$availableForegroundColors)))); + throw new InvalidArgumentException(sprintf('Invalid foreground color specified: "%s". Expected one of (%s).', $color, implode(', ', array_keys(static::$availableForegroundColors)))); } $this->foreground = static::$availableForegroundColors[$color]; @@ -104,19 +105,24 @@ class OutputFormatterStyle implements OutputFormatterStyleInterface } if (!isset(static::$availableBackgroundColors[$color])) { - throw new InvalidArgumentException(sprintf('Invalid background color specified: "%s". Expected one of (%s)', $color, implode(', ', array_keys(static::$availableBackgroundColors)))); + throw new InvalidArgumentException(sprintf('Invalid background color specified: "%s". Expected one of (%s).', $color, implode(', ', array_keys(static::$availableBackgroundColors)))); } $this->background = static::$availableBackgroundColors[$color]; } + public function setHref(string $url): void + { + $this->href = $url; + } + /** * {@inheritdoc} */ public function setOption($option) { if (!isset(static::$availableOptions[$option])) { - throw new InvalidArgumentException(sprintf('Invalid option specified: "%s". Expected one of (%s)', $option, implode(', ', array_keys(static::$availableOptions)))); + throw new InvalidArgumentException(sprintf('Invalid option specified: "%s". Expected one of (%s).', $option, implode(', ', array_keys(static::$availableOptions)))); } if (!\in_array(static::$availableOptions[$option], $this->options)) { @@ -130,7 +136,7 @@ class OutputFormatterStyle implements OutputFormatterStyleInterface public function unsetOption($option) { if (!isset(static::$availableOptions[$option])) { - throw new InvalidArgumentException(sprintf('Invalid option specified: "%s". Expected one of (%s)', $option, implode(', ', array_keys(static::$availableOptions)))); + throw new InvalidArgumentException(sprintf('Invalid option specified: "%s". Expected one of (%s).', $option, implode(', ', array_keys(static::$availableOptions)))); } $pos = array_search(static::$availableOptions[$option], $this->options); @@ -159,6 +165,11 @@ class OutputFormatterStyle implements OutputFormatterStyleInterface $setCodes = []; $unsetCodes = []; + if (null === $this->handlesHrefGracefully) { + $this->handlesHrefGracefully = 'JetBrains-JediTerm' !== getenv('TERMINAL_EMULATOR') + && (!getenv('KONSOLE_VERSION') || (int) getenv('KONSOLE_VERSION') > 201100); + } + if (null !== $this->foreground) { $setCodes[] = $this->foreground['set']; $unsetCodes[] = $this->foreground['unset']; @@ -167,11 +178,14 @@ class OutputFormatterStyle implements OutputFormatterStyleInterface $setCodes[] = $this->background['set']; $unsetCodes[] = $this->background['unset']; } - if (\count($this->options)) { - foreach ($this->options as $option) { - $setCodes[] = $option['set']; - $unsetCodes[] = $option['unset']; - } + + foreach ($this->options as $option) { + $setCodes[] = $option['set']; + $unsetCodes[] = $option['unset']; + } + + if (null !== $this->href && $this->handlesHrefGracefully) { + $text = "\033]8;;$this->href\033\\$text\033]8;;\033\\"; } if (0 === \count($setCodes)) { diff --git a/vendor/symfony/console/Formatter/OutputFormatterStyleStack.php b/vendor/symfony/console/Formatter/OutputFormatterStyleStack.php index 33f7d5222..fc48dc0e1 100644 --- a/vendor/symfony/console/Formatter/OutputFormatterStyleStack.php +++ b/vendor/symfony/console/Formatter/OutputFormatterStyleStack.php @@ -28,7 +28,7 @@ class OutputFormatterStyleStack implements ResetInterface public function __construct(OutputFormatterStyleInterface $emptyStyle = null) { - $this->emptyStyle = $emptyStyle ?: new OutputFormatterStyle(); + $this->emptyStyle = $emptyStyle ?? new OutputFormatterStyle(); $this->reset(); } diff --git a/vendor/symfony/console/Helper/DebugFormatterHelper.php b/vendor/symfony/console/Helper/DebugFormatterHelper.php index 16d117553..1653edeb1 100644 --- a/vendor/symfony/console/Helper/DebugFormatterHelper.php +++ b/vendor/symfony/console/Helper/DebugFormatterHelper.php @@ -107,12 +107,7 @@ class DebugFormatterHelper extends Helper return $message; } - /** - * @param string $id The id of the formatting session - * - * @return string - */ - private function getBorder($id) + private function getBorder(string $id): string { return sprintf(' ', $this->colors[$this->started[$id]['border']]); } diff --git a/vendor/symfony/console/Helper/DescriptorHelper.php b/vendor/symfony/console/Helper/DescriptorHelper.php index f8a3847b4..3055baefd 100644 --- a/vendor/symfony/console/Helper/DescriptorHelper.php +++ b/vendor/symfony/console/Helper/DescriptorHelper.php @@ -48,9 +48,7 @@ class DescriptorHelper extends Helper * * format: string, the output format name * * raw_text: boolean, sets output type as raw * - * @param OutputInterface $output - * @param object $object - * @param array $options + * @param object $object * * @throws InvalidArgumentException when the given format is not supported */ @@ -72,8 +70,7 @@ class DescriptorHelper extends Helper /** * Registers a descriptor. * - * @param string $format - * @param DescriptorInterface $descriptor + * @param string $format * * @return $this */ diff --git a/vendor/symfony/console/Helper/Dumper.php b/vendor/symfony/console/Helper/Dumper.php new file mode 100644 index 000000000..b013b6c52 --- /dev/null +++ b/vendor/symfony/console/Helper/Dumper.php @@ -0,0 +1,64 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Helper; + +use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\VarDumper\Cloner\ClonerInterface; +use Symfony\Component\VarDumper\Cloner\VarCloner; +use Symfony\Component\VarDumper\Dumper\CliDumper; + +/** + * @author Roland Franssen + */ +final class Dumper +{ + private $output; + private $dumper; + private $cloner; + private $handler; + + public function __construct(OutputInterface $output, CliDumper $dumper = null, ClonerInterface $cloner = null) + { + $this->output = $output; + $this->dumper = $dumper; + $this->cloner = $cloner; + + if (class_exists(CliDumper::class)) { + $this->handler = function ($var): string { + $dumper = $this->dumper ?? $this->dumper = new CliDumper(null, null, CliDumper::DUMP_LIGHT_ARRAY | CliDumper::DUMP_COMMA_SEPARATOR); + $dumper->setColors($this->output->isDecorated()); + + return rtrim($dumper->dump(($this->cloner ?? $this->cloner = new VarCloner())->cloneVar($var)->withRefHandles(false), true)); + }; + } else { + $this->handler = function ($var): string { + switch (true) { + case null === $var: + return 'null'; + case true === $var: + return 'true'; + case false === $var: + return 'false'; + case \is_string($var): + return '"'.$var.'"'; + default: + return rtrim(print_r($var, true)); + } + }; + } + } + + public function __invoke($var): string + { + return ($this->handler)($var); + } +} diff --git a/vendor/symfony/console/Helper/FormatterHelper.php b/vendor/symfony/console/Helper/FormatterHelper.php index 4ad63856d..d6eccee8e 100644 --- a/vendor/symfony/console/Helper/FormatterHelper.php +++ b/vendor/symfony/console/Helper/FormatterHelper.php @@ -54,12 +54,12 @@ class FormatterHelper extends Helper foreach ($messages as $message) { $message = OutputFormatter::escape($message); $lines[] = sprintf($large ? ' %s ' : ' %s ', $message); - $len = max($this->strlen($message) + ($large ? 4 : 2), $len); + $len = max(self::strlen($message) + ($large ? 4 : 2), $len); } $messages = $large ? [str_repeat(' ', $len)] : []; for ($i = 0; isset($lines[$i]); ++$i) { - $messages[] = $lines[$i].str_repeat(' ', $len - $this->strlen($lines[$i])); + $messages[] = $lines[$i].str_repeat(' ', $len - self::strlen($lines[$i])); } if ($large) { $messages[] = str_repeat(' ', $len); @@ -83,17 +83,13 @@ class FormatterHelper extends Helper */ public function truncate($message, $length, $suffix = '...') { - $computedLength = $length - $this->strlen($suffix); + $computedLength = $length - self::strlen($suffix); - if ($computedLength > $this->strlen($message)) { + if ($computedLength > self::strlen($message)) { return $message; } - if (false === $encoding = mb_detect_encoding($message, null, true)) { - return substr($message, 0, $length).$suffix; - } - - return mb_substr($message, 0, $length, $encoding).$suffix; + return self::substr($message, 0, $length).$suffix; } /** diff --git a/vendor/symfony/console/Helper/Helper.php b/vendor/symfony/console/Helper/Helper.php index 0ddddf6bc..0521aaf7d 100644 --- a/vendor/symfony/console/Helper/Helper.php +++ b/vendor/symfony/console/Helper/Helper.php @@ -47,6 +47,8 @@ abstract class Helper implements HelperInterface */ public static function strlen($string) { + $string = (string) $string; + if (false === $encoding = mb_detect_encoding($string, null, true)) { return \strlen($string); } @@ -65,6 +67,8 @@ abstract class Helper implements HelperInterface */ public static function substr($string, $from, $length = null) { + $string = (string) $string; + if (false === $encoding = mb_detect_encoding($string, null, true)) { return substr($string, $from, $length); } diff --git a/vendor/symfony/console/Helper/HelperSet.php b/vendor/symfony/console/Helper/HelperSet.php index c73fecd47..9aa1e67ba 100644 --- a/vendor/symfony/console/Helper/HelperSet.php +++ b/vendor/symfony/console/Helper/HelperSet.php @@ -40,8 +40,7 @@ class HelperSet implements \IteratorAggregate /** * Sets a helper. * - * @param HelperInterface $helper The helper instance - * @param string $alias An alias + * @param string $alias An alias */ public function set(HelperInterface $helper, $alias = null) { @@ -99,8 +98,9 @@ class HelperSet implements \IteratorAggregate } /** - * @return Helper[] + * @return \Traversable */ + #[\ReturnTypeWillChange] public function getIterator() { return new \ArrayIterator($this->helpers); diff --git a/vendor/symfony/console/Helper/ProcessHelper.php b/vendor/symfony/console/Helper/ProcessHelper.php index 41f128bb4..862d09f21 100644 --- a/vendor/symfony/console/Helper/ProcessHelper.php +++ b/vendor/symfony/console/Helper/ProcessHelper.php @@ -28,17 +28,20 @@ class ProcessHelper extends Helper /** * Runs an external process. * - * @param OutputInterface $output An OutputInterface instance - * @param array|Process $cmd An instance of Process or an array of the command and arguments - * @param string|null $error An error message that must be displayed if something went wrong - * @param callable|null $callback A PHP callback to run whenever there is some - * output available on STDOUT or STDERR - * @param int $verbosity The threshold for verbosity + * @param array|Process $cmd An instance of Process or an array of the command and arguments + * @param string|null $error An error message that must be displayed if something went wrong + * @param callable|null $callback A PHP callback to run whenever there is some + * output available on STDOUT or STDERR + * @param int $verbosity The threshold for verbosity * * @return Process The process that ran */ public function run(OutputInterface $output, $cmd, $error = null, callable $callback = null, $verbosity = OutputInterface::VERBOSITY_VERY_VERBOSE) { + if (!class_exists(Process::class)) { + throw new \LogicException('The ProcessHelper cannot be run as the Process component is not installed. Try running "compose require symfony/process".'); + } + if ($output instanceof ConsoleOutputInterface) { $output = $output->getErrorOutput(); } @@ -50,7 +53,7 @@ class ProcessHelper extends Helper } if (!\is_array($cmd)) { - @trigger_error(sprintf('Passing a command as a string to "%s()" is deprecated since Symfony 4.2, pass it the command as an array of arguments instead.', __METHOD__), E_USER_DEPRECATED); + @trigger_error(sprintf('Passing a command as a string to "%s()" is deprecated since Symfony 4.2, pass it the command as an array of arguments instead.', __METHOD__), \E_USER_DEPRECATED); $cmd = [method_exists(Process::class, 'fromShellCommandline') ? Process::fromShellCommandline($cmd) : new Process($cmd)]; } @@ -92,11 +95,10 @@ class ProcessHelper extends Helper * This is identical to run() except that an exception is thrown if the process * exits with a non-zero exit code. * - * @param OutputInterface $output An OutputInterface instance - * @param string|Process $cmd An instance of Process or a command to run - * @param string|null $error An error message that must be displayed if something went wrong - * @param callable|null $callback A PHP callback to run whenever there is some - * output available on STDOUT or STDERR + * @param array|Process $cmd An instance of Process or a command to run + * @param string|null $error An error message that must be displayed if something went wrong + * @param callable|null $callback A PHP callback to run whenever there is some + * output available on STDOUT or STDERR * * @return Process The process that ran * @@ -118,10 +120,6 @@ class ProcessHelper extends Helper /** * Wraps a Process callback to add debugging output. * - * @param OutputInterface $output An OutputInterface interface - * @param Process $process The Process - * @param callable|null $callback A PHP callable - * * @return callable */ public function wrapCallback(OutputInterface $output, Process $process, callable $callback = null) @@ -141,7 +139,7 @@ class ProcessHelper extends Helper }; } - private function escapeString($str) + private function escapeString(string $str): string { return str_replace('<', '\\<', $str); } diff --git a/vendor/symfony/console/Helper/ProgressBar.php b/vendor/symfony/console/Helper/ProgressBar.php index 12a6cf224..1de9b7b3c 100644 --- a/vendor/symfony/console/Helper/ProgressBar.php +++ b/vendor/symfony/console/Helper/ProgressBar.php @@ -32,6 +32,10 @@ final class ProgressBar private $format; private $internalFormat; private $redrawFreq = 1; + private $writeCount; + private $lastWriteTime; + private $minSecondsBetweenRedraws = 0; + private $maxSecondsBetweenRedraws = 1; private $output; private $step = 0; private $max; @@ -42,16 +46,15 @@ final class ProgressBar private $messages = []; private $overwrite = true; private $terminal; - private $firstRun = true; + private $previousMessage; private static $formatters; private static $formats; /** - * @param OutputInterface $output An OutputInterface instance - * @param int $max Maximum steps (0 if unknown) + * @param int $max Maximum steps (0 if unknown) */ - public function __construct(OutputInterface $output, int $max = 0) + public function __construct(OutputInterface $output, int $max = 0, float $minSecondsBetweenRedraws = 0.1) { if ($output instanceof ConsoleOutputInterface) { $output = $output->getErrorOutput(); @@ -61,12 +64,17 @@ final class ProgressBar $this->setMaxSteps($max); $this->terminal = new Terminal(); + if (0 < $minSecondsBetweenRedraws) { + $this->redrawFreq = null; + $this->minSecondsBetweenRedraws = $minSecondsBetweenRedraws; + } + if (!$this->output->isDecorated()) { // disable overwrite when output does not support ANSI codes. $this->overwrite = false; // set a reasonable redraw frequency so output isn't flooded - $this->setRedrawFrequency($max / 10); + $this->redrawFreq = null; } $this->startTime = time(); @@ -102,7 +110,7 @@ final class ProgressBar self::$formatters = self::initPlaceholderFormatters(); } - return isset(self::$formatters[$name]) ? self::$formatters[$name] : null; + return self::$formatters[$name] ?? null; } /** @@ -135,7 +143,7 @@ final class ProgressBar self::$formats = self::initFormats(); } - return isset(self::$formats[$name]) ? self::$formats[$name] : null; + return self::$formats[$name] ?? null; } /** @@ -183,6 +191,11 @@ final class ProgressBar return $this->percent; } + public function getBarOffset(): int + { + return floor($this->max ? $this->percent * $this->barWidth : (null === $this->redrawFreq ? (int) (min(5, $this->barWidth / 15) * $this->writeCount) : $this->step) % $this->barWidth); + } + public function setBarWidth(int $size) { $this->barWidth = max(1, $size); @@ -236,11 +249,39 @@ final class ProgressBar /** * Sets the redraw frequency. * - * @param int|float $freq The frequency in steps + * @param int|null $freq The frequency in steps */ - public function setRedrawFrequency(int $freq) + public function setRedrawFrequency(?int $freq) { - $this->redrawFreq = max($freq, 1); + $this->redrawFreq = null !== $freq ? max(1, $freq) : null; + } + + public function minSecondsBetweenRedraws(float $seconds): void + { + $this->minSecondsBetweenRedraws = $seconds; + } + + public function maxSecondsBetweenRedraws(float $seconds): void + { + $this->maxSecondsBetweenRedraws = $seconds; + } + + /** + * Returns an iterator that will automatically update the progress bar when iterated. + * + * @param int|null $max Number of steps to complete the bar (0 if indeterminate), if null it will be inferred from $iterable + */ + public function iterate(iterable $iterable, int $max = null): iterable + { + $this->start($max ?? (is_countable($iterable) ? \count($iterable) : 0)); + + foreach ($iterable as $key => $value) { + yield $key => $value; + + $this->advance(); + } + + $this->finish(); } /** @@ -287,11 +328,27 @@ final class ProgressBar $step = 0; } - $prevPeriod = (int) ($this->step / $this->redrawFreq); - $currPeriod = (int) ($step / $this->redrawFreq); + $redrawFreq = $this->redrawFreq ?? (($this->max ?: 10) / 10); + $prevPeriod = (int) ($this->step / $redrawFreq); + $currPeriod = (int) ($step / $redrawFreq); $this->step = $step; $this->percent = $this->max ? (float) $this->step / $this->max : 0; - if ($prevPeriod !== $currPeriod || $this->max === $step) { + $timeInterval = microtime(true) - $this->lastWriteTime; + + // Draw regardless of other limits + if ($this->max === $step) { + $this->display(); + + return; + } + + // Throttling + if ($timeInterval < $this->minSecondsBetweenRedraws) { + return; + } + + // Draw each step period, but not too late + if ($prevPeriod !== $currPeriod || $timeInterval >= $this->maxSecondsBetweenRedraws) { $this->display(); } } @@ -375,11 +432,24 @@ final class ProgressBar */ private function overwrite(string $message): void { + if ($this->previousMessage === $message) { + return; + } + + $originalMessage = $message; + if ($this->overwrite) { - if (!$this->firstRun) { + if (null !== $this->previousMessage) { if ($this->output instanceof ConsoleSectionOutput) { - $lines = floor(Helper::strlen($message) / $this->terminal->getWidth()) + $this->formatLineCount + 1; - $this->output->clear($lines); + $messageLines = explode("\n", $message); + $lineCount = \count($messageLines); + foreach ($messageLines as $messageLine) { + $messageLineLength = Helper::strlenWithoutDecoration($this->output->getFormatter(), $messageLine); + if ($messageLineLength > $this->terminal->getWidth()) { + $lineCount += floor($messageLineLength / $this->terminal->getWidth()); + } + } + $this->output->clear($lineCount); } else { // Erase previous lines if ($this->formatLineCount > 0) { @@ -391,12 +461,14 @@ final class ProgressBar } } } elseif ($this->step > 0) { - $message = PHP_EOL.$message; + $message = \PHP_EOL.$message; } - $this->firstRun = false; + $this->previousMessage = $originalMessage; + $this->lastWriteTime = microtime(true); $this->output->write($message); + ++$this->writeCount; } private function determineBestFormat(): string @@ -418,7 +490,7 @@ final class ProgressBar { return [ 'bar' => function (self $bar, OutputInterface $output) { - $completeBars = floor($bar->getMaxSteps() > 0 ? $bar->getProgressPercent() * $bar->getBarWidth() : $bar->getProgress() % $bar->getBarWidth()); + $completeBars = $bar->getBarOffset(); $display = str_repeat($bar->getBarCharacter(), $completeBars); if ($completeBars < $bar->getBarWidth()) { $emptyBars = $bar->getBarWidth() - $completeBars - Helper::strlenWithoutDecoration($output->getFormatter(), $bar->getProgressCharacter()); @@ -460,7 +532,7 @@ final class ProgressBar return Helper::formatMemory(memory_get_usage(true)); }, 'current' => function (self $bar) { - return str_pad($bar->getProgress(), $bar->getStepWidth(), ' ', STR_PAD_LEFT); + return str_pad($bar->getProgress(), $bar->getStepWidth(), ' ', \STR_PAD_LEFT); }, 'max' => function (self $bar) { return $bar->getMaxSteps(); diff --git a/vendor/symfony/console/Helper/ProgressIndicator.php b/vendor/symfony/console/Helper/ProgressIndicator.php index 301be27ea..dc37148ed 100644 --- a/vendor/symfony/console/Helper/ProgressIndicator.php +++ b/vendor/symfony/console/Helper/ProgressIndicator.php @@ -34,10 +34,9 @@ class ProgressIndicator private static $formats; /** - * @param OutputInterface $output - * @param string|null $format Indicator format - * @param int $indicatorChangeInterval Change interval in milliseconds - * @param array|null $indicatorValues Animated indicator characters + * @param string|null $format Indicator format + * @param int $indicatorChangeInterval Change interval in milliseconds + * @param array|null $indicatorValues Animated indicator characters */ public function __construct(OutputInterface $output, string $format = null, int $indicatorChangeInterval = 100, array $indicatorValues = null) { @@ -150,7 +149,7 @@ class ProgressIndicator self::$formats = self::initFormats(); } - return isset(self::$formats[$name]) ? self::$formats[$name] : null; + return self::$formats[$name] ?? null; } /** @@ -183,7 +182,7 @@ class ProgressIndicator self::$formatters = self::initPlaceholderFormatters(); } - return isset(self::$formatters[$name]) ? self::$formatters[$name] : null; + return self::$formatters[$name] ?? null; } private function display() @@ -192,18 +191,16 @@ class ProgressIndicator return; } - $self = $this; - - $this->overwrite(preg_replace_callback("{%([a-z\-_]+)(?:\:([^%]+))?%}i", function ($matches) use ($self) { - if ($formatter = $self::getPlaceholderFormatterDefinition($matches[1])) { - return $formatter($self); + $this->overwrite(preg_replace_callback("{%([a-z\-_]+)(?:\:([^%]+))?%}i", function ($matches) { + if ($formatter = self::getPlaceholderFormatterDefinition($matches[1])) { + return $formatter($this); } return $matches[0]; - }, $this->format)); + }, $this->format ?? '')); } - private function determineBestFormat() + private function determineBestFormat(): string { switch ($this->output->getVerbosity()) { // OutputInterface::VERBOSITY_QUIET: display is disabled anyway @@ -230,12 +227,12 @@ class ProgressIndicator } } - private function getCurrentTimeInMilliseconds() + private function getCurrentTimeInMilliseconds(): float { return round(microtime(true) * 1000); } - private static function initPlaceholderFormatters() + private static function initPlaceholderFormatters(): array { return [ 'indicator' => function (self $indicator) { @@ -253,7 +250,7 @@ class ProgressIndicator ]; } - private static function initFormats() + private static function initFormats(): array { return [ 'normal' => ' %indicator% %message%', diff --git a/vendor/symfony/console/Helper/QuestionHelper.php b/vendor/symfony/console/Helper/QuestionHelper.php index 4c8c8e166..a4754b824 100644 --- a/vendor/symfony/console/Helper/QuestionHelper.php +++ b/vendor/symfony/console/Helper/QuestionHelper.php @@ -11,6 +11,7 @@ namespace Symfony\Component\Console\Helper; +use Symfony\Component\Console\Exception\MissingInputException; use Symfony\Component\Console\Exception\RuntimeException; use Symfony\Component\Console\Formatter\OutputFormatter; use Symfony\Component\Console\Formatter\OutputFormatterStyle; @@ -21,6 +22,7 @@ use Symfony\Component\Console\Output\ConsoleSectionOutput; use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Question\ChoiceQuestion; use Symfony\Component\Console\Question\Question; +use Symfony\Component\Console\Terminal; /** * The QuestionHelper class provides helpers to interact with the user. @@ -31,7 +33,8 @@ class QuestionHelper extends Helper { private $inputStream; private static $shell; - private static $stty; + private static $stty = true; + private static $stdinIsInteractive; /** * Asks a question to the user. @@ -47,44 +50,32 @@ class QuestionHelper extends Helper } if (!$input->isInteractive()) { - $default = $question->getDefault(); - - if (null === $default) { - return $default; - } - - if ($validator = $question->getValidator()) { - return \call_user_func($question->getValidator(), $default); - } elseif ($question instanceof ChoiceQuestion) { - $choices = $question->getChoices(); - - if (!$question->isMultiselect()) { - return isset($choices[$default]) ? $choices[$default] : $default; - } - - $default = explode(',', $default); - foreach ($default as $k => $v) { - $v = trim($v); - $default[$k] = isset($choices[$v]) ? $choices[$v] : $v; - } - } - - return $default; + return $this->getDefaultAnswer($question); } if ($input instanceof StreamableInputInterface && $stream = $input->getStream()) { $this->inputStream = $stream; } - if (!$question->getValidator()) { - return $this->doAsk($output, $question); + try { + if (!$question->getValidator()) { + return $this->doAsk($output, $question); + } + + $interviewer = function () use ($output, $question) { + return $this->doAsk($output, $question); + }; + + return $this->validateAttempts($interviewer, $output, $question); + } catch (MissingInputException $exception) { + $input->setInteractive(false); + + if (null === $fallbackOutput = $this->getDefaultAnswer($question)) { + throw $exception; + } + + return $fallbackOutput; } - - $interviewer = function () use ($output, $question) { - return $this->doAsk($output, $question); - }; - - return $this->validateAttempts($interviewer, $output, $question); } /** @@ -106,7 +97,7 @@ class QuestionHelper extends Helper /** * Asks the question to the user. * - * @return bool|mixed|string|null + * @return mixed * * @throws RuntimeException In case the fallback is deactivated and the response cannot be hidden */ @@ -114,14 +105,15 @@ class QuestionHelper extends Helper { $this->writePrompt($output, $question); - $inputStream = $this->inputStream ?: STDIN; - $autocomplete = $question->getAutocompleterValues(); + $inputStream = $this->inputStream ?: \STDIN; + $autocomplete = $question->getAutocompleterCallback(); - if (null === $autocomplete || !$this->hasSttyAvailable()) { + if (null === $autocomplete || !self::$stty || !Terminal::hasSttyAvailable()) { $ret = false; if ($question->isHidden()) { try { - $ret = trim($this->getHiddenResponse($output, $inputStream)); + $hiddenResponse = $this->getHiddenResponse($output, $inputStream, $question->isTrimmable()); + $ret = $question->isTrimmable() ? trim($hiddenResponse) : $hiddenResponse; } catch (RuntimeException $e) { if (!$question->isHiddenFallback()) { throw $e; @@ -130,14 +122,19 @@ class QuestionHelper extends Helper } if (false === $ret) { + $cp = $this->setIOCodepage(); $ret = fgets($inputStream, 4096); + $ret = $this->resetIOCodepage($cp, $ret); if (false === $ret) { - throw new RuntimeException('Aborted.'); + throw new MissingInputException('Aborted.'); + } + if ($question->isTrimmable()) { + $ret = trim($ret); } - $ret = trim($ret); } } else { - $ret = trim($this->autocomplete($output, $question, $inputStream, \is_array($autocomplete) ? $autocomplete : iterator_to_array($autocomplete, false))); + $autocomplete = $this->autocomplete($output, $question, $inputStream, $autocomplete); + $ret = $question->isTrimmable() ? trim($autocomplete) : $autocomplete; } if ($output instanceof ConsoleSectionOutput) { @@ -153,6 +150,36 @@ class QuestionHelper extends Helper return $ret; } + /** + * @return mixed + */ + private function getDefaultAnswer(Question $question) + { + $default = $question->getDefault(); + + if (null === $default) { + return $default; + } + + if ($validator = $question->getValidator()) { + return \call_user_func($question->getValidator(), $default); + } elseif ($question instanceof ChoiceQuestion) { + $choices = $question->getChoices(); + + if (!$question->isMultiselect()) { + return $choices[$default] ?? $default; + } + + $default = explode(',', $default); + foreach ($default as $k => $v) { + $v = $question->isTrimmable() ? trim($v) : $v; + $default[$k] = $choices[$v] ?? $v; + } + } + + return $default; + } + /** * Outputs the question prompt. */ @@ -161,15 +188,9 @@ class QuestionHelper extends Helper $message = $question->getQuestion(); if ($question instanceof ChoiceQuestion) { - $maxWidth = max(array_map([$this, 'strlen'], array_keys($question->getChoices()))); - - $messages = (array) $question->getQuestion(); - foreach ($question->getChoices() as $key => $value) { - $width = $maxWidth - $this->strlen($key); - $messages[] = ' ['.$key.str_repeat(' ', $width).'] '.$value; - } - - $output->writeln($messages); + $output->writeln(array_merge([ + $question->getQuestion(), + ], $this->formatChoiceQuestionChoices($question, 'info'))); $message = $question->getPrompt(); } @@ -177,6 +198,26 @@ class QuestionHelper extends Helper $output->write($message); } + /** + * @param string $tag + * + * @return string[] + */ + protected function formatChoiceQuestionChoices(ChoiceQuestion $question, $tag) + { + $messages = []; + + $maxWidth = max(array_map([__CLASS__, 'strlen'], array_keys($choices = $question->getChoices()))); + + foreach ($choices as $key => $value) { + $padding = str_repeat(' ', $maxWidth - self::strlen($key)); + + $messages[] = sprintf(" [<$tag>%s$padding] %s", $key, $value); + } + + return $messages; + } + /** * Outputs an error message. */ @@ -194,18 +235,16 @@ class QuestionHelper extends Helper /** * Autocompletes a question. * - * @param OutputInterface $output - * @param Question $question - * @param resource $inputStream + * @param resource $inputStream */ - private function autocomplete(OutputInterface $output, Question $question, $inputStream, array $autocomplete): string + private function autocomplete(OutputInterface $output, Question $question, $inputStream, callable $autocomplete): string { $fullChoice = ''; $ret = ''; $i = 0; $ofs = -1; - $matches = $autocomplete; + $matches = $autocomplete($ret); $numMatches = \count($matches); $sttyMode = shell_exec('stty -g'); @@ -223,25 +262,25 @@ class QuestionHelper extends Helper // as opposed to fgets(), fread() returns an empty string when the stream content is empty, not false. if (false === $c || ('' === $ret && '' === $c && null === $question->getDefault())) { shell_exec(sprintf('stty %s', $sttyMode)); - throw new RuntimeException('Aborted.'); + throw new MissingInputException('Aborted.'); } elseif ("\177" === $c) { // Backspace Character if (0 === $numMatches && 0 !== $i) { --$i; - $fullChoice = substr($fullChoice, 0, -1); + $fullChoice = self::substr($fullChoice, 0, $i); // Move cursor backwards $output->write("\033[1D"); } if (0 === $i) { $ofs = -1; - $matches = $autocomplete; + $matches = $autocomplete($ret); $numMatches = \count($matches); } else { $numMatches = 0; } // Pop the last character off the end of our string - $ret = substr($ret, 0, $i); + $ret = self::substr($ret, 0, $i); } elseif ("\033" === $c) { // Did we read an escape sequence? $c .= fread($inputStream, 2); @@ -262,12 +301,21 @@ class QuestionHelper extends Helper } elseif (\ord($c) < 32) { if ("\t" === $c || "\n" === $c) { if ($numMatches > 0 && -1 !== $ofs) { - $ret = $matches[$ofs]; + $ret = (string) $matches[$ofs]; // Echo out remaining chars for current match $remainingCharacters = substr($ret, \strlen(trim($this->mostRecentlyEnteredValue($fullChoice)))); $output->write($remainingCharacters); $fullChoice .= $remainingCharacters; - $i = \strlen($fullChoice); + $i = (false === $encoding = mb_detect_encoding($fullChoice, null, true)) ? \strlen($fullChoice) : mb_strlen($fullChoice, $encoding); + + $matches = array_filter( + $autocomplete($ret), + function ($match) use ($ret) { + return '' === $ret || str_starts_with($match, $ret); + } + ); + $numMatches = \count($matches); + $ofs = -1; } if ("\n" === $c) { @@ -298,9 +346,9 @@ class QuestionHelper extends Helper $numMatches = 0; $ofs = 0; - foreach ($autocomplete as $value) { + foreach ($autocomplete($ret) as $value) { // If typed characters match the beginning chunk of value (e.g. [AcmeDe]moBundle) - if (0 === strpos($value, $tempRet)) { + if (str_starts_with($value, $tempRet)) { $matches[$numMatches++] = $value; } } @@ -326,15 +374,15 @@ class QuestionHelper extends Helper return $fullChoice; } - private function mostRecentlyEnteredValue($entered) + private function mostRecentlyEnteredValue(string $entered): string { // Determine the most recent value that the user entered - if (false === strpos($entered, ',')) { + if (!str_contains($entered, ',')) { return $entered; } $choices = explode(',', $entered); - if (\strlen($lastChoice = trim($choices[\count($choices) - 1])) > 0) { + if ('' !== $lastChoice = trim($choices[\count($choices) - 1])) { return $lastChoice; } @@ -344,12 +392,12 @@ class QuestionHelper extends Helper /** * Gets a hidden response from user. * - * @param OutputInterface $output An Output instance - * @param resource $inputStream The handler resource + * @param resource $inputStream The handler resource + * @param bool $trimmable Is the answer trimmable * * @throws RuntimeException In case the fallback is deactivated and the response cannot be hidden */ - private function getHiddenResponse(OutputInterface $output, $inputStream): string + private function getHiddenResponse(OutputInterface $output, $inputStream, bool $trimmable = true): string { if ('\\' === \DIRECTORY_SEPARATOR) { $exe = __DIR__.'/../Resources/bin/hiddeninput.exe'; @@ -361,7 +409,8 @@ class QuestionHelper extends Helper $exe = $tmpExe; } - $value = rtrim(shell_exec($exe)); + $sExec = shell_exec('"'.$exe.'"'); + $value = $trimmable ? rtrim($sExec) : $sExec; $output->writeln(''); if (isset($tmpExe)) { @@ -371,41 +420,34 @@ class QuestionHelper extends Helper return $value; } - if ($this->hasSttyAvailable()) { + if (self::$stty && Terminal::hasSttyAvailable()) { $sttyMode = shell_exec('stty -g'); - shell_exec('stty -echo'); - $value = fgets($inputStream, 4096); + } elseif ($this->isInteractiveInput($inputStream)) { + throw new RuntimeException('Unable to hide the response.'); + } + + $value = fgets($inputStream, 4096); + + if (self::$stty && Terminal::hasSttyAvailable()) { shell_exec(sprintf('stty %s', $sttyMode)); + } - if (false === $value) { - throw new RuntimeException('Aborted.'); - } - + if (false === $value) { + throw new MissingInputException('Aborted.'); + } + if ($trimmable) { $value = trim($value); - $output->writeln(''); - - return $value; } + $output->writeln(''); - if (false !== $shell = $this->getShell()) { - $readCmd = 'csh' === $shell ? 'set mypassword = $<' : 'read -r mypassword'; - $command = sprintf("/usr/bin/env %s -c 'stty -echo; %s; stty echo; echo \$mypassword'", $shell, $readCmd); - $value = rtrim(shell_exec($command)); - $output->writeln(''); - - return $value; - } - - throw new RuntimeException('Unable to hide the response.'); + return $value; } /** * Validates an attempt. * - * @param callable $interviewer A callable that will ask for a question and return the result - * @param OutputInterface $output An Output instance - * @param Question $question A Question instance + * @param callable $interviewer A callable that will ask for a question and return the result * * @return mixed The validated response * @@ -415,6 +457,7 @@ class QuestionHelper extends Helper { $error = null; $attempts = $question->getMaxAttempts(); + while (null === $attempts || $attempts--) { if (null !== $error) { $this->writeError($output, $error); @@ -431,44 +474,67 @@ class QuestionHelper extends Helper throw $error; } - /** - * Returns a valid unix shell. - * - * @return string|bool The valid shell name, false in case no valid shell is found - */ - private function getShell() + private function isInteractiveInput($inputStream): bool { - if (null !== self::$shell) { - return self::$shell; + if ('php://stdin' !== (stream_get_meta_data($inputStream)['uri'] ?? null)) { + return false; } - self::$shell = false; + if (null !== self::$stdinIsInteractive) { + return self::$stdinIsInteractive; + } - if (file_exists('/usr/bin/env')) { - // handle other OSs with bash/zsh/ksh/csh if available to hide the answer - $test = "/usr/bin/env %s -c 'echo OK' 2> /dev/null"; - foreach (['bash', 'zsh', 'ksh', 'csh'] as $sh) { - if ('OK' === rtrim(shell_exec(sprintf($test, $sh)))) { - self::$shell = $sh; - break; - } + if (\function_exists('stream_isatty')) { + return self::$stdinIsInteractive = @stream_isatty(fopen('php://stdin', 'r')); + } + + if (\function_exists('posix_isatty')) { + return self::$stdinIsInteractive = @posix_isatty(fopen('php://stdin', 'r')); + } + + if (!\function_exists('exec')) { + return self::$stdinIsInteractive = true; + } + + exec('stty 2> /dev/null', $output, $status); + + return self::$stdinIsInteractive = 1 !== $status; + } + + /** + * Sets console I/O to the host code page. + * + * @return int Previous code page in IBM/EBCDIC format + */ + private function setIOCodepage(): int + { + if (\function_exists('sapi_windows_cp_set')) { + $cp = sapi_windows_cp_get(); + sapi_windows_cp_set(sapi_windows_cp_get('oem')); + + return $cp; + } + + return 0; + } + + /** + * Sets console I/O to the specified code page and converts the user input. + * + * @param string|false $input + * + * @return string|false + */ + private function resetIOCodepage(int $cp, $input) + { + if (0 !== $cp) { + sapi_windows_cp_set($cp); + + if (false !== $input && '' !== $input) { + $input = sapi_windows_cp_conv(sapi_windows_cp_get('oem'), $cp, $input); } } - return self::$shell; - } - - /** - * Returns whether Stty is available or not. - */ - private function hasSttyAvailable(): bool - { - if (null !== self::$stty) { - return self::$stty; - } - - exec('stty 2>&1', $output, $exitcode); - - return self::$stty = 0 === $exitcode; + return $input; } } diff --git a/vendor/symfony/console/Helper/SymfonyQuestionHelper.php b/vendor/symfony/console/Helper/SymfonyQuestionHelper.php index 260c03e20..ace5e1868 100644 --- a/vendor/symfony/console/Helper/SymfonyQuestionHelper.php +++ b/vendor/symfony/console/Helper/SymfonyQuestionHelper.php @@ -58,7 +58,7 @@ class SymfonyQuestionHelper extends QuestionHelper case $question instanceof ChoiceQuestion: $choices = $question->getChoices(); - $text = sprintf(' %s [%s]:', $text, OutputFormatter::escape(isset($choices[$default]) ? $choices[$default] : $default)); + $text = sprintf(' %s [%s]:', $text, OutputFormatter::escape($choices[$default] ?? $default)); break; @@ -68,15 +68,15 @@ class SymfonyQuestionHelper extends QuestionHelper $output->writeln($text); - if ($question instanceof ChoiceQuestion) { - $width = max(array_map('strlen', array_keys($question->getChoices()))); + $prompt = ' > '; - foreach ($question->getChoices() as $key => $value) { - $output->writeln(sprintf(" [%-${width}s] %s", $key, $value)); - } + if ($question instanceof ChoiceQuestion) { + $output->writeln($this->formatChoiceQuestionChoices($question, 'comment')); + + $prompt = $question->getPrompt(); } - $output->write(' > '); + $output->write($prompt); } /** diff --git a/vendor/symfony/console/Helper/Table.php b/vendor/symfony/console/Helper/Table.php index ce759953f..1d0a22baa 100644 --- a/vendor/symfony/console/Helper/Table.php +++ b/vendor/symfony/console/Helper/Table.php @@ -48,6 +48,7 @@ class Table * Table rows. */ private $rows = []; + private $horizontal = false; /** * Column widths cache. @@ -102,8 +103,7 @@ class Table /** * Sets a style definition. * - * @param string $name The style name - * @param TableStyle $style A TableStyle instance + * @param string $name The style name */ public static function setStyleDefinition($name, TableStyle $style) { @@ -207,8 +207,6 @@ class Table /** * Sets the minimum width of all columns. * - * @param array $widths - * * @return $this */ public function setColumnWidths(array $widths) @@ -325,6 +323,13 @@ class Table return $this; } + public function setHorizontal(bool $horizontal = true): self + { + $this->horizontal = $horizontal; + + return $this; + } + /** * Renders table to output. * @@ -340,14 +345,36 @@ class Table */ public function render() { - $rows = array_merge($this->headers, [$divider = new TableSeparator()], $this->rows); + $divider = new TableSeparator(); + if ($this->horizontal) { + $rows = []; + foreach ($this->headers[0] ?? [] as $i => $header) { + $rows[$i] = [$header]; + foreach ($this->rows as $row) { + if ($row instanceof TableSeparator) { + continue; + } + if (isset($row[$i])) { + $rows[$i][] = $row[$i]; + } elseif ($rows[$i][0] instanceof TableCell && $rows[$i][0]->getColspan() >= 2) { + // Noop, there is a "title" + } else { + $rows[$i][] = null; + } + } + } + } else { + $rows = array_merge($this->headers, [$divider], $this->rows); + } + $this->calculateNumberOfColumns($rows); $rows = $this->buildTableRows($rows); $this->calculateColumnsWidth($rows); - $isHeader = true; - $isFirstRow = false; + $isHeader = !$this->horizontal; + $isFirstRow = $this->horizontal; + $hasTitle = (bool) $this->headerTitle; foreach ($rows as $row) { if ($divider === $row) { $isHeader = false; @@ -365,15 +392,19 @@ class Table } if ($isHeader || $isFirstRow) { - if ($isFirstRow) { - $this->renderRowSeparator(self::SEPARATOR_TOP_BOTTOM); - $isFirstRow = false; - } else { - $this->renderRowSeparator(self::SEPARATOR_TOP, $this->headerTitle, $this->style->getHeaderTitleFormat()); - } + $this->renderRowSeparator( + $isHeader ? self::SEPARATOR_TOP : self::SEPARATOR_TOP_BOTTOM, + $hasTitle ? $this->headerTitle : null, + $hasTitle ? $this->style->getHeaderTitleFormat() : null + ); + $isFirstRow = false; + $hasTitle = false; + } + if ($this->horizontal) { + $this->renderRow($row, $this->style->getCellRowFormat(), $this->style->getCellHeaderFormat()); + } else { + $this->renderRow($row, $isHeader ? $this->style->getCellHeaderFormat() : $this->style->getCellRowFormat()); } - - $this->renderRow($row, $isHeader ? $this->style->getCellHeaderFormat() : $this->style->getCellRowFormat()); } $this->renderRowSeparator(self::SEPARATOR_BOTTOM, $this->footerTitle, $this->style->getFooterTitleFormat()); @@ -401,13 +432,13 @@ class Table $crossings = $this->style->getCrossingChars(); if (self::SEPARATOR_MID === $type) { - list($horizontal, $leftChar, $midChar, $rightChar) = [$borders[2], $crossings[8], $crossings[0], $crossings[4]]; + [$horizontal, $leftChar, $midChar, $rightChar] = [$borders[2], $crossings[8], $crossings[0], $crossings[4]]; } elseif (self::SEPARATOR_TOP === $type) { - list($horizontal, $leftChar, $midChar, $rightChar) = [$borders[0], $crossings[1], $crossings[2], $crossings[3]]; + [$horizontal, $leftChar, $midChar, $rightChar] = [$borders[0], $crossings[1], $crossings[2], $crossings[3]]; } elseif (self::SEPARATOR_TOP_BOTTOM === $type) { - list($horizontal, $leftChar, $midChar, $rightChar) = [$borders[0], $crossings[9], $crossings[10], $crossings[11]]; + [$horizontal, $leftChar, $midChar, $rightChar] = [$borders[0], $crossings[9], $crossings[10], $crossings[11]]; } else { - list($horizontal, $leftChar, $midChar, $rightChar) = [$borders[0], $crossings[7], $crossings[6], $crossings[5]]; + [$horizontal, $leftChar, $midChar, $rightChar] = [$borders[0], $crossings[7], $crossings[6], $crossings[5]]; } $markup = $leftChar; @@ -425,7 +456,7 @@ class Table $formattedTitle = sprintf($titleFormat, Helper::substr($title, 0, $limit - $formatLength - 3).'...'); } - $titleStart = ($markupLength - $titleLength) / 2; + $titleStart = intdiv($markupLength - $titleLength, 2); if (false === mb_detect_encoding($markup, null, true)) { $markup = substr_replace($markup, $formattedTitle, $titleStart, $titleLength); } else { @@ -439,7 +470,7 @@ class Table /** * Renders vertical column separator. */ - private function renderColumnSeparator($type = self::BORDER_OUTSIDE) + private function renderColumnSeparator(int $type = self::BORDER_OUTSIDE): string { $borders = $this->style->getBorderChars(); @@ -453,13 +484,17 @@ class Table * * | 9971-5-0210-0 | A Tale of Two Cities | Charles Dickens | */ - private function renderRow(array $row, string $cellFormat) + private function renderRow(array $row, string $cellFormat, string $firstCellFormat = null) { $rowContent = $this->renderColumnSeparator(self::BORDER_OUTSIDE); $columns = $this->getRowColumns($row); $last = \count($columns) - 1; foreach ($columns as $i => $column) { - $rowContent .= $this->renderCell($row, $column, $cellFormat); + if ($firstCellFormat && 0 === $i) { + $rowContent .= $this->renderCell($row, $column, $firstCellFormat); + } else { + $rowContent .= $this->renderCell($row, $column, $cellFormat); + } $rowContent .= $this->renderColumnSeparator($last === $i ? self::BORDER_OUTSIDE : self::BORDER_INSIDE); } $this->output->writeln($rowContent); @@ -468,9 +503,9 @@ class Table /** * Renders table cell with padding. */ - private function renderCell(array $row, int $column, string $cellFormat) + private function renderCell(array $row, int $column, string $cellFormat): string { - $cell = isset($row[$column]) ? $row[$column] : ''; + $cell = $row[$column] ?? ''; $width = $this->effectiveColumnWidths[$column]; if ($cell instanceof TableCell && $cell->getColspan() > 1) { // add the width of the following columns(numbers of colspan). @@ -499,7 +534,7 @@ class Table /** * Calculate number of columns for this table. */ - private function calculateNumberOfColumns($rows) + private function calculateNumberOfColumns(array $rows) { $columns = [0]; foreach ($rows as $row) { @@ -513,7 +548,7 @@ class Table $this->numberOfColumns = max($columns); } - private function buildTableRows($rows) + private function buildTableRows(array $rows): TableRows { /** @var WrappableOutputFormatterInterface $formatter */ $formatter = $this->output->getFormatter(); @@ -528,7 +563,7 @@ class Table if (isset($this->columnMaxWidths[$column]) && Helper::strlenWithoutDecoration($formatter, $cell) > $this->columnMaxWidths[$column]) { $cell = $formatter->formatAndWrap($cell, $this->columnMaxWidths[$column] * $colspan); } - if (!strstr($cell, "\n")) { + if (!strstr($cell ?? '', "\n")) { continue; } $escaped = implode("\n", array_map([OutputFormatter::class, 'escapeTrailingBackslash'], explode("\n", $cell))); @@ -541,19 +576,22 @@ class Table if (0 === $lineKey) { $rows[$rowKey][$column] = $line; } else { + if (!\array_key_exists($rowKey, $unmergedRows) || !\array_key_exists($lineKey, $unmergedRows[$rowKey])) { + $unmergedRows[$rowKey][$lineKey] = $this->copyRow($rows, $rowKey); + } $unmergedRows[$rowKey][$lineKey][$column] = $line; } } } } - return new TableRows(function () use ($rows, $unmergedRows) { + return new TableRows(function () use ($rows, $unmergedRows): \Traversable { foreach ($rows as $rowKey => $row) { - yield $this->fillCells($row); + yield $row instanceof TableSeparator ? $row : $this->fillCells($row); if (isset($unmergedRows[$rowKey])) { foreach ($unmergedRows[$rowKey] as $row) { - yield $row; + yield $row instanceof TableSeparator ? $row : $this->fillCells($row); } } } @@ -568,7 +606,9 @@ class Table ++$numberOfRows; // Add row for header separator } - ++$numberOfRows; // Add row for footer separator + if (\count($this->rows) > 0) { + ++$numberOfRows; // Add row for footer separator + } return $numberOfRows; } @@ -583,7 +623,7 @@ class Table $unmergedRows = []; foreach ($rows[$line] as $column => $cell) { if (null !== $cell && !$cell instanceof TableCell && !is_scalar($cell) && !(\is_object($cell) && method_exists($cell, '__toString'))) { - throw new InvalidArgumentException(sprintf('A cell must be a TableCell, a scalar or an object implementing __toString, %s given.', \gettype($cell))); + throw new InvalidArgumentException(sprintf('A cell must be a TableCell, a scalar or an object implementing "__toString()", "%s" given.', \gettype($cell))); } if ($cell instanceof TableCell && $cell->getRowspan() > 1) { $nbLines = $cell->getRowspan() - 1; @@ -599,7 +639,7 @@ class Table // create a two dimensional array (rowspan x colspan) $unmergedRows = array_replace_recursive(array_fill($line + 1, $nbLines, []), $unmergedRows); foreach ($unmergedRows as $unmergedRowKey => $unmergedRow) { - $value = isset($lines[$unmergedRowKey - $line]) ? $lines[$unmergedRowKey - $line] : ''; + $value = $lines[$unmergedRowKey - $line] ?? ''; $unmergedRows[$unmergedRowKey][$column] = new TableCell($value, ['colspan' => $cell->getColspan()]); if ($nbLines === $unmergedRowKey - $line) { break; @@ -632,9 +672,10 @@ class Table /** * fill cells for a row that contains colspan > 1. */ - private function fillCells($row) + private function fillCells(iterable $row) { $newRow = []; + foreach ($row as $column => $cell) { $newRow[] = $cell; if ($cell instanceof TableCell && $cell->getColspan() > 1) { @@ -736,7 +777,7 @@ class Table $cellWidth = Helper::strlenWithoutDecoration($this->output->getFormatter(), $cell); } - $columnWidth = isset($this->columnWidths[$column]) ? $this->columnWidths[$column] : 0; + $columnWidth = $this->columnWidths[$column] ?? 0; $cellWidth = max($cellWidth, $columnWidth); return isset($this->columnMaxWidths[$column]) ? min($this->columnMaxWidths[$column], $cellWidth) : $cellWidth; @@ -751,7 +792,7 @@ class Table $this->numberOfColumns = null; } - private static function initStyles() + private static function initStyles(): array { $borderless = new TableStyle(); $borderless @@ -798,7 +839,7 @@ class Table ]; } - private function resolveStyle($name) + private function resolveStyle($name): TableStyle { if ($name instanceof TableStyle) { return $name; diff --git a/vendor/symfony/console/Helper/TableRows.php b/vendor/symfony/console/Helper/TableRows.php index 4809daf1c..16aabb3fc 100644 --- a/vendor/symfony/console/Helper/TableRows.php +++ b/vendor/symfony/console/Helper/TableRows.php @@ -23,7 +23,7 @@ class TableRows implements \IteratorAggregate $this->generator = $generator; } - public function getIterator() + public function getIterator(): \Traversable { $g = $this->generator; diff --git a/vendor/symfony/console/Helper/TableStyle.php b/vendor/symfony/console/Helper/TableStyle.php index 02dd693c8..a8df59b3a 100644 --- a/vendor/symfony/console/Helper/TableStyle.php +++ b/vendor/symfony/console/Helper/TableStyle.php @@ -46,7 +46,7 @@ class TableStyle private $cellRowFormat = '%s'; private $cellRowContentFormat = ' %s '; private $borderFormat = '%s'; - private $padType = STR_PAD_RIGHT; + private $padType = \STR_PAD_RIGHT; /** * Sets padding character, used for cell padding. @@ -58,7 +58,7 @@ class TableStyle public function setPaddingChar($paddingChar) { if (!$paddingChar) { - throw new LogicException('The padding char must not be empty'); + throw new LogicException('The padding char must not be empty.'); } $this->paddingChar = $paddingChar; @@ -112,7 +112,7 @@ class TableStyle */ public function setHorizontalBorderChar($horizontalBorderChar) { - @trigger_error(sprintf('The "%s()" method is deprecated since Symfony 4.1, use setHorizontalBorderChars() instead.', __METHOD__), E_USER_DEPRECATED); + @trigger_error(sprintf('The "%s()" method is deprecated since Symfony 4.1, use setHorizontalBorderChars() instead.', __METHOD__), \E_USER_DEPRECATED); return $this->setHorizontalBorderChars($horizontalBorderChar, $horizontalBorderChar); } @@ -126,7 +126,7 @@ class TableStyle */ public function getHorizontalBorderChar() { - @trigger_error(sprintf('The "%s()" method is deprecated since Symfony 4.1, use getBorderChars() instead.', __METHOD__), E_USER_DEPRECATED); + @trigger_error(sprintf('The "%s()" method is deprecated since Symfony 4.1, use getBorderChars() instead.', __METHOD__), \E_USER_DEPRECATED); return $this->horizontalOutsideBorderChar; } @@ -168,7 +168,7 @@ class TableStyle */ public function setVerticalBorderChar($verticalBorderChar) { - @trigger_error(sprintf('The "%s()" method is deprecated since Symfony 4.1, use setVerticalBorderChars() instead.', __METHOD__), E_USER_DEPRECATED); + @trigger_error(sprintf('The "%s()" method is deprecated since Symfony 4.1, use setVerticalBorderChars() instead.', __METHOD__), \E_USER_DEPRECATED); return $this->setVerticalBorderChars($verticalBorderChar, $verticalBorderChar); } @@ -182,7 +182,7 @@ class TableStyle */ public function getVerticalBorderChar() { - @trigger_error(sprintf('The "%s()" method is deprecated since Symfony 4.1, use getBorderChars() instead.', __METHOD__), E_USER_DEPRECATED); + @trigger_error(sprintf('The "%s()" method is deprecated since Symfony 4.1, use getBorderChars() instead.', __METHOD__), \E_USER_DEPRECATED); return $this->verticalOutsideBorderChar; } @@ -192,7 +192,7 @@ class TableStyle * * @internal */ - public function getBorderChars() + public function getBorderChars(): array { return [ $this->horizontalOutsideBorderChar, @@ -270,7 +270,7 @@ class TableStyle */ public function setCrossingChar($crossingChar) { - @trigger_error(sprintf('The "%s()" method is deprecated since Symfony 4.1. Use setDefaultCrossingChar() instead.', __METHOD__), E_USER_DEPRECATED); + @trigger_error(sprintf('The "%s()" method is deprecated since Symfony 4.1. Use setDefaultCrossingChar() instead.', __METHOD__), \E_USER_DEPRECATED); return $this->setDefaultCrossingChar($crossingChar); } @@ -413,7 +413,7 @@ class TableStyle */ public function setPadType($padType) { - if (!\in_array($padType, [STR_PAD_LEFT, STR_PAD_RIGHT, STR_PAD_BOTH], true)) { + if (!\in_array($padType, [\STR_PAD_LEFT, \STR_PAD_RIGHT, \STR_PAD_BOTH], true)) { throw new InvalidArgumentException('Invalid padding type. Expected one of (STR_PAD_LEFT, STR_PAD_RIGHT, STR_PAD_BOTH).'); } diff --git a/vendor/symfony/console/Input/ArgvInput.php b/vendor/symfony/console/Input/ArgvInput.php index c56c20c68..63f40f271 100644 --- a/vendor/symfony/console/Input/ArgvInput.php +++ b/vendor/symfony/console/Input/ArgvInput.php @@ -44,14 +44,11 @@ class ArgvInput extends Input private $parsed; /** - * @param array|null $argv An array of parameters from the CLI (in the argv format) - * @param InputDefinition|null $definition A InputDefinition instance + * @param array|null $argv An array of parameters from the CLI (in the argv format) */ public function __construct(array $argv = null, InputDefinition $definition = null) { - if (null === $argv) { - $argv = $_SERVER['argv']; - } + $argv = $argv ?? $_SERVER['argv'] ?? []; // strip the application name array_shift($argv); @@ -78,7 +75,7 @@ class ArgvInput extends Input $this->parseArgument($token); } elseif ($parseOptions && '--' == $token) { $parseOptions = false; - } elseif ($parseOptions && 0 === strpos($token, '--')) { + } elseif ($parseOptions && str_starts_with($token, '--')) { $this->parseLongOption($token); } elseif ($parseOptions && '-' === $token[0] && '-' !== $token) { $this->parseShortOption($token); @@ -90,10 +87,8 @@ class ArgvInput extends Input /** * Parses a short option. - * - * @param string $token The current token */ - private function parseShortOption($token) + private function parseShortOption(string $token) { $name = substr($token, 1); @@ -112,11 +107,9 @@ class ArgvInput extends Input /** * Parses a short option set. * - * @param string $name The current token - * * @throws RuntimeException When option given doesn't exist */ - private function parseShortOptionSet($name) + private function parseShortOptionSet(string $name) { $len = \strlen($name); for ($i = 0; $i < $len; ++$i) { @@ -138,15 +131,13 @@ class ArgvInput extends Input /** * Parses a long option. - * - * @param string $token The current token */ - private function parseLongOption($token) + private function parseLongOption(string $token) { $name = substr($token, 2); if (false !== $pos = strpos($name, '=')) { - if (0 === \strlen($value = substr($name, $pos + 1))) { + if ('' === $value = substr($name, $pos + 1)) { array_unshift($this->parsed, $value); } $this->addLongOption(substr($name, 0, $pos), $value); @@ -158,11 +149,9 @@ class ArgvInput extends Input /** * Parses an argument. * - * @param string $token The current token - * * @throws RuntimeException When too many arguments are given */ - private function parseArgument($token) + private function parseArgument(string $token) { $c = \count($this->arguments); @@ -190,12 +179,9 @@ class ArgvInput extends Input /** * Adds a short option value. * - * @param string $shortcut The short option key - * @param mixed $value The value for the option - * * @throws RuntimeException When option given doesn't exist */ - private function addShortOption($shortcut, $value) + private function addShortOption(string $shortcut, $value) { if (!$this->definition->hasShortcut($shortcut)) { throw new RuntimeException(sprintf('The "-%s" option does not exist.', $shortcut)); @@ -207,12 +193,9 @@ class ArgvInput extends Input /** * Adds a long option value. * - * @param string $name The long option key - * @param mixed $value The value for the option - * * @throws RuntimeException When option given doesn't exist */ - private function addLongOption($name, $value) + private function addLongOption(string $name, $value) { if (!$this->definition->hasOption($name)) { throw new RuntimeException(sprintf('The "--%s" option does not exist.', $name)); @@ -260,7 +243,7 @@ class ArgvInput extends Input $isOption = false; foreach ($this->tokens as $i => $token) { if ($token && '-' === $token[0]) { - if (false !== strpos($token, '=') || !isset($this->tokens[$i + 1])) { + if (str_contains($token, '=') || !isset($this->tokens[$i + 1])) { continue; } @@ -283,6 +266,8 @@ class ArgvInput extends Input return $token; } + + return null; } /** @@ -300,8 +285,8 @@ class ArgvInput extends Input // Options with values: // For long options, test for '--option=' at beginning // For short options, test for '-o' at beginning - $leading = 0 === strpos($value, '--') ? $value.'=' : $value; - if ($token === $value || '' !== $leading && 0 === strpos($token, $leading)) { + $leading = str_starts_with($value, '--') ? $value.'=' : $value; + if ($token === $value || '' !== $leading && str_starts_with($token, $leading)) { return true; } } @@ -331,8 +316,8 @@ class ArgvInput extends Input // Options with values: // For long options, test for '--option=' at beginning // For short options, test for '-o' at beginning - $leading = 0 === strpos($value, '--') ? $value.'=' : $value; - if ('' !== $leading && 0 === strpos($token, $leading)) { + $leading = str_starts_with($value, '--') ? $value.'=' : $value; + if ('' !== $leading && str_starts_with($token, $leading)) { return substr($token, \strlen($leading)); } } diff --git a/vendor/symfony/console/Input/ArrayInput.php b/vendor/symfony/console/Input/ArrayInput.php index 44c2f0d5c..30bd2054a 100644 --- a/vendor/symfony/console/Input/ArrayInput.php +++ b/vendor/symfony/console/Input/ArrayInput.php @@ -39,13 +39,15 @@ class ArrayInput extends Input */ public function getFirstArgument() { - foreach ($this->parameters as $key => $value) { - if ($key && '-' === $key[0]) { + foreach ($this->parameters as $param => $value) { + if ($param && \is_string($param) && '-' === $param[0]) { continue; } return $value; } + + return null; } /** @@ -105,13 +107,14 @@ class ArrayInput extends Input { $params = []; foreach ($this->parameters as $param => $val) { - if ($param && '-' === $param[0]) { + if ($param && \is_string($param) && '-' === $param[0]) { + $glue = ('-' === $param[1]) ? '=' : ' '; if (\is_array($val)) { foreach ($val as $v) { - $params[] = $param.('' != $v ? '='.$this->escapeToken($v) : ''); + $params[] = $param.('' != $v ? $glue.$this->escapeToken($v) : ''); } } else { - $params[] = $param.('' != $val ? '='.$this->escapeToken($val) : ''); + $params[] = $param.('' != $val ? $glue.$this->escapeToken($val) : ''); } } else { $params[] = \is_array($val) ? implode(' ', array_map([$this, 'escapeToken'], $val)) : $this->escapeToken($val); @@ -130,9 +133,9 @@ class ArrayInput extends Input if ('--' === $key) { return; } - if (0 === strpos($key, '--')) { + if (str_starts_with($key, '--')) { $this->addLongOption(substr($key, 2), $value); - } elseif ('-' === $key[0]) { + } elseif (str_starts_with($key, '-')) { $this->addShortOption(substr($key, 1), $value); } else { $this->addArgument($key, $value); @@ -143,12 +146,9 @@ class ArrayInput extends Input /** * Adds a short option value. * - * @param string $shortcut The short option key - * @param mixed $value The value for the option - * * @throws InvalidOptionException When option given doesn't exist */ - private function addShortOption($shortcut, $value) + private function addShortOption(string $shortcut, $value) { if (!$this->definition->hasShortcut($shortcut)) { throw new InvalidOptionException(sprintf('The "-%s" option does not exist.', $shortcut)); @@ -160,13 +160,10 @@ class ArrayInput extends Input /** * Adds a long option value. * - * @param string $name The long option key - * @param mixed $value The value for the option - * * @throws InvalidOptionException When option given doesn't exist * @throws InvalidOptionException When a required value is missing */ - private function addLongOption($name, $value) + private function addLongOption(string $name, $value) { if (!$this->definition->hasOption($name)) { throw new InvalidOptionException(sprintf('The "--%s" option does not exist.', $name)); @@ -190,8 +187,8 @@ class ArrayInput extends Input /** * Adds an argument value. * - * @param string $name The argument name - * @param mixed $value The value for the argument + * @param string|int $name The argument name + * @param mixed $value The value for the argument * * @throws InvalidArgumentException When argument given doesn't exist */ diff --git a/vendor/symfony/console/Input/Input.php b/vendor/symfony/console/Input/Input.php index c1220316d..d7f29073e 100644 --- a/vendor/symfony/console/Input/Input.php +++ b/vendor/symfony/console/Input/Input.php @@ -106,11 +106,11 @@ abstract class Input implements InputInterface, StreamableInputInterface */ public function getArgument($name) { - if (!$this->definition->hasArgument($name)) { + if (!$this->definition->hasArgument((string) $name)) { throw new InvalidArgumentException(sprintf('The "%s" argument does not exist.', $name)); } - return isset($this->arguments[$name]) ? $this->arguments[$name] : $this->definition->getArgument($name)->getDefault(); + return $this->arguments[$name] ?? $this->definition->getArgument($name)->getDefault(); } /** @@ -118,7 +118,7 @@ abstract class Input implements InputInterface, StreamableInputInterface */ public function setArgument($name, $value) { - if (!$this->definition->hasArgument($name)) { + if (!$this->definition->hasArgument((string) $name)) { throw new InvalidArgumentException(sprintf('The "%s" argument does not exist.', $name)); } @@ -130,7 +130,7 @@ abstract class Input implements InputInterface, StreamableInputInterface */ public function hasArgument($name) { - return $this->definition->hasArgument($name); + return $this->definition->hasArgument((string) $name); } /** diff --git a/vendor/symfony/console/Input/InputArgument.php b/vendor/symfony/console/Input/InputArgument.php index b6aa6452a..085aca5a7 100644 --- a/vendor/symfony/console/Input/InputArgument.php +++ b/vendor/symfony/console/Input/InputArgument.php @@ -21,9 +21,9 @@ use Symfony\Component\Console\Exception\LogicException; */ class InputArgument { - const REQUIRED = 1; - const OPTIONAL = 2; - const IS_ARRAY = 4; + public const REQUIRED = 1; + public const OPTIONAL = 2; + public const IS_ARRAY = 4; private $name; private $mode; @@ -31,10 +31,10 @@ class InputArgument private $description; /** - * @param string $name The argument name - * @param int|null $mode The argument mode: self::REQUIRED or self::OPTIONAL - * @param string $description A description text - * @param string|string[]|null $default The default value (for self::OPTIONAL mode only) + * @param string $name The argument name + * @param int|null $mode The argument mode: self::REQUIRED or self::OPTIONAL + * @param string $description A description text + * @param string|bool|int|float|array|null $default The default value (for self::OPTIONAL mode only) * * @throws InvalidArgumentException When argument mode is not valid */ @@ -86,7 +86,7 @@ class InputArgument /** * Sets the default value. * - * @param string|string[]|null $default The default value + * @param string|bool|int|float|array|null $default * * @throws LogicException When incorrect default value is given */ @@ -110,7 +110,7 @@ class InputArgument /** * Returns the default value. * - * @return string|string[]|null The default value + * @return string|bool|int|float|array|null */ public function getDefault() { diff --git a/vendor/symfony/console/Input/InputDefinition.php b/vendor/symfony/console/Input/InputDefinition.php index 2189c4628..e2cd6d714 100644 --- a/vendor/symfony/console/Input/InputDefinition.php +++ b/vendor/symfony/console/Input/InputDefinition.php @@ -171,7 +171,7 @@ class InputDefinition */ public function getArgumentCount() { - return $this->hasAnArrayArgument ? PHP_INT_MAX : \count($this->arguments); + return $this->hasAnArrayArgument ? \PHP_INT_MAX : \count($this->arguments); } /** @@ -185,9 +185,7 @@ class InputDefinition } /** - * Gets the default values. - * - * @return array An array of default values + * @return array */ public function getArgumentDefaults() { @@ -316,9 +314,7 @@ class InputDefinition } /** - * Gets an array of default values. - * - * @return array An array of all default values + * @return array */ public function getOptionDefaults() { @@ -333,15 +329,11 @@ class InputDefinition /** * Returns the InputOption name given a shortcut. * - * @param string $shortcut The shortcut - * - * @return string The InputOption name - * * @throws InvalidArgumentException When option given does not exist * * @internal */ - public function shortcutToName($shortcut) + public function shortcutToName(string $shortcut): string { if (!isset($this->shortcuts[$shortcut])) { throw new InvalidArgumentException(sprintf('The "-%s" option does not exist.', $shortcut)); diff --git a/vendor/symfony/console/Input/InputInterface.php b/vendor/symfony/console/Input/InputInterface.php index b9bcf3bbc..8efc62326 100644 --- a/vendor/symfony/console/Input/InputInterface.php +++ b/vendor/symfony/console/Input/InputInterface.php @@ -51,9 +51,9 @@ interface InputInterface * Does not necessarily return the correct result for short options * when multiple flags are combined in the same option. * - * @param string|array $values The value(s) to look for in the raw parameters (can be an array) - * @param mixed $default The default value to return if no result is found - * @param bool $onlyParams Only check real parameters, skip those following an end of options (--) signal + * @param string|array $values The value(s) to look for in the raw parameters (can be an array) + * @param string|bool|int|float|array|null $default The default value to return if no result is found + * @param bool $onlyParams Only check real parameters, skip those following an end of options (--) signal * * @return mixed The option value */ @@ -76,7 +76,7 @@ interface InputInterface /** * Returns all the given arguments merged with the default values. * - * @return array + * @return array */ public function getArguments(); @@ -85,7 +85,7 @@ interface InputInterface * * @param string $name The argument name * - * @return string|string[]|null The argument value + * @return mixed * * @throws InvalidArgumentException When argument given doesn't exist */ @@ -94,8 +94,8 @@ interface InputInterface /** * Sets an argument value by name. * - * @param string $name The argument name - * @param string|string[]|null $value The argument value + * @param string $name The argument name + * @param mixed $value The argument value * * @throws InvalidArgumentException When argument given doesn't exist */ @@ -104,7 +104,7 @@ interface InputInterface /** * Returns true if an InputArgument object exists by name or position. * - * @param string|int $name The InputArgument name or position + * @param string $name The argument name * * @return bool true if the InputArgument object exists, false otherwise */ @@ -113,7 +113,7 @@ interface InputInterface /** * Returns all the given options merged with the default values. * - * @return array + * @return array */ public function getOptions(); @@ -122,7 +122,7 @@ interface InputInterface * * @param string $name The option name * - * @return string|string[]|bool|null The option value + * @return mixed * * @throws InvalidArgumentException When option given doesn't exist */ @@ -131,8 +131,8 @@ interface InputInterface /** * Sets an option value by name. * - * @param string $name The option name - * @param string|string[]|bool|null $value The option value + * @param string $name The option name + * @param mixed $value The option value * * @throws InvalidArgumentException When option given doesn't exist */ diff --git a/vendor/symfony/console/Input/InputOption.php b/vendor/symfony/console/Input/InputOption.php index d62e0aea0..c7729db20 100644 --- a/vendor/symfony/console/Input/InputOption.php +++ b/vendor/symfony/console/Input/InputOption.php @@ -21,10 +21,25 @@ use Symfony\Component\Console\Exception\LogicException; */ class InputOption { - const VALUE_NONE = 1; - const VALUE_REQUIRED = 2; - const VALUE_OPTIONAL = 4; - const VALUE_IS_ARRAY = 8; + /** + * Do not accept input for the option (e.g. --yell). This is the default behavior of options. + */ + public const VALUE_NONE = 1; + + /** + * A value must be passed when the option is used (e.g. --iterations=5 or -i5). + */ + public const VALUE_REQUIRED = 2; + + /** + * The option may or may not have a value (e.g. --yell or --yell=loud). + */ + public const VALUE_OPTIONAL = 4; + + /** + * The option accepts multiple values (e.g. --dir=/foo --dir=/bar). + */ + public const VALUE_IS_ARRAY = 8; private $name; private $shortcut; @@ -33,17 +48,17 @@ class InputOption private $description; /** - * @param string $name The option name - * @param string|array|null $shortcut The shortcuts, can be null, a string of shortcuts delimited by | or an array of shortcuts - * @param int|null $mode The option mode: One of the VALUE_* constants - * @param string $description A description text - * @param string|string[]|int|bool|null $default The default value (must be null for self::VALUE_NONE) + * @param string $name The option name + * @param string|array|null $shortcut The shortcuts, can be null, a string of shortcuts delimited by | or an array of shortcuts + * @param int|null $mode The option mode: One of the VALUE_* constants + * @param string $description A description text + * @param string|bool|int|float|array|null $default The default value (must be null for self::VALUE_NONE) * * @throws InvalidArgumentException If option mode is invalid or incompatible */ public function __construct(string $name, $shortcut = null, int $mode = null, string $description = '', $default = null) { - if (0 === strpos($name, '--')) { + if (str_starts_with($name, '--')) { $name = substr($name, 2); } @@ -147,11 +162,7 @@ class InputOption } /** - * Sets the default value. - * - * @param string|string[]|int|bool|null $default The default value - * - * @throws LogicException When incorrect default value is given + * @param string|bool|int|float|array|null $default */ public function setDefault($default = null) { @@ -173,7 +184,7 @@ class InputOption /** * Returns the default value. * - * @return string|string[]|int|bool|null The default value + * @return string|bool|int|float|array|null */ public function getDefault() { diff --git a/vendor/symfony/console/Input/StringInput.php b/vendor/symfony/console/Input/StringInput.php index 0c63ed0e0..76f1d5030 100644 --- a/vendor/symfony/console/Input/StringInput.php +++ b/vendor/symfony/console/Input/StringInput.php @@ -24,8 +24,8 @@ use Symfony\Component\Console\Exception\InvalidArgumentException; */ class StringInput extends ArgvInput { - const REGEX_STRING = '([^\s]+?)(?:\s|(? * - * @see http://www.php-fig.org/psr/psr-3/ + * @see https://www.php-fig.org/psr/psr-3/ */ class ConsoleLogger extends AbstractLogger { - const INFO = 'info'; - const ERROR = 'error'; + public const INFO = 'info'; + public const ERROR = 'error'; private $output; private $verbosityLevelMap = [ @@ -61,6 +61,8 @@ class ConsoleLogger extends AbstractLogger /** * {@inheritdoc} + * + * @return void */ public function log($level, $message, array $context = []) { @@ -102,7 +104,7 @@ class ConsoleLogger extends AbstractLogger */ private function interpolate(string $message, array $context): string { - if (false === strpos($message, '{')) { + if (!str_contains($message, '{')) { return $message; } diff --git a/vendor/symfony/console/Output/BufferedOutput.php b/vendor/symfony/console/Output/BufferedOutput.php index 8afc8931e..fefaac271 100644 --- a/vendor/symfony/console/Output/BufferedOutput.php +++ b/vendor/symfony/console/Output/BufferedOutput.php @@ -39,7 +39,7 @@ class BufferedOutput extends Output $this->buffer .= $message; if ($newline) { - $this->buffer .= PHP_EOL; + $this->buffer .= \PHP_EOL; } } } diff --git a/vendor/symfony/console/Output/ConsoleOutput.php b/vendor/symfony/console/Output/ConsoleOutput.php index 8430c9c82..484fcbdea 100644 --- a/vendor/symfony/console/Output/ConsoleOutput.php +++ b/vendor/symfony/console/Output/ConsoleOutput.php @@ -41,6 +41,13 @@ class ConsoleOutput extends StreamOutput implements ConsoleOutputInterface { parent::__construct($this->openOutputStream(), $verbosity, $decorated, $formatter); + if (null === $formatter) { + // for BC reasons, stdErr has it own Formatter only when user don't inject a specific formatter. + $this->stderr = new StreamOutput($this->openErrorStream(), $verbosity, $decorated); + + return; + } + $actualDecorated = $this->isDecorated(); $this->stderr = new StreamOutput($this->openErrorStream(), $verbosity, $decorated, $this->getFormatter()); @@ -125,15 +132,13 @@ class ConsoleOutput extends StreamOutput implements ConsoleOutputInterface /** * Checks if current executing environment is IBM iSeries (OS400), which * doesn't properly convert character-encodings between ASCII to EBCDIC. - * - * @return bool */ - private function isRunningOS400() + private function isRunningOS400(): bool { $checks = [ \function_exists('php_uname') ? php_uname('s') : '', getenv('OSTYPE'), - PHP_OS, + \PHP_OS, ]; return false !== stripos(implode(';', $checks), 'OS400'); @@ -148,7 +153,8 @@ class ConsoleOutput extends StreamOutput implements ConsoleOutputInterface return fopen('php://output', 'w'); } - return @fopen('php://stdout', 'w') ?: fopen('php://output', 'w'); + // Use STDOUT when possible to prevent from opening too many file descriptors + return \defined('STDOUT') ? \STDOUT : (@fopen('php://stdout', 'w') ?: fopen('php://output', 'w')); } /** @@ -156,6 +162,11 @@ class ConsoleOutput extends StreamOutput implements ConsoleOutputInterface */ private function openErrorStream() { - return fopen($this->hasStderrSupport() ? 'php://stderr' : 'php://output', 'w'); + if (!$this->hasStderrSupport()) { + return fopen('php://output', 'w'); + } + + // Use STDERR when possible to prevent from opening too many file descriptors + return \defined('STDERR') ? \STDERR : (@fopen('php://stderr', 'w') ?: fopen('php://output', 'w')); } } diff --git a/vendor/symfony/console/Output/ConsoleSectionOutput.php b/vendor/symfony/console/Output/ConsoleSectionOutput.php index ce2c28ba1..c19edbf95 100644 --- a/vendor/symfony/console/Output/ConsoleSectionOutput.php +++ b/vendor/symfony/console/Output/ConsoleSectionOutput.php @@ -82,10 +82,10 @@ class ConsoleSectionOutput extends StreamOutput */ public function addContent(string $input) { - foreach (explode(PHP_EOL, $input) as $lineContent) { + foreach (explode(\PHP_EOL, $input) as $lineContent) { $this->lines += ceil($this->getDisplayLength($lineContent) / $this->terminal->getWidth()) ?: 1; $this->content[] = $lineContent; - $this->content[] = PHP_EOL; + $this->content[] = \PHP_EOL; } } @@ -95,7 +95,9 @@ class ConsoleSectionOutput extends StreamOutput protected function doWrite($message, $newline) { if (!$this->isDecorated()) { - return parent::doWrite($message, $newline); + parent::doWrite($message, $newline); + + return; } $erasedContent = $this->popStreamContentUntilCurrentSection(); diff --git a/vendor/symfony/console/Output/Output.php b/vendor/symfony/console/Output/Output.php index 9dd765113..fb838f053 100644 --- a/vendor/symfony/console/Output/Output.php +++ b/vendor/symfony/console/Output/Output.php @@ -40,7 +40,7 @@ abstract class Output implements OutputInterface public function __construct(?int $verbosity = self::VERBOSITY_NORMAL, bool $decorated = false, OutputFormatterInterface $formatter = null) { $this->verbosity = null === $verbosity ? self::VERBOSITY_NORMAL : $verbosity; - $this->formatter = $formatter ?: new OutputFormatter(); + $this->formatter = $formatter ?? new OutputFormatter(); $this->formatter->setDecorated($decorated); } @@ -163,7 +163,7 @@ abstract class Output implements OutputInterface break; } - $this->doWrite($message, $newline); + $this->doWrite($message ?? '', $newline); } } diff --git a/vendor/symfony/console/Output/OutputInterface.php b/vendor/symfony/console/Output/OutputInterface.php index 0dfd12b98..671d5bd78 100644 --- a/vendor/symfony/console/Output/OutputInterface.php +++ b/vendor/symfony/console/Output/OutputInterface.php @@ -20,15 +20,15 @@ use Symfony\Component\Console\Formatter\OutputFormatterInterface; */ interface OutputInterface { - const VERBOSITY_QUIET = 16; - const VERBOSITY_NORMAL = 32; - const VERBOSITY_VERBOSE = 64; - const VERBOSITY_VERY_VERBOSE = 128; - const VERBOSITY_DEBUG = 256; + public const VERBOSITY_QUIET = 16; + public const VERBOSITY_NORMAL = 32; + public const VERBOSITY_VERBOSE = 64; + public const VERBOSITY_VERY_VERBOSE = 128; + public const VERBOSITY_DEBUG = 256; - const OUTPUT_NORMAL = 1; - const OUTPUT_RAW = 2; - const OUTPUT_PLAIN = 4; + public const OUTPUT_NORMAL = 1; + public const OUTPUT_RAW = 2; + public const OUTPUT_PLAIN = 4; /** * Writes a message to the output. diff --git a/vendor/symfony/console/Output/StreamOutput.php b/vendor/symfony/console/Output/StreamOutput.php index 43f7a2f23..9c2243644 100644 --- a/vendor/symfony/console/Output/StreamOutput.php +++ b/vendor/symfony/console/Output/StreamOutput.php @@ -12,7 +12,6 @@ namespace Symfony\Component\Console\Output; use Symfony\Component\Console\Exception\InvalidArgumentException; -use Symfony\Component\Console\Exception\RuntimeException; use Symfony\Component\Console\Formatter\OutputFormatterInterface; /** @@ -71,13 +70,10 @@ class StreamOutput extends Output protected function doWrite($message, $newline) { if ($newline) { - $message .= PHP_EOL; + $message .= \PHP_EOL; } - if (false === @fwrite($this->stream, $message)) { - // should never happen - throw new RuntimeException('Unable to write output.'); - } + @fwrite($this->stream, $message); fflush($this->stream); } @@ -97,6 +93,11 @@ class StreamOutput extends Output */ protected function hasColorSupport() { + // Follow https://no-color.org/ + if (isset($_SERVER['NO_COLOR']) || false !== getenv('NO_COLOR')) { + return false; + } + if ('Hyper' === getenv('TERM_PROGRAM')) { return true; } diff --git a/vendor/symfony/console/Output/TrimmedBufferOutput.php b/vendor/symfony/console/Output/TrimmedBufferOutput.php new file mode 100644 index 000000000..87c04a892 --- /dev/null +++ b/vendor/symfony/console/Output/TrimmedBufferOutput.php @@ -0,0 +1,63 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Output; + +use Symfony\Component\Console\Exception\InvalidArgumentException; +use Symfony\Component\Console\Formatter\OutputFormatterInterface; + +/** + * A BufferedOutput that keeps only the last N chars. + * + * @author Jérémy Derussé + */ +class TrimmedBufferOutput extends Output +{ + private $maxLength; + private $buffer = ''; + + public function __construct(int $maxLength, ?int $verbosity = self::VERBOSITY_NORMAL, bool $decorated = false, OutputFormatterInterface $formatter = null) + { + if ($maxLength <= 0) { + throw new InvalidArgumentException(sprintf('"%s()" expects a strictly positive maxLength. Got %d.', __METHOD__, $maxLength)); + } + + parent::__construct($verbosity, $decorated, $formatter); + $this->maxLength = $maxLength; + } + + /** + * Empties buffer and returns its content. + * + * @return string + */ + public function fetch() + { + $content = $this->buffer; + $this->buffer = ''; + + return $content; + } + + /** + * {@inheritdoc} + */ + protected function doWrite($message, $newline) + { + $this->buffer .= $message; + + if ($newline) { + $this->buffer .= \PHP_EOL; + } + + $this->buffer = substr($this->buffer, 0 - $this->maxLength); + } +} diff --git a/vendor/symfony/console/Question/ChoiceQuestion.php b/vendor/symfony/console/Question/ChoiceQuestion.php index 44b70abf1..6247ca716 100644 --- a/vendor/symfony/console/Question/ChoiceQuestion.php +++ b/vendor/symfony/console/Question/ChoiceQuestion.php @@ -131,13 +131,19 @@ class ChoiceQuestion extends Question return function ($selected) use ($choices, $errorMessage, $multiselect, $isAssoc) { if ($multiselect) { // Check for a separated comma values - if (!preg_match('/^[^,]+(?:,[^,]+)*$/', $selected, $matches)) { + if (!preg_match('/^[^,]+(?:,[^,]+)*$/', (string) $selected, $matches)) { throw new InvalidArgumentException(sprintf($errorMessage, $selected)); } - $selectedChoices = array_map('trim', explode(',', $selected)); + $selectedChoices = explode(',', (string) $selected); } else { - $selectedChoices = [trim($selected)]; + $selectedChoices = [$selected]; + } + + if ($this->isTrimmable()) { + foreach ($selectedChoices as $k => $v) { + $selectedChoices[$k] = trim((string) $v); + } } $multiselectChoices = []; @@ -150,7 +156,7 @@ class ChoiceQuestion extends Question } if (\count($results) > 1) { - throw new InvalidArgumentException(sprintf('The provided answer is ambiguous. Value should be one of %s.', implode(' or ', $results))); + throw new InvalidArgumentException(sprintf('The provided answer is ambiguous. Value should be one of "%s".', implode('" or "', $results))); } $result = array_search($value, $choices); diff --git a/vendor/symfony/console/Question/ConfirmationQuestion.php b/vendor/symfony/console/Question/ConfirmationQuestion.php index 88227dfa6..4228521b9 100644 --- a/vendor/symfony/console/Question/ConfirmationQuestion.php +++ b/vendor/symfony/console/Question/ConfirmationQuestion.php @@ -35,10 +35,8 @@ class ConfirmationQuestion extends Question /** * Returns the default answer normalizer. - * - * @return callable */ - private function getDefaultNormalizer() + private function getDefaultNormalizer(): callable { $default = $this->getDefault(); $regex = $this->trueAnswerRegex; diff --git a/vendor/symfony/console/Question/Question.php b/vendor/symfony/console/Question/Question.php index eac82cfad..cc108018f 100644 --- a/vendor/symfony/console/Question/Question.php +++ b/vendor/symfony/console/Question/Question.php @@ -25,14 +25,15 @@ class Question private $attempts; private $hidden = false; private $hiddenFallback = true; - private $autocompleterValues; + private $autocompleterCallback; private $validator; private $default; private $normalizer; + private $trimmable = true; /** - * @param string $question The question to ask to the user - * @param mixed $default The default answer to return if the user enters nothing + * @param string $question The question to ask to the user + * @param string|bool|int|float|null $default The default answer to return if the user enters nothing */ public function __construct(string $question, $default = null) { @@ -53,7 +54,7 @@ class Question /** * Returns the default answer. * - * @return mixed + * @return string|bool|int|float|null */ public function getDefault() { @@ -81,7 +82,7 @@ class Question */ public function setHidden($hidden) { - if ($this->autocompleterValues) { + if ($this->autocompleterCallback) { throw new LogicException('A hidden question cannot use the autocompleter.'); } @@ -121,7 +122,9 @@ class Question */ public function getAutocompleterValues() { - return $this->autocompleterValues; + $callback = $this->getAutocompleterCallback(); + + return $callback ? $callback('') : null; } /** @@ -138,17 +141,46 @@ class Question { if (\is_array($values)) { $values = $this->isAssoc($values) ? array_merge(array_keys($values), array_values($values)) : array_values($values); - } - if (null !== $values && !\is_array($values) && !$values instanceof \Traversable) { + $callback = static function () use ($values) { + return $values; + }; + } elseif ($values instanceof \Traversable) { + $valueCache = null; + $callback = static function () use ($values, &$valueCache) { + return $valueCache ?? $valueCache = iterator_to_array($values, false); + }; + } elseif (null === $values) { + $callback = null; + } else { throw new InvalidArgumentException('Autocompleter values can be either an array, "null" or a "Traversable" object.'); } - if ($this->hidden) { + return $this->setAutocompleterCallback($callback); + } + + /** + * Gets the callback function used for the autocompleter. + */ + public function getAutocompleterCallback(): ?callable + { + return $this->autocompleterCallback; + } + + /** + * Sets the callback function used for the autocompleter. + * + * The callback is passed the user input as argument and should return an iterable of corresponding suggestions. + * + * @return $this + */ + public function setAutocompleterCallback(callable $callback = null): self + { + if ($this->hidden && null !== $callback) { throw new LogicException('A hidden question cannot use the autocompleter.'); } - $this->autocompleterValues = $values; + $this->autocompleterCallback = $callback; return $this; } @@ -156,8 +188,6 @@ class Question /** * Sets a validator for the question. * - * @param callable|null $validator - * * @return $this */ public function setValidator(callable $validator = null) @@ -190,8 +220,11 @@ class Question */ public function setMaxAttempts($attempts) { - if (null !== $attempts && $attempts < 1) { - throw new InvalidArgumentException('Maximum number of attempts must be a positive value.'); + if (null !== $attempts) { + $attempts = (int) $attempts; + if ($attempts < 1) { + throw new InvalidArgumentException('Maximum number of attempts must be a positive value.'); + } } $this->attempts = $attempts; @@ -216,8 +249,6 @@ class Question * * The normalizer can be a callable (a string), a closure or a class implementing __invoke. * - * @param callable $normalizer - * * @return $this */ public function setNormalizer(callable $normalizer) @@ -232,7 +263,7 @@ class Question * * The normalizer can ba a callable (a string), a closure or a class implementing __invoke. * - * @return callable + * @return callable|null */ public function getNormalizer() { @@ -243,4 +274,19 @@ class Question { return (bool) \count(array_filter(array_keys($array), 'is_string')); } + + public function isTrimmable(): bool + { + return $this->trimmable; + } + + /** + * @return $this + */ + public function setTrimmable(bool $trimmable): self + { + $this->trimmable = $trimmable; + + return $this; + } } diff --git a/vendor/symfony/console/README.md b/vendor/symfony/console/README.md index 664a37c0e..c89b4a1a2 100644 --- a/vendor/symfony/console/README.md +++ b/vendor/symfony/console/README.md @@ -7,11 +7,11 @@ interfaces. Resources --------- - * [Documentation](https://symfony.com/doc/current/components/console/index.html) - * [Contributing](https://symfony.com/doc/current/contributing/index.html) - * [Report issues](https://github.com/symfony/symfony/issues) and - [send Pull Requests](https://github.com/symfony/symfony/pulls) - in the [main Symfony repository](https://github.com/symfony/symfony) + * [Documentation](https://symfony.com/doc/current/components/console.html) + * [Contributing](https://symfony.com/doc/current/contributing/index.html) + * [Report issues](https://github.com/symfony/symfony/issues) and + [send Pull Requests](https://github.com/symfony/symfony/pulls) + in the [main Symfony repository](https://github.com/symfony/symfony) Credits ------- diff --git a/vendor/symfony/console/Style/OutputStyle.php b/vendor/symfony/console/Style/OutputStyle.php index b1262b55d..14d2d60b2 100644 --- a/vendor/symfony/console/Style/OutputStyle.php +++ b/vendor/symfony/console/Style/OutputStyle.php @@ -35,7 +35,7 @@ abstract class OutputStyle implements OutputInterface, StyleInterface */ public function newLine($count = 1) { - $this->output->write(str_repeat(PHP_EOL, $count)); + $this->output->write(str_repeat(\PHP_EOL, $count)); } /** diff --git a/vendor/symfony/console/Style/StyleInterface.php b/vendor/symfony/console/Style/StyleInterface.php index 475c268ff..3b5b8af51 100644 --- a/vendor/symfony/console/Style/StyleInterface.php +++ b/vendor/symfony/console/Style/StyleInterface.php @@ -119,7 +119,6 @@ interface StyleInterface * Asks a choice question. * * @param string $question - * @param array $choices * @param string|int|null $default * * @return mixed diff --git a/vendor/symfony/console/Style/SymfonyStyle.php b/vendor/symfony/console/Style/SymfonyStyle.php index b46162de6..66db3ad5a 100644 --- a/vendor/symfony/console/Style/SymfonyStyle.php +++ b/vendor/symfony/console/Style/SymfonyStyle.php @@ -11,15 +11,18 @@ namespace Symfony\Component\Console\Style; +use Symfony\Component\Console\Exception\InvalidArgumentException; use Symfony\Component\Console\Exception\RuntimeException; use Symfony\Component\Console\Formatter\OutputFormatter; use Symfony\Component\Console\Helper\Helper; use Symfony\Component\Console\Helper\ProgressBar; use Symfony\Component\Console\Helper\SymfonyQuestionHelper; use Symfony\Component\Console\Helper\Table; +use Symfony\Component\Console\Helper\TableCell; +use Symfony\Component\Console\Helper\TableSeparator; use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Output\BufferedOutput; use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Console\Output\TrimmedBufferOutput; use Symfony\Component\Console\Question\ChoiceQuestion; use Symfony\Component\Console\Question\ConfirmationQuestion; use Symfony\Component\Console\Question\Question; @@ -32,7 +35,7 @@ use Symfony\Component\Console\Terminal; */ class SymfonyStyle extends OutputStyle { - const MAX_LINE_LENGTH = 120; + public const MAX_LINE_LENGTH = 120; private $input; private $questionHelper; @@ -43,7 +46,7 @@ class SymfonyStyle extends OutputStyle public function __construct(InputInterface $input, OutputInterface $output) { $this->input = $input; - $this->bufferedOutput = new BufferedOutput($output->getVerbosity(), false, clone $output->getFormatter()); + $this->bufferedOutput = new TrimmedBufferOutput(\DIRECTORY_SEPARATOR === '\\' ? 4 : 2, $output->getVerbosity(), false, clone $output->getFormatter()); // Windows cmd wraps lines as soon as the terminal width is reached, whether there are following chars or not. $width = (new Terminal())->getWidth() ?: self::MAX_LINE_LENGTH; $this->lineLength = min($width - (int) (\DIRECTORY_SEPARATOR === '\\'), self::MAX_LINE_LENGTH); @@ -154,7 +157,7 @@ class SymfonyStyle extends OutputStyle */ public function warning($message) { - $this->block($message, 'WARNING', 'fg=white;bg=red', ' ', true); + $this->block($message, 'WARNING', 'fg=black;bg=yellow', ' ', true); } /** @@ -190,6 +193,69 @@ class SymfonyStyle extends OutputStyle $this->newLine(); } + /** + * Formats a horizontal table. + */ + public function horizontalTable(array $headers, array $rows) + { + $style = clone Table::getStyleDefinition('symfony-style-guide'); + $style->setCellHeaderFormat('%s'); + + $table = new Table($this); + $table->setHeaders($headers); + $table->setRows($rows); + $table->setStyle($style); + $table->setHorizontal(true); + + $table->render(); + $this->newLine(); + } + + /** + * Formats a list of key/value horizontally. + * + * Each row can be one of: + * * 'A title' + * * ['key' => 'value'] + * * new TableSeparator() + * + * @param string|array|TableSeparator ...$list + */ + public function definitionList(...$list) + { + $style = clone Table::getStyleDefinition('symfony-style-guide'); + $style->setCellHeaderFormat('%s'); + + $table = new Table($this); + $headers = []; + $row = []; + foreach ($list as $value) { + if ($value instanceof TableSeparator) { + $headers[] = $value; + $row[] = $value; + continue; + } + if (\is_string($value)) { + $headers[] = new TableCell($value, ['colspan' => 2]); + $row[] = null; + continue; + } + if (!\is_array($value)) { + throw new InvalidArgumentException('Value should be an array, string, or an instance of TableSeparator.'); + } + $headers[] = key($value); + $row[] = current($value); + } + + $table->setHeaders($headers); + $table->setRows([$row]); + $table->setHorizontal(); + $table->setStyle($style); + + $table->render(); + $this->newLine(); + } + /** * {@inheritdoc} */ @@ -229,7 +295,7 @@ class SymfonyStyle extends OutputStyle { if (null !== $default) { $values = array_flip($choices); - $default = $values[$default]; + $default = $values[$default] ?? $default; } return $this->askQuestion(new ChoiceQuestion($question, $choices, $default)); @@ -361,7 +427,7 @@ class SymfonyStyle extends OutputStyle private function autoPrependBlock(): void { - $chars = substr(str_replace(PHP_EOL, "\n", $this->bufferedOutput->fetch()), -2); + $chars = substr(str_replace(\PHP_EOL, "\n", $this->bufferedOutput->fetch()), -2); if (!isset($chars[0])) { $this->newLine(); //empty history, so we should start with a new line. @@ -376,19 +442,18 @@ class SymfonyStyle extends OutputStyle { $fetched = $this->bufferedOutput->fetch(); //Prepend new line if last char isn't EOL: - if ("\n" !== substr($fetched, -1)) { + if (!str_ends_with($fetched, "\n")) { $this->newLine(); } } private function writeBuffer(string $message, bool $newLine, int $type): void { - // We need to know if the two last chars are PHP_EOL - // Preserve the last 4 chars inserted (PHP_EOL on windows is two chars) in the history buffer - $this->bufferedOutput->write(substr($message, -4), $newLine, $type); + // We need to know if the last chars are PHP_EOL + $this->bufferedOutput->write($message, $newLine, $type); } - private function createBlock(iterable $messages, string $type = null, string $style = null, string $prefix = ' ', bool $padding = false, bool $escape = false) + private function createBlock(iterable $messages, string $type = null, string $style = null, string $prefix = ' ', bool $padding = false, bool $escape = false): array { $indentLength = 0; $prefixLength = Helper::strlenWithoutDecoration($this->getFormatter(), $prefix); @@ -406,7 +471,12 @@ class SymfonyStyle extends OutputStyle $message = OutputFormatter::escape($message); } - $lines = array_merge($lines, explode(PHP_EOL, wordwrap($message, $this->lineLength - $prefixLength - $indentLength, PHP_EOL, true))); + $decorationLength = Helper::strlen($message) - Helper::strlenWithoutDecoration($this->getFormatter(), $message); + $messageLineLength = min($this->lineLength - $prefixLength - $indentLength + $decorationLength, $this->lineLength); + $messageLines = explode(\PHP_EOL, wordwrap($message, $messageLineLength, \PHP_EOL, true)); + foreach ($messageLines as $messageLine) { + $lines[] = $messageLine; + } if (\count($messages) > 1 && $key < \count($messages) - 1) { $lines[] = ''; @@ -426,7 +496,7 @@ class SymfonyStyle extends OutputStyle } $line = $prefix.$line; - $line .= str_repeat(' ', $this->lineLength - Helper::strlenWithoutDecoration($this->getFormatter(), $line)); + $line .= str_repeat(' ', max($this->lineLength - Helper::strlenWithoutDecoration($this->getFormatter(), $line), 0)); if ($style) { $line = sprintf('<%s>%s', $style, $line); diff --git a/vendor/symfony/console/Terminal.php b/vendor/symfony/console/Terminal.php index 456cca11c..5e5a3c2f7 100644 --- a/vendor/symfony/console/Terminal.php +++ b/vendor/symfony/console/Terminal.php @@ -15,6 +15,7 @@ class Terminal { private static $width; private static $height; + private static $stty; /** * Gets the terminal width. @@ -54,6 +55,27 @@ class Terminal return self::$height ?: 50; } + /** + * @internal + * + * @return bool + */ + public static function hasSttyAvailable() + { + if (null !== self::$stty) { + return self::$stty; + } + + // skip check if exec function is disabled + if (!\function_exists('exec')) { + return false; + } + + exec('stty 2>&1', $output, $exitcode); + + return self::$stty = 0 === $exitcode; + } + private static function initDimensions() { if ('\\' === \DIRECTORY_SEPARATOR) { @@ -62,12 +84,34 @@ class Terminal // or [w, h] from "wxh" self::$width = (int) $matches[1]; self::$height = isset($matches[4]) ? (int) $matches[4] : (int) $matches[2]; + } elseif (!self::hasVt100Support() && self::hasSttyAvailable()) { + // only use stty on Windows if the terminal does not support vt100 (e.g. Windows 7 + git-bash) + // testing for stty in a Windows 10 vt100-enabled console will implicitly disable vt100 support on STDOUT + self::initDimensionsUsingStty(); } elseif (null !== $dimensions = self::getConsoleMode()) { // extract [w, h] from "wxh" self::$width = (int) $dimensions[0]; self::$height = (int) $dimensions[1]; } - } elseif ($sttyString = self::getSttyColumns()) { + } else { + self::initDimensionsUsingStty(); + } + } + + /** + * Returns whether STDOUT has vt100 support (some Windows 10+ configurations). + */ + private static function hasVt100Support(): bool + { + return \function_exists('sapi_windows_vt100_support') && sapi_windows_vt100_support(fopen('php://stdout', 'w')); + } + + /** + * Initializes dimensions using the output of an stty columns line. + */ + private static function initDimensionsUsingStty() + { + if ($sttyString = self::getSttyColumns()) { if (preg_match('/rows.(\d+);.columns.(\d+);/i', $sttyString, $matches)) { // extract [w, h] from "rows h; columns w;" self::$width = (int) $matches[2]; @@ -85,38 +129,29 @@ class Terminal * * @return int[]|null An array composed of the width and the height or null if it could not be parsed */ - private static function getConsoleMode() + private static function getConsoleMode(): ?array { - if (!\function_exists('proc_open')) { - return; + $info = self::readFromProcess('mode CON'); + + if (null === $info || !preg_match('/--------+\r?\n.+?(\d+)\r?\n.+?(\d+)\r?\n/', $info, $matches)) { + return null; } - $descriptorspec = [ - 1 => ['pipe', 'w'], - 2 => ['pipe', 'w'], - ]; - $process = proc_open('mode CON', $descriptorspec, $pipes, null, null, ['suppress_errors' => true]); - if (\is_resource($process)) { - $info = stream_get_contents($pipes[1]); - fclose($pipes[1]); - fclose($pipes[2]); - proc_close($process); - - if (preg_match('/--------+\r?\n.+?(\d+)\r?\n.+?(\d+)\r?\n/', $info, $matches)) { - return [(int) $matches[2], (int) $matches[1]]; - } - } + return [(int) $matches[2], (int) $matches[1]]; } /** * Runs and parses stty -a if it's available, suppressing any error output. - * - * @return string|null */ - private static function getSttyColumns() + private static function getSttyColumns(): ?string + { + return self::readFromProcess('stty -a | grep columns'); + } + + private static function readFromProcess(string $command): ?string { if (!\function_exists('proc_open')) { - return; + return null; } $descriptorspec = [ @@ -124,14 +159,16 @@ class Terminal 2 => ['pipe', 'w'], ]; - $process = proc_open('stty -a | grep columns', $descriptorspec, $pipes, null, null, ['suppress_errors' => true]); - if (\is_resource($process)) { - $info = stream_get_contents($pipes[1]); - fclose($pipes[1]); - fclose($pipes[2]); - proc_close($process); - - return $info; + $process = proc_open($command, $descriptorspec, $pipes, null, null, ['suppress_errors' => true]); + if (!\is_resource($process)) { + return null; } + + $info = stream_get_contents($pipes[1]); + fclose($pipes[1]); + fclose($pipes[2]); + proc_close($process); + + return $info; } } diff --git a/vendor/symfony/console/Tester/ApplicationTester.php b/vendor/symfony/console/Tester/ApplicationTester.php index ced56cff2..4f99da18d 100644 --- a/vendor/symfony/console/Tester/ApplicationTester.php +++ b/vendor/symfony/console/Tester/ApplicationTester.php @@ -59,19 +59,12 @@ class ApplicationTester $this->input->setInteractive($options['interactive']); } - $shellInteractive = getenv('SHELL_INTERACTIVE'); - if ($this->inputs) { $this->input->setStream(self::createStream($this->inputs)); - putenv('SHELL_INTERACTIVE=1'); } $this->initOutput($options); - $this->statusCode = $this->application->run($this->input, $this->output); - - putenv($shellInteractive ? "SHELL_INTERACTIVE=$shellInteractive" : 'SHELL_INTERACTIVE'); - - return $this->statusCode; + return $this->statusCode = $this->application->run($this->input, $this->output); } } diff --git a/vendor/symfony/console/Tester/TesterTrait.php b/vendor/symfony/console/Tester/TesterTrait.php index 5b7e993a8..27d598559 100644 --- a/vendor/symfony/console/Tester/TesterTrait.php +++ b/vendor/symfony/console/Tester/TesterTrait.php @@ -44,7 +44,7 @@ trait TesterTrait $display = stream_get_contents($this->output->getStream()); if ($normalize) { - $display = str_replace(PHP_EOL, "\n", $display); + $display = str_replace(\PHP_EOL, "\n", $display); } return $display; @@ -68,7 +68,7 @@ trait TesterTrait $display = stream_get_contents($this->output->getErrorOutput()->getStream()); if ($normalize) { - $display = str_replace(PHP_EOL, "\n", $display); + $display = str_replace(\PHP_EOL, "\n", $display); } return $display; @@ -110,7 +110,7 @@ trait TesterTrait * @param array $inputs An array of strings representing each input * passed to the command input stream * - * @return self + * @return $this */ public function setInputs(array $inputs) { @@ -141,8 +141,8 @@ trait TesterTrait } } else { $this->output = new ConsoleOutput( - isset($options['verbosity']) ? $options['verbosity'] : ConsoleOutput::VERBOSITY_NORMAL, - isset($options['decorated']) ? $options['decorated'] : null + $options['verbosity'] ?? ConsoleOutput::VERBOSITY_NORMAL, + $options['decorated'] ?? null ); $errorOutput = new StreamOutput(fopen('php://memory', 'w', false)); @@ -162,12 +162,15 @@ trait TesterTrait } } + /** + * @return resource + */ private static function createStream(array $inputs) { $stream = fopen('php://memory', 'r+', false); foreach ($inputs as $input) { - fwrite($stream, $input.PHP_EOL); + fwrite($stream, $input.\PHP_EOL); } rewind($stream); diff --git a/vendor/symfony/console/Tests/ApplicationTest.php b/vendor/symfony/console/Tests/ApplicationTest.php deleted file mode 100644 index e153e5609..000000000 --- a/vendor/symfony/console/Tests/ApplicationTest.php +++ /dev/null @@ -1,1836 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Tests; - -use PHPUnit\Framework\TestCase; -use Symfony\Component\Console\Application; -use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\CommandLoader\FactoryCommandLoader; -use Symfony\Component\Console\DependencyInjection\AddConsoleCommandPass; -use Symfony\Component\Console\Event\ConsoleCommandEvent; -use Symfony\Component\Console\Event\ConsoleErrorEvent; -use Symfony\Component\Console\Event\ConsoleTerminateEvent; -use Symfony\Component\Console\Exception\CommandNotFoundException; -use Symfony\Component\Console\Exception\NamespaceNotFoundException; -use Symfony\Component\Console\Helper\FormatterHelper; -use Symfony\Component\Console\Helper\HelperSet; -use Symfony\Component\Console\Input\ArgvInput; -use Symfony\Component\Console\Input\ArrayInput; -use Symfony\Component\Console\Input\InputArgument; -use Symfony\Component\Console\Input\InputDefinition; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Input\InputOption; -use Symfony\Component\Console\Output\NullOutput; -use Symfony\Component\Console\Output\Output; -use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\Console\Output\StreamOutput; -use Symfony\Component\Console\Tester\ApplicationTester; -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\EventDispatcher\EventDispatcher; - -class ApplicationTest extends TestCase -{ - protected static $fixturesPath; - - private $colSize; - - protected function setUp() - { - $this->colSize = getenv('COLUMNS'); - } - - protected function tearDown() - { - putenv($this->colSize ? 'COLUMNS='.$this->colSize : 'COLUMNS'); - putenv('SHELL_VERBOSITY'); - unset($_ENV['SHELL_VERBOSITY']); - unset($_SERVER['SHELL_VERBOSITY']); - } - - public static function setUpBeforeClass() - { - self::$fixturesPath = realpath(__DIR__.'/Fixtures/'); - require_once self::$fixturesPath.'/FooCommand.php'; - require_once self::$fixturesPath.'/FooOptCommand.php'; - require_once self::$fixturesPath.'/Foo1Command.php'; - require_once self::$fixturesPath.'/Foo2Command.php'; - require_once self::$fixturesPath.'/Foo3Command.php'; - require_once self::$fixturesPath.'/Foo4Command.php'; - require_once self::$fixturesPath.'/Foo5Command.php'; - require_once self::$fixturesPath.'/FooSameCaseUppercaseCommand.php'; - require_once self::$fixturesPath.'/FooSameCaseLowercaseCommand.php'; - require_once self::$fixturesPath.'/FoobarCommand.php'; - require_once self::$fixturesPath.'/BarBucCommand.php'; - require_once self::$fixturesPath.'/FooSubnamespaced1Command.php'; - require_once self::$fixturesPath.'/FooSubnamespaced2Command.php'; - require_once self::$fixturesPath.'/FooWithoutAliasCommand.php'; - require_once self::$fixturesPath.'/TestAmbiguousCommandRegistering.php'; - require_once self::$fixturesPath.'/TestAmbiguousCommandRegistering2.php'; - } - - protected function normalizeLineBreaks($text) - { - return str_replace(PHP_EOL, "\n", $text); - } - - /** - * Replaces the dynamic placeholders of the command help text with a static version. - * The placeholder %command.full_name% includes the script path that is not predictable - * and can not be tested against. - */ - protected function ensureStaticCommandHelp(Application $application) - { - foreach ($application->all() as $command) { - $command->setHelp(str_replace('%command.full_name%', 'app/console %command.name%', $command->getHelp())); - } - } - - public function testConstructor() - { - $application = new Application('foo', 'bar'); - $this->assertEquals('foo', $application->getName(), '__construct() takes the application name as its first argument'); - $this->assertEquals('bar', $application->getVersion(), '__construct() takes the application version as its second argument'); - $this->assertEquals(['help', 'list'], array_keys($application->all()), '__construct() registered the help and list commands by default'); - } - - public function testSetGetName() - { - $application = new Application(); - $application->setName('foo'); - $this->assertEquals('foo', $application->getName(), '->setName() sets the name of the application'); - } - - public function testSetGetVersion() - { - $application = new Application(); - $application->setVersion('bar'); - $this->assertEquals('bar', $application->getVersion(), '->setVersion() sets the version of the application'); - } - - public function testGetLongVersion() - { - $application = new Application('foo', 'bar'); - $this->assertEquals('foo bar', $application->getLongVersion(), '->getLongVersion() returns the long version of the application'); - } - - public function testHelp() - { - $application = new Application(); - $this->assertStringEqualsFile(self::$fixturesPath.'/application_gethelp.txt', $this->normalizeLineBreaks($application->getHelp()), '->getHelp() returns a help message'); - } - - public function testAll() - { - $application = new Application(); - $commands = $application->all(); - $this->assertInstanceOf('Symfony\\Component\\Console\\Command\\HelpCommand', $commands['help'], '->all() returns the registered commands'); - - $application->add(new \FooCommand()); - $commands = $application->all('foo'); - $this->assertCount(1, $commands, '->all() takes a namespace as its first argument'); - } - - public function testAllWithCommandLoader() - { - $application = new Application(); - $commands = $application->all(); - $this->assertInstanceOf('Symfony\\Component\\Console\\Command\\HelpCommand', $commands['help'], '->all() returns the registered commands'); - - $application->add(new \FooCommand()); - $commands = $application->all('foo'); - $this->assertCount(1, $commands, '->all() takes a namespace as its first argument'); - - $application->setCommandLoader(new FactoryCommandLoader([ - 'foo:bar1' => function () { return new \Foo1Command(); }, - ])); - $commands = $application->all('foo'); - $this->assertCount(2, $commands, '->all() takes a namespace as its first argument'); - $this->assertInstanceOf(\FooCommand::class, $commands['foo:bar'], '->all() returns the registered commands'); - $this->assertInstanceOf(\Foo1Command::class, $commands['foo:bar1'], '->all() returns the registered commands'); - } - - public function testRegister() - { - $application = new Application(); - $command = $application->register('foo'); - $this->assertEquals('foo', $command->getName(), '->register() registers a new command'); - } - - public function testRegisterAmbiguous() - { - $code = function (InputInterface $input, OutputInterface $output) { - $output->writeln('It works!'); - }; - - $application = new Application(); - $application->setAutoExit(false); - $application - ->register('test-foo') - ->setAliases(['test']) - ->setCode($code); - - $application - ->register('test-bar') - ->setCode($code); - - $tester = new ApplicationTester($application); - $tester->run(['test']); - $this->assertContains('It works!', $tester->getDisplay(true)); - } - - public function testAdd() - { - $application = new Application(); - $application->add($foo = new \FooCommand()); - $commands = $application->all(); - $this->assertEquals($foo, $commands['foo:bar'], '->add() registers a command'); - - $application = new Application(); - $application->addCommands([$foo = new \FooCommand(), $foo1 = new \Foo1Command()]); - $commands = $application->all(); - $this->assertEquals([$foo, $foo1], [$commands['foo:bar'], $commands['foo:bar1']], '->addCommands() registers an array of commands'); - } - - /** - * @expectedException \LogicException - * @expectedExceptionMessage Command class "Foo5Command" is not correctly initialized. You probably forgot to call the parent constructor. - */ - public function testAddCommandWithEmptyConstructor() - { - $application = new Application(); - $application->add(new \Foo5Command()); - } - - public function testHasGet() - { - $application = new Application(); - $this->assertTrue($application->has('list'), '->has() returns true if a named command is registered'); - $this->assertFalse($application->has('afoobar'), '->has() returns false if a named command is not registered'); - - $application->add($foo = new \FooCommand()); - $this->assertTrue($application->has('afoobar'), '->has() returns true if an alias is registered'); - $this->assertEquals($foo, $application->get('foo:bar'), '->get() returns a command by name'); - $this->assertEquals($foo, $application->get('afoobar'), '->get() returns a command by alias'); - - $application = new Application(); - $application->add($foo = new \FooCommand()); - // simulate --help - $r = new \ReflectionObject($application); - $p = $r->getProperty('wantHelps'); - $p->setAccessible(true); - $p->setValue($application, true); - $command = $application->get('foo:bar'); - $this->assertInstanceOf('Symfony\Component\Console\Command\HelpCommand', $command, '->get() returns the help command if --help is provided as the input'); - } - - public function testHasGetWithCommandLoader() - { - $application = new Application(); - $this->assertTrue($application->has('list'), '->has() returns true if a named command is registered'); - $this->assertFalse($application->has('afoobar'), '->has() returns false if a named command is not registered'); - - $application->add($foo = new \FooCommand()); - $this->assertTrue($application->has('afoobar'), '->has() returns true if an alias is registered'); - $this->assertEquals($foo, $application->get('foo:bar'), '->get() returns a command by name'); - $this->assertEquals($foo, $application->get('afoobar'), '->get() returns a command by alias'); - - $application->setCommandLoader(new FactoryCommandLoader([ - 'foo:bar1' => function () { return new \Foo1Command(); }, - ])); - - $this->assertTrue($application->has('afoobar'), '->has() returns true if an instance is registered for an alias even with command loader'); - $this->assertEquals($foo, $application->get('foo:bar'), '->get() returns an instance by name even with command loader'); - $this->assertEquals($foo, $application->get('afoobar'), '->get() returns an instance by alias even with command loader'); - $this->assertTrue($application->has('foo:bar1'), '->has() returns true for commands registered in the loader'); - $this->assertInstanceOf(\Foo1Command::class, $foo1 = $application->get('foo:bar1'), '->get() returns a command by name from the command loader'); - $this->assertTrue($application->has('afoobar1'), '->has() returns true for commands registered in the loader'); - $this->assertEquals($foo1, $application->get('afoobar1'), '->get() returns a command by name from the command loader'); - } - - public function testSilentHelp() - { - $application = new Application(); - $application->setAutoExit(false); - $application->setCatchExceptions(false); - - $tester = new ApplicationTester($application); - $tester->run(['-h' => true, '-q' => true], ['decorated' => false]); - - $this->assertEmpty($tester->getDisplay(true)); - } - - /** - * @expectedException \Symfony\Component\Console\Exception\CommandNotFoundException - * @expectedExceptionMessage The command "foofoo" does not exist. - */ - public function testGetInvalidCommand() - { - $application = new Application(); - $application->get('foofoo'); - } - - public function testGetNamespaces() - { - $application = new Application(); - $application->add(new \FooCommand()); - $application->add(new \Foo1Command()); - $this->assertEquals(['foo'], $application->getNamespaces(), '->getNamespaces() returns an array of unique used namespaces'); - } - - public function testFindNamespace() - { - $application = new Application(); - $application->add(new \FooCommand()); - $this->assertEquals('foo', $application->findNamespace('foo'), '->findNamespace() returns the given namespace if it exists'); - $this->assertEquals('foo', $application->findNamespace('f'), '->findNamespace() finds a namespace given an abbreviation'); - $application->add(new \Foo2Command()); - $this->assertEquals('foo', $application->findNamespace('foo'), '->findNamespace() returns the given namespace if it exists'); - } - - public function testFindNamespaceWithSubnamespaces() - { - $application = new Application(); - $application->add(new \FooSubnamespaced1Command()); - $application->add(new \FooSubnamespaced2Command()); - $this->assertEquals('foo', $application->findNamespace('foo'), '->findNamespace() returns commands even if the commands are only contained in subnamespaces'); - } - - public function testFindAmbiguousNamespace() - { - $application = new Application(); - $application->add(new \BarBucCommand()); - $application->add(new \FooCommand()); - $application->add(new \Foo2Command()); - - $expectedMsg = "The namespace \"f\" is ambiguous.\nDid you mean one of these?\n foo\n foo1"; - - if (method_exists($this, 'expectException')) { - $this->expectException(NamespaceNotFoundException::class); - $this->expectExceptionMessage($expectedMsg); - } else { - $this->setExpectedException(NamespaceNotFoundException::class, $expectedMsg); - } - - $application->findNamespace('f'); - } - - public function testFindNonAmbiguous() - { - $application = new Application(); - $application->add(new \TestAmbiguousCommandRegistering()); - $application->add(new \TestAmbiguousCommandRegistering2()); - $this->assertEquals('test-ambiguous', $application->find('test')->getName()); - } - - /** - * @expectedException \Symfony\Component\Console\Exception\NamespaceNotFoundException - * @expectedExceptionMessage There are no commands defined in the "bar" namespace. - */ - public function testFindInvalidNamespace() - { - $application = new Application(); - $application->findNamespace('bar'); - } - - /** - * @expectedException \Symfony\Component\Console\Exception\CommandNotFoundException - * @expectedExceptionMessage Command "foo1" is not defined - */ - public function testFindUniqueNameButNamespaceName() - { - $application = new Application(); - $application->add(new \FooCommand()); - $application->add(new \Foo1Command()); - $application->add(new \Foo2Command()); - - $application->find($commandName = 'foo1'); - } - - public function testFind() - { - $application = new Application(); - $application->add(new \FooCommand()); - - $this->assertInstanceOf('FooCommand', $application->find('foo:bar'), '->find() returns a command if its name exists'); - $this->assertInstanceOf('Symfony\Component\Console\Command\HelpCommand', $application->find('h'), '->find() returns a command if its name exists'); - $this->assertInstanceOf('FooCommand', $application->find('f:bar'), '->find() returns a command if the abbreviation for the namespace exists'); - $this->assertInstanceOf('FooCommand', $application->find('f:b'), '->find() returns a command if the abbreviation for the namespace and the command name exist'); - $this->assertInstanceOf('FooCommand', $application->find('a'), '->find() returns a command if the abbreviation exists for an alias'); - } - - public function testFindCaseSensitiveFirst() - { - $application = new Application(); - $application->add(new \FooSameCaseUppercaseCommand()); - $application->add(new \FooSameCaseLowercaseCommand()); - - $this->assertInstanceOf('FooSameCaseUppercaseCommand', $application->find('f:B'), '->find() returns a command if the abbreviation is the correct case'); - $this->assertInstanceOf('FooSameCaseUppercaseCommand', $application->find('f:BAR'), '->find() returns a command if the abbreviation is the correct case'); - $this->assertInstanceOf('FooSameCaseLowercaseCommand', $application->find('f:b'), '->find() returns a command if the abbreviation is the correct case'); - $this->assertInstanceOf('FooSameCaseLowercaseCommand', $application->find('f:bar'), '->find() returns a command if the abbreviation is the correct case'); - } - - public function testFindCaseInsensitiveAsFallback() - { - $application = new Application(); - $application->add(new \FooSameCaseLowercaseCommand()); - - $this->assertInstanceOf('FooSameCaseLowercaseCommand', $application->find('f:b'), '->find() returns a command if the abbreviation is the correct case'); - $this->assertInstanceOf('FooSameCaseLowercaseCommand', $application->find('f:B'), '->find() will fallback to case insensitivity'); - $this->assertInstanceOf('FooSameCaseLowercaseCommand', $application->find('FoO:BaR'), '->find() will fallback to case insensitivity'); - } - - /** - * @expectedException \Symfony\Component\Console\Exception\CommandNotFoundException - * @expectedExceptionMessage Command "FoO:BaR" is ambiguous - */ - public function testFindCaseInsensitiveSuggestions() - { - $application = new Application(); - $application->add(new \FooSameCaseLowercaseCommand()); - $application->add(new \FooSameCaseUppercaseCommand()); - - $this->assertInstanceOf('FooSameCaseLowercaseCommand', $application->find('FoO:BaR'), '->find() will find two suggestions with case insensitivity'); - } - - public function testFindWithCommandLoader() - { - $application = new Application(); - $application->setCommandLoader(new FactoryCommandLoader([ - 'foo:bar' => $f = function () { return new \FooCommand(); }, - ])); - - $this->assertInstanceOf('FooCommand', $application->find('foo:bar'), '->find() returns a command if its name exists'); - $this->assertInstanceOf('Symfony\Component\Console\Command\HelpCommand', $application->find('h'), '->find() returns a command if its name exists'); - $this->assertInstanceOf('FooCommand', $application->find('f:bar'), '->find() returns a command if the abbreviation for the namespace exists'); - $this->assertInstanceOf('FooCommand', $application->find('f:b'), '->find() returns a command if the abbreviation for the namespace and the command name exist'); - $this->assertInstanceOf('FooCommand', $application->find('a'), '->find() returns a command if the abbreviation exists for an alias'); - } - - /** - * @dataProvider provideAmbiguousAbbreviations - */ - public function testFindWithAmbiguousAbbreviations($abbreviation, $expectedExceptionMessage) - { - putenv('COLUMNS=120'); - if (method_exists($this, 'expectException')) { - $this->expectException('Symfony\Component\Console\Exception\CommandNotFoundException'); - $this->expectExceptionMessage($expectedExceptionMessage); - } else { - $this->setExpectedException('Symfony\Component\Console\Exception\CommandNotFoundException', $expectedExceptionMessage); - } - - $application = new Application(); - $application->add(new \FooCommand()); - $application->add(new \Foo1Command()); - $application->add(new \Foo2Command()); - - $application->find($abbreviation); - } - - public function provideAmbiguousAbbreviations() - { - return [ - ['f', 'Command "f" is not defined.'], - [ - 'a', - "Command \"a\" is ambiguous.\nDid you mean one of these?\n". - " afoobar The foo:bar command\n". - " afoobar1 The foo:bar1 command\n". - ' afoobar2 The foo1:bar command', - ], - [ - 'foo:b', - "Command \"foo:b\" is ambiguous.\nDid you mean one of these?\n". - " foo:bar The foo:bar command\n". - " foo:bar1 The foo:bar1 command\n". - ' foo1:bar The foo1:bar command', - ], - ]; - } - - public function testFindCommandEqualNamespace() - { - $application = new Application(); - $application->add(new \Foo3Command()); - $application->add(new \Foo4Command()); - - $this->assertInstanceOf('Foo3Command', $application->find('foo3:bar'), '->find() returns the good command even if a namespace has same name'); - $this->assertInstanceOf('Foo4Command', $application->find('foo3:bar:toh'), '->find() returns a command even if its namespace equals another command name'); - } - - public function testFindCommandWithAmbiguousNamespacesButUniqueName() - { - $application = new Application(); - $application->add(new \FooCommand()); - $application->add(new \FoobarCommand()); - - $this->assertInstanceOf('FoobarCommand', $application->find('f:f')); - } - - public function testFindCommandWithMissingNamespace() - { - $application = new Application(); - $application->add(new \Foo4Command()); - - $this->assertInstanceOf('Foo4Command', $application->find('f::t')); - } - - /** - * @dataProvider provideInvalidCommandNamesSingle - * @expectedException \Symfony\Component\Console\Exception\CommandNotFoundException - * @expectedExceptionMessage Did you mean this - */ - public function testFindAlternativeExceptionMessageSingle($name) - { - $application = new Application(); - $application->add(new \Foo3Command()); - $application->find($name); - } - - public function testDontRunAlternativeNamespaceName() - { - $application = new Application(); - $application->add(new \Foo1Command()); - $application->setAutoExit(false); - $tester = new ApplicationTester($application); - $tester->run(['command' => 'foos:bar1'], ['decorated' => false]); - $this->assertSame(' - - There are no commands defined in the "foos" namespace. - - Did you mean this? - foo - - -', $tester->getDisplay(true)); - } - - public function testCanRunAlternativeCommandName() - { - $application = new Application(); - $application->add(new \FooWithoutAliasCommand()); - $application->setAutoExit(false); - $tester = new ApplicationTester($application); - $tester->setInputs(['y']); - $tester->run(['command' => 'foos'], ['decorated' => false]); - $display = trim($tester->getDisplay(true)); - $this->assertContains('Command "foos" is not defined', $display); - $this->assertContains('Do you want to run "foo" instead? (yes/no) [no]:', $display); - $this->assertContains('called', $display); - } - - public function testDontRunAlternativeCommandName() - { - $application = new Application(); - $application->add(new \FooWithoutAliasCommand()); - $application->setAutoExit(false); - $tester = new ApplicationTester($application); - $tester->setInputs(['n']); - $exitCode = $tester->run(['command' => 'foos'], ['decorated' => false]); - $this->assertSame(1, $exitCode); - $display = trim($tester->getDisplay(true)); - $this->assertContains('Command "foos" is not defined', $display); - $this->assertContains('Do you want to run "foo" instead? (yes/no) [no]:', $display); - } - - public function provideInvalidCommandNamesSingle() - { - return [ - ['foo3:barr'], - ['fooo3:bar'], - ]; - } - - public function testFindAlternativeExceptionMessageMultiple() - { - putenv('COLUMNS=120'); - $application = new Application(); - $application->add(new \FooCommand()); - $application->add(new \Foo1Command()); - $application->add(new \Foo2Command()); - - // Command + plural - try { - $application->find('foo:baR'); - $this->fail('->find() throws a CommandNotFoundException if command does not exist, with alternatives'); - } catch (\Exception $e) { - $this->assertInstanceOf('Symfony\Component\Console\Exception\CommandNotFoundException', $e, '->find() throws a CommandNotFoundException if command does not exist, with alternatives'); - $this->assertRegExp('/Did you mean one of these/', $e->getMessage(), '->find() throws a CommandNotFoundException if command does not exist, with alternatives'); - $this->assertRegExp('/foo1:bar/', $e->getMessage()); - $this->assertRegExp('/foo:bar/', $e->getMessage()); - } - - // Namespace + plural - try { - $application->find('foo2:bar'); - $this->fail('->find() throws a CommandNotFoundException if command does not exist, with alternatives'); - } catch (\Exception $e) { - $this->assertInstanceOf('Symfony\Component\Console\Exception\CommandNotFoundException', $e, '->find() throws a CommandNotFoundException if command does not exist, with alternatives'); - $this->assertRegExp('/Did you mean one of these/', $e->getMessage(), '->find() throws a CommandNotFoundException if command does not exist, with alternatives'); - $this->assertRegExp('/foo1/', $e->getMessage()); - } - - $application->add(new \Foo3Command()); - $application->add(new \Foo4Command()); - - // Subnamespace + plural - try { - $a = $application->find('foo3:'); - $this->fail('->find() should throw an Symfony\Component\Console\Exception\CommandNotFoundException if a command is ambiguous because of a subnamespace, with alternatives'); - } catch (\Exception $e) { - $this->assertInstanceOf('Symfony\Component\Console\Exception\CommandNotFoundException', $e); - $this->assertRegExp('/foo3:bar/', $e->getMessage()); - $this->assertRegExp('/foo3:bar:toh/', $e->getMessage()); - } - } - - public function testFindAlternativeCommands() - { - $application = new Application(); - - $application->add(new \FooCommand()); - $application->add(new \Foo1Command()); - $application->add(new \Foo2Command()); - - try { - $application->find($commandName = 'Unknown command'); - $this->fail('->find() throws a CommandNotFoundException if command does not exist'); - } catch (\Exception $e) { - $this->assertInstanceOf('Symfony\Component\Console\Exception\CommandNotFoundException', $e, '->find() throws a CommandNotFoundException if command does not exist'); - $this->assertSame([], $e->getAlternatives()); - $this->assertEquals(sprintf('Command "%s" is not defined.', $commandName), $e->getMessage(), '->find() throws a CommandNotFoundException if command does not exist, without alternatives'); - } - - // Test if "bar1" command throw a "CommandNotFoundException" and does not contain - // "foo:bar" as alternative because "bar1" is too far from "foo:bar" - try { - $application->find($commandName = 'bar1'); - $this->fail('->find() throws a CommandNotFoundException if command does not exist'); - } catch (\Exception $e) { - $this->assertInstanceOf('Symfony\Component\Console\Exception\CommandNotFoundException', $e, '->find() throws a CommandNotFoundException if command does not exist'); - $this->assertSame(['afoobar1', 'foo:bar1'], $e->getAlternatives()); - $this->assertRegExp(sprintf('/Command "%s" is not defined./', $commandName), $e->getMessage(), '->find() throws a CommandNotFoundException if command does not exist, with alternatives'); - $this->assertRegExp('/afoobar1/', $e->getMessage(), '->find() throws a CommandNotFoundException if command does not exist, with alternative : "afoobar1"'); - $this->assertRegExp('/foo:bar1/', $e->getMessage(), '->find() throws a CommandNotFoundException if command does not exist, with alternative : "foo:bar1"'); - $this->assertNotRegExp('/foo:bar(?>!1)/', $e->getMessage(), '->find() throws a CommandNotFoundException if command does not exist, without "foo:bar" alternative'); - } - } - - public function testFindAlternativeCommandsWithAnAlias() - { - $fooCommand = new \FooCommand(); - $fooCommand->setAliases(['foo2']); - - $application = new Application(); - $application->add($fooCommand); - - $result = $application->find('foo'); - - $this->assertSame($fooCommand, $result); - } - - public function testFindAlternativeNamespace() - { - $application = new Application(); - - $application->add(new \FooCommand()); - $application->add(new \Foo1Command()); - $application->add(new \Foo2Command()); - $application->add(new \Foo3Command()); - - try { - $application->find('Unknown-namespace:Unknown-command'); - $this->fail('->find() throws a CommandNotFoundException if namespace does not exist'); - } catch (\Exception $e) { - $this->assertInstanceOf('Symfony\Component\Console\Exception\CommandNotFoundException', $e, '->find() throws a CommandNotFoundException if namespace does not exist'); - $this->assertSame([], $e->getAlternatives()); - $this->assertEquals('There are no commands defined in the "Unknown-namespace" namespace.', $e->getMessage(), '->find() throws a CommandNotFoundException if namespace does not exist, without alternatives'); - } - - try { - $application->find('foo2:command'); - $this->fail('->find() throws a CommandNotFoundException if namespace does not exist'); - } catch (\Exception $e) { - $this->assertInstanceOf('Symfony\Component\Console\Exception\NamespaceNotFoundException', $e, '->find() throws a NamespaceNotFoundException if namespace does not exist'); - $this->assertInstanceOf('Symfony\Component\Console\Exception\CommandNotFoundException', $e, 'NamespaceNotFoundException extends from CommandNotFoundException'); - $this->assertCount(3, $e->getAlternatives()); - $this->assertContains('foo', $e->getAlternatives()); - $this->assertContains('foo1', $e->getAlternatives()); - $this->assertContains('foo3', $e->getAlternatives()); - $this->assertRegExp('/There are no commands defined in the "foo2" namespace./', $e->getMessage(), '->find() throws a CommandNotFoundException if namespace does not exist, with alternative'); - $this->assertRegExp('/foo/', $e->getMessage(), '->find() throws a CommandNotFoundException if namespace does not exist, with alternative : "foo"'); - $this->assertRegExp('/foo1/', $e->getMessage(), '->find() throws a CommandNotFoundException if namespace does not exist, with alternative : "foo1"'); - $this->assertRegExp('/foo3/', $e->getMessage(), '->find() throws a CommandNotFoundException if namespace does not exist, with alternative : "foo3"'); - } - } - - public function testFindAlternativesOutput() - { - $application = new Application(); - - $application->add(new \FooCommand()); - $application->add(new \Foo1Command()); - $application->add(new \Foo2Command()); - $application->add(new \Foo3Command()); - - $expectedAlternatives = [ - 'afoobar', - 'afoobar1', - 'afoobar2', - 'foo1:bar', - 'foo3:bar', - 'foo:bar', - 'foo:bar1', - ]; - - try { - $application->find('foo'); - $this->fail('->find() throws a CommandNotFoundException if command is not defined'); - } catch (\Exception $e) { - $this->assertInstanceOf('Symfony\Component\Console\Exception\CommandNotFoundException', $e, '->find() throws a CommandNotFoundException if command is not defined'); - $this->assertSame($expectedAlternatives, $e->getAlternatives()); - - $this->assertRegExp('/Command "foo" is not defined\..*Did you mean one of these\?.*/Ums', $e->getMessage()); - } - } - - public function testFindNamespaceDoesNotFailOnDeepSimilarNamespaces() - { - $application = $this->getMockBuilder('Symfony\Component\Console\Application')->setMethods(['getNamespaces'])->getMock(); - $application->expects($this->once()) - ->method('getNamespaces') - ->willReturn(['foo:sublong', 'bar:sub']); - - $this->assertEquals('foo:sublong', $application->findNamespace('f:sub')); - } - - /** - * @expectedException \Symfony\Component\Console\Exception\CommandNotFoundException - * @expectedExceptionMessage Command "foo::bar" is not defined. - */ - public function testFindWithDoubleColonInNameThrowsException() - { - $application = new Application(); - $application->add(new \FooCommand()); - $application->add(new \Foo4Command()); - $application->find('foo::bar'); - } - - public function testSetCatchExceptions() - { - $application = new Application(); - $application->setAutoExit(false); - putenv('COLUMNS=120'); - $tester = new ApplicationTester($application); - - $application->setCatchExceptions(true); - $this->assertTrue($application->areExceptionsCaught()); - - $tester->run(['command' => 'foo'], ['decorated' => false]); - $this->assertStringEqualsFile(self::$fixturesPath.'/application_renderexception1.txt', $tester->getDisplay(true), '->setCatchExceptions() sets the catch exception flag'); - - $tester->run(['command' => 'foo'], ['decorated' => false, 'capture_stderr_separately' => true]); - $this->assertStringEqualsFile(self::$fixturesPath.'/application_renderexception1.txt', $tester->getErrorOutput(true), '->setCatchExceptions() sets the catch exception flag'); - $this->assertSame('', $tester->getDisplay(true)); - - $application->setCatchExceptions(false); - try { - $tester->run(['command' => 'foo'], ['decorated' => false]); - $this->fail('->setCatchExceptions() sets the catch exception flag'); - } catch (\Exception $e) { - $this->assertInstanceOf('\Exception', $e, '->setCatchExceptions() sets the catch exception flag'); - $this->assertEquals('Command "foo" is not defined.', $e->getMessage(), '->setCatchExceptions() sets the catch exception flag'); - } - } - - public function testAutoExitSetting() - { - $application = new Application(); - $this->assertTrue($application->isAutoExitEnabled()); - - $application->setAutoExit(false); - $this->assertFalse($application->isAutoExitEnabled()); - } - - public function testRenderException() - { - $application = new Application(); - $application->setAutoExit(false); - putenv('COLUMNS=120'); - $tester = new ApplicationTester($application); - - $tester->run(['command' => 'foo'], ['decorated' => false, 'capture_stderr_separately' => true]); - $this->assertStringEqualsFile(self::$fixturesPath.'/application_renderexception1.txt', $tester->getErrorOutput(true), '->renderException() renders a pretty exception'); - - $tester->run(['command' => 'foo'], ['decorated' => false, 'verbosity' => Output::VERBOSITY_VERBOSE, 'capture_stderr_separately' => true]); - $this->assertContains('Exception trace', $tester->getErrorOutput(), '->renderException() renders a pretty exception with a stack trace when verbosity is verbose'); - - $tester->run(['command' => 'list', '--foo' => true], ['decorated' => false, 'capture_stderr_separately' => true]); - $this->assertStringEqualsFile(self::$fixturesPath.'/application_renderexception2.txt', $tester->getErrorOutput(true), '->renderException() renders the command synopsis when an exception occurs in the context of a command'); - - $application->add(new \Foo3Command()); - $tester = new ApplicationTester($application); - $tester->run(['command' => 'foo3:bar'], ['decorated' => false, 'capture_stderr_separately' => true]); - $this->assertStringEqualsFile(self::$fixturesPath.'/application_renderexception3.txt', $tester->getErrorOutput(true), '->renderException() renders a pretty exceptions with previous exceptions'); - - $tester->run(['command' => 'foo3:bar'], ['decorated' => false, 'verbosity' => Output::VERBOSITY_VERBOSE]); - $this->assertRegExp('/\[Exception\]\s*First exception/', $tester->getDisplay(), '->renderException() renders a pretty exception without code exception when code exception is default and verbosity is verbose'); - $this->assertRegExp('/\[Exception\]\s*Second exception/', $tester->getDisplay(), '->renderException() renders a pretty exception without code exception when code exception is 0 and verbosity is verbose'); - $this->assertRegExp('/\[Exception \(404\)\]\s*Third exception/', $tester->getDisplay(), '->renderException() renders a pretty exception with code exception when code exception is 404 and verbosity is verbose'); - - $tester->run(['command' => 'foo3:bar'], ['decorated' => true]); - $this->assertStringEqualsFile(self::$fixturesPath.'/application_renderexception3decorated.txt', $tester->getDisplay(true), '->renderException() renders a pretty exceptions with previous exceptions'); - - $tester->run(['command' => 'foo3:bar'], ['decorated' => true, 'capture_stderr_separately' => true]); - $this->assertStringEqualsFile(self::$fixturesPath.'/application_renderexception3decorated.txt', $tester->getErrorOutput(true), '->renderException() renders a pretty exceptions with previous exceptions'); - - $application = new Application(); - $application->setAutoExit(false); - putenv('COLUMNS=32'); - $tester = new ApplicationTester($application); - - $tester->run(['command' => 'foo'], ['decorated' => false, 'capture_stderr_separately' => true]); - $this->assertStringEqualsFile(self::$fixturesPath.'/application_renderexception4.txt', $tester->getErrorOutput(true), '->renderException() wraps messages when they are bigger than the terminal'); - putenv('COLUMNS=120'); - } - - public function testRenderExceptionWithDoubleWidthCharacters() - { - $application = new Application(); - $application->setAutoExit(false); - putenv('COLUMNS=120'); - $application->register('foo')->setCode(function () { - throw new \Exception('エラーメッセージ'); - }); - $tester = new ApplicationTester($application); - - $tester->run(['command' => 'foo'], ['decorated' => false, 'capture_stderr_separately' => true]); - $this->assertStringMatchesFormatFile(self::$fixturesPath.'/application_renderexception_doublewidth1.txt', $tester->getErrorOutput(true), '->renderException() renders a pretty exceptions with previous exceptions'); - - $tester->run(['command' => 'foo'], ['decorated' => true, 'capture_stderr_separately' => true]); - $this->assertStringMatchesFormatFile(self::$fixturesPath.'/application_renderexception_doublewidth1decorated.txt', $tester->getErrorOutput(true), '->renderException() renders a pretty exceptions with previous exceptions'); - - $application = new Application(); - $application->setAutoExit(false); - putenv('COLUMNS=32'); - $application->register('foo')->setCode(function () { - throw new \Exception('コマンドの実行中にエラーが発生しました。'); - }); - $tester = new ApplicationTester($application); - $tester->run(['command' => 'foo'], ['decorated' => false, 'capture_stderr_separately' => true]); - $this->assertStringMatchesFormatFile(self::$fixturesPath.'/application_renderexception_doublewidth2.txt', $tester->getErrorOutput(true), '->renderException() wraps messages when they are bigger than the terminal'); - putenv('COLUMNS=120'); - } - - public function testRenderExceptionEscapesLines() - { - $application = new Application(); - $application->setAutoExit(false); - putenv('COLUMNS=22'); - $application->register('foo')->setCode(function () { - throw new \Exception('dont break here !'); - }); - $tester = new ApplicationTester($application); - - $tester->run(['command' => 'foo'], ['decorated' => false]); - $this->assertStringMatchesFormatFile(self::$fixturesPath.'/application_renderexception_escapeslines.txt', $tester->getDisplay(true), '->renderException() escapes lines containing formatting'); - putenv('COLUMNS=120'); - } - - public function testRenderExceptionLineBreaks() - { - $application = $this->getMockBuilder('Symfony\Component\Console\Application')->setMethods(['getTerminalWidth'])->getMock(); - $application->setAutoExit(false); - $application->expects($this->any()) - ->method('getTerminalWidth') - ->willReturn(120); - $application->register('foo')->setCode(function () { - throw new \InvalidArgumentException("\n\nline 1 with extra spaces \nline 2\n\nline 4\n"); - }); - $tester = new ApplicationTester($application); - - $tester->run(['command' => 'foo'], ['decorated' => false]); - $this->assertStringMatchesFormatFile(self::$fixturesPath.'/application_renderexception_linebreaks.txt', $tester->getDisplay(true), '->renderException() keep multiple line breaks'); - } - - public function testRenderAnonymousException() - { - $application = new Application(); - $application->setAutoExit(false); - $application->register('foo')->setCode(function () { - throw new class('') extends \InvalidArgumentException { - }; - }); - $tester = new ApplicationTester($application); - - $tester->run(['command' => 'foo'], ['decorated' => false]); - $this->assertContains('[InvalidArgumentException@anonymous]', $tester->getDisplay(true)); - - $application = new Application(); - $application->setAutoExit(false); - $application->register('foo')->setCode(function () { - throw new \InvalidArgumentException(sprintf('Dummy type "%s" is invalid.', \get_class(new class() { - }))); - }); - $tester = new ApplicationTester($application); - - $tester->run(['command' => 'foo'], ['decorated' => false]); - $this->assertContains('Dummy type "@anonymous" is invalid.', $tester->getDisplay(true)); - } - - public function testRenderExceptionStackTraceContainsRootException() - { - $application = new Application(); - $application->setAutoExit(false); - $application->register('foo')->setCode(function () { - throw new class('') extends \InvalidArgumentException { - }; - }); - $tester = new ApplicationTester($application); - - $tester->run(['command' => 'foo'], ['decorated' => false]); - $this->assertContains('[InvalidArgumentException@anonymous]', $tester->getDisplay(true)); - - $application = new Application(); - $application->setAutoExit(false); - $application->register('foo')->setCode(function () { - throw new \InvalidArgumentException(sprintf('Dummy type "%s" is invalid.', \get_class(new class() { - }))); - }); - $tester = new ApplicationTester($application); - - $tester->run(['command' => 'foo'], ['decorated' => false]); - $this->assertContains('Dummy type "@anonymous" is invalid.', $tester->getDisplay(true)); - } - - public function testRun() - { - $application = new Application(); - $application->setAutoExit(false); - $application->setCatchExceptions(false); - $application->add($command = new \Foo1Command()); - $_SERVER['argv'] = ['cli.php', 'foo:bar1']; - - ob_start(); - $application->run(); - ob_end_clean(); - - $this->assertInstanceOf('Symfony\Component\Console\Input\ArgvInput', $command->input, '->run() creates an ArgvInput by default if none is given'); - $this->assertInstanceOf('Symfony\Component\Console\Output\ConsoleOutput', $command->output, '->run() creates a ConsoleOutput by default if none is given'); - - $application = new Application(); - $application->setAutoExit(false); - $application->setCatchExceptions(false); - - $this->ensureStaticCommandHelp($application); - $tester = new ApplicationTester($application); - - $tester->run([], ['decorated' => false]); - $this->assertStringEqualsFile(self::$fixturesPath.'/application_run1.txt', $tester->getDisplay(true), '->run() runs the list command if no argument is passed'); - - $tester->run(['--help' => true], ['decorated' => false]); - $this->assertStringEqualsFile(self::$fixturesPath.'/application_run2.txt', $tester->getDisplay(true), '->run() runs the help command if --help is passed'); - - $tester->run(['-h' => true], ['decorated' => false]); - $this->assertStringEqualsFile(self::$fixturesPath.'/application_run2.txt', $tester->getDisplay(true), '->run() runs the help command if -h is passed'); - - $tester->run(['command' => 'list', '--help' => true], ['decorated' => false]); - $this->assertStringEqualsFile(self::$fixturesPath.'/application_run3.txt', $tester->getDisplay(true), '->run() displays the help if --help is passed'); - - $tester->run(['command' => 'list', '-h' => true], ['decorated' => false]); - $this->assertStringEqualsFile(self::$fixturesPath.'/application_run3.txt', $tester->getDisplay(true), '->run() displays the help if -h is passed'); - - $tester->run(['--ansi' => true]); - $this->assertTrue($tester->getOutput()->isDecorated(), '->run() forces color output if --ansi is passed'); - - $tester->run(['--no-ansi' => true]); - $this->assertFalse($tester->getOutput()->isDecorated(), '->run() forces color output to be disabled if --no-ansi is passed'); - - $tester->run(['--version' => true], ['decorated' => false]); - $this->assertStringEqualsFile(self::$fixturesPath.'/application_run4.txt', $tester->getDisplay(true), '->run() displays the program version if --version is passed'); - - $tester->run(['-V' => true], ['decorated' => false]); - $this->assertStringEqualsFile(self::$fixturesPath.'/application_run4.txt', $tester->getDisplay(true), '->run() displays the program version if -v is passed'); - - $tester->run(['command' => 'list', '--quiet' => true]); - $this->assertSame('', $tester->getDisplay(), '->run() removes all output if --quiet is passed'); - $this->assertFalse($tester->getInput()->isInteractive(), '->run() sets off the interactive mode if --quiet is passed'); - - $tester->run(['command' => 'list', '-q' => true]); - $this->assertSame('', $tester->getDisplay(), '->run() removes all output if -q is passed'); - $this->assertFalse($tester->getInput()->isInteractive(), '->run() sets off the interactive mode if -q is passed'); - - $tester->run(['command' => 'list', '--verbose' => true]); - $this->assertSame(Output::VERBOSITY_VERBOSE, $tester->getOutput()->getVerbosity(), '->run() sets the output to verbose if --verbose is passed'); - - $tester->run(['command' => 'list', '--verbose' => 1]); - $this->assertSame(Output::VERBOSITY_VERBOSE, $tester->getOutput()->getVerbosity(), '->run() sets the output to verbose if --verbose=1 is passed'); - - $tester->run(['command' => 'list', '--verbose' => 2]); - $this->assertSame(Output::VERBOSITY_VERY_VERBOSE, $tester->getOutput()->getVerbosity(), '->run() sets the output to very verbose if --verbose=2 is passed'); - - $tester->run(['command' => 'list', '--verbose' => 3]); - $this->assertSame(Output::VERBOSITY_DEBUG, $tester->getOutput()->getVerbosity(), '->run() sets the output to debug if --verbose=3 is passed'); - - $tester->run(['command' => 'list', '--verbose' => 4]); - $this->assertSame(Output::VERBOSITY_VERBOSE, $tester->getOutput()->getVerbosity(), '->run() sets the output to verbose if unknown --verbose level is passed'); - - $tester->run(['command' => 'list', '-v' => true]); - $this->assertSame(Output::VERBOSITY_VERBOSE, $tester->getOutput()->getVerbosity(), '->run() sets the output to verbose if -v is passed'); - - $tester->run(['command' => 'list', '-vv' => true]); - $this->assertSame(Output::VERBOSITY_VERY_VERBOSE, $tester->getOutput()->getVerbosity(), '->run() sets the output to verbose if -v is passed'); - - $tester->run(['command' => 'list', '-vvv' => true]); - $this->assertSame(Output::VERBOSITY_DEBUG, $tester->getOutput()->getVerbosity(), '->run() sets the output to verbose if -v is passed'); - - $application = new Application(); - $application->setAutoExit(false); - $application->setCatchExceptions(false); - $application->add(new \FooCommand()); - $tester = new ApplicationTester($application); - - $tester->run(['command' => 'foo:bar', '--no-interaction' => true], ['decorated' => false]); - $this->assertSame('called'.PHP_EOL, $tester->getDisplay(), '->run() does not call interact() if --no-interaction is passed'); - - $tester->run(['command' => 'foo:bar', '-n' => true], ['decorated' => false]); - $this->assertSame('called'.PHP_EOL, $tester->getDisplay(), '->run() does not call interact() if -n is passed'); - } - - public function testRunWithGlobalOptionAndNoCommand() - { - $application = new Application(); - $application->setAutoExit(false); - $application->setCatchExceptions(false); - $application->getDefinition()->addOption(new InputOption('foo', 'f', InputOption::VALUE_OPTIONAL)); - - $output = new StreamOutput(fopen('php://memory', 'w', false)); - $input = new ArgvInput(['cli.php', '--foo', 'bar']); - - $this->assertSame(0, $application->run($input, $output)); - } - - /** - * Issue #9285. - * - * If the "verbose" option is just before an argument in ArgvInput, - * an argument value should not be treated as verbosity value. - * This test will fail with "Not enough arguments." if broken - */ - public function testVerboseValueNotBreakArguments() - { - $application = new Application(); - $application->setAutoExit(false); - $application->setCatchExceptions(false); - $application->add(new \FooCommand()); - - $output = new StreamOutput(fopen('php://memory', 'w', false)); - - $input = new ArgvInput(['cli.php', '-v', 'foo:bar']); - $application->run($input, $output); - - $this->addToAssertionCount(1); - - $input = new ArgvInput(['cli.php', '--verbose', 'foo:bar']); - $application->run($input, $output); - - $this->addToAssertionCount(1); - } - - public function testRunReturnsIntegerExitCode() - { - $exception = new \Exception('', 4); - - $application = $this->getMockBuilder('Symfony\Component\Console\Application')->setMethods(['doRun'])->getMock(); - $application->setAutoExit(false); - $application->expects($this->once()) - ->method('doRun') - ->willThrowException($exception); - - $exitCode = $application->run(new ArrayInput([]), new NullOutput()); - - $this->assertSame(4, $exitCode, '->run() returns integer exit code extracted from raised exception'); - } - - public function testRunDispatchesIntegerExitCode() - { - $passedRightValue = false; - - // We can assume here that some other test asserts that the event is dispatched at all - $dispatcher = new EventDispatcher(); - $dispatcher->addListener('console.terminate', function (ConsoleTerminateEvent $event) use (&$passedRightValue) { - $passedRightValue = (4 === $event->getExitCode()); - }); - - $application = new Application(); - $application->setDispatcher($dispatcher); - $application->setAutoExit(false); - - $application->register('test')->setCode(function (InputInterface $input, OutputInterface $output) { - throw new \Exception('', 4); - }); - - $tester = new ApplicationTester($application); - $tester->run(['command' => 'test']); - - $this->assertTrue($passedRightValue, '-> exit code 4 was passed in the console.terminate event'); - } - - public function testRunReturnsExitCodeOneForExceptionCodeZero() - { - $exception = new \Exception('', 0); - - $application = $this->getMockBuilder('Symfony\Component\Console\Application')->setMethods(['doRun'])->getMock(); - $application->setAutoExit(false); - $application->expects($this->once()) - ->method('doRun') - ->willThrowException($exception); - - $exitCode = $application->run(new ArrayInput([]), new NullOutput()); - - $this->assertSame(1, $exitCode, '->run() returns exit code 1 when exception code is 0'); - } - - public function testRunDispatchesExitCodeOneForExceptionCodeZero() - { - $passedRightValue = false; - - // We can assume here that some other test asserts that the event is dispatched at all - $dispatcher = new EventDispatcher(); - $dispatcher->addListener('console.terminate', function (ConsoleTerminateEvent $event) use (&$passedRightValue) { - $passedRightValue = (1 === $event->getExitCode()); - }); - - $application = new Application(); - $application->setDispatcher($dispatcher); - $application->setAutoExit(false); - - $application->register('test')->setCode(function (InputInterface $input, OutputInterface $output) { - throw new \Exception(); - }); - - $tester = new ApplicationTester($application); - $tester->run(['command' => 'test']); - - $this->assertTrue($passedRightValue, '-> exit code 1 was passed in the console.terminate event'); - } - - /** - * @expectedException \LogicException - * @expectedExceptionMessage An option with shortcut "e" already exists. - */ - public function testAddingOptionWithDuplicateShortcut() - { - $dispatcher = new EventDispatcher(); - $application = new Application(); - $application->setAutoExit(false); - $application->setCatchExceptions(false); - $application->setDispatcher($dispatcher); - - $application->getDefinition()->addOption(new InputOption('--env', '-e', InputOption::VALUE_REQUIRED, 'Environment')); - - $application - ->register('foo') - ->setAliases(['f']) - ->setDefinition([new InputOption('survey', 'e', InputOption::VALUE_REQUIRED, 'My option with a shortcut.')]) - ->setCode(function (InputInterface $input, OutputInterface $output) {}) - ; - - $input = new ArrayInput(['command' => 'foo']); - $output = new NullOutput(); - - $application->run($input, $output); - } - - /** - * @expectedException \LogicException - * @dataProvider getAddingAlreadySetDefinitionElementData - */ - public function testAddingAlreadySetDefinitionElementData($def) - { - $application = new Application(); - $application->setAutoExit(false); - $application->setCatchExceptions(false); - $application - ->register('foo') - ->setDefinition([$def]) - ->setCode(function (InputInterface $input, OutputInterface $output) {}) - ; - - $input = new ArrayInput(['command' => 'foo']); - $output = new NullOutput(); - $application->run($input, $output); - } - - public function getAddingAlreadySetDefinitionElementData() - { - return [ - [new InputArgument('command', InputArgument::REQUIRED)], - [new InputOption('quiet', '', InputOption::VALUE_NONE)], - [new InputOption('query', 'q', InputOption::VALUE_NONE)], - ]; - } - - public function testGetDefaultHelperSetReturnsDefaultValues() - { - $application = new Application(); - $application->setAutoExit(false); - $application->setCatchExceptions(false); - - $helperSet = $application->getHelperSet(); - - $this->assertTrue($helperSet->has('formatter')); - } - - public function testAddingSingleHelperSetOverwritesDefaultValues() - { - $application = new Application(); - $application->setAutoExit(false); - $application->setCatchExceptions(false); - - $application->setHelperSet(new HelperSet([new FormatterHelper()])); - - $helperSet = $application->getHelperSet(); - - $this->assertTrue($helperSet->has('formatter')); - - // no other default helper set should be returned - $this->assertFalse($helperSet->has('dialog')); - $this->assertFalse($helperSet->has('progress')); - } - - public function testOverwritingDefaultHelperSetOverwritesDefaultValues() - { - $application = new CustomApplication(); - $application->setAutoExit(false); - $application->setCatchExceptions(false); - - $application->setHelperSet(new HelperSet([new FormatterHelper()])); - - $helperSet = $application->getHelperSet(); - - $this->assertTrue($helperSet->has('formatter')); - - // no other default helper set should be returned - $this->assertFalse($helperSet->has('dialog')); - $this->assertFalse($helperSet->has('progress')); - } - - public function testGetDefaultInputDefinitionReturnsDefaultValues() - { - $application = new Application(); - $application->setAutoExit(false); - $application->setCatchExceptions(false); - - $inputDefinition = $application->getDefinition(); - - $this->assertTrue($inputDefinition->hasArgument('command')); - - $this->assertTrue($inputDefinition->hasOption('help')); - $this->assertTrue($inputDefinition->hasOption('quiet')); - $this->assertTrue($inputDefinition->hasOption('verbose')); - $this->assertTrue($inputDefinition->hasOption('version')); - $this->assertTrue($inputDefinition->hasOption('ansi')); - $this->assertTrue($inputDefinition->hasOption('no-ansi')); - $this->assertTrue($inputDefinition->hasOption('no-interaction')); - } - - public function testOverwritingDefaultInputDefinitionOverwritesDefaultValues() - { - $application = new CustomApplication(); - $application->setAutoExit(false); - $application->setCatchExceptions(false); - - $inputDefinition = $application->getDefinition(); - - // check whether the default arguments and options are not returned any more - $this->assertFalse($inputDefinition->hasArgument('command')); - - $this->assertFalse($inputDefinition->hasOption('help')); - $this->assertFalse($inputDefinition->hasOption('quiet')); - $this->assertFalse($inputDefinition->hasOption('verbose')); - $this->assertFalse($inputDefinition->hasOption('version')); - $this->assertFalse($inputDefinition->hasOption('ansi')); - $this->assertFalse($inputDefinition->hasOption('no-ansi')); - $this->assertFalse($inputDefinition->hasOption('no-interaction')); - - $this->assertTrue($inputDefinition->hasOption('custom')); - } - - public function testSettingCustomInputDefinitionOverwritesDefaultValues() - { - $application = new Application(); - $application->setAutoExit(false); - $application->setCatchExceptions(false); - - $application->setDefinition(new InputDefinition([new InputOption('--custom', '-c', InputOption::VALUE_NONE, 'Set the custom input definition.')])); - - $inputDefinition = $application->getDefinition(); - - // check whether the default arguments and options are not returned any more - $this->assertFalse($inputDefinition->hasArgument('command')); - - $this->assertFalse($inputDefinition->hasOption('help')); - $this->assertFalse($inputDefinition->hasOption('quiet')); - $this->assertFalse($inputDefinition->hasOption('verbose')); - $this->assertFalse($inputDefinition->hasOption('version')); - $this->assertFalse($inputDefinition->hasOption('ansi')); - $this->assertFalse($inputDefinition->hasOption('no-ansi')); - $this->assertFalse($inputDefinition->hasOption('no-interaction')); - - $this->assertTrue($inputDefinition->hasOption('custom')); - } - - public function testRunWithDispatcher() - { - $application = new Application(); - $application->setAutoExit(false); - $application->setDispatcher($this->getDispatcher()); - - $application->register('foo')->setCode(function (InputInterface $input, OutputInterface $output) { - $output->write('foo.'); - }); - - $tester = new ApplicationTester($application); - $tester->run(['command' => 'foo']); - $this->assertEquals('before.foo.after.'.PHP_EOL, $tester->getDisplay()); - } - - /** - * @expectedException \LogicException - * @expectedExceptionMessage error - */ - public function testRunWithExceptionAndDispatcher() - { - $application = new Application(); - $application->setDispatcher($this->getDispatcher()); - $application->setAutoExit(false); - $application->setCatchExceptions(false); - - $application->register('foo')->setCode(function (InputInterface $input, OutputInterface $output) { - throw new \RuntimeException('foo'); - }); - - $tester = new ApplicationTester($application); - $tester->run(['command' => 'foo']); - } - - public function testRunDispatchesAllEventsWithException() - { - $application = new Application(); - $application->setDispatcher($this->getDispatcher()); - $application->setAutoExit(false); - - $application->register('foo')->setCode(function (InputInterface $input, OutputInterface $output) { - $output->write('foo.'); - - throw new \RuntimeException('foo'); - }); - - $tester = new ApplicationTester($application); - $tester->run(['command' => 'foo']); - $this->assertContains('before.foo.error.after.', $tester->getDisplay()); - } - - public function testRunDispatchesAllEventsWithExceptionInListener() - { - $dispatcher = $this->getDispatcher(); - $dispatcher->addListener('console.command', function () { - throw new \RuntimeException('foo'); - }); - - $application = new Application(); - $application->setDispatcher($dispatcher); - $application->setAutoExit(false); - - $application->register('foo')->setCode(function (InputInterface $input, OutputInterface $output) { - $output->write('foo.'); - }); - - $tester = new ApplicationTester($application); - $tester->run(['command' => 'foo']); - $this->assertContains('before.error.after.', $tester->getDisplay()); - } - - public function testRunWithError() - { - $application = new Application(); - $application->setAutoExit(false); - $application->setCatchExceptions(false); - - $application->register('dym')->setCode(function (InputInterface $input, OutputInterface $output) { - $output->write('dym.'); - - throw new \Error('dymerr'); - }); - - $tester = new ApplicationTester($application); - - try { - $tester->run(['command' => 'dym']); - $this->fail('Error expected.'); - } catch (\Error $e) { - $this->assertSame('dymerr', $e->getMessage()); - } - } - - public function testRunAllowsErrorListenersToSilenceTheException() - { - $dispatcher = $this->getDispatcher(); - $dispatcher->addListener('console.error', function (ConsoleErrorEvent $event) { - $event->getOutput()->write('silenced.'); - - $event->setExitCode(0); - }); - - $dispatcher->addListener('console.command', function () { - throw new \RuntimeException('foo'); - }); - - $application = new Application(); - $application->setDispatcher($dispatcher); - $application->setAutoExit(false); - - $application->register('foo')->setCode(function (InputInterface $input, OutputInterface $output) { - $output->write('foo.'); - }); - - $tester = new ApplicationTester($application); - $tester->run(['command' => 'foo']); - $this->assertContains('before.error.silenced.after.', $tester->getDisplay()); - $this->assertEquals(ConsoleCommandEvent::RETURN_CODE_DISABLED, $tester->getStatusCode()); - } - - public function testConsoleErrorEventIsTriggeredOnCommandNotFound() - { - $dispatcher = new EventDispatcher(); - $dispatcher->addListener('console.error', function (ConsoleErrorEvent $event) { - $this->assertNull($event->getCommand()); - $this->assertInstanceOf(CommandNotFoundException::class, $event->getError()); - $event->getOutput()->write('silenced command not found'); - }); - - $application = new Application(); - $application->setDispatcher($dispatcher); - $application->setAutoExit(false); - - $tester = new ApplicationTester($application); - $tester->run(['command' => 'unknown']); - $this->assertContains('silenced command not found', $tester->getDisplay()); - $this->assertEquals(1, $tester->getStatusCode()); - } - - public function testErrorIsRethrownIfNotHandledByConsoleErrorEvent() - { - $application = new Application(); - $application->setAutoExit(false); - $application->setCatchExceptions(false); - $application->setDispatcher(new EventDispatcher()); - - $application->register('dym')->setCode(function (InputInterface $input, OutputInterface $output) { - new \UnknownClass(); - }); - - $tester = new ApplicationTester($application); - - try { - $tester->run(['command' => 'dym']); - $this->fail('->run() should rethrow PHP errors if not handled via ConsoleErrorEvent.'); - } catch (\Error $e) { - $this->assertSame($e->getMessage(), 'Class \'UnknownClass\' not found'); - } - } - - /** - * @expectedException \LogicException - * @expectedExceptionMessage error - */ - public function testRunWithErrorAndDispatcher() - { - $application = new Application(); - $application->setDispatcher($this->getDispatcher()); - $application->setAutoExit(false); - $application->setCatchExceptions(false); - - $application->register('dym')->setCode(function (InputInterface $input, OutputInterface $output) { - $output->write('dym.'); - - throw new \Error('dymerr'); - }); - - $tester = new ApplicationTester($application); - $tester->run(['command' => 'dym']); - $this->assertContains('before.dym.error.after.', $tester->getDisplay(), 'The PHP Error did not dispached events'); - } - - public function testRunDispatchesAllEventsWithError() - { - $application = new Application(); - $application->setDispatcher($this->getDispatcher()); - $application->setAutoExit(false); - - $application->register('dym')->setCode(function (InputInterface $input, OutputInterface $output) { - $output->write('dym.'); - - throw new \Error('dymerr'); - }); - - $tester = new ApplicationTester($application); - $tester->run(['command' => 'dym']); - $this->assertContains('before.dym.error.after.', $tester->getDisplay(), 'The PHP Error did not dispached events'); - } - - public function testRunWithErrorFailingStatusCode() - { - $application = new Application(); - $application->setDispatcher($this->getDispatcher()); - $application->setAutoExit(false); - - $application->register('dus')->setCode(function (InputInterface $input, OutputInterface $output) { - $output->write('dus.'); - - throw new \Error('duserr'); - }); - - $tester = new ApplicationTester($application); - $tester->run(['command' => 'dus']); - $this->assertSame(1, $tester->getStatusCode(), 'Status code should be 1'); - } - - public function testRunWithDispatcherSkippingCommand() - { - $application = new Application(); - $application->setDispatcher($this->getDispatcher(true)); - $application->setAutoExit(false); - - $application->register('foo')->setCode(function (InputInterface $input, OutputInterface $output) { - $output->write('foo.'); - }); - - $tester = new ApplicationTester($application); - $exitCode = $tester->run(['command' => 'foo']); - $this->assertContains('before.after.', $tester->getDisplay()); - $this->assertEquals(ConsoleCommandEvent::RETURN_CODE_DISABLED, $exitCode); - } - - public function testRunWithDispatcherAccessingInputOptions() - { - $noInteractionValue = null; - $quietValue = null; - - $dispatcher = $this->getDispatcher(); - $dispatcher->addListener('console.command', function (ConsoleCommandEvent $event) use (&$noInteractionValue, &$quietValue) { - $input = $event->getInput(); - - $noInteractionValue = $input->getOption('no-interaction'); - $quietValue = $input->getOption('quiet'); - }); - - $application = new Application(); - $application->setDispatcher($dispatcher); - $application->setAutoExit(false); - - $application->register('foo')->setCode(function (InputInterface $input, OutputInterface $output) { - $output->write('foo.'); - }); - - $tester = new ApplicationTester($application); - $tester->run(['command' => 'foo', '--no-interaction' => true]); - - $this->assertTrue($noInteractionValue); - $this->assertFalse($quietValue); - } - - public function testRunWithDispatcherAddingInputOptions() - { - $extraValue = null; - - $dispatcher = $this->getDispatcher(); - $dispatcher->addListener('console.command', function (ConsoleCommandEvent $event) use (&$extraValue) { - $definition = $event->getCommand()->getDefinition(); - $input = $event->getInput(); - - $definition->addOption(new InputOption('extra', null, InputOption::VALUE_REQUIRED)); - $input->bind($definition); - - $extraValue = $input->getOption('extra'); - }); - - $application = new Application(); - $application->setDispatcher($dispatcher); - $application->setAutoExit(false); - - $application->register('foo')->setCode(function (InputInterface $input, OutputInterface $output) { - $output->write('foo.'); - }); - - $tester = new ApplicationTester($application); - $tester->run(['command' => 'foo', '--extra' => 'some test value']); - - $this->assertEquals('some test value', $extraValue); - } - - public function testSetRunCustomDefaultCommand() - { - $command = new \FooCommand(); - - $application = new Application(); - $application->setAutoExit(false); - $application->add($command); - $application->setDefaultCommand($command->getName()); - - $tester = new ApplicationTester($application); - $tester->run([], ['interactive' => false]); - $this->assertEquals('called'.PHP_EOL, $tester->getDisplay(), 'Application runs the default set command if different from \'list\' command'); - - $application = new CustomDefaultCommandApplication(); - $application->setAutoExit(false); - - $tester = new ApplicationTester($application); - $tester->run([], ['interactive' => false]); - - $this->assertEquals('called'.PHP_EOL, $tester->getDisplay(), 'Application runs the default set command if different from \'list\' command'); - } - - public function testSetRunCustomDefaultCommandWithOption() - { - $command = new \FooOptCommand(); - - $application = new Application(); - $application->setAutoExit(false); - $application->add($command); - $application->setDefaultCommand($command->getName()); - - $tester = new ApplicationTester($application); - $tester->run(['--fooopt' => 'opt'], ['interactive' => false]); - - $this->assertEquals('called'.PHP_EOL.'opt'.PHP_EOL, $tester->getDisplay(), 'Application runs the default set command if different from \'list\' command'); - } - - public function testSetRunCustomSingleCommand() - { - $command = new \FooCommand(); - - $application = new Application(); - $application->setAutoExit(false); - $application->add($command); - $application->setDefaultCommand($command->getName(), true); - - $tester = new ApplicationTester($application); - - $tester->run([]); - $this->assertContains('called', $tester->getDisplay()); - - $tester->run(['--help' => true]); - $this->assertContains('The foo:bar command', $tester->getDisplay()); - } - - /** - * @requires function posix_isatty - */ - public function testCanCheckIfTerminalIsInteractive() - { - $application = new CustomDefaultCommandApplication(); - $application->setAutoExit(false); - - $tester = new ApplicationTester($application); - $tester->run(['command' => 'help']); - - $this->assertFalse($tester->getInput()->hasParameterOption(['--no-interaction', '-n'])); - - $inputStream = $tester->getInput()->getStream(); - $this->assertEquals($tester->getInput()->isInteractive(), @posix_isatty($inputStream)); - } - - public function testRunLazyCommandService() - { - $container = new ContainerBuilder(); - $container->addCompilerPass(new AddConsoleCommandPass()); - $container - ->register('lazy-command', LazyCommand::class) - ->addTag('console.command', ['command' => 'lazy:command']) - ->addTag('console.command', ['command' => 'lazy:alias']) - ->addTag('console.command', ['command' => 'lazy:alias2']); - $container->compile(); - - $application = new Application(); - $application->setCommandLoader($container->get('console.command_loader')); - $application->setAutoExit(false); - - $tester = new ApplicationTester($application); - - $tester->run(['command' => 'lazy:command']); - $this->assertSame("lazy-command called\n", $tester->getDisplay(true)); - - $tester->run(['command' => 'lazy:alias']); - $this->assertSame("lazy-command called\n", $tester->getDisplay(true)); - - $tester->run(['command' => 'lazy:alias2']); - $this->assertSame("lazy-command called\n", $tester->getDisplay(true)); - - $command = $application->get('lazy:command'); - $this->assertSame(['lazy:alias', 'lazy:alias2'], $command->getAliases()); - } - - /** - * @expectedException \Symfony\Component\Console\Exception\CommandNotFoundException - */ - public function testGetDisabledLazyCommand() - { - $application = new Application(); - $application->setCommandLoader(new FactoryCommandLoader(['disabled' => function () { return new DisabledCommand(); }])); - $application->get('disabled'); - } - - public function testHasReturnsFalseForDisabledLazyCommand() - { - $application = new Application(); - $application->setCommandLoader(new FactoryCommandLoader(['disabled' => function () { return new DisabledCommand(); }])); - $this->assertFalse($application->has('disabled')); - } - - public function testAllExcludesDisabledLazyCommand() - { - $application = new Application(); - $application->setCommandLoader(new FactoryCommandLoader(['disabled' => function () { return new DisabledCommand(); }])); - $this->assertArrayNotHasKey('disabled', $application->all()); - } - - protected function getDispatcher($skipCommand = false) - { - $dispatcher = new EventDispatcher(); - $dispatcher->addListener('console.command', function (ConsoleCommandEvent $event) use ($skipCommand) { - $event->getOutput()->write('before.'); - - if ($skipCommand) { - $event->disableCommand(); - } - }); - $dispatcher->addListener('console.terminate', function (ConsoleTerminateEvent $event) use ($skipCommand) { - $event->getOutput()->writeln('after.'); - - if (!$skipCommand) { - $event->setExitCode(ConsoleCommandEvent::RETURN_CODE_DISABLED); - } - }); - $dispatcher->addListener('console.error', function (ConsoleErrorEvent $event) { - $event->getOutput()->write('error.'); - - $event->setError(new \LogicException('error.', $event->getExitCode(), $event->getError())); - }); - - return $dispatcher; - } - - public function testErrorIsRethrownIfNotHandledByConsoleErrorEventWithCatchingEnabled() - { - $application = new Application(); - $application->setAutoExit(false); - $application->setDispatcher(new EventDispatcher()); - - $application->register('dym')->setCode(function (InputInterface $input, OutputInterface $output) { - new \UnknownClass(); - }); - - $tester = new ApplicationTester($application); - - try { - $tester->run(['command' => 'dym']); - $this->fail('->run() should rethrow PHP errors if not handled via ConsoleErrorEvent.'); - } catch (\Error $e) { - $this->assertSame($e->getMessage(), 'Class \'UnknownClass\' not found'); - } - } - - /** - * @expectedException \RuntimeException - * @expectedExceptionMessage foo - */ - public function testThrowingErrorListener() - { - $dispatcher = $this->getDispatcher(); - $dispatcher->addListener('console.error', function (ConsoleErrorEvent $event) { - throw new \RuntimeException('foo'); - }); - - $dispatcher->addListener('console.command', function () { - throw new \RuntimeException('bar'); - }); - - $application = new Application(); - $application->setDispatcher($dispatcher); - $application->setAutoExit(false); - $application->setCatchExceptions(false); - - $application->register('foo')->setCode(function (InputInterface $input, OutputInterface $output) { - $output->write('foo.'); - }); - - $tester = new ApplicationTester($application); - $tester->run(['command' => 'foo']); - } -} - -class CustomApplication extends Application -{ - /** - * Overwrites the default input definition. - * - * @return InputDefinition An InputDefinition instance - */ - protected function getDefaultInputDefinition() - { - return new InputDefinition([new InputOption('--custom', '-c', InputOption::VALUE_NONE, 'Set the custom input definition.')]); - } - - /** - * Gets the default helper set with the helpers that should always be available. - * - * @return HelperSet A HelperSet instance - */ - protected function getDefaultHelperSet() - { - return new HelperSet([new FormatterHelper()]); - } -} - -class CustomDefaultCommandApplication extends Application -{ - /** - * Overwrites the constructor in order to set a different default command. - */ - public function __construct() - { - parent::__construct(); - - $command = new \FooCommand(); - $this->add($command); - $this->setDefaultCommand($command->getName()); - } -} - -class LazyCommand extends Command -{ - public function execute(InputInterface $input, OutputInterface $output) - { - $output->writeln('lazy-command called'); - } -} - -class DisabledCommand extends Command -{ - public function isEnabled() - { - return false; - } -} diff --git a/vendor/symfony/console/Tests/Command/CommandTest.php b/vendor/symfony/console/Tests/Command/CommandTest.php deleted file mode 100644 index 3e1673dd5..000000000 --- a/vendor/symfony/console/Tests/Command/CommandTest.php +++ /dev/null @@ -1,436 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Tests\Command; - -use PHPUnit\Framework\TestCase; -use Symfony\Component\Console\Application; -use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Helper\FormatterHelper; -use Symfony\Component\Console\Input\InputArgument; -use Symfony\Component\Console\Input\InputDefinition; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Input\InputOption; -use Symfony\Component\Console\Input\StringInput; -use Symfony\Component\Console\Output\NullOutput; -use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\Console\Tester\CommandTester; - -class CommandTest extends TestCase -{ - protected static $fixturesPath; - - public static function setUpBeforeClass() - { - self::$fixturesPath = __DIR__.'/../Fixtures/'; - require_once self::$fixturesPath.'/TestCommand.php'; - } - - public function testConstructor() - { - $command = new Command('foo:bar'); - $this->assertEquals('foo:bar', $command->getName(), '__construct() takes the command name as its first argument'); - } - - /** - * @expectedException \LogicException - * @expectedExceptionMessage The command defined in "Symfony\Component\Console\Command\Command" cannot have an empty name. - */ - public function testCommandNameCannotBeEmpty() - { - (new Application())->add(new Command()); - } - - public function testSetApplication() - { - $application = new Application(); - $command = new \TestCommand(); - $command->setApplication($application); - $this->assertEquals($application, $command->getApplication(), '->setApplication() sets the current application'); - $this->assertEquals($application->getHelperSet(), $command->getHelperSet()); - } - - public function testSetApplicationNull() - { - $command = new \TestCommand(); - $command->setApplication(null); - $this->assertNull($command->getHelperSet()); - } - - public function testSetGetDefinition() - { - $command = new \TestCommand(); - $ret = $command->setDefinition($definition = new InputDefinition()); - $this->assertEquals($command, $ret, '->setDefinition() implements a fluent interface'); - $this->assertEquals($definition, $command->getDefinition(), '->setDefinition() sets the current InputDefinition instance'); - $command->setDefinition([new InputArgument('foo'), new InputOption('bar')]); - $this->assertTrue($command->getDefinition()->hasArgument('foo'), '->setDefinition() also takes an array of InputArguments and InputOptions as an argument'); - $this->assertTrue($command->getDefinition()->hasOption('bar'), '->setDefinition() also takes an array of InputArguments and InputOptions as an argument'); - $command->setDefinition(new InputDefinition()); - } - - public function testAddArgument() - { - $command = new \TestCommand(); - $ret = $command->addArgument('foo'); - $this->assertEquals($command, $ret, '->addArgument() implements a fluent interface'); - $this->assertTrue($command->getDefinition()->hasArgument('foo'), '->addArgument() adds an argument to the command'); - } - - public function testAddOption() - { - $command = new \TestCommand(); - $ret = $command->addOption('foo'); - $this->assertEquals($command, $ret, '->addOption() implements a fluent interface'); - $this->assertTrue($command->getDefinition()->hasOption('foo'), '->addOption() adds an option to the command'); - } - - public function testSetHidden() - { - $command = new \TestCommand(); - $command->setHidden(true); - $this->assertTrue($command->isHidden()); - } - - public function testGetNamespaceGetNameSetName() - { - $command = new \TestCommand(); - $this->assertEquals('namespace:name', $command->getName(), '->getName() returns the command name'); - $command->setName('foo'); - $this->assertEquals('foo', $command->getName(), '->setName() sets the command name'); - - $ret = $command->setName('foobar:bar'); - $this->assertEquals($command, $ret, '->setName() implements a fluent interface'); - $this->assertEquals('foobar:bar', $command->getName(), '->setName() sets the command name'); - } - - /** - * @dataProvider provideInvalidCommandNames - */ - public function testInvalidCommandNames($name) - { - if (method_exists($this, 'expectException')) { - $this->expectException('InvalidArgumentException'); - $this->expectExceptionMessage(sprintf('Command name "%s" is invalid.', $name)); - } else { - $this->setExpectedException('InvalidArgumentException', sprintf('Command name "%s" is invalid.', $name)); - } - - $command = new \TestCommand(); - $command->setName($name); - } - - public function provideInvalidCommandNames() - { - return [ - [''], - ['foo:'], - ]; - } - - public function testGetSetDescription() - { - $command = new \TestCommand(); - $this->assertEquals('description', $command->getDescription(), '->getDescription() returns the description'); - $ret = $command->setDescription('description1'); - $this->assertEquals($command, $ret, '->setDescription() implements a fluent interface'); - $this->assertEquals('description1', $command->getDescription(), '->setDescription() sets the description'); - } - - public function testGetSetHelp() - { - $command = new \TestCommand(); - $this->assertEquals('help', $command->getHelp(), '->getHelp() returns the help'); - $ret = $command->setHelp('help1'); - $this->assertEquals($command, $ret, '->setHelp() implements a fluent interface'); - $this->assertEquals('help1', $command->getHelp(), '->setHelp() sets the help'); - $command->setHelp(''); - $this->assertEquals('', $command->getHelp(), '->getHelp() does not fall back to the description'); - } - - public function testGetProcessedHelp() - { - $command = new \TestCommand(); - $command->setHelp('The %command.name% command does... Example: php %command.full_name%.'); - $this->assertContains('The namespace:name command does...', $command->getProcessedHelp(), '->getProcessedHelp() replaces %command.name% correctly'); - $this->assertNotContains('%command.full_name%', $command->getProcessedHelp(), '->getProcessedHelp() replaces %command.full_name%'); - - $command = new \TestCommand(); - $command->setHelp(''); - $this->assertContains('description', $command->getProcessedHelp(), '->getProcessedHelp() falls back to the description'); - - $command = new \TestCommand(); - $command->setHelp('The %command.name% command does... Example: php %command.full_name%.'); - $application = new Application(); - $application->add($command); - $application->setDefaultCommand('namespace:name', true); - $this->assertContains('The namespace:name command does...', $command->getProcessedHelp(), '->getProcessedHelp() replaces %command.name% correctly in single command applications'); - $this->assertNotContains('%command.full_name%', $command->getProcessedHelp(), '->getProcessedHelp() replaces %command.full_name% in single command applications'); - } - - public function testGetSetAliases() - { - $command = new \TestCommand(); - $this->assertEquals(['name'], $command->getAliases(), '->getAliases() returns the aliases'); - $ret = $command->setAliases(['name1']); - $this->assertEquals($command, $ret, '->setAliases() implements a fluent interface'); - $this->assertEquals(['name1'], $command->getAliases(), '->setAliases() sets the aliases'); - } - - public function testSetAliasesNull() - { - $command = new \TestCommand(); - $this->{method_exists($this, $_ = 'expectException') ? $_ : 'setExpectedException'}('InvalidArgumentException'); - $command->setAliases(null); - } - - public function testGetSynopsis() - { - $command = new \TestCommand(); - $command->addOption('foo'); - $command->addArgument('bar'); - $this->assertEquals('namespace:name [--foo] [--] []', $command->getSynopsis(), '->getSynopsis() returns the synopsis'); - } - - public function testAddGetUsages() - { - $command = new \TestCommand(); - $command->addUsage('foo1'); - $command->addUsage('foo2'); - $this->assertContains('namespace:name foo1', $command->getUsages()); - $this->assertContains('namespace:name foo2', $command->getUsages()); - } - - public function testGetHelper() - { - $application = new Application(); - $command = new \TestCommand(); - $command->setApplication($application); - $formatterHelper = new FormatterHelper(); - $this->assertEquals($formatterHelper->getName(), $command->getHelper('formatter')->getName(), '->getHelper() returns the correct helper'); - } - - /** - * @expectedException \LogicException - * @expectedExceptionMessage Cannot retrieve helper "formatter" because there is no HelperSet defined. - */ - public function testGetHelperWithoutHelperSet() - { - $command = new \TestCommand(); - $command->getHelper('formatter'); - } - - public function testMergeApplicationDefinition() - { - $application1 = new Application(); - $application1->getDefinition()->addArguments([new InputArgument('foo')]); - $application1->getDefinition()->addOptions([new InputOption('bar')]); - $command = new \TestCommand(); - $command->setApplication($application1); - $command->setDefinition($definition = new InputDefinition([new InputArgument('bar'), new InputOption('foo')])); - - $r = new \ReflectionObject($command); - $m = $r->getMethod('mergeApplicationDefinition'); - $m->setAccessible(true); - $m->invoke($command); - $this->assertTrue($command->getDefinition()->hasArgument('foo'), '->mergeApplicationDefinition() merges the application arguments and the command arguments'); - $this->assertTrue($command->getDefinition()->hasArgument('bar'), '->mergeApplicationDefinition() merges the application arguments and the command arguments'); - $this->assertTrue($command->getDefinition()->hasOption('foo'), '->mergeApplicationDefinition() merges the application options and the command options'); - $this->assertTrue($command->getDefinition()->hasOption('bar'), '->mergeApplicationDefinition() merges the application options and the command options'); - - $m->invoke($command); - $this->assertEquals(3, $command->getDefinition()->getArgumentCount(), '->mergeApplicationDefinition() does not try to merge twice the application arguments and options'); - } - - public function testMergeApplicationDefinitionWithoutArgsThenWithArgsAddsArgs() - { - $application1 = new Application(); - $application1->getDefinition()->addArguments([new InputArgument('foo')]); - $application1->getDefinition()->addOptions([new InputOption('bar')]); - $command = new \TestCommand(); - $command->setApplication($application1); - $command->setDefinition($definition = new InputDefinition([])); - - $r = new \ReflectionObject($command); - $m = $r->getMethod('mergeApplicationDefinition'); - $m->setAccessible(true); - $m->invoke($command, false); - $this->assertTrue($command->getDefinition()->hasOption('bar'), '->mergeApplicationDefinition(false) merges the application and the command options'); - $this->assertFalse($command->getDefinition()->hasArgument('foo'), '->mergeApplicationDefinition(false) does not merge the application arguments'); - - $m->invoke($command, true); - $this->assertTrue($command->getDefinition()->hasArgument('foo'), '->mergeApplicationDefinition(true) merges the application arguments and the command arguments'); - - $m->invoke($command); - $this->assertEquals(2, $command->getDefinition()->getArgumentCount(), '->mergeApplicationDefinition() does not try to merge twice the application arguments'); - } - - public function testRunInteractive() - { - $tester = new CommandTester(new \TestCommand()); - - $tester->execute([], ['interactive' => true]); - - $this->assertEquals('interact called'.PHP_EOL.'execute called'.PHP_EOL, $tester->getDisplay(), '->run() calls the interact() method if the input is interactive'); - } - - public function testRunNonInteractive() - { - $tester = new CommandTester(new \TestCommand()); - - $tester->execute([], ['interactive' => false]); - - $this->assertEquals('execute called'.PHP_EOL, $tester->getDisplay(), '->run() does not call the interact() method if the input is not interactive'); - } - - /** - * @expectedException \LogicException - * @expectedExceptionMessage You must override the execute() method in the concrete command class. - */ - public function testExecuteMethodNeedsToBeOverridden() - { - $command = new Command('foo'); - $command->run(new StringInput(''), new NullOutput()); - } - - /** - * @expectedException \Symfony\Component\Console\Exception\InvalidOptionException - * @expectedExceptionMessage The "--bar" option does not exist. - */ - public function testRunWithInvalidOption() - { - $command = new \TestCommand(); - $tester = new CommandTester($command); - $tester->execute(['--bar' => true]); - } - - public function testRunReturnsIntegerExitCode() - { - $command = new \TestCommand(); - $exitCode = $command->run(new StringInput(''), new NullOutput()); - $this->assertSame(0, $exitCode, '->run() returns integer exit code (treats null as 0)'); - - $command = $this->getMockBuilder('TestCommand')->setMethods(['execute'])->getMock(); - $command->expects($this->once()) - ->method('execute') - ->willReturn('2.3'); - $exitCode = $command->run(new StringInput(''), new NullOutput()); - $this->assertSame(2, $exitCode, '->run() returns integer exit code (casts numeric to int)'); - } - - public function testRunWithApplication() - { - $command = new \TestCommand(); - $command->setApplication(new Application()); - $exitCode = $command->run(new StringInput(''), new NullOutput()); - - $this->assertSame(0, $exitCode, '->run() returns an integer exit code'); - } - - public function testRunReturnsAlwaysInteger() - { - $command = new \TestCommand(); - - $this->assertSame(0, $command->run(new StringInput(''), new NullOutput())); - } - - public function testRunWithProcessTitle() - { - $command = new \TestCommand(); - $command->setApplication(new Application()); - $command->setProcessTitle('foo'); - $this->assertSame(0, $command->run(new StringInput(''), new NullOutput())); - if (\function_exists('cli_set_process_title')) { - if (null === @cli_get_process_title() && 'Darwin' === PHP_OS) { - $this->markTestSkipped('Running "cli_get_process_title" as an unprivileged user is not supported on MacOS.'); - } - $this->assertEquals('foo', cli_get_process_title()); - } - } - - public function testSetCode() - { - $command = new \TestCommand(); - $ret = $command->setCode(function (InputInterface $input, OutputInterface $output) { - $output->writeln('from the code...'); - }); - $this->assertEquals($command, $ret, '->setCode() implements a fluent interface'); - $tester = new CommandTester($command); - $tester->execute([]); - $this->assertEquals('interact called'.PHP_EOL.'from the code...'.PHP_EOL, $tester->getDisplay()); - } - - public function getSetCodeBindToClosureTests() - { - return [ - [true, 'not bound to the command'], - [false, 'bound to the command'], - ]; - } - - /** - * @dataProvider getSetCodeBindToClosureTests - */ - public function testSetCodeBindToClosure($previouslyBound, $expected) - { - $code = createClosure(); - if ($previouslyBound) { - $code = $code->bindTo($this); - } - - $command = new \TestCommand(); - $command->setCode($code); - $tester = new CommandTester($command); - $tester->execute([]); - $this->assertEquals('interact called'.PHP_EOL.$expected.PHP_EOL, $tester->getDisplay()); - } - - public function testSetCodeWithStaticClosure() - { - $command = new \TestCommand(); - $command->setCode(self::createClosure()); - $tester = new CommandTester($command); - $tester->execute([]); - - $this->assertEquals('interact called'.PHP_EOL.'bound'.PHP_EOL, $tester->getDisplay()); - } - - private static function createClosure() - { - return function (InputInterface $input, OutputInterface $output) { - $output->writeln(isset($this) ? 'bound' : 'not bound'); - }; - } - - public function testSetCodeWithNonClosureCallable() - { - $command = new \TestCommand(); - $ret = $command->setCode([$this, 'callableMethodCommand']); - $this->assertEquals($command, $ret, '->setCode() implements a fluent interface'); - $tester = new CommandTester($command); - $tester->execute([]); - $this->assertEquals('interact called'.PHP_EOL.'from the code...'.PHP_EOL, $tester->getDisplay()); - } - - public function callableMethodCommand(InputInterface $input, OutputInterface $output) - { - $output->writeln('from the code...'); - } -} - -// In order to get an unbound closure, we should create it outside a class -// scope. -function createClosure() -{ - return function (InputInterface $input, OutputInterface $output) { - $output->writeln($this instanceof Command ? 'bound to the command' : 'not bound to the command'); - }; -} diff --git a/vendor/symfony/console/Tests/Command/HelpCommandTest.php b/vendor/symfony/console/Tests/Command/HelpCommandTest.php deleted file mode 100644 index ce9d8d4fe..000000000 --- a/vendor/symfony/console/Tests/Command/HelpCommandTest.php +++ /dev/null @@ -1,71 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Tests\Command; - -use PHPUnit\Framework\TestCase; -use Symfony\Component\Console\Application; -use Symfony\Component\Console\Command\HelpCommand; -use Symfony\Component\Console\Command\ListCommand; -use Symfony\Component\Console\Tester\CommandTester; - -class HelpCommandTest extends TestCase -{ - public function testExecuteForCommandAlias() - { - $command = new HelpCommand(); - $command->setApplication(new Application()); - $commandTester = new CommandTester($command); - $commandTester->execute(['command_name' => 'li'], ['decorated' => false]); - $this->assertContains('list [options] [--] []', $commandTester->getDisplay(), '->execute() returns a text help for the given command alias'); - $this->assertContains('format=FORMAT', $commandTester->getDisplay(), '->execute() returns a text help for the given command alias'); - $this->assertContains('raw', $commandTester->getDisplay(), '->execute() returns a text help for the given command alias'); - } - - public function testExecuteForCommand() - { - $command = new HelpCommand(); - $commandTester = new CommandTester($command); - $command->setCommand(new ListCommand()); - $commandTester->execute([], ['decorated' => false]); - $this->assertContains('list [options] [--] []', $commandTester->getDisplay(), '->execute() returns a text help for the given command'); - $this->assertContains('format=FORMAT', $commandTester->getDisplay(), '->execute() returns a text help for the given command'); - $this->assertContains('raw', $commandTester->getDisplay(), '->execute() returns a text help for the given command'); - } - - public function testExecuteForCommandWithXmlOption() - { - $command = new HelpCommand(); - $commandTester = new CommandTester($command); - $command->setCommand(new ListCommand()); - $commandTester->execute(['--format' => 'xml']); - $this->assertContains('getDisplay(), '->execute() returns an XML help text if --xml is passed'); - } - - public function testExecuteForApplicationCommand() - { - $application = new Application(); - $commandTester = new CommandTester($application->get('help')); - $commandTester->execute(['command_name' => 'list']); - $this->assertContains('list [options] [--] []', $commandTester->getDisplay(), '->execute() returns a text help for the given command'); - $this->assertContains('format=FORMAT', $commandTester->getDisplay(), '->execute() returns a text help for the given command'); - $this->assertContains('raw', $commandTester->getDisplay(), '->execute() returns a text help for the given command'); - } - - public function testExecuteForApplicationCommandWithXmlOption() - { - $application = new Application(); - $commandTester = new CommandTester($application->get('help')); - $commandTester->execute(['command_name' => 'list', '--format' => 'xml']); - $this->assertContains('list [--raw] [--format FORMAT] [--] [<namespace>]', $commandTester->getDisplay(), '->execute() returns a text help for the given command'); - $this->assertContains('getDisplay(), '->execute() returns an XML help text if --format=xml is passed'); - } -} diff --git a/vendor/symfony/console/Tests/Command/ListCommandTest.php b/vendor/symfony/console/Tests/Command/ListCommandTest.php deleted file mode 100644 index 57687d4c6..000000000 --- a/vendor/symfony/console/Tests/Command/ListCommandTest.php +++ /dev/null @@ -1,113 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Tests\Command; - -use PHPUnit\Framework\TestCase; -use Symfony\Component\Console\Application; -use Symfony\Component\Console\Tester\CommandTester; - -class ListCommandTest extends TestCase -{ - public function testExecuteListsCommands() - { - $application = new Application(); - $commandTester = new CommandTester($command = $application->get('list')); - $commandTester->execute(['command' => $command->getName()], ['decorated' => false]); - - $this->assertRegExp('/help\s{2,}Displays help for a command/', $commandTester->getDisplay(), '->execute() returns a list of available commands'); - } - - public function testExecuteListsCommandsWithXmlOption() - { - $application = new Application(); - $commandTester = new CommandTester($command = $application->get('list')); - $commandTester->execute(['command' => $command->getName(), '--format' => 'xml']); - $this->assertRegExp('/