diff --git a/requirements.txt b/.docker/requirements.txt similarity index 51% rename from requirements.txt rename to .docker/requirements.txt index 5f46be82d..285820e6d 100644 --- a/requirements.txt +++ b/.docker/requirements.txt @@ -1,10 +1,13 @@ # This file is just used to get security alerts from GitHub. Make sure the versions match -# in .docker/worker.dockerfile. -numpy==1.22.* +# in worker.dockerfile. +numpy==1.24.* opencv-contrib-python-headless==4.6.0 -scipy==1.10.0 -scikit-learn -matplotlib==3.5.2 +scipy==1.10.* +scikit-learn==1.2.* +matplotlib==3.6.* PyExcelerate==0.6.7 -Pillow==10.0.1 +Pillow==10.2.0 Shapely==1.8.1 +torch==2.1.* +torchvision==0.16.* +pandas==1.5.3 diff --git a/.docker/worker.dockerfile b/.docker/worker.dockerfile index 3f22309f5..5339ed683 100644 --- a/.docker/worker.dockerfile +++ b/.docker/worker.dockerfile @@ -1,32 +1,37 @@ -# PHP 8.1.13 -#FROM php:8.1-alpine -FROM php@sha256:f9e31f22bdd89c1334a03db5c8800a5f3b1e1fe042d470adccf58a29672c6202 +# PHP 8.1.27 +# FROM php:8.1 +FROM php@sha256:9b5dfb7deef3e48d67b2599e4d3967bb3ece19fd5ba09cb8e7ee10f5facf36e0 MAINTAINER Martin Zurowietz LABEL org.opencontainers.image.source https://github.com/biigle/core -ARG OPENCV_VERSION=4.6.0-r3 -RUN apk add --no-cache \ - eigen \ +RUN LC_ALL=C.UTF-8 apt-get update \ + && apt-get install -y --no-install-recommends \ ffmpeg \ - lapack \ - openblas \ - py3-numpy \ python3 \ - py3-opencv="$OPENCV_VERSION" + python3-numpy \ + python3-opencv \ + python3-scipy \ + python3-sklearn \ + python3-matplotlib \ + python3-shapely \ + python3-pandas \ + && apt-get -y autoremove \ + && apt-get clean \ + && rm -r /var/lib/apt/lists/* RUN ln -s "$PHP_INI_DIR/php.ini-production" "$PHP_INI_DIR/php.ini" ADD ".docker/all-php.ini" "$PHP_INI_DIR/conf.d/all.ini" -RUN apk add --no-cache \ - libxml2 \ - libzip \ - openssl \ - postgresql \ - && apk add --no-cache --virtual .build-deps \ +RUN LC_ALL=C.UTF-8 apt-get update \ + && apt-get install -y --no-install-recommends \ libxml2-dev \ libzip-dev \ - postgresql-dev \ - && docker-php-ext-configure pgsql -with-pgsql=/usr/local/pgsql \ + libpq-dev \ + && apt-get install -y --no-install-recommends \ + libxml2 \ + libzip4 \ + postgresql-client \ + && docker-php-ext-configure pgsql -with-pgsql=/usr/bin/pgsql \ && docker-php-ext-install -j$(nproc) \ exif \ pcntl \ @@ -35,15 +40,29 @@ RUN apk add --no-cache \ pgsql \ soap \ zip \ - && apk del --purge .build-deps + && apt-get purge -y \ + libxml2-dev \ + libzip-dev \ + libpq-dev \ + && apt-get -y autoremove \ + && apt-get clean \ + && rm -r /var/lib/apt/lists/* # Configure proxy if there is any. See: https://stackoverflow.com/a/2266500/1796523 RUN [ -z "$HTTP_PROXY" ] || pear config-set http_proxy $HTTP_PROXY -RUN apk add --no-cache yaml \ - && apk add --no-cache --virtual .build-deps g++ make autoconf yaml-dev \ + +RUN LC_ALL=C.UTF-8 apt-get update \ + && apt-get install -y --no-install-recommends \ + libyaml-dev \ + && apt-get install -y --no-install-recommends \ + libyaml-0-2 \ && pecl install yaml \ - && docker-php-ext-enable yaml \ - && apk del --purge .build-deps + && printf "\n" | docker-php-ext-enable yaml \ + && apt-get purge -y \ + libyaml-dev \ + && apt-get -y autoremove \ + && apt-get clean \ + && rm -r /var/lib/apt/lists/* ARG PHPREDIS_VERSION=5.3.7 RUN curl -L -o /tmp/redis.tar.gz https://github.com/phpredis/phpredis/archive/${PHPREDIS_VERSION}.tar.gz \ @@ -53,70 +72,38 @@ RUN curl -L -o /tmp/redis.tar.gz https://github.com/phpredis/phpredis/archive/${ && mv phpredis-${PHPREDIS_VERSION} /usr/src/php/ext/redis \ && docker-php-ext-install -j$(nproc) redis -ENV PKG_CONFIG_PATH="/usr/local/lib/pkgconfig:${PKG_CONFIG_PATH}" -# Install vips from source because the apk package does not have dzsave support! Install -# libvips and the vips PHP extension in one go so the *-dev dependencies are reused. -ARG LIBVIPS_VERSION=8.12.2 -ARG PHP_VIPS_EXT_VERSION=1.0.13 -RUN apk add --no-cache --virtual .build-deps \ - autoconf \ - automake \ - build-base \ - expat-dev \ - glib-dev \ - libgsf-dev \ - libjpeg-turbo-dev \ - libpng-dev \ - tiff-dev \ - && apk add --no-cache \ - expat \ - glib \ - libgsf \ - libjpeg-turbo \ - libpng \ - tiff \ - && cd /tmp \ - && curl -L https://github.com/libvips/libvips/releases/download/v${LIBVIPS_VERSION}/vips-${LIBVIPS_VERSION}.tar.gz -o vips-${LIBVIPS_VERSION}.tar.gz \ - && tar -xzf vips-${LIBVIPS_VERSION}.tar.gz \ - && cd vips-${LIBVIPS_VERSION} \ - && ./configure \ - --without-python \ - --enable-debug=no \ - --disable-dependency-tracking \ - --disable-static \ - && make -j $(nproc) \ - && make -s install-strip \ - && cd /tmp \ - && curl -L https://github.com/libvips/php-vips-ext/raw/master/vips-${PHP_VIPS_EXT_VERSION}.tgz -o vips-${PHP_VIPS_EXT_VERSION}.tgz \ - && echo '' | pecl install vips-${PHP_VIPS_EXT_VERSION}.tgz \ +# ENV PKG_CONFIG_PATH="/usr/local/lib/pkgconfig:${PKG_CONFIG_PATH}" + +RUN LC_ALL=C.UTF-8 apt-get update \ + && apt-get install -y --no-install-recommends \ + libvips-dev \ + && apt-get install -y --no-install-recommends \ + libvips42 \ + && pecl install vips \ && docker-php-ext-enable vips \ - && rm -r /tmp/* \ - && apk del --purge .build-deps \ - && rm -rf /var/cache/apk/* + && apt-get purge -y \ + libvips-dev \ + && apt-get -y autoremove \ + && apt-get clean \ + && rm -r /var/lib/apt/lists/* # Unset proxy configuration again. RUN [ -z "$HTTP_PROXY" ] || pear config-set http_proxy "" -# Other Python dependencies are added with the OpenCV build above. -RUN apk add --no-cache py3-scipy py3-scikit-learn py3-matplotlib py3-shapely - -# Set this library path so the Python modules are linked correctly. -# See: https://github.com/python-pillow/Pillow/issues/1763#issuecomment-204252397 -ENV LIBRARY_PATH=/lib:/usr/lib -# Install Python dependencies. Note that these also depend on some image processing libs -# that were installed along with vips. -RUN apk add --no-cache --virtual .build-deps \ - python3-dev \ - py3-pip \ - py3-wheel \ - build-base \ - libjpeg-turbo-dev \ - libpng-dev \ - && pip3 install --no-cache-dir \ +RUN LC_ALL=C.UTF-8 apt-get update \ + && apt-get install -y --no-install-recommends \ + python3-pip \ + && pip3 install --no-cache-dir --break-system-packages \ PyExcelerate==0.6.7 \ - Pillow==10.0.1 \ - && apk del --purge .build-deps \ - && rm -rf /var/cache/apk/* + Pillow==10.2.0 \ + && pip3 install --no-cache-dir --break-system-packages --index-url https://download.pytorch.org/whl/cpu \ + torch==2.1.* \ + torchvision==0.16.* \ + && apt-get purge -y \ + python3-pip \ + && apt-get -y autoremove \ + && apt-get clean \ + && rm -r /var/lib/apt/lists/* WORKDIR /var/www diff --git a/.env.example b/.env.example index c28ab4eec..95fc1dfb5 100644 --- a/.env.example +++ b/.env.example @@ -21,12 +21,6 @@ DB_DATABASE="biigle" DB_USERNAME="biigle" DB_PASSWORD="secret" -VECTOR_DB_HOST="vector_database" -VECTOR_DB_PORT=5432 -VECTOR_DB_DATABASE="biigle" -VECTOR_DB_USERNAME="biigle" -VECTOR_DB_PASSWORD="secret" - VOLUME_ADMIN_STORAGE_DISKS=local BROADCAST_DRIVER=pusher diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 000000000..62d13e938 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,26 @@ +version: 2 +updates: + - package-ecosystem: pip + directory: "/.docker" + schedule: + interval: "weekly" + # Disable version updates + open-pull-requests-limit: 0 + - package-ecosystem: composer + directory: "/" + schedule: + interval: "weekly" + # Disable version updates + open-pull-requests-limit: 0 + - package-ecosystem: npm + directory: "/" + schedule: + interval: "weekly" + # Disable version updates + open-pull-requests-limit: 0 + - package-ecosystem: github-actions + directory: "/" + schedule: + interval: "weekly" + # Disable version updates + open-pull-requests-limit: 0 diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 186e9b977..20158218a 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -37,7 +37,6 @@ jobs: - name: Start test database run: | docker-compose up -d --no-build database_testing - docker-compose up -d --no-build vector_database_testing sleep 5 - name: Run tests @@ -80,7 +79,6 @@ jobs: - name: Start test database run: | docker-compose up -d --no-build database_testing - docker-compose up -d --no-build vector_database_testing sleep 5 - name: Run tests diff --git a/.github/workflows/update-schema.yml b/.github/workflows/update-schema.yml index 46ea35c70..c117d1cab 100644 --- a/.github/workflows/update-schema.yml +++ b/.github/workflows/update-schema.yml @@ -16,7 +16,7 @@ jobs: - name: Trigger schema update run: | curl -X POST --fail \ - -H "Authorization: token ${{ secrets.TOKEN }}" \ + -H "Authorization: token ${{ secrets.BIIGLE_SCHEMA_API_TOKEN }}" \ -H "Content-Type: application/json" \ --data '{"event_type": "build_application"}' \ https://api.github.com/repos/biigle/schema/dispatches diff --git a/DEVELOPING.md b/DEVELOPING.md index cb74a00df..f5fadd97f 100644 --- a/DEVELOPING.md +++ b/DEVELOPING.md @@ -34,7 +34,7 @@ composer create-project biigle/core:dev-dev-modules \ Note the `--ignore-platform-reqs` flag to keep Composer from complaining about missing requirements. These requirements will be met by the Docker containers. -This will set up the project in the `dev-modules` branch of this repository. The `dev-modules` branch is configured with all BIIGLE modules which makes it easy to start module development. If you want to develop a feature directly in `biigle/core`, please switch to the `master` branch (or create your own branch based on `master`). +This will set up the project in the `dev-modules` branch of this repository. The `dev-modules` branch is configured with all BIIGLE modules which makes it easy to start module development. If you want to develop a feature directly in `biigle/core`, please switch to the `master` branch (or create your own branch based on `master`). Pull requests from a `dev-modules`-based branch will not be accepted. ### 2. Build and run the application diff --git a/app/Console/Commands/NewUser.php b/app/Console/Commands/NewUser.php index 1059b6b1e..785d503c2 100644 --- a/app/Console/Commands/NewUser.php +++ b/app/Console/Commands/NewUser.php @@ -39,6 +39,8 @@ public function handle() if ($this->confirm('Should the user be global admin? [y|N]')) { $u->role_id = Role::adminId(); + } else { + $u->role_id = Role::editorId(); } if ($this->confirm('Do you wish to auto-generate a password? [y|N]')) { diff --git a/app/Events/AnnotationLabelAttached.php b/app/Events/AnnotationLabelAttached.php new file mode 100644 index 000000000..c710c9991 --- /dev/null +++ b/app/Events/AnnotationLabelAttached.php @@ -0,0 +1,17 @@ +annotation); + AnnotationLabelAttached::dispatch($annotationLabel); + return response($annotationLabel, 201); } catch (QueryException $e) { // Although we check for existence above, this error happened some time. diff --git a/app/Http/Controllers/Api/VideoAnnotationLabelController.php b/app/Http/Controllers/Api/VideoAnnotationLabelController.php index c949988c7..377e3be1b 100644 --- a/app/Http/Controllers/Api/VideoAnnotationLabelController.php +++ b/app/Http/Controllers/Api/VideoAnnotationLabelController.php @@ -2,6 +2,7 @@ namespace Biigle\Http\Controllers\Api; +use Biigle\Events\AnnotationLabelAttached; use Biigle\Http\Requests\DestroyVideoAnnotationLabel; use Biigle\Http\Requests\StoreVideoAnnotationLabel; use Biigle\VideoAnnotationLabel; @@ -65,6 +66,8 @@ public function store(StoreVideoAnnotationLabel $request) // should not be returned unset($annotationLabel->annotation); + AnnotationLabelAttached::dispatch($annotationLabel); + return response($annotationLabel, 201); } catch (QueryException $e) { // Although we check for existence above, this error happened some time. diff --git a/app/Http/Controllers/Views/Videos/VideoController.php b/app/Http/Controllers/Views/Videos/VideoController.php index 873fd9d74..7bcbc516a 100644 --- a/app/Http/Controllers/Views/Videos/VideoController.php +++ b/app/Http/Controllers/Views/Videos/VideoController.php @@ -72,15 +72,36 @@ public function show(Request $request, $id) 'too-large' => VIDEO::ERROR_TOO_LARGE, ]); - return view('videos.show', compact( - 'user', - 'video', - 'volume', - 'videos', - 'shapes', - 'labelTrees', - 'annotationSessions', - 'errors' - )); + $fileIds = $volume->orderedFiles()->pluck('uuid', 'id'); + + $thumbUriTemplate = thumbnail_url(':uuid', config('videos.thumbnail_storage_disk')); + + $spritesThumbnailsPerSprite = config('videos.sprites_thumbnails_per_sprite'); + $spritesThumbnailInterval = config('videos.sprites_thumbnail_interval'); + $spritesMaxThumbnails = config('videos.sprites_max_thumbnails'); + $spritesMinThumbnails = config('videos.sprites_min_thumbnails'); + $spritesThumbnailWidth = config('videos.sprites_thumbnail_width'); + $spritesThumbnailHeight = config('videos.sprites_thumbnail_height'); + return view( + 'videos.show', + compact( + 'user', + 'video', + 'volume', + 'videos', + 'shapes', + 'labelTrees', + 'annotationSessions', + 'errors', + 'fileIds', + 'thumbUriTemplate', + 'spritesThumbnailsPerSprite', + 'spritesThumbnailInterval', + 'spritesMaxThumbnails', + 'spritesMinThumbnails', + 'spritesThumbnailWidth', + 'spritesThumbnailHeight' + ) + ); } } diff --git a/app/Http/Requests/StoreVolume.php b/app/Http/Requests/StoreVolume.php index 0536b53b0..ae34feb48 100644 --- a/app/Http/Requests/StoreVolume.php +++ b/app/Http/Requests/StoreVolume.php @@ -48,7 +48,7 @@ public function rules() return [ 'name' => 'required|max:512', 'media_type' => ['filled', Rule::in(array_keys(MediaType::INSTANCES))], - 'url' => ['required', 'max:256', new VolumeUrl], + 'url' => ['required', 'string', 'max:256', new VolumeUrl], 'files' => [ 'required', 'array', diff --git a/app/Http/Requests/UpdateVolume.php b/app/Http/Requests/UpdateVolume.php index c9be93624..d1ad2c6b3 100644 --- a/app/Http/Requests/UpdateVolume.php +++ b/app/Http/Requests/UpdateVolume.php @@ -37,7 +37,7 @@ public function rules() { return [ 'name' => 'filled|max:512', - 'url' => ['filled', new VolumeUrl], + 'url' => ['filled', 'string', 'max:256', new VolumeUrl], 'handle' => ['nullable', 'max:256', new Handle], ]; } diff --git a/app/Jobs/CloneImagesOrVideos.php b/app/Jobs/CloneImagesOrVideos.php index f087975d4..bf58c1e5f 100644 --- a/app/Jobs/CloneImagesOrVideos.php +++ b/app/Jobs/CloneImagesOrVideos.php @@ -8,8 +8,8 @@ use Biigle\ImageAnnotation; use Biigle\ImageAnnotationLabel; use Biigle\ImageLabel; -use Biigle\Modules\Largo\Jobs\GenerateImageAnnotationPatch; -use Biigle\Modules\Largo\Jobs\GenerateVideoAnnotationPatch; +use Biigle\Modules\Largo\Jobs\ProcessAnnotatedImage; +use Biigle\Modules\Largo\Jobs\ProcessAnnotatedVideo; use Biigle\Project; use Biigle\Traits\ChecksMetadataStrings; use Biigle\Video; @@ -144,10 +144,10 @@ public function handle() if ($volume->hasIfdo()) { $this->copyIfdoFile($volume->id, $copy->id); } - $copy->save(); - $copy->creating_async = false; + $copy->save(); + event('volume.cloned', [$copy->id]); }); @@ -162,24 +162,26 @@ public function postProcessCloning($volume) { ProcessNewVolumeFiles::dispatch($volume); - if (class_exists(GenerateImageAnnotationPatch::class)) { - ImageAnnotation::join('images', 'images.id', '=', 'image_annotations.image_id') - ->where('images.volume_id', "=", $volume->id) - ->select('image_annotations.id') - ->eachById(function ($annotation) { - GenerateImageAnnotationPatch::dispatch($annotation) + // Give the ProcessNewVolumeFiles job a head start so the file thumbnails are + // generated (mostly) before the annotation thumbnails. + $delay = now()->addSeconds(30); + + if (class_exists(ProcessAnnotatedImage::class)) { + $volume->images()->whereHas('annotations') + ->eachById(function ($image) use ($delay) { + ProcessAnnotatedImage::dispatch($image) + ->delay($delay) ->onQueue(config('largo.generate_annotation_patch_queue')); - }, 1000, 'image_annotations.id', 'id'); + }); } - if (class_exists(GenerateVideoAnnotationPatch::class)) { - VideoAnnotation::join('videos', 'videos.id', '=', 'video_annotations.video_id') - ->where('videos.volume_id', "=", $volume->id) - ->select('video_annotations.id') - ->eachById(function ($annotation) { - GenerateVideoAnnotationPatch::dispatch($annotation) + if (class_exists(ProcessAnnotatedVideo::class)) { + $volume->videos() + ->whereHas('annotations')->eachById(function ($video) use ($delay) { + ProcessAnnotatedVideo::dispatch($video) + ->delay($delay) ->onQueue(config('largo.generate_annotation_patch_queue')); - }, 1000, 'video_annotations.id', 'id'); + }); } } diff --git a/app/Jobs/ProcessNewVideo.php b/app/Jobs/ProcessNewVideo.php index 4efa99580..f411d33e5 100644 --- a/app/Jobs/ProcessNewVideo.php +++ b/app/Jobs/ProcessNewVideo.php @@ -240,7 +240,7 @@ protected function generateVideoThumbnail($path, $time, $width, $height) $buffer = $this->ffmpegVideo->frame(TimeCode::fromSeconds($time)) ->save(null, false, true); - return VipsImage::thumbnail_buffer($buffer, $width, ['height' => $height]) + return VipsImage::thumbnail_buffer($buffer, $width, ['height' => $height, 'size' => 'force']) ; } @@ -290,29 +290,29 @@ protected function getThumbnailTimes($duration) protected function generateSprites($path, $duration, $disk, $fragment) { - $maxFrames = config('videos.sprites_max_frames'); - $minFrames = config('videos.sprites_min_frames'); - $framesPerSprite = config('videos.frames_per_sprite'); - $thumbsPerRow = sqrt($framesPerSprite); + $maxThumbnails = config('videos.sprites_max_thumbnails'); + $minThumbnails = config('videos.sprites_min_thumbnails'); + $thumbnailsPerSprite = config('videos.sprites_thumbnails_per_sprite'); + $thumbnailsPerRow = sqrt($thumbnailsPerSprite); $thumbnailWidth = config('videos.sprites_thumbnail_width'); $thumbnailHeight = config('videos.sprites_thumbnail_height'); $spriteFormat = config('videos.sprites_format'); - $intervalSeconds = config('videos.sprites_interval_seconds'); + $defaultThumbnailInterval = config('videos.sprites_thumbnail_interval'); $durationRounded = floor($duration * 10) / 10; - $estimatedFrames = $durationRounded / $intervalSeconds; - // Adjust the frame time based on the number of estimated frames - $intervalSeconds = ($estimatedFrames > $maxFrames) ? $durationRounded / $maxFrames - : (($estimatedFrames < $minFrames) ? $durationRounded / $minFrames : 10); + $estimatedThumbnails = $durationRounded / $defaultThumbnailInterval; + // Adjust the frame time based on the number of estimated thumbnails + $thumbnailInterval = ($estimatedThumbnails > $maxThumbnails) ? $durationRounded / $maxThumbnails + : (($estimatedThumbnails < $minThumbnails) ? $durationRounded / $minThumbnails : $defaultThumbnailInterval); $thumbnails = []; $spritesCounter = 0; - for ($time = 0.0; $time < $durationRounded && $durationRounded > 0; $time += $intervalSeconds) { + for ($time = 0.0; $time < $durationRounded && $durationRounded > 0; $time += $thumbnailInterval) { $time = round($time, 1); // Create a thumbnail from the video at the specified time and add it to the thumbnails array. $thumbnails[] = $this->generateVideoThumbnail($path, $time, $thumbnailWidth, $thumbnailHeight); - if (count($thumbnails) === $framesPerSprite || $time >= abs($durationRounded - $intervalSeconds)) { + if (count($thumbnails) === $thumbnailsPerSprite || $time >= abs($durationRounded - $thumbnailInterval)) { // Join the thumbnails into a NxN sprite - $sprite = VipsImage::arrayjoin($thumbnails, ['across' => $thumbsPerRow]); + $sprite = VipsImage::arrayjoin($thumbnails, ['across' => $thumbnailsPerRow]); // Write the sprite to buffer with quality 75 and stripped metadata $spriteBuffer = $sprite->writeToBuffer(".{$spriteFormat}", [ 'Q' => 75, diff --git a/app/VideoAnnotation.php b/app/VideoAnnotation.php index f3bde3df5..a8bb6b9c1 100644 --- a/app/VideoAnnotation.php +++ b/app/VideoAnnotation.php @@ -105,7 +105,8 @@ public function validatePoints(array $points = []) throw new Exception('The number of key frames does not match the number of annotation coordinates.'); } - array_map([$this, 'parent::validatePoints'], $this->points); + // Gaps are represented as empty arrays + array_map(function ($point) { if (count($point)) { parent::validatePoints($point); } }, $this->points); } /** diff --git a/composer.json b/composer.json index 95fc3371b..6d7909886 100644 --- a/composer.json +++ b/composer.json @@ -23,7 +23,6 @@ "ext-soap": "*", "ext-vips": "*", "ext-yaml": "*", - "ankane/pgvector": "^0.1.3", "biigle/laravel-file-cache": "^4.0", "doctrine/dbal": "^3.0", "duncan3dc/bom-string": "^1.1", @@ -34,6 +33,7 @@ "laravel/tinker": "^2.8", "laravel/ui": "^4.0", "msurguy/honeypot": "^1.0", + "pgvector/pgvector": "^0.1.4", "php-ffmpeg/php-ffmpeg": "^1.0", "pusher/pusher-php-server": "^7.2", "ramsey/uuid": "^4.0", diff --git a/composer.lock b/composer.lock index 4fbd6435f..2f0a46f09 100644 --- a/composer.lock +++ b/composer.lock @@ -4,60 +4,8 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "ab35d47f47714e545261a34f23ee8be7", + "content-hash": "ca56d5f114fc956ac8efe6bcdefe8180", "packages": [ - { - "name": "ankane/pgvector", - "version": "v0.1.3", - "source": { - "type": "git", - "url": "https://github.com/pgvector/pgvector-php.git", - "reference": "ff407388899b5e9e268021448c106655846ede91" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/pgvector/pgvector-php/zipball/ff407388899b5e9e268021448c106655846ede91", - "reference": "ff407388899b5e9e268021448c106655846ede91", - "shasum": "" - }, - "require": { - "php": ">= 7.4" - }, - "require-dev": { - "illuminate/database": ">= 9.0", - "phpunit/phpunit": "^9" - }, - "type": "library", - "extra": { - "laravel": { - "providers": [ - "Pgvector\\Laravel\\PgvectorServiceProvider" - ] - } - }, - "autoload": { - "psr-4": { - "Pgvector\\": "src/", - "Pgvector\\Laravel\\": "src/laravel/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Andrew Kane", - "email": "andrew@ankane.org" - } - ], - "description": "pgvector support for PHP", - "support": { - "issues": "https://github.com/pgvector/pgvector-php/issues", - "source": "https://github.com/pgvector/pgvector-php" - }, - "time": "2023-10-03T23:29:14+00:00" - }, { "name": "bacon/bacon-qr-code", "version": "2.0.8", @@ -226,6 +174,75 @@ ], "time": "2023-01-15T23:15:59+00:00" }, + { + "name": "carbonphp/carbon-doctrine-types", + "version": "2.0.0", + "source": { + "type": "git", + "url": "https://github.com/CarbonPHP/carbon-doctrine-types.git", + "reference": "67a77972b9f398ae7068dabacc39c08aeee170d5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/CarbonPHP/carbon-doctrine-types/zipball/67a77972b9f398ae7068dabacc39c08aeee170d5", + "reference": "67a77972b9f398ae7068dabacc39c08aeee170d5", + "shasum": "" + }, + "require": { + "php": "^7.4 || ^8.0" + }, + "conflict": { + "doctrine/dbal": "<3.7.0 || >=4.0.0" + }, + "require-dev": { + "doctrine/dbal": "^3.7.0", + "nesbot/carbon": "^2.71.0 || ^3.0.0", + "phpunit/phpunit": "^10.3" + }, + "type": "library", + "autoload": { + "psr-4": { + "Carbon\\Doctrine\\": "src/Carbon/Doctrine/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "KyleKatarn", + "email": "kylekatarnls@gmail.com" + } + ], + "description": "Types to use Carbon in Doctrine", + "keywords": [ + "carbon", + "date", + "datetime", + "doctrine", + "time" + ], + "support": { + "issues": "https://github.com/CarbonPHP/carbon-doctrine-types/issues", + "source": "https://github.com/CarbonPHP/carbon-doctrine-types/tree/2.0.0" + }, + "funding": [ + { + "url": "https://github.com/kylekatarnls", + "type": "github" + }, + { + "url": "https://opencollective.com/Carbon", + "type": "open_collective" + }, + { + "url": "https://tidelift.com/funding/github/packagist/nesbot/carbon", + "type": "tidelift" + } + ], + "time": "2023-10-01T14:29:01+00:00" + }, { "name": "dasprid/enum", "version": "1.0.5", @@ -446,16 +463,16 @@ }, { "name": "doctrine/dbal", - "version": "3.7.0", + "version": "3.7.2", "source": { "type": "git", "url": "https://github.com/doctrine/dbal.git", - "reference": "00d03067f07482f025d41ab55e4ba0db5eca2cdf" + "reference": "0ac3c270590e54910715e9a1a044cc368df282b2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/dbal/zipball/00d03067f07482f025d41ab55e4ba0db5eca2cdf", - "reference": "00d03067f07482f025d41ab55e4ba0db5eca2cdf", + "url": "https://api.github.com/repos/doctrine/dbal/zipball/0ac3c270590e54910715e9a1a044cc368df282b2", + "reference": "0ac3c270590e54910715e9a1a044cc368df282b2", "shasum": "" }, "require": { @@ -471,7 +488,7 @@ "doctrine/coding-standard": "12.0.0", "fig/log-test": "^1", "jetbrains/phpstorm-stubs": "2023.1", - "phpstan/phpstan": "1.10.35", + "phpstan/phpstan": "1.10.42", "phpstan/phpstan-strict-rules": "^1.5", "phpunit/phpunit": "9.6.13", "psalm/plugin-phpunit": "0.18.4", @@ -539,7 +556,7 @@ ], "support": { "issues": "https://github.com/doctrine/dbal/issues", - "source": "https://github.com/doctrine/dbal/tree/3.7.0" + "source": "https://github.com/doctrine/dbal/tree/3.7.2" }, "funding": [ { @@ -555,20 +572,20 @@ "type": "tidelift" } ], - "time": "2023-09-26T20:56:55+00:00" + "time": "2023-11-19T08:06:58+00:00" }, { "name": "doctrine/deprecations", - "version": "v1.1.1", + "version": "1.1.2", "source": { "type": "git", "url": "https://github.com/doctrine/deprecations.git", - "reference": "612a3ee5ab0d5dd97b7cf3874a6efe24325efac3" + "reference": "4f2d4f2836e7ec4e7a8625e75c6aa916004db931" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/deprecations/zipball/612a3ee5ab0d5dd97b7cf3874a6efe24325efac3", - "reference": "612a3ee5ab0d5dd97b7cf3874a6efe24325efac3", + "url": "https://api.github.com/repos/doctrine/deprecations/zipball/4f2d4f2836e7ec4e7a8625e75c6aa916004db931", + "reference": "4f2d4f2836e7ec4e7a8625e75c6aa916004db931", "shasum": "" }, "require": { @@ -600,9 +617,9 @@ "homepage": "https://www.doctrine-project.org/", "support": { "issues": "https://github.com/doctrine/deprecations/issues", - "source": "https://github.com/doctrine/deprecations/tree/v1.1.1" + "source": "https://github.com/doctrine/deprecations/tree/1.1.2" }, - "time": "2023-06-03T09:27:29+00:00" + "time": "2023-09-27T20:04:15+00:00" }, { "name": "doctrine/event-manager", @@ -983,16 +1000,16 @@ }, { "name": "egulias/email-validator", - "version": "4.0.1", + "version": "4.0.2", "source": { "type": "git", "url": "https://github.com/egulias/EmailValidator.git", - "reference": "3a85486b709bc384dae8eb78fb2eec649bdb64ff" + "reference": "ebaaf5be6c0286928352e054f2d5125608e5405e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/egulias/EmailValidator/zipball/3a85486b709bc384dae8eb78fb2eec649bdb64ff", - "reference": "3a85486b709bc384dae8eb78fb2eec649bdb64ff", + "url": "https://api.github.com/repos/egulias/EmailValidator/zipball/ebaaf5be6c0286928352e054f2d5125608e5405e", + "reference": "ebaaf5be6c0286928352e054f2d5125608e5405e", "shasum": "" }, "require": { @@ -1001,8 +1018,8 @@ "symfony/polyfill-intl-idn": "^1.26" }, "require-dev": { - "phpunit/phpunit": "^9.5.27", - "vimeo/psalm": "^4.30" + "phpunit/phpunit": "^10.2", + "vimeo/psalm": "^5.12" }, "suggest": { "ext-intl": "PHP Internationalization Libraries are required to use the SpoofChecking validation" @@ -1038,7 +1055,7 @@ ], "support": { "issues": "https://github.com/egulias/EmailValidator/issues", - "source": "https://github.com/egulias/EmailValidator/tree/4.0.1" + "source": "https://github.com/egulias/EmailValidator/tree/4.0.2" }, "funding": [ { @@ -1046,20 +1063,20 @@ "type": "github" } ], - "time": "2023-01-14T14:17:03+00:00" + "time": "2023-10-06T06:47:41+00:00" }, { "name": "endroid/qr-code", - "version": "4.8.4", + "version": "4.8.5", "source": { "type": "git", "url": "https://github.com/endroid/qr-code.git", - "reference": "a122b85d4a5a3257d471257a43ac3e5676a27ffe" + "reference": "0db25b506a8411a5e1644ebaa67123a6eb7b6a77" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/endroid/qr-code/zipball/a122b85d4a5a3257d471257a43ac3e5676a27ffe", - "reference": "a122b85d4a5a3257d471257a43ac3e5676a27ffe", + "url": "https://api.github.com/repos/endroid/qr-code/zipball/0db25b506a8411a5e1644ebaa67123a6eb7b6a77", + "reference": "0db25b506a8411a5e1644ebaa67123a6eb7b6a77", "shasum": "" }, "require": { @@ -1113,7 +1130,7 @@ ], "support": { "issues": "https://github.com/endroid/qr-code/issues", - "source": "https://github.com/endroid/qr-code/tree/4.8.4" + "source": "https://github.com/endroid/qr-code/tree/4.8.5" }, "funding": [ { @@ -1121,7 +1138,7 @@ "type": "github" } ], - "time": "2023-08-28T18:12:07+00:00" + "time": "2023-09-29T14:03:20+00:00" }, { "name": "evenement/evenement", @@ -1172,21 +1189,21 @@ }, { "name": "fruitcake/php-cors", - "version": "v1.2.0", + "version": "v1.3.0", "source": { "type": "git", "url": "https://github.com/fruitcake/php-cors.git", - "reference": "58571acbaa5f9f462c9c77e911700ac66f446d4e" + "reference": "3d158f36e7875e2f040f37bc0573956240a5a38b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/fruitcake/php-cors/zipball/58571acbaa5f9f462c9c77e911700ac66f446d4e", - "reference": "58571acbaa5f9f462c9c77e911700ac66f446d4e", + "url": "https://api.github.com/repos/fruitcake/php-cors/zipball/3d158f36e7875e2f040f37bc0573956240a5a38b", + "reference": "3d158f36e7875e2f040f37bc0573956240a5a38b", "shasum": "" }, "require": { "php": "^7.4|^8.0", - "symfony/http-foundation": "^4.4|^5.4|^6" + "symfony/http-foundation": "^4.4|^5.4|^6|^7" }, "require-dev": { "phpstan/phpstan": "^1.4", @@ -1196,7 +1213,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "1.1-dev" + "dev-master": "1.2-dev" } }, "autoload": { @@ -1227,7 +1244,7 @@ ], "support": { "issues": "https://github.com/fruitcake/php-cors/issues", - "source": "https://github.com/fruitcake/php-cors/tree/v1.2.0" + "source": "https://github.com/fruitcake/php-cors/tree/v1.3.0" }, "funding": [ { @@ -1239,28 +1256,28 @@ "type": "github" } ], - "time": "2022-02-20T15:07:15+00:00" + "time": "2023-10-12T05:21:21+00:00" }, { "name": "graham-campbell/result-type", - "version": "v1.1.1", + "version": "v1.1.2", "source": { "type": "git", "url": "https://github.com/GrahamCampbell/Result-Type.git", - "reference": "672eff8cf1d6fe1ef09ca0f89c4b287d6a3eb831" + "reference": "fbd48bce38f73f8a4ec8583362e732e4095e5862" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/GrahamCampbell/Result-Type/zipball/672eff8cf1d6fe1ef09ca0f89c4b287d6a3eb831", - "reference": "672eff8cf1d6fe1ef09ca0f89c4b287d6a3eb831", + "url": "https://api.github.com/repos/GrahamCampbell/Result-Type/zipball/fbd48bce38f73f8a4ec8583362e732e4095e5862", + "reference": "fbd48bce38f73f8a4ec8583362e732e4095e5862", "shasum": "" }, "require": { "php": "^7.2.5 || ^8.0", - "phpoption/phpoption": "^1.9.1" + "phpoption/phpoption": "^1.9.2" }, "require-dev": { - "phpunit/phpunit": "^8.5.32 || ^9.6.3 || ^10.0.12" + "phpunit/phpunit": "^8.5.34 || ^9.6.13 || ^10.4.2" }, "type": "library", "autoload": { @@ -1289,7 +1306,7 @@ ], "support": { "issues": "https://github.com/GrahamCampbell/Result-Type/issues", - "source": "https://github.com/GrahamCampbell/Result-Type/tree/v1.1.1" + "source": "https://github.com/GrahamCampbell/Result-Type/tree/v1.1.2" }, "funding": [ { @@ -1301,20 +1318,20 @@ "type": "tidelift" } ], - "time": "2023-02-25T20:23:15+00:00" + "time": "2023-11-12T22:16:48+00:00" }, { "name": "guzzlehttp/guzzle", - "version": "7.8.0", + "version": "7.8.1", "source": { "type": "git", "url": "https://github.com/guzzle/guzzle.git", - "reference": "1110f66a6530a40fe7aea0378fe608ee2b2248f9" + "reference": "41042bc7ab002487b876a0683fc8dce04ddce104" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/guzzle/zipball/1110f66a6530a40fe7aea0378fe608ee2b2248f9", - "reference": "1110f66a6530a40fe7aea0378fe608ee2b2248f9", + "url": "https://api.github.com/repos/guzzle/guzzle/zipball/41042bc7ab002487b876a0683fc8dce04ddce104", + "reference": "41042bc7ab002487b876a0683fc8dce04ddce104", "shasum": "" }, "require": { @@ -1329,11 +1346,11 @@ "psr/http-client-implementation": "1.0" }, "require-dev": { - "bamarni/composer-bin-plugin": "^1.8.1", + "bamarni/composer-bin-plugin": "^1.8.2", "ext-curl": "*", "php-http/client-integration-tests": "dev-master#2c025848417c1135031fdf9c728ee53d0a7ceaee as 3.0.999", "php-http/message-factory": "^1.1", - "phpunit/phpunit": "^8.5.29 || ^9.5.23", + "phpunit/phpunit": "^8.5.36 || ^9.6.15", "psr/log": "^1.1 || ^2.0 || ^3.0" }, "suggest": { @@ -1411,7 +1428,7 @@ ], "support": { "issues": "https://github.com/guzzle/guzzle/issues", - "source": "https://github.com/guzzle/guzzle/tree/7.8.0" + "source": "https://github.com/guzzle/guzzle/tree/7.8.1" }, "funding": [ { @@ -1427,28 +1444,28 @@ "type": "tidelift" } ], - "time": "2023-08-27T10:20:53+00:00" + "time": "2023-12-03T20:35:24+00:00" }, { "name": "guzzlehttp/promises", - "version": "2.0.1", + "version": "2.0.2", "source": { "type": "git", "url": "https://github.com/guzzle/promises.git", - "reference": "111166291a0f8130081195ac4556a5587d7f1b5d" + "reference": "bbff78d96034045e58e13dedd6ad91b5d1253223" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/promises/zipball/111166291a0f8130081195ac4556a5587d7f1b5d", - "reference": "111166291a0f8130081195ac4556a5587d7f1b5d", + "url": "https://api.github.com/repos/guzzle/promises/zipball/bbff78d96034045e58e13dedd6ad91b5d1253223", + "reference": "bbff78d96034045e58e13dedd6ad91b5d1253223", "shasum": "" }, "require": { "php": "^7.2.5 || ^8.0" }, "require-dev": { - "bamarni/composer-bin-plugin": "^1.8.1", - "phpunit/phpunit": "^8.5.29 || ^9.5.23" + "bamarni/composer-bin-plugin": "^1.8.2", + "phpunit/phpunit": "^8.5.36 || ^9.6.15" }, "type": "library", "extra": { @@ -1494,7 +1511,7 @@ ], "support": { "issues": "https://github.com/guzzle/promises/issues", - "source": "https://github.com/guzzle/promises/tree/2.0.1" + "source": "https://github.com/guzzle/promises/tree/2.0.2" }, "funding": [ { @@ -1510,20 +1527,20 @@ "type": "tidelift" } ], - "time": "2023-08-03T15:11:55+00:00" + "time": "2023-12-03T20:19:20+00:00" }, { "name": "guzzlehttp/psr7", - "version": "2.6.1", + "version": "2.6.2", "source": { "type": "git", "url": "https://github.com/guzzle/psr7.git", - "reference": "be45764272e8873c72dbe3d2edcfdfcc3bc9f727" + "reference": "45b30f99ac27b5ca93cb4831afe16285f57b8221" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/psr7/zipball/be45764272e8873c72dbe3d2edcfdfcc3bc9f727", - "reference": "be45764272e8873c72dbe3d2edcfdfcc3bc9f727", + "url": "https://api.github.com/repos/guzzle/psr7/zipball/45b30f99ac27b5ca93cb4831afe16285f57b8221", + "reference": "45b30f99ac27b5ca93cb4831afe16285f57b8221", "shasum": "" }, "require": { @@ -1537,9 +1554,9 @@ "psr/http-message-implementation": "1.0" }, "require-dev": { - "bamarni/composer-bin-plugin": "^1.8.1", + "bamarni/composer-bin-plugin": "^1.8.2", "http-interop/http-factory-tests": "^0.9", - "phpunit/phpunit": "^8.5.29 || ^9.5.23" + "phpunit/phpunit": "^8.5.36 || ^9.6.15" }, "suggest": { "laminas/laminas-httphandlerrunner": "Emit PSR-7 responses" @@ -1610,7 +1627,7 @@ ], "support": { "issues": "https://github.com/guzzle/psr7/issues", - "source": "https://github.com/guzzle/psr7/tree/2.6.1" + "source": "https://github.com/guzzle/psr7/tree/2.6.2" }, "funding": [ { @@ -1626,32 +1643,38 @@ "type": "tidelift" } ], - "time": "2023-08-27T10:13:57+00:00" + "time": "2023-12-03T20:05:35+00:00" }, { "name": "guzzlehttp/uri-template", - "version": "v1.0.2", + "version": "v1.0.3", "source": { "type": "git", "url": "https://github.com/guzzle/uri-template.git", - "reference": "61bf437fc2197f587f6857d3ff903a24f1731b5d" + "reference": "ecea8feef63bd4fef1f037ecb288386999ecc11c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/uri-template/zipball/61bf437fc2197f587f6857d3ff903a24f1731b5d", - "reference": "61bf437fc2197f587f6857d3ff903a24f1731b5d", + "url": "https://api.github.com/repos/guzzle/uri-template/zipball/ecea8feef63bd4fef1f037ecb288386999ecc11c", + "reference": "ecea8feef63bd4fef1f037ecb288386999ecc11c", "shasum": "" }, "require": { "php": "^7.2.5 || ^8.0", - "symfony/polyfill-php80": "^1.17" + "symfony/polyfill-php80": "^1.24" }, "require-dev": { - "bamarni/composer-bin-plugin": "^1.8.1", - "phpunit/phpunit": "^8.5.19 || ^9.5.8", + "bamarni/composer-bin-plugin": "^1.8.2", + "phpunit/phpunit": "^8.5.36 || ^9.6.15", "uri-template/tests": "1.0.0" }, "type": "library", + "extra": { + "bamarni-bin": { + "bin-links": true, + "forward-command": false + } + }, "autoload": { "psr-4": { "GuzzleHttp\\UriTemplate\\": "src" @@ -1690,7 +1713,7 @@ ], "support": { "issues": "https://github.com/guzzle/uri-template/issues", - "source": "https://github.com/guzzle/uri-template/tree/v1.0.2" + "source": "https://github.com/guzzle/uri-template/tree/v1.0.3" }, "funding": [ { @@ -1706,7 +1729,7 @@ "type": "tidelift" } ], - "time": "2023-08-27T10:19:19+00:00" + "time": "2023-12-03T19:50:20+00:00" }, { "name": "jcupitt/vips", @@ -1771,16 +1794,16 @@ }, { "name": "laravel/framework", - "version": "v10.25.1", + "version": "v10.35.0", "source": { "type": "git", "url": "https://github.com/laravel/framework.git", - "reference": "cd0a440f43eaaad247d6f6575d3782c156ec913c" + "reference": "91ec2d92d2f6007e9084fe06438b99c91845da69" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/framework/zipball/cd0a440f43eaaad247d6f6575d3782c156ec913c", - "reference": "cd0a440f43eaaad247d6f6575d3782c156ec913c", + "url": "https://api.github.com/repos/laravel/framework/zipball/91ec2d92d2f6007e9084fe06438b99c91845da69", + "reference": "91ec2d92d2f6007e9084fe06438b99c91845da69", "shasum": "" }, "require": { @@ -1813,7 +1836,7 @@ "symfony/console": "^6.2", "symfony/error-handler": "^6.2", "symfony/finder": "^6.2", - "symfony/http-foundation": "^6.2", + "symfony/http-foundation": "^6.4", "symfony/http-kernel": "^6.2", "symfony/mailer": "^6.2", "symfony/mime": "^6.2", @@ -1880,13 +1903,15 @@ "league/flysystem-read-only": "^3.3", "league/flysystem-sftp-v3": "^3.0", "mockery/mockery": "^1.5.1", - "orchestra/testbench-core": "^8.12", + "nyholm/psr7": "^1.2", + "orchestra/testbench-core": "^8.15.1", "pda/pheanstalk": "^4.0", "phpstan/phpstan": "^1.4.7", "phpunit/phpunit": "^10.0.7", "predis/predis": "^2.0.2", "symfony/cache": "^6.2", - "symfony/http-client": "^6.2.4" + "symfony/http-client": "^6.2.4", + "symfony/psr-http-message-bridge": "^2.0" }, "suggest": { "ably/ably-php": "Required to use the Ably broadcast driver (^1.0).", @@ -1967,27 +1992,27 @@ "issues": "https://github.com/laravel/framework/issues", "source": "https://github.com/laravel/framework" }, - "time": "2023-09-27T01:29:32+00:00" + "time": "2023-12-05T14:50:33+00:00" }, { "name": "laravel/prompts", - "version": "v0.1.9", + "version": "v0.1.13", "source": { "type": "git", "url": "https://github.com/laravel/prompts.git", - "reference": "b603410e7af1040aa2d29e0a2cdca570bb63e827" + "reference": "e1379d8ead15edd6cc4369c22274345982edc95a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/prompts/zipball/b603410e7af1040aa2d29e0a2cdca570bb63e827", - "reference": "b603410e7af1040aa2d29e0a2cdca570bb63e827", + "url": "https://api.github.com/repos/laravel/prompts/zipball/e1379d8ead15edd6cc4369c22274345982edc95a", + "reference": "e1379d8ead15edd6cc4369c22274345982edc95a", "shasum": "" }, "require": { "ext-mbstring": "*", "illuminate/collections": "^10.0|^11.0", "php": "^8.1", - "symfony/console": "^6.2" + "symfony/console": "^6.2|^7.0" }, "conflict": { "illuminate/console": ">=10.17.0 <10.25.0", @@ -2022,22 +2047,22 @@ ], "support": { "issues": "https://github.com/laravel/prompts/issues", - "source": "https://github.com/laravel/prompts/tree/v0.1.9" + "source": "https://github.com/laravel/prompts/tree/v0.1.13" }, - "time": "2023-09-26T13:14:20+00:00" + "time": "2023-10-27T13:53:59+00:00" }, { "name": "laravel/serializable-closure", - "version": "v1.3.1", + "version": "v1.3.3", "source": { "type": "git", "url": "https://github.com/laravel/serializable-closure.git", - "reference": "e5a3057a5591e1cfe8183034b0203921abe2c902" + "reference": "3dbf8a8e914634c48d389c1234552666b3d43754" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/serializable-closure/zipball/e5a3057a5591e1cfe8183034b0203921abe2c902", - "reference": "e5a3057a5591e1cfe8183034b0203921abe2c902", + "url": "https://api.github.com/repos/laravel/serializable-closure/zipball/3dbf8a8e914634c48d389c1234552666b3d43754", + "reference": "3dbf8a8e914634c48d389c1234552666b3d43754", "shasum": "" }, "require": { @@ -2084,7 +2109,7 @@ "issues": "https://github.com/laravel/serializable-closure/issues", "source": "https://github.com/laravel/serializable-closure" }, - "time": "2023-07-14T13:56:28+00:00" + "time": "2023-11-08T14:08:06+00:00" }, { "name": "laravel/tinker", @@ -2157,16 +2182,16 @@ }, { "name": "laravel/ui", - "version": "v4.2.2", + "version": "v4.2.3", "source": { "type": "git", "url": "https://github.com/laravel/ui.git", - "reference": "a58ec468db4a340b33f3426c778784717a2c144b" + "reference": "eb532ea096ca1c0298c87c19233daf011fda743a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/ui/zipball/a58ec468db4a340b33f3426c778784717a2c144b", - "reference": "a58ec468db4a340b33f3426c778784717a2c144b", + "url": "https://api.github.com/repos/laravel/ui/zipball/eb532ea096ca1c0298c87c19233daf011fda743a", + "reference": "eb532ea096ca1c0298c87c19233daf011fda743a", "shasum": "" }, "require": { @@ -2213,9 +2238,9 @@ "ui" ], "support": { - "source": "https://github.com/laravel/ui/tree/v4.2.2" + "source": "https://github.com/laravel/ui/tree/v4.2.3" }, - "time": "2023-05-09T19:47:28+00:00" + "time": "2023-11-23T14:44:22+00:00" }, { "name": "league/commonmark", @@ -2407,16 +2432,16 @@ }, { "name": "league/flysystem", - "version": "3.16.0", + "version": "3.23.0", "source": { "type": "git", "url": "https://github.com/thephpleague/flysystem.git", - "reference": "4fdf372ca6b63c6e281b1c01a624349ccb757729" + "reference": "d4ad81e2b67396e33dc9d7e54ec74ccf73151dcc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/thephpleague/flysystem/zipball/4fdf372ca6b63c6e281b1c01a624349ccb757729", - "reference": "4fdf372ca6b63c6e281b1c01a624349ccb757729", + "url": "https://api.github.com/repos/thephpleague/flysystem/zipball/d4ad81e2b67396e33dc9d7e54ec74ccf73151dcc", + "reference": "d4ad81e2b67396e33dc9d7e54ec74ccf73151dcc", "shasum": "" }, "require": { @@ -2434,8 +2459,8 @@ "symfony/http-client": "<5.2" }, "require-dev": { - "async-aws/s3": "^1.5", - "async-aws/simple-s3": "^1.1", + "async-aws/s3": "^1.5 || ^2.0", + "async-aws/simple-s3": "^1.1 || ^2.0", "aws/aws-sdk-php": "^3.220.0", "composer/semver": "^3.0", "ext-fileinfo": "*", @@ -2444,8 +2469,8 @@ "friendsofphp/php-cs-fixer": "^3.5", "google/cloud-storage": "^1.23", "microsoft/azure-storage-blob": "^1.1", - "phpseclib/phpseclib": "^3.0.14", - "phpstan/phpstan": "^0.12.26", + "phpseclib/phpseclib": "^3.0.34", + "phpstan/phpstan": "^1.10", "phpunit/phpunit": "^9.5.11|^10.0", "sabre/dav": "^4.3.1" }, @@ -2481,7 +2506,7 @@ ], "support": { "issues": "https://github.com/thephpleague/flysystem/issues", - "source": "https://github.com/thephpleague/flysystem/tree/3.16.0" + "source": "https://github.com/thephpleague/flysystem/tree/3.23.0" }, "funding": [ { @@ -2493,20 +2518,20 @@ "type": "github" } ], - "time": "2023-09-07T19:22:17+00:00" + "time": "2023-12-04T10:16:17+00:00" }, { "name": "league/flysystem-local", - "version": "3.16.0", + "version": "3.23.0", "source": { "type": "git", "url": "https://github.com/thephpleague/flysystem-local.git", - "reference": "ec7383f25642e6fd4bb0c9554fc2311245391781" + "reference": "5cf046ba5f059460e86a997c504dd781a39a109b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/thephpleague/flysystem-local/zipball/ec7383f25642e6fd4bb0c9554fc2311245391781", - "reference": "ec7383f25642e6fd4bb0c9554fc2311245391781", + "url": "https://api.github.com/repos/thephpleague/flysystem-local/zipball/5cf046ba5f059460e86a997c504dd781a39a109b", + "reference": "5cf046ba5f059460e86a997c504dd781a39a109b", "shasum": "" }, "require": { @@ -2541,7 +2566,7 @@ ], "support": { "issues": "https://github.com/thephpleague/flysystem-local/issues", - "source": "https://github.com/thephpleague/flysystem-local/tree/3.16.0" + "source": "https://github.com/thephpleague/flysystem-local/tree/3.23.0" }, "funding": [ { @@ -2553,20 +2578,20 @@ "type": "github" } ], - "time": "2023-08-30T10:23:59+00:00" + "time": "2023-12-04T10:14:46+00:00" }, { "name": "league/mime-type-detection", - "version": "1.13.0", + "version": "1.14.0", "source": { "type": "git", "url": "https://github.com/thephpleague/mime-type-detection.git", - "reference": "a6dfb1194a2946fcdc1f38219445234f65b35c96" + "reference": "b6a5854368533df0295c5761a0253656a2e52d9e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/thephpleague/mime-type-detection/zipball/a6dfb1194a2946fcdc1f38219445234f65b35c96", - "reference": "a6dfb1194a2946fcdc1f38219445234f65b35c96", + "url": "https://api.github.com/repos/thephpleague/mime-type-detection/zipball/b6a5854368533df0295c5761a0253656a2e52d9e", + "reference": "b6a5854368533df0295c5761a0253656a2e52d9e", "shasum": "" }, "require": { @@ -2597,7 +2622,7 @@ "description": "Mime-type detection for Flysystem", "support": { "issues": "https://github.com/thephpleague/mime-type-detection/issues", - "source": "https://github.com/thephpleague/mime-type-detection/tree/1.13.0" + "source": "https://github.com/thephpleague/mime-type-detection/tree/1.14.0" }, "funding": [ { @@ -2609,20 +2634,20 @@ "type": "tidelift" } ], - "time": "2023-08-05T12:09:49+00:00" + "time": "2023-10-17T14:13:20+00:00" }, { "name": "monolog/monolog", - "version": "3.4.0", + "version": "3.5.0", "source": { "type": "git", "url": "https://github.com/Seldaek/monolog.git", - "reference": "e2392369686d420ca32df3803de28b5d6f76867d" + "reference": "c915e2634718dbc8a4a15c61b0e62e7a44e14448" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Seldaek/monolog/zipball/e2392369686d420ca32df3803de28b5d6f76867d", - "reference": "e2392369686d420ca32df3803de28b5d6f76867d", + "url": "https://api.github.com/repos/Seldaek/monolog/zipball/c915e2634718dbc8a4a15c61b0e62e7a44e14448", + "reference": "c915e2634718dbc8a4a15c61b0e62e7a44e14448", "shasum": "" }, "require": { @@ -2698,7 +2723,7 @@ ], "support": { "issues": "https://github.com/Seldaek/monolog/issues", - "source": "https://github.com/Seldaek/monolog/tree/3.4.0" + "source": "https://github.com/Seldaek/monolog/tree/3.5.0" }, "funding": [ { @@ -2710,7 +2735,7 @@ "type": "tidelift" } ], - "time": "2023-06-21T08:46:11+00:00" + "time": "2023-10-27T15:32:31+00:00" }, { "name": "msurguy/honeypot", @@ -2777,19 +2802,20 @@ }, { "name": "nesbot/carbon", - "version": "2.71.0", + "version": "2.72.0", "source": { "type": "git", "url": "https://github.com/briannesbitt/Carbon.git", - "reference": "98276233188583f2ff845a0f992a235472d9466a" + "reference": "a6885fcbad2ec4360b0e200ee0da7d9b7c90786b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/briannesbitt/Carbon/zipball/98276233188583f2ff845a0f992a235472d9466a", - "reference": "98276233188583f2ff845a0f992a235472d9466a", + "url": "https://api.github.com/repos/briannesbitt/Carbon/zipball/a6885fcbad2ec4360b0e200ee0da7d9b7c90786b", + "reference": "a6885fcbad2ec4360b0e200ee0da7d9b7c90786b", "shasum": "" }, "require": { + "carbonphp/carbon-doctrine-types": "*", "ext-json": "*", "php": "^7.1.8 || ^8.0", "psr/clock": "^1.0", @@ -2801,8 +2827,8 @@ "psr/clock-implementation": "1.0" }, "require-dev": { - "doctrine/dbal": "^2.0 || ^3.1.4", - "doctrine/orm": "^2.7", + "doctrine/dbal": "^2.0 || ^3.1.4 || ^4.0", + "doctrine/orm": "^2.7 || ^3.0", "friendsofphp/php-cs-fixer": "^3.0", "kylekatarnls/multi-tester": "^2.0", "ondrejmirtes/better-reflection": "*", @@ -2879,20 +2905,20 @@ "type": "tidelift" } ], - "time": "2023-09-25T11:31:05+00:00" + "time": "2023-11-28T10:13:25+00:00" }, { "name": "nette/schema", - "version": "v1.2.4", + "version": "v1.2.5", "source": { "type": "git", "url": "https://github.com/nette/schema.git", - "reference": "c9ff517a53903b3d4e29ec547fb20feecb05b8ab" + "reference": "0462f0166e823aad657c9224d0f849ecac1ba10a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nette/schema/zipball/c9ff517a53903b3d4e29ec547fb20feecb05b8ab", - "reference": "c9ff517a53903b3d4e29ec547fb20feecb05b8ab", + "url": "https://api.github.com/repos/nette/schema/zipball/0462f0166e823aad657c9224d0f849ecac1ba10a", + "reference": "0462f0166e823aad657c9224d0f849ecac1ba10a", "shasum": "" }, "require": { @@ -2939,22 +2965,22 @@ ], "support": { "issues": "https://github.com/nette/schema/issues", - "source": "https://github.com/nette/schema/tree/v1.2.4" + "source": "https://github.com/nette/schema/tree/v1.2.5" }, - "time": "2023-08-05T18:56:25+00:00" + "time": "2023-10-05T20:37:59+00:00" }, { "name": "nette/utils", - "version": "v4.0.2", + "version": "v4.0.3", "source": { "type": "git", "url": "https://github.com/nette/utils.git", - "reference": "cead6637226456b35e1175cc53797dd585d85545" + "reference": "a9d127dd6a203ce6d255b2e2db49759f7506e015" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nette/utils/zipball/cead6637226456b35e1175cc53797dd585d85545", - "reference": "cead6637226456b35e1175cc53797dd585d85545", + "url": "https://api.github.com/repos/nette/utils/zipball/a9d127dd6a203ce6d255b2e2db49759f7506e015", + "reference": "a9d127dd6a203ce6d255b2e2db49759f7506e015", "shasum": "" }, "require": { @@ -3025,9 +3051,9 @@ ], "support": { "issues": "https://github.com/nette/utils/issues", - "source": "https://github.com/nette/utils/tree/v4.0.2" + "source": "https://github.com/nette/utils/tree/v4.0.3" }, - "time": "2023-09-19T11:58:07+00:00" + "time": "2023-10-29T21:02:13+00:00" }, { "name": "nikic/php-parser", @@ -3307,6 +3333,58 @@ }, "time": "2023-04-30T00:54:53+00:00" }, + { + "name": "pgvector/pgvector", + "version": "v0.1.4", + "source": { + "type": "git", + "url": "https://github.com/pgvector/pgvector-php.git", + "reference": "301ce729091b496b477c28f548bcba285d59d86d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/pgvector/pgvector-php/zipball/301ce729091b496b477c28f548bcba285d59d86d", + "reference": "301ce729091b496b477c28f548bcba285d59d86d", + "shasum": "" + }, + "require": { + "php": ">= 7.4" + }, + "require-dev": { + "illuminate/database": ">= 9.0", + "phpunit/phpunit": "^9" + }, + "type": "library", + "extra": { + "laravel": { + "providers": [ + "Pgvector\\Laravel\\PgvectorServiceProvider" + ] + } + }, + "autoload": { + "psr-4": { + "Pgvector\\": "src/", + "Pgvector\\Laravel\\": "src/laravel/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Andrew Kane", + "email": "andrew@ankane.org" + } + ], + "description": "pgvector support for PHP", + "support": { + "issues": "https://github.com/pgvector/pgvector-php/issues", + "source": "https://github.com/pgvector/pgvector-php" + }, + "time": "2023-11-15T02:20:37+00:00" + }, { "name": "php-ffmpeg/php-ffmpeg", "version": "v1.1.0", @@ -3398,16 +3476,16 @@ }, { "name": "phpoption/phpoption", - "version": "1.9.1", + "version": "1.9.2", "source": { "type": "git", "url": "https://github.com/schmittjoh/php-option.git", - "reference": "dd3a383e599f49777d8b628dadbb90cae435b87e" + "reference": "80735db690fe4fc5c76dfa7f9b770634285fa820" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/schmittjoh/php-option/zipball/dd3a383e599f49777d8b628dadbb90cae435b87e", - "reference": "dd3a383e599f49777d8b628dadbb90cae435b87e", + "url": "https://api.github.com/repos/schmittjoh/php-option/zipball/80735db690fe4fc5c76dfa7f9b770634285fa820", + "reference": "80735db690fe4fc5c76dfa7f9b770634285fa820", "shasum": "" }, "require": { @@ -3415,7 +3493,7 @@ }, "require-dev": { "bamarni/composer-bin-plugin": "^1.8.2", - "phpunit/phpunit": "^8.5.32 || ^9.6.3 || ^10.0.12" + "phpunit/phpunit": "^8.5.34 || ^9.6.13 || ^10.4.2" }, "type": "library", "extra": { @@ -3457,7 +3535,7 @@ ], "support": { "issues": "https://github.com/schmittjoh/php-option/issues", - "source": "https://github.com/schmittjoh/php-option/tree/1.9.1" + "source": "https://github.com/schmittjoh/php-option/tree/1.9.2" }, "funding": [ { @@ -3469,7 +3547,7 @@ "type": "tidelift" } ], - "time": "2023-02-25T19:38:58+00:00" + "time": "2023-11-12T21:59:55+00:00" }, { "name": "psr/cache", @@ -3934,16 +4012,16 @@ }, { "name": "psy/psysh", - "version": "v0.11.21", + "version": "v0.11.22", "source": { "type": "git", "url": "https://github.com/bobthecow/psysh.git", - "reference": "bcb22101107f3bf770523b65630c9d547f60c540" + "reference": "128fa1b608be651999ed9789c95e6e2a31b5802b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/bobthecow/psysh/zipball/bcb22101107f3bf770523b65630c9d547f60c540", - "reference": "bcb22101107f3bf770523b65630c9d547f60c540", + "url": "https://api.github.com/repos/bobthecow/psysh/zipball/128fa1b608be651999ed9789c95e6e2a31b5802b", + "reference": "128fa1b608be651999ed9789c95e6e2a31b5802b", "shasum": "" }, "require": { @@ -3972,7 +4050,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "0.11.x-dev" + "dev-0.11": "0.11.x-dev" }, "bamarni-bin": { "bin-links": false, @@ -4008,9 +4086,9 @@ ], "support": { "issues": "https://github.com/bobthecow/psysh/issues", - "source": "https://github.com/bobthecow/psysh/tree/v0.11.21" + "source": "https://github.com/bobthecow/psysh/tree/v0.11.22" }, - "time": "2023-09-17T21:15:54+00:00" + "time": "2023-10-14T21:56:36+00:00" }, { "name": "pusher/pusher-php-server", @@ -4208,16 +4286,16 @@ }, { "name": "ramsey/uuid", - "version": "4.7.4", + "version": "4.7.5", "source": { "type": "git", "url": "https://github.com/ramsey/uuid.git", - "reference": "60a4c63ab724854332900504274f6150ff26d286" + "reference": "5f0df49ae5ad6efb7afa69e6bfab4e5b1e080d8e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/ramsey/uuid/zipball/60a4c63ab724854332900504274f6150ff26d286", - "reference": "60a4c63ab724854332900504274f6150ff26d286", + "url": "https://api.github.com/repos/ramsey/uuid/zipball/5f0df49ae5ad6efb7afa69e6bfab4e5b1e080d8e", + "reference": "5f0df49ae5ad6efb7afa69e6bfab4e5b1e080d8e", "shasum": "" }, "require": { @@ -4284,7 +4362,7 @@ ], "support": { "issues": "https://github.com/ramsey/uuid/issues", - "source": "https://github.com/ramsey/uuid/tree/4.7.4" + "source": "https://github.com/ramsey/uuid/tree/4.7.5" }, "funding": [ { @@ -4296,7 +4374,7 @@ "type": "tidelift" } ], - "time": "2023-04-15T23:01:58+00:00" + "time": "2023-11-08T05:53:05+00:00" }, { "name": "ramsey/uuid-doctrine", @@ -4428,16 +4506,16 @@ }, { "name": "symfony/cache", - "version": "v6.3.4", + "version": "v6.4.0", "source": { "type": "git", "url": "https://github.com/symfony/cache.git", - "reference": "e60d00b4f633efa4c1ef54e77c12762d9073e7b3" + "reference": "ac2d25f97b17eec6e19760b6b9962a4f7c44356a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/cache/zipball/e60d00b4f633efa4c1ef54e77c12762d9073e7b3", - "reference": "e60d00b4f633efa4c1ef54e77c12762d9073e7b3", + "url": "https://api.github.com/repos/symfony/cache/zipball/ac2d25f97b17eec6e19760b6b9962a4f7c44356a", + "reference": "ac2d25f97b17eec6e19760b6b9962a4f7c44356a", "shasum": "" }, "require": { @@ -4446,7 +4524,7 @@ "psr/log": "^1.1|^2|^3", "symfony/cache-contracts": "^2.5|^3", "symfony/service-contracts": "^2.5|^3", - "symfony/var-exporter": "^6.2.10" + "symfony/var-exporter": "^6.3.6|^7.0" }, "conflict": { "doctrine/dbal": "<2.13.1", @@ -4461,15 +4539,15 @@ }, "require-dev": { "cache/integration-tests": "dev-master", - "doctrine/dbal": "^2.13.1|^3.0", + "doctrine/dbal": "^2.13.1|^3|^4", "predis/predis": "^1.1|^2.0", "psr/simple-cache": "^1.0|^2.0|^3.0", - "symfony/config": "^5.4|^6.0", - "symfony/dependency-injection": "^5.4|^6.0", - "symfony/filesystem": "^5.4|^6.0", - "symfony/http-kernel": "^5.4|^6.0", - "symfony/messenger": "^5.4|^6.0", - "symfony/var-dumper": "^5.4|^6.0" + "symfony/config": "^5.4|^6.0|^7.0", + "symfony/dependency-injection": "^5.4|^6.0|^7.0", + "symfony/filesystem": "^5.4|^6.0|^7.0", + "symfony/http-kernel": "^5.4|^6.0|^7.0", + "symfony/messenger": "^5.4|^6.0|^7.0", + "symfony/var-dumper": "^5.4|^6.0|^7.0" }, "type": "library", "autoload": { @@ -4504,7 +4582,7 @@ "psr6" ], "support": { - "source": "https://github.com/symfony/cache/tree/v6.3.4" + "source": "https://github.com/symfony/cache/tree/v6.4.0" }, "funding": [ { @@ -4520,20 +4598,20 @@ "type": "tidelift" } ], - "time": "2023-08-05T09:10:27+00:00" + "time": "2023-11-24T19:28:07+00:00" }, { "name": "symfony/cache-contracts", - "version": "v3.3.0", + "version": "v3.4.0", "source": { "type": "git", "url": "https://github.com/symfony/cache-contracts.git", - "reference": "ad945640ccc0ae6e208bcea7d7de4b39b569896b" + "reference": "1d74b127da04ffa87aa940abe15446fa89653778" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/cache-contracts/zipball/ad945640ccc0ae6e208bcea7d7de4b39b569896b", - "reference": "ad945640ccc0ae6e208bcea7d7de4b39b569896b", + "url": "https://api.github.com/repos/symfony/cache-contracts/zipball/1d74b127da04ffa87aa940abe15446fa89653778", + "reference": "1d74b127da04ffa87aa940abe15446fa89653778", "shasum": "" }, "require": { @@ -4580,7 +4658,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/cache-contracts/tree/v3.3.0" + "source": "https://github.com/symfony/cache-contracts/tree/v3.4.0" }, "funding": [ { @@ -4596,20 +4674,20 @@ "type": "tidelift" } ], - "time": "2023-05-23T14:45:45+00:00" + "time": "2023-09-25T12:52:38+00:00" }, { "name": "symfony/console", - "version": "v6.3.4", + "version": "v6.4.1", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "eca495f2ee845130855ddf1cf18460c38966c8b6" + "reference": "a550a7c99daeedef3f9d23fb82e3531525ff11fd" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/eca495f2ee845130855ddf1cf18460c38966c8b6", - "reference": "eca495f2ee845130855ddf1cf18460c38966c8b6", + "url": "https://api.github.com/repos/symfony/console/zipball/a550a7c99daeedef3f9d23fb82e3531525ff11fd", + "reference": "a550a7c99daeedef3f9d23fb82e3531525ff11fd", "shasum": "" }, "require": { @@ -4617,7 +4695,7 @@ "symfony/deprecation-contracts": "^2.5|^3", "symfony/polyfill-mbstring": "~1.0", "symfony/service-contracts": "^2.5|^3", - "symfony/string": "^5.4|^6.0" + "symfony/string": "^5.4|^6.0|^7.0" }, "conflict": { "symfony/dependency-injection": "<5.4", @@ -4631,12 +4709,16 @@ }, "require-dev": { "psr/log": "^1|^2|^3", - "symfony/config": "^5.4|^6.0", - "symfony/dependency-injection": "^5.4|^6.0", - "symfony/event-dispatcher": "^5.4|^6.0", - "symfony/lock": "^5.4|^6.0", - "symfony/process": "^5.4|^6.0", - "symfony/var-dumper": "^5.4|^6.0" + "symfony/config": "^5.4|^6.0|^7.0", + "symfony/dependency-injection": "^5.4|^6.0|^7.0", + "symfony/event-dispatcher": "^5.4|^6.0|^7.0", + "symfony/http-foundation": "^6.4|^7.0", + "symfony/http-kernel": "^6.4|^7.0", + "symfony/lock": "^5.4|^6.0|^7.0", + "symfony/messenger": "^5.4|^6.0|^7.0", + "symfony/process": "^5.4|^6.0|^7.0", + "symfony/stopwatch": "^5.4|^6.0|^7.0", + "symfony/var-dumper": "^5.4|^6.0|^7.0" }, "type": "library", "autoload": { @@ -4670,7 +4752,7 @@ "terminal" ], "support": { - "source": "https://github.com/symfony/console/tree/v6.3.4" + "source": "https://github.com/symfony/console/tree/v6.4.1" }, "funding": [ { @@ -4686,20 +4768,20 @@ "type": "tidelift" } ], - "time": "2023-08-16T10:10:12+00:00" + "time": "2023-11-30T10:54:28+00:00" }, { "name": "symfony/css-selector", - "version": "v6.3.2", + "version": "v6.4.0", "source": { "type": "git", "url": "https://github.com/symfony/css-selector.git", - "reference": "883d961421ab1709877c10ac99451632a3d6fa57" + "reference": "d036c6c0d0b09e24a14a35f8292146a658f986e4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/css-selector/zipball/883d961421ab1709877c10ac99451632a3d6fa57", - "reference": "883d961421ab1709877c10ac99451632a3d6fa57", + "url": "https://api.github.com/repos/symfony/css-selector/zipball/d036c6c0d0b09e24a14a35f8292146a658f986e4", + "reference": "d036c6c0d0b09e24a14a35f8292146a658f986e4", "shasum": "" }, "require": { @@ -4735,7 +4817,7 @@ "description": "Converts CSS selectors to XPath expressions", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/css-selector/tree/v6.3.2" + "source": "https://github.com/symfony/css-selector/tree/v6.4.0" }, "funding": [ { @@ -4751,11 +4833,11 @@ "type": "tidelift" } ], - "time": "2023-07-12T16:00:22+00:00" + "time": "2023-10-31T08:40:20+00:00" }, { "name": "symfony/deprecation-contracts", - "version": "v3.3.0", + "version": "v3.4.0", "source": { "type": "git", "url": "https://github.com/symfony/deprecation-contracts.git", @@ -4802,7 +4884,7 @@ "description": "A generic function and convention to trigger deprecation notices", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/deprecation-contracts/tree/v3.3.0" + "source": "https://github.com/symfony/deprecation-contracts/tree/v3.4.0" }, "funding": [ { @@ -4822,30 +4904,31 @@ }, { "name": "symfony/error-handler", - "version": "v6.3.2", + "version": "v6.4.0", "source": { "type": "git", "url": "https://github.com/symfony/error-handler.git", - "reference": "85fd65ed295c4078367c784e8a5a6cee30348b7a" + "reference": "c873490a1c97b3a0a4838afc36ff36c112d02788" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/error-handler/zipball/85fd65ed295c4078367c784e8a5a6cee30348b7a", - "reference": "85fd65ed295c4078367c784e8a5a6cee30348b7a", + "url": "https://api.github.com/repos/symfony/error-handler/zipball/c873490a1c97b3a0a4838afc36ff36c112d02788", + "reference": "c873490a1c97b3a0a4838afc36ff36c112d02788", "shasum": "" }, "require": { "php": ">=8.1", "psr/log": "^1|^2|^3", - "symfony/var-dumper": "^5.4|^6.0" + "symfony/var-dumper": "^5.4|^6.0|^7.0" }, "conflict": { - "symfony/deprecation-contracts": "<2.5" + "symfony/deprecation-contracts": "<2.5", + "symfony/http-kernel": "<6.4" }, "require-dev": { "symfony/deprecation-contracts": "^2.5|^3", - "symfony/http-kernel": "^5.4|^6.0", - "symfony/serializer": "^5.4|^6.0" + "symfony/http-kernel": "^6.4|^7.0", + "symfony/serializer": "^5.4|^6.0|^7.0" }, "bin": [ "Resources/bin/patch-type-declarations" @@ -4876,7 +4959,7 @@ "description": "Provides tools to manage errors and ease debugging PHP code", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/error-handler/tree/v6.3.2" + "source": "https://github.com/symfony/error-handler/tree/v6.4.0" }, "funding": [ { @@ -4892,20 +4975,20 @@ "type": "tidelift" } ], - "time": "2023-07-16T17:05:46+00:00" + "time": "2023-10-18T09:43:34+00:00" }, { "name": "symfony/event-dispatcher", - "version": "v6.3.2", + "version": "v6.4.0", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher.git", - "reference": "adb01fe097a4ee930db9258a3cc906b5beb5cf2e" + "reference": "d76d2632cfc2206eecb5ad2b26cd5934082941b6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/adb01fe097a4ee930db9258a3cc906b5beb5cf2e", - "reference": "adb01fe097a4ee930db9258a3cc906b5beb5cf2e", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/d76d2632cfc2206eecb5ad2b26cd5934082941b6", + "reference": "d76d2632cfc2206eecb5ad2b26cd5934082941b6", "shasum": "" }, "require": { @@ -4922,13 +5005,13 @@ }, "require-dev": { "psr/log": "^1|^2|^3", - "symfony/config": "^5.4|^6.0", - "symfony/dependency-injection": "^5.4|^6.0", - "symfony/error-handler": "^5.4|^6.0", - "symfony/expression-language": "^5.4|^6.0", - "symfony/http-foundation": "^5.4|^6.0", + "symfony/config": "^5.4|^6.0|^7.0", + "symfony/dependency-injection": "^5.4|^6.0|^7.0", + "symfony/error-handler": "^5.4|^6.0|^7.0", + "symfony/expression-language": "^5.4|^6.0|^7.0", + "symfony/http-foundation": "^5.4|^6.0|^7.0", "symfony/service-contracts": "^2.5|^3", - "symfony/stopwatch": "^5.4|^6.0" + "symfony/stopwatch": "^5.4|^6.0|^7.0" }, "type": "library", "autoload": { @@ -4956,7 +5039,7 @@ "description": "Provides tools that allow your application components to communicate with each other by dispatching events and listening to them", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/event-dispatcher/tree/v6.3.2" + "source": "https://github.com/symfony/event-dispatcher/tree/v6.4.0" }, "funding": [ { @@ -4972,11 +5055,11 @@ "type": "tidelift" } ], - "time": "2023-07-06T06:56:43+00:00" + "time": "2023-07-27T06:52:43+00:00" }, { "name": "symfony/event-dispatcher-contracts", - "version": "v3.3.0", + "version": "v3.4.0", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher-contracts.git", @@ -5032,7 +5115,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/event-dispatcher-contracts/tree/v3.3.0" + "source": "https://github.com/symfony/event-dispatcher-contracts/tree/v3.4.0" }, "funding": [ { @@ -5052,23 +5135,23 @@ }, { "name": "symfony/finder", - "version": "v6.3.3", + "version": "v6.4.0", "source": { "type": "git", "url": "https://github.com/symfony/finder.git", - "reference": "9915db259f67d21eefee768c1abcf1cc61b1fc9e" + "reference": "11d736e97f116ac375a81f96e662911a34cd50ce" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/9915db259f67d21eefee768c1abcf1cc61b1fc9e", - "reference": "9915db259f67d21eefee768c1abcf1cc61b1fc9e", + "url": "https://api.github.com/repos/symfony/finder/zipball/11d736e97f116ac375a81f96e662911a34cd50ce", + "reference": "11d736e97f116ac375a81f96e662911a34cd50ce", "shasum": "" }, "require": { "php": ">=8.1" }, "require-dev": { - "symfony/filesystem": "^6.0" + "symfony/filesystem": "^6.0|^7.0" }, "type": "library", "autoload": { @@ -5096,7 +5179,7 @@ "description": "Finds files and directories via an intuitive fluent interface", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/finder/tree/v6.3.3" + "source": "https://github.com/symfony/finder/tree/v6.4.0" }, "funding": [ { @@ -5112,20 +5195,20 @@ "type": "tidelift" } ], - "time": "2023-07-31T08:31:44+00:00" + "time": "2023-10-31T17:30:12+00:00" }, { "name": "symfony/http-foundation", - "version": "v6.3.4", + "version": "v6.4.0", "source": { "type": "git", "url": "https://github.com/symfony/http-foundation.git", - "reference": "cac1556fdfdf6719668181974104e6fcfa60e844" + "reference": "44a6d39a9cc11e154547d882d5aac1e014440771" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-foundation/zipball/cac1556fdfdf6719668181974104e6fcfa60e844", - "reference": "cac1556fdfdf6719668181974104e6fcfa60e844", + "url": "https://api.github.com/repos/symfony/http-foundation/zipball/44a6d39a9cc11e154547d882d5aac1e014440771", + "reference": "44a6d39a9cc11e154547d882d5aac1e014440771", "shasum": "" }, "require": { @@ -5135,17 +5218,17 @@ "symfony/polyfill-php83": "^1.27" }, "conflict": { - "symfony/cache": "<6.2" + "symfony/cache": "<6.3" }, "require-dev": { - "doctrine/dbal": "^2.13.1|^3.0", + "doctrine/dbal": "^2.13.1|^3|^4", "predis/predis": "^1.1|^2.0", - "symfony/cache": "^5.4|^6.0", - "symfony/dependency-injection": "^5.4|^6.0", - "symfony/expression-language": "^5.4|^6.0", - "symfony/http-kernel": "^5.4.12|^6.0.12|^6.1.4", - "symfony/mime": "^5.4|^6.0", - "symfony/rate-limiter": "^5.2|^6.0" + "symfony/cache": "^6.3|^7.0", + "symfony/dependency-injection": "^5.4|^6.0|^7.0", + "symfony/expression-language": "^5.4|^6.0|^7.0", + "symfony/http-kernel": "^5.4.12|^6.0.12|^6.1.4|^7.0", + "symfony/mime": "^5.4|^6.0|^7.0", + "symfony/rate-limiter": "^5.4|^6.0|^7.0" }, "type": "library", "autoload": { @@ -5173,7 +5256,7 @@ "description": "Defines an object-oriented layer for the HTTP specification", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/http-foundation/tree/v6.3.4" + "source": "https://github.com/symfony/http-foundation/tree/v6.4.0" }, "funding": [ { @@ -5189,29 +5272,29 @@ "type": "tidelift" } ], - "time": "2023-08-22T08:20:46+00:00" + "time": "2023-11-20T16:41:16+00:00" }, { "name": "symfony/http-kernel", - "version": "v6.3.4", + "version": "v6.4.1", "source": { "type": "git", "url": "https://github.com/symfony/http-kernel.git", - "reference": "36abb425b4af863ae1fe54d8a8b8b4c76a2bccdb" + "reference": "2953274c16a229b3933ef73a6898e18388e12e1b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-kernel/zipball/36abb425b4af863ae1fe54d8a8b8b4c76a2bccdb", - "reference": "36abb425b4af863ae1fe54d8a8b8b4c76a2bccdb", + "url": "https://api.github.com/repos/symfony/http-kernel/zipball/2953274c16a229b3933ef73a6898e18388e12e1b", + "reference": "2953274c16a229b3933ef73a6898e18388e12e1b", "shasum": "" }, "require": { "php": ">=8.1", "psr/log": "^1|^2|^3", "symfony/deprecation-contracts": "^2.5|^3", - "symfony/error-handler": "^6.3", - "symfony/event-dispatcher": "^5.4|^6.0", - "symfony/http-foundation": "^6.3.4", + "symfony/error-handler": "^6.4|^7.0", + "symfony/event-dispatcher": "^5.4|^6.0|^7.0", + "symfony/http-foundation": "^6.4|^7.0", "symfony/polyfill-ctype": "^1.8" }, "conflict": { @@ -5219,7 +5302,7 @@ "symfony/cache": "<5.4", "symfony/config": "<6.1", "symfony/console": "<5.4", - "symfony/dependency-injection": "<6.3.4", + "symfony/dependency-injection": "<6.4", "symfony/doctrine-bridge": "<5.4", "symfony/form": "<5.4", "symfony/http-client": "<5.4", @@ -5229,7 +5312,7 @@ "symfony/translation": "<5.4", "symfony/translation-contracts": "<2.5", "symfony/twig-bridge": "<5.4", - "symfony/validator": "<5.4", + "symfony/validator": "<6.4", "symfony/var-dumper": "<6.3", "twig/twig": "<2.13" }, @@ -5238,26 +5321,26 @@ }, "require-dev": { "psr/cache": "^1.0|^2.0|^3.0", - "symfony/browser-kit": "^5.4|^6.0", - "symfony/clock": "^6.2", - "symfony/config": "^6.1", - "symfony/console": "^5.4|^6.0", - "symfony/css-selector": "^5.4|^6.0", - "symfony/dependency-injection": "^6.3.4", - "symfony/dom-crawler": "^5.4|^6.0", - "symfony/expression-language": "^5.4|^6.0", - "symfony/finder": "^5.4|^6.0", + "symfony/browser-kit": "^5.4|^6.0|^7.0", + "symfony/clock": "^6.2|^7.0", + "symfony/config": "^6.1|^7.0", + "symfony/console": "^5.4|^6.0|^7.0", + "symfony/css-selector": "^5.4|^6.0|^7.0", + "symfony/dependency-injection": "^6.4|^7.0", + "symfony/dom-crawler": "^5.4|^6.0|^7.0", + "symfony/expression-language": "^5.4|^6.0|^7.0", + "symfony/finder": "^5.4|^6.0|^7.0", "symfony/http-client-contracts": "^2.5|^3", - "symfony/process": "^5.4|^6.0", - "symfony/property-access": "^5.4.5|^6.0.5", - "symfony/routing": "^5.4|^6.0", - "symfony/serializer": "^6.3", - "symfony/stopwatch": "^5.4|^6.0", - "symfony/translation": "^5.4|^6.0", + "symfony/process": "^5.4|^6.0|^7.0", + "symfony/property-access": "^5.4.5|^6.0.5|^7.0", + "symfony/routing": "^5.4|^6.0|^7.0", + "symfony/serializer": "^6.3|^7.0", + "symfony/stopwatch": "^5.4|^6.0|^7.0", + "symfony/translation": "^5.4|^6.0|^7.0", "symfony/translation-contracts": "^2.5|^3", - "symfony/uid": "^5.4|^6.0", - "symfony/validator": "^6.3", - "symfony/var-exporter": "^6.2", + "symfony/uid": "^5.4|^6.0|^7.0", + "symfony/validator": "^6.4|^7.0", + "symfony/var-exporter": "^6.2|^7.0", "twig/twig": "^2.13|^3.0.4" }, "type": "library", @@ -5286,7 +5369,7 @@ "description": "Provides a structured process for converting a Request into a Response", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/http-kernel/tree/v6.3.4" + "source": "https://github.com/symfony/http-kernel/tree/v6.4.1" }, "funding": [ { @@ -5302,20 +5385,20 @@ "type": "tidelift" } ], - "time": "2023-08-26T13:54:49+00:00" + "time": "2023-12-01T17:02:02+00:00" }, { "name": "symfony/mailer", - "version": "v6.3.0", + "version": "v6.4.0", "source": { "type": "git", "url": "https://github.com/symfony/mailer.git", - "reference": "7b03d9be1dea29bfec0a6c7b603f5072a4c97435" + "reference": "ca8dcf8892cdc5b4358ecf2528429bb5e706f7ba" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/mailer/zipball/7b03d9be1dea29bfec0a6c7b603f5072a4c97435", - "reference": "7b03d9be1dea29bfec0a6c7b603f5072a4c97435", + "url": "https://api.github.com/repos/symfony/mailer/zipball/ca8dcf8892cdc5b4358ecf2528429bb5e706f7ba", + "reference": "ca8dcf8892cdc5b4358ecf2528429bb5e706f7ba", "shasum": "" }, "require": { @@ -5323,8 +5406,8 @@ "php": ">=8.1", "psr/event-dispatcher": "^1", "psr/log": "^1|^2|^3", - "symfony/event-dispatcher": "^5.4|^6.0", - "symfony/mime": "^6.2", + "symfony/event-dispatcher": "^5.4|^6.0|^7.0", + "symfony/mime": "^6.2|^7.0", "symfony/service-contracts": "^2.5|^3" }, "conflict": { @@ -5335,10 +5418,10 @@ "symfony/twig-bridge": "<6.2.1" }, "require-dev": { - "symfony/console": "^5.4|^6.0", - "symfony/http-client": "^5.4|^6.0", - "symfony/messenger": "^6.2", - "symfony/twig-bridge": "^6.2" + "symfony/console": "^5.4|^6.0|^7.0", + "symfony/http-client": "^5.4|^6.0|^7.0", + "symfony/messenger": "^6.2|^7.0", + "symfony/twig-bridge": "^6.2|^7.0" }, "type": "library", "autoload": { @@ -5366,7 +5449,7 @@ "description": "Helps sending emails", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/mailer/tree/v6.3.0" + "source": "https://github.com/symfony/mailer/tree/v6.4.0" }, "funding": [ { @@ -5382,20 +5465,20 @@ "type": "tidelift" } ], - "time": "2023-05-29T12:49:39+00:00" + "time": "2023-11-12T18:02:22+00:00" }, { "name": "symfony/mime", - "version": "v6.3.3", + "version": "v6.4.0", "source": { "type": "git", "url": "https://github.com/symfony/mime.git", - "reference": "9a0cbd52baa5ba5a5b1f0cacc59466f194730f98" + "reference": "ca4f58b2ef4baa8f6cecbeca2573f88cd577d205" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/mime/zipball/9a0cbd52baa5ba5a5b1f0cacc59466f194730f98", - "reference": "9a0cbd52baa5ba5a5b1f0cacc59466f194730f98", + "url": "https://api.github.com/repos/symfony/mime/zipball/ca4f58b2ef4baa8f6cecbeca2573f88cd577d205", + "reference": "ca4f58b2ef4baa8f6cecbeca2573f88cd577d205", "shasum": "" }, "require": { @@ -5409,16 +5492,16 @@ "phpdocumentor/reflection-docblock": "<3.2.2", "phpdocumentor/type-resolver": "<1.4.0", "symfony/mailer": "<5.4", - "symfony/serializer": "<6.2.13|>=6.3,<6.3.2" + "symfony/serializer": "<6.3.2" }, "require-dev": { "egulias/email-validator": "^2.1.10|^3.1|^4", "league/html-to-markdown": "^5.0", "phpdocumentor/reflection-docblock": "^3.0|^4.0|^5.0", - "symfony/dependency-injection": "^5.4|^6.0", - "symfony/property-access": "^5.4|^6.0", - "symfony/property-info": "^5.4|^6.0", - "symfony/serializer": "~6.2.13|^6.3.2" + "symfony/dependency-injection": "^5.4|^6.0|^7.0", + "symfony/property-access": "^5.4|^6.0|^7.0", + "symfony/property-info": "^5.4|^6.0|^7.0", + "symfony/serializer": "^6.3.2|^7.0" }, "type": "library", "autoload": { @@ -5450,7 +5533,7 @@ "mime-type" ], "support": { - "source": "https://github.com/symfony/mime/tree/v6.3.3" + "source": "https://github.com/symfony/mime/tree/v6.4.0" }, "funding": [ { @@ -5466,7 +5549,7 @@ "type": "tidelift" } ], - "time": "2023-07-31T07:08:24+00:00" + "time": "2023-10-17T11:49:05+00:00" }, { "name": "symfony/polyfill-ctype", @@ -6208,16 +6291,16 @@ }, { "name": "symfony/process", - "version": "v6.3.4", + "version": "v6.4.0", "source": { "type": "git", "url": "https://github.com/symfony/process.git", - "reference": "0b5c29118f2e980d455d2e34a5659f4579847c54" + "reference": "191703b1566d97a5425dc969e4350d32b8ef17aa" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/0b5c29118f2e980d455d2e34a5659f4579847c54", - "reference": "0b5c29118f2e980d455d2e34a5659f4579847c54", + "url": "https://api.github.com/repos/symfony/process/zipball/191703b1566d97a5425dc969e4350d32b8ef17aa", + "reference": "191703b1566d97a5425dc969e4350d32b8ef17aa", "shasum": "" }, "require": { @@ -6249,7 +6332,7 @@ "description": "Executes commands in sub-processes", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/process/tree/v6.3.4" + "source": "https://github.com/symfony/process/tree/v6.4.0" }, "funding": [ { @@ -6265,20 +6348,20 @@ "type": "tidelift" } ], - "time": "2023-08-07T10:39:22+00:00" + "time": "2023-11-17T21:06:49+00:00" }, { "name": "symfony/routing", - "version": "v6.3.3", + "version": "v6.4.1", "source": { "type": "git", "url": "https://github.com/symfony/routing.git", - "reference": "e7243039ab663822ff134fbc46099b5fdfa16f6a" + "reference": "0c95c164fdba18b12523b75e64199ca3503e6d40" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/routing/zipball/e7243039ab663822ff134fbc46099b5fdfa16f6a", - "reference": "e7243039ab663822ff134fbc46099b5fdfa16f6a", + "url": "https://api.github.com/repos/symfony/routing/zipball/0c95c164fdba18b12523b75e64199ca3503e6d40", + "reference": "0c95c164fdba18b12523b75e64199ca3503e6d40", "shasum": "" }, "require": { @@ -6294,11 +6377,11 @@ "require-dev": { "doctrine/annotations": "^1.12|^2", "psr/log": "^1|^2|^3", - "symfony/config": "^6.2", - "symfony/dependency-injection": "^5.4|^6.0", - "symfony/expression-language": "^5.4|^6.0", - "symfony/http-foundation": "^5.4|^6.0", - "symfony/yaml": "^5.4|^6.0" + "symfony/config": "^6.2|^7.0", + "symfony/dependency-injection": "^5.4|^6.0|^7.0", + "symfony/expression-language": "^5.4|^6.0|^7.0", + "symfony/http-foundation": "^5.4|^6.0|^7.0", + "symfony/yaml": "^5.4|^6.0|^7.0" }, "type": "library", "autoload": { @@ -6332,7 +6415,7 @@ "url" ], "support": { - "source": "https://github.com/symfony/routing/tree/v6.3.3" + "source": "https://github.com/symfony/routing/tree/v6.4.1" }, "funding": [ { @@ -6348,20 +6431,20 @@ "type": "tidelift" } ], - "time": "2023-07-31T07:08:24+00:00" + "time": "2023-12-01T14:54:37+00:00" }, { "name": "symfony/service-contracts", - "version": "v3.3.0", + "version": "v3.4.0", "source": { "type": "git", "url": "https://github.com/symfony/service-contracts.git", - "reference": "40da9cc13ec349d9e4966ce18b5fbcd724ab10a4" + "reference": "b3313c2dbffaf71c8de2934e2ea56ed2291a3838" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/service-contracts/zipball/40da9cc13ec349d9e4966ce18b5fbcd724ab10a4", - "reference": "40da9cc13ec349d9e4966ce18b5fbcd724ab10a4", + "url": "https://api.github.com/repos/symfony/service-contracts/zipball/b3313c2dbffaf71c8de2934e2ea56ed2291a3838", + "reference": "b3313c2dbffaf71c8de2934e2ea56ed2291a3838", "shasum": "" }, "require": { @@ -6414,7 +6497,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/service-contracts/tree/v3.3.0" + "source": "https://github.com/symfony/service-contracts/tree/v3.4.0" }, "funding": [ { @@ -6430,20 +6513,20 @@ "type": "tidelift" } ], - "time": "2023-05-23T14:45:45+00:00" + "time": "2023-07-30T20:28:31+00:00" }, { "name": "symfony/string", - "version": "v6.3.2", + "version": "v6.4.0", "source": { "type": "git", "url": "https://github.com/symfony/string.git", - "reference": "53d1a83225002635bca3482fcbf963001313fb68" + "reference": "b45fcf399ea9c3af543a92edf7172ba21174d809" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/string/zipball/53d1a83225002635bca3482fcbf963001313fb68", - "reference": "53d1a83225002635bca3482fcbf963001313fb68", + "url": "https://api.github.com/repos/symfony/string/zipball/b45fcf399ea9c3af543a92edf7172ba21174d809", + "reference": "b45fcf399ea9c3af543a92edf7172ba21174d809", "shasum": "" }, "require": { @@ -6457,11 +6540,11 @@ "symfony/translation-contracts": "<2.5" }, "require-dev": { - "symfony/error-handler": "^5.4|^6.0", - "symfony/http-client": "^5.4|^6.0", - "symfony/intl": "^6.2", + "symfony/error-handler": "^5.4|^6.0|^7.0", + "symfony/http-client": "^5.4|^6.0|^7.0", + "symfony/intl": "^6.2|^7.0", "symfony/translation-contracts": "^2.5|^3.0", - "symfony/var-exporter": "^5.4|^6.0" + "symfony/var-exporter": "^5.4|^6.0|^7.0" }, "type": "library", "autoload": { @@ -6500,7 +6583,7 @@ "utf8" ], "support": { - "source": "https://github.com/symfony/string/tree/v6.3.2" + "source": "https://github.com/symfony/string/tree/v6.4.0" }, "funding": [ { @@ -6516,20 +6599,20 @@ "type": "tidelift" } ], - "time": "2023-07-05T08:41:27+00:00" + "time": "2023-11-28T20:41:49+00:00" }, { "name": "symfony/translation", - "version": "v6.3.3", + "version": "v6.4.0", "source": { "type": "git", "url": "https://github.com/symfony/translation.git", - "reference": "3ed078c54bc98bbe4414e1e9b2d5e85ed5a5c8bd" + "reference": "b1035dbc2a344b21f8fa8ac451c7ecec4ea45f37" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/translation/zipball/3ed078c54bc98bbe4414e1e9b2d5e85ed5a5c8bd", - "reference": "3ed078c54bc98bbe4414e1e9b2d5e85ed5a5c8bd", + "url": "https://api.github.com/repos/symfony/translation/zipball/b1035dbc2a344b21f8fa8ac451c7ecec4ea45f37", + "reference": "b1035dbc2a344b21f8fa8ac451c7ecec4ea45f37", "shasum": "" }, "require": { @@ -6554,17 +6637,17 @@ "require-dev": { "nikic/php-parser": "^4.13", "psr/log": "^1|^2|^3", - "symfony/config": "^5.4|^6.0", - "symfony/console": "^5.4|^6.0", - "symfony/dependency-injection": "^5.4|^6.0", - "symfony/finder": "^5.4|^6.0", + "symfony/config": "^5.4|^6.0|^7.0", + "symfony/console": "^5.4|^6.0|^7.0", + "symfony/dependency-injection": "^5.4|^6.0|^7.0", + "symfony/finder": "^5.4|^6.0|^7.0", "symfony/http-client-contracts": "^2.5|^3.0", - "symfony/http-kernel": "^5.4|^6.0", - "symfony/intl": "^5.4|^6.0", + "symfony/http-kernel": "^5.4|^6.0|^7.0", + "symfony/intl": "^5.4|^6.0|^7.0", "symfony/polyfill-intl-icu": "^1.21", - "symfony/routing": "^5.4|^6.0", + "symfony/routing": "^5.4|^6.0|^7.0", "symfony/service-contracts": "^2.5|^3", - "symfony/yaml": "^5.4|^6.0" + "symfony/yaml": "^5.4|^6.0|^7.0" }, "type": "library", "autoload": { @@ -6595,7 +6678,7 @@ "description": "Provides tools to internationalize your application", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/translation/tree/v6.3.3" + "source": "https://github.com/symfony/translation/tree/v6.4.0" }, "funding": [ { @@ -6611,20 +6694,20 @@ "type": "tidelift" } ], - "time": "2023-07-31T07:08:24+00:00" + "time": "2023-11-29T08:14:36+00:00" }, { "name": "symfony/translation-contracts", - "version": "v3.3.0", + "version": "v3.4.0", "source": { "type": "git", "url": "https://github.com/symfony/translation-contracts.git", - "reference": "02c24deb352fb0d79db5486c0c79905a85e37e86" + "reference": "dee0c6e5b4c07ce851b462530088e64b255ac9c5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/translation-contracts/zipball/02c24deb352fb0d79db5486c0c79905a85e37e86", - "reference": "02c24deb352fb0d79db5486c0c79905a85e37e86", + "url": "https://api.github.com/repos/symfony/translation-contracts/zipball/dee0c6e5b4c07ce851b462530088e64b255ac9c5", + "reference": "dee0c6e5b4c07ce851b462530088e64b255ac9c5", "shasum": "" }, "require": { @@ -6673,7 +6756,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/translation-contracts/tree/v3.3.0" + "source": "https://github.com/symfony/translation-contracts/tree/v3.4.0" }, "funding": [ { @@ -6689,20 +6772,20 @@ "type": "tidelift" } ], - "time": "2023-05-30T17:17:10+00:00" + "time": "2023-07-25T15:08:44+00:00" }, { "name": "symfony/uid", - "version": "v6.3.0", + "version": "v6.4.0", "source": { "type": "git", "url": "https://github.com/symfony/uid.git", - "reference": "01b0f20b1351d997711c56f1638f7a8c3061e384" + "reference": "8092dd1b1a41372110d06374f99ee62f7f0b9a92" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/uid/zipball/01b0f20b1351d997711c56f1638f7a8c3061e384", - "reference": "01b0f20b1351d997711c56f1638f7a8c3061e384", + "url": "https://api.github.com/repos/symfony/uid/zipball/8092dd1b1a41372110d06374f99ee62f7f0b9a92", + "reference": "8092dd1b1a41372110d06374f99ee62f7f0b9a92", "shasum": "" }, "require": { @@ -6710,7 +6793,7 @@ "symfony/polyfill-uuid": "^1.15" }, "require-dev": { - "symfony/console": "^5.4|^6.0" + "symfony/console": "^5.4|^6.0|^7.0" }, "type": "library", "autoload": { @@ -6747,7 +6830,7 @@ "uuid" ], "support": { - "source": "https://github.com/symfony/uid/tree/v6.3.0" + "source": "https://github.com/symfony/uid/tree/v6.4.0" }, "funding": [ { @@ -6763,20 +6846,20 @@ "type": "tidelift" } ], - "time": "2023-04-08T07:25:02+00:00" + "time": "2023-10-31T08:18:17+00:00" }, { "name": "symfony/var-dumper", - "version": "v6.3.4", + "version": "v6.4.0", "source": { "type": "git", "url": "https://github.com/symfony/var-dumper.git", - "reference": "2027be14f8ae8eae999ceadebcda5b4909b81d45" + "reference": "c40f7d17e91d8b407582ed51a2bbf83c52c367f6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/var-dumper/zipball/2027be14f8ae8eae999ceadebcda5b4909b81d45", - "reference": "2027be14f8ae8eae999ceadebcda5b4909b81d45", + "url": "https://api.github.com/repos/symfony/var-dumper/zipball/c40f7d17e91d8b407582ed51a2bbf83c52c367f6", + "reference": "c40f7d17e91d8b407582ed51a2bbf83c52c367f6", "shasum": "" }, "require": { @@ -6789,10 +6872,11 @@ }, "require-dev": { "ext-iconv": "*", - "symfony/console": "^5.4|^6.0", - "symfony/http-kernel": "^5.4|^6.0", - "symfony/process": "^5.4|^6.0", - "symfony/uid": "^5.4|^6.0", + "symfony/console": "^5.4|^6.0|^7.0", + "symfony/error-handler": "^6.3|^7.0", + "symfony/http-kernel": "^5.4|^6.0|^7.0", + "symfony/process": "^5.4|^6.0|^7.0", + "symfony/uid": "^5.4|^6.0|^7.0", "twig/twig": "^2.13|^3.0.4" }, "bin": [ @@ -6831,7 +6915,7 @@ "dump" ], "support": { - "source": "https://github.com/symfony/var-dumper/tree/v6.3.4" + "source": "https://github.com/symfony/var-dumper/tree/v6.4.0" }, "funding": [ { @@ -6847,27 +6931,28 @@ "type": "tidelift" } ], - "time": "2023-08-24T14:51:05+00:00" + "time": "2023-11-09T08:28:32+00:00" }, { "name": "symfony/var-exporter", - "version": "v6.3.4", + "version": "v6.4.1", "source": { "type": "git", "url": "https://github.com/symfony/var-exporter.git", - "reference": "df1f8aac5751871b83d30bf3e2c355770f8f0691" + "reference": "2d08ca6b9cc704dce525615d1e6d1788734f36d9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/var-exporter/zipball/df1f8aac5751871b83d30bf3e2c355770f8f0691", - "reference": "df1f8aac5751871b83d30bf3e2c355770f8f0691", + "url": "https://api.github.com/repos/symfony/var-exporter/zipball/2d08ca6b9cc704dce525615d1e6d1788734f36d9", + "reference": "2d08ca6b9cc704dce525615d1e6d1788734f36d9", "shasum": "" }, "require": { - "php": ">=8.1" + "php": ">=8.1", + "symfony/deprecation-contracts": "^2.5|^3" }, "require-dev": { - "symfony/var-dumper": "^5.4|^6.0" + "symfony/var-dumper": "^5.4|^6.0|^7.0" }, "type": "library", "autoload": { @@ -6905,7 +6990,7 @@ "serialize" ], "support": { - "source": "https://github.com/symfony/var-exporter/tree/v6.3.4" + "source": "https://github.com/symfony/var-exporter/tree/v6.4.1" }, "funding": [ { @@ -6921,7 +7006,7 @@ "type": "tidelift" } ], - "time": "2023-08-16T18:14:47+00:00" + "time": "2023-11-30T10:32:10+00:00" }, { "name": "tijsverkoyen/css-to-inline-styles", @@ -6978,31 +7063,31 @@ }, { "name": "vlucas/phpdotenv", - "version": "v5.5.0", + "version": "v5.6.0", "source": { "type": "git", "url": "https://github.com/vlucas/phpdotenv.git", - "reference": "1a7ea2afc49c3ee6d87061f5a233e3a035d0eae7" + "reference": "2cf9fb6054c2bb1d59d1f3817706ecdb9d2934c4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/vlucas/phpdotenv/zipball/1a7ea2afc49c3ee6d87061f5a233e3a035d0eae7", - "reference": "1a7ea2afc49c3ee6d87061f5a233e3a035d0eae7", + "url": "https://api.github.com/repos/vlucas/phpdotenv/zipball/2cf9fb6054c2bb1d59d1f3817706ecdb9d2934c4", + "reference": "2cf9fb6054c2bb1d59d1f3817706ecdb9d2934c4", "shasum": "" }, "require": { "ext-pcre": "*", - "graham-campbell/result-type": "^1.0.2", - "php": "^7.1.3 || ^8.0", - "phpoption/phpoption": "^1.8", - "symfony/polyfill-ctype": "^1.23", - "symfony/polyfill-mbstring": "^1.23.1", - "symfony/polyfill-php80": "^1.23.1" + "graham-campbell/result-type": "^1.1.2", + "php": "^7.2.5 || ^8.0", + "phpoption/phpoption": "^1.9.2", + "symfony/polyfill-ctype": "^1.24", + "symfony/polyfill-mbstring": "^1.24", + "symfony/polyfill-php80": "^1.24" }, "require-dev": { - "bamarni/composer-bin-plugin": "^1.4.1", + "bamarni/composer-bin-plugin": "^1.8.2", "ext-filter": "*", - "phpunit/phpunit": "^7.5.20 || ^8.5.30 || ^9.5.25" + "phpunit/phpunit": "^8.5.34 || ^9.6.13 || ^10.4.2" }, "suggest": { "ext-filter": "Required to use the boolean validator." @@ -7014,7 +7099,7 @@ "forward-command": true }, "branch-alias": { - "dev-master": "5.5-dev" + "dev-master": "5.6-dev" } }, "autoload": { @@ -7046,7 +7131,7 @@ ], "support": { "issues": "https://github.com/vlucas/phpdotenv/issues", - "source": "https://github.com/vlucas/phpdotenv/tree/v5.5.0" + "source": "https://github.com/vlucas/phpdotenv/tree/v5.6.0" }, "funding": [ { @@ -7058,7 +7143,7 @@ "type": "tidelift" } ], - "time": "2022-10-16T01:01:54+00:00" + "time": "2023-11-12T22:43:29+00:00" }, { "name": "voku/portable-ascii", @@ -7581,16 +7666,16 @@ }, { "name": "composer/pcre", - "version": "3.1.0", + "version": "3.1.1", "source": { "type": "git", "url": "https://github.com/composer/pcre.git", - "reference": "4bff79ddd77851fe3cdd11616ed3f92841ba5bd2" + "reference": "00104306927c7a0919b4ced2aaa6782c1e61a3c9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/composer/pcre/zipball/4bff79ddd77851fe3cdd11616ed3f92841ba5bd2", - "reference": "4bff79ddd77851fe3cdd11616ed3f92841ba5bd2", + "url": "https://api.github.com/repos/composer/pcre/zipball/00104306927c7a0919b4ced2aaa6782c1e61a3c9", + "reference": "00104306927c7a0919b4ced2aaa6782c1e61a3c9", "shasum": "" }, "require": { @@ -7632,7 +7717,7 @@ ], "support": { "issues": "https://github.com/composer/pcre/issues", - "source": "https://github.com/composer/pcre/tree/3.1.0" + "source": "https://github.com/composer/pcre/tree/3.1.1" }, "funding": [ { @@ -7648,7 +7733,7 @@ "type": "tidelift" } ], - "time": "2022-11-17T09:50:14+00:00" + "time": "2023-10-11T07:11:09+00:00" }, { "name": "composer/semver", @@ -8066,16 +8151,16 @@ }, { "name": "filp/whoops", - "version": "2.15.3", + "version": "2.15.4", "source": { "type": "git", "url": "https://github.com/filp/whoops.git", - "reference": "c83e88a30524f9360b11f585f71e6b17313b7187" + "reference": "a139776fa3f5985a50b509f2a02ff0f709d2a546" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/filp/whoops/zipball/c83e88a30524f9360b11f585f71e6b17313b7187", - "reference": "c83e88a30524f9360b11f585f71e6b17313b7187", + "url": "https://api.github.com/repos/filp/whoops/zipball/a139776fa3f5985a50b509f2a02ff0f709d2a546", + "reference": "a139776fa3f5985a50b509f2a02ff0f709d2a546", "shasum": "" }, "require": { @@ -8125,7 +8210,7 @@ ], "support": { "issues": "https://github.com/filp/whoops/issues", - "source": "https://github.com/filp/whoops/tree/2.15.3" + "source": "https://github.com/filp/whoops/tree/2.15.4" }, "funding": [ { @@ -8133,56 +8218,54 @@ "type": "github" } ], - "time": "2023-07-13T12:00:00+00:00" + "time": "2023-11-03T12:00:00+00:00" }, { "name": "friendsofphp/php-cs-fixer", - "version": "v3.30.0", + "version": "v3.40.2", "source": { "type": "git", "url": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer.git", - "reference": "95c64693b2f149966a2bc05a7a4981b0343ea52f" + "reference": "4344562a516b76afe8f2d64b2e52214c30d64ed8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/95c64693b2f149966a2bc05a7a4981b0343ea52f", - "reference": "95c64693b2f149966a2bc05a7a4981b0343ea52f", + "url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/4344562a516b76afe8f2d64b2e52214c30d64ed8", + "reference": "4344562a516b76afe8f2d64b2e52214c30d64ed8", "shasum": "" }, "require": { - "composer/semver": "^3.3", + "composer/semver": "^3.4", "composer/xdebug-handler": "^3.0.3", "ext-json": "*", "ext-tokenizer": "*", "php": "^7.4 || ^8.0", "sebastian/diff": "^4.0 || ^5.0", - "symfony/console": "^5.4 || ^6.0", - "symfony/event-dispatcher": "^5.4 || ^6.0", - "symfony/filesystem": "^5.4 || ^6.0", - "symfony/finder": "^5.4 || ^6.0", - "symfony/options-resolver": "^5.4 || ^6.0", - "symfony/polyfill-mbstring": "^1.27", - "symfony/polyfill-php80": "^1.27", - "symfony/polyfill-php81": "^1.27", - "symfony/process": "^5.4 || ^6.0", - "symfony/stopwatch": "^5.4 || ^6.0" + "symfony/console": "^5.4 || ^6.0 || ^7.0", + "symfony/event-dispatcher": "^5.4 || ^6.0 || ^7.0", + "symfony/filesystem": "^5.4 || ^6.0 || ^7.0", + "symfony/finder": "^5.4 || ^6.0 || ^7.0", + "symfony/options-resolver": "^5.4 || ^6.0 || ^7.0", + "symfony/polyfill-mbstring": "^1.28", + "symfony/polyfill-php80": "^1.28", + "symfony/polyfill-php81": "^1.28", + "symfony/process": "^5.4 || ^6.0 || ^7.0", + "symfony/stopwatch": "^5.4 || ^6.0 || ^7.0" }, "require-dev": { "facile-it/paraunit": "^1.3 || ^2.0", "justinrainbow/json-schema": "^5.2", - "keradus/cli-executor": "^2.0", + "keradus/cli-executor": "^2.1", "mikey179/vfsstream": "^1.6.11", - "php-coveralls/php-coveralls": "^2.5.3", + "php-coveralls/php-coveralls": "^2.7", "php-cs-fixer/accessible-object": "^1.1", - "php-cs-fixer/phpunit-constraint-isidenticalstring": "^1.2", - "php-cs-fixer/phpunit-constraint-xmlmatchesxsd": "^1.2.1", - "phpspec/prophecy": "^1.16", + "php-cs-fixer/phpunit-constraint-isidenticalstring": "^1.4", + "php-cs-fixer/phpunit-constraint-xmlmatchesxsd": "^1.4", + "phpspec/prophecy": "^1.17", "phpspec/prophecy-phpunit": "^2.0", - "phpunit/phpunit": "^9.5", - "phpunitgoodpractices/polyfill": "^1.6", - "phpunitgoodpractices/traits": "^1.9.2", - "symfony/phpunit-bridge": "^6.2.3", - "symfony/yaml": "^5.4 || ^6.0" + "phpunit/phpunit": "^9.6", + "symfony/phpunit-bridge": "^6.3.8 || ^7.0", + "symfony/yaml": "^5.4 || ^6.0 || ^7.0" }, "suggest": { "ext-dom": "For handling output formats in XML", @@ -8220,7 +8303,7 @@ ], "support": { "issues": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/issues", - "source": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/tree/v3.30.0" + "source": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/tree/v3.40.2" }, "funding": [ { @@ -8228,7 +8311,7 @@ "type": "github" } ], - "time": "2023-09-26T22:10:43+00:00" + "time": "2023-12-03T09:21:33+00:00" }, { "name": "hamcrest/hamcrest-php", @@ -8478,16 +8561,16 @@ }, { "name": "nunomaduro/collision", - "version": "v7.9.0", + "version": "v7.10.0", "source": { "type": "git", "url": "https://github.com/nunomaduro/collision.git", - "reference": "296d0cf9fe462837ac0da8a568b56fc026b132da" + "reference": "49ec67fa7b002712da8526678abd651c09f375b2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nunomaduro/collision/zipball/296d0cf9fe462837ac0da8a568b56fc026b132da", - "reference": "296d0cf9fe462837ac0da8a568b56fc026b132da", + "url": "https://api.github.com/repos/nunomaduro/collision/zipball/49ec67fa7b002712da8526678abd651c09f375b2", + "reference": "49ec67fa7b002712da8526678abd651c09f375b2", "shasum": "" }, "require": { @@ -8496,19 +8579,22 @@ "php": "^8.1.0", "symfony/console": "^6.3.4" }, + "conflict": { + "laravel/framework": ">=11.0.0" + }, "require-dev": { - "brianium/paratest": "^7.2.7", - "laravel/framework": "^10.23.1", - "laravel/pint": "^1.13.1", + "brianium/paratest": "^7.3.0", + "laravel/framework": "^10.28.0", + "laravel/pint": "^1.13.3", "laravel/sail": "^1.25.0", "laravel/sanctum": "^3.3.1", "laravel/tinker": "^2.8.2", "nunomaduro/larastan": "^2.6.4", - "orchestra/testbench-core": "^8.11.0", - "pestphp/pest": "^2.19.1", - "phpunit/phpunit": "^10.3.5", + "orchestra/testbench-core": "^8.13.0", + "pestphp/pest": "^2.23.2", + "phpunit/phpunit": "^10.4.1", "sebastian/environment": "^6.0.1", - "spatie/laravel-ignition": "^2.3.0" + "spatie/laravel-ignition": "^2.3.1" }, "type": "library", "extra": { @@ -8567,34 +8653,36 @@ "type": "patreon" } ], - "time": "2023-09-19T10:45:09+00:00" + "time": "2023-10-11T15:45:01+00:00" }, { "name": "orchestra/canvas", - "version": "v8.10.1", + "version": "v8.11.4", "source": { "type": "git", "url": "https://github.com/orchestral/canvas.git", - "reference": "eef3eb34e263cc462c0eb284ba002f2829b04e2a" + "reference": "466ed3d7c1755e49be1c8e5557b434381b8ab6d1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/orchestral/canvas/zipball/eef3eb34e263cc462c0eb284ba002f2829b04e2a", - "reference": "eef3eb34e263cc462c0eb284ba002f2829b04e2a", + "url": "https://api.github.com/repos/orchestral/canvas/zipball/466ed3d7c1755e49be1c8e5557b434381b8ab6d1", + "reference": "466ed3d7c1755e49be1c8e5557b434381b8ab6d1", "shasum": "" }, "require": { "composer-runtime-api": "^2.2", "composer/semver": "^3.0", - "illuminate/database": "^10.23", - "illuminate/support": "^10.23", - "orchestra/canvas-core": "^8.8", + "illuminate/console": "^10.33", + "illuminate/database": "^10.33", + "illuminate/support": "^10.33", + "orchestra/canvas-core": "^8.10.1", "orchestra/testbench-core": "^8.11", "php": "^8.1", + "symfony/polyfill-php83": "^1.28", "symfony/yaml": "^6.2" }, "require-dev": { - "laravel/framework": "^10.23", + "laravel/framework": "^10.33", "laravel/pint": "^1.6", "mockery/mockery": "^1.5.1", "phpstan/phpstan": "^1.10.5", @@ -8637,42 +8725,41 @@ "description": "Code Generators for Laravel Applications and Packages", "support": { "issues": "https://github.com/orchestral/canvas/issues", - "source": "https://github.com/orchestral/canvas/tree/v8.10.1" + "source": "https://github.com/orchestral/canvas/tree/v8.11.4" }, - "time": "2023-09-25T08:37:12+00:00" + "time": "2023-11-27T04:47:24+00:00" }, { "name": "orchestra/canvas-core", - "version": "v8.8.0", + "version": "v8.10.1", "source": { "type": "git", "url": "https://github.com/orchestral/canvas-core.git", - "reference": "d44ffd6895685a6535949c7cce2650a67dd7d364" + "reference": "d4c3325d231deceecdc33fa0b3698efd132ce9f0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/orchestral/canvas-core/zipball/d44ffd6895685a6535949c7cce2650a67dd7d364", - "reference": "d44ffd6895685a6535949c7cce2650a67dd7d364", + "url": "https://api.github.com/repos/orchestral/canvas-core/zipball/d4c3325d231deceecdc33fa0b3698efd132ce9f0", + "reference": "d4c3325d231deceecdc33fa0b3698efd132ce9f0", "shasum": "" }, "require": { "composer-runtime-api": "^2.2", "composer/semver": "^3.0", - "illuminate/console": "^10.17", - "illuminate/filesystem": "^10.17", - "php": "^8.1" + "illuminate/console": "^10.26", + "illuminate/filesystem": "^10.26", + "php": "^8.1", + "symfony/polyfill-php83": "^1.28" }, "conflict": { - "orchestra/canvas": "<8.9.0", + "orchestra/canvas": "<8.11.0", "orchestra/testbench-core": "<8.2.0" }, "require-dev": { - "fakerphp/faker": "^1.21", - "laravel/framework": "^10.17", + "laravel/framework": "^10.26", "laravel/pint": "^1.6", "mockery/mockery": "^1.5.1", - "orchestra/testbench-core": "^8.11", - "orchestra/workbench": "^0.3", + "orchestra/testbench-core": "^8.15", "phpstan/phpstan": "^1.10.6", "phpunit/phpunit": "^10.1", "symfony/yaml": "^6.2" @@ -8710,34 +8797,33 @@ "description": "Code Generators Builder for Laravel Applications and Packages", "support": { "issues": "https://github.com/orchestral/canvas/issues", - "source": "https://github.com/orchestral/canvas-core/tree/v8.8.0" + "source": "https://github.com/orchestral/canvas-core/tree/v8.10.1" }, - "time": "2023-09-19T04:26:25+00:00" + "time": "2023-11-27T03:19:28+00:00" }, { "name": "orchestra/testbench", - "version": "v8.12.1", + "version": "v8.17.0", "source": { "type": "git", "url": "https://github.com/orchestral/testbench.git", - "reference": "9bae3c28789295db875eee0d3395c4ba23f1e5ae" + "reference": "3bbe0956df4b6f811ca879e2a8d69a8a8b626587" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/orchestral/testbench/zipball/9bae3c28789295db875eee0d3395c4ba23f1e5ae", - "reference": "9bae3c28789295db875eee0d3395c4ba23f1e5ae", + "url": "https://api.github.com/repos/orchestral/testbench/zipball/3bbe0956df4b6f811ca879e2a8d69a8a8b626587", + "reference": "3bbe0956df4b6f811ca879e2a8d69a8a8b626587", "shasum": "" }, "require": { "composer-runtime-api": "^2.2", "fakerphp/faker": "^1.21", - "laravel/framework": ">=10.23.1 <10.26.0", + "laravel/framework": "^10.23.1", "mockery/mockery": "^1.5.1", - "orchestra/testbench-core": ">=8.12.0 <8.13.0", - "orchestra/workbench": "^0.4.0", + "orchestra/testbench-core": "^8.17", + "orchestra/workbench": "^1.2 || ^8.2", "php": "^8.1", "phpunit/phpunit": "^9.6 || ^10.1", - "spatie/laravel-ray": "^1.32.4", "symfony/process": "^6.2", "symfony/yaml": "^6.2", "vlucas/phpdotenv": "^5.4.1" @@ -8766,27 +8852,35 @@ ], "support": { "issues": "https://github.com/orchestral/testbench/issues", - "source": "https://github.com/orchestral/testbench/tree/v8.12.1" + "source": "https://github.com/orchestral/testbench/tree/v8.17.0" }, - "time": "2023-09-25T14:33:44+00:00" + "time": "2023-12-06T03:25:17+00:00" }, { "name": "orchestra/testbench-core", - "version": "v8.12.1", + "version": "v8.17.1", "source": { "type": "git", "url": "https://github.com/orchestral/testbench-core.git", - "reference": "9a7b63f9cd10dd15cf7c9d4aad2ccaa688465a1f" + "reference": "6856e979790c18705812b2b6c3c73bb1f6d8baa8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/orchestral/testbench-core/zipball/9a7b63f9cd10dd15cf7c9d4aad2ccaa688465a1f", - "reference": "9a7b63f9cd10dd15cf7c9d4aad2ccaa688465a1f", + "url": "https://api.github.com/repos/orchestral/testbench-core/zipball/6856e979790c18705812b2b6c3c73bb1f6d8baa8", + "reference": "6856e979790c18705812b2b6c3c73bb1f6d8baa8", "shasum": "" }, "require": { "composer-runtime-api": "^2.2", - "php": "^8.1" + "php": "^8.1", + "symfony/polyfill-php83": "^1.28" + }, + "conflict": { + "brianium/paratest": "<6.4.0 || >=7.0.0 <7.1.4 || >=8.0.0", + "laravel/framework": "<10.23.1 || >=11.0.0", + "nunomaduro/collision": "<6.4.0 || >=7.0.0 <7.4.0 || >=8.0.0", + "orchestra/workbench": "<1.0.0", + "phpunit/phpunit": "<9.6.0 || >=10.6.0" }, "require-dev": { "fakerphp/faker": "^1.21", @@ -8801,7 +8895,7 @@ "vlucas/phpdotenv": "^5.4.1" }, "suggest": { - "brianium/paratest": "Allow using parallel tresting (^6.4 || ^7.1.4).", + "brianium/paratest": "Allow using parallel testing (^6.4 || ^7.1.4).", "fakerphp/faker": "Allow using Faker for testing (^1.21).", "laravel/framework": "Required for testing (^10.23).", "mockery/mockery": "Allow using Mockery for testing (^1.5.1).", @@ -8849,45 +8943,45 @@ "issues": "https://github.com/orchestral/testbench/issues", "source": "https://github.com/orchestral/testbench-core" }, - "time": "2023-09-26T12:50:24+00:00" + "time": "2023-12-06T08:00:50+00:00" }, { "name": "orchestra/workbench", - "version": "v0.4.1", + "version": "v8.2.0", "source": { "type": "git", "url": "https://github.com/orchestral/workbench.git", - "reference": "21acf1015ac48e36cb468bffd161115689958782" + "reference": "63b3961efa515abfcfd340805e6713eb540b7a39" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/orchestral/workbench/zipball/21acf1015ac48e36cb468bffd161115689958782", - "reference": "21acf1015ac48e36cb468bffd161115689958782", + "url": "https://api.github.com/repos/orchestral/workbench/zipball/63b3961efa515abfcfd340805e6713eb540b7a39", + "reference": "63b3961efa515abfcfd340805e6713eb540b7a39", "shasum": "" }, "require": { "composer-runtime-api": "^2.2", - "illuminate/console": "^9.52.15 || ^10.23.0", - "illuminate/support": "^9.52.15 || ^10.23.0", + "fakerphp/faker": "^1.21", + "laravel/framework": "^10.26", "laravel/tinker": "^2.8.2", - "orchestra/canvas": "^7.10.0 || ^8.9.0", - "orchestra/testbench-core": "^7.32.0 || ^8.12.0", - "php": "^8.0" + "orchestra/canvas": "^8.11.4", + "orchestra/testbench-core": "^8.17", + "php": "^8.1", + "spatie/laravel-ray": "^1.32.4", + "symfony/polyfill-php83": "^1.28", + "symfony/yaml": "^6.2" }, "require-dev": { - "fakerphp/faker": "^1.21", - "laravel/framework": "^9.52.15 || ^10.23.0", "laravel/pint": "^1.4", "mockery/mockery": "^1.5.1", "phpstan/phpstan": "^1.10.7", - "phpunit/phpunit": "^9.6", - "spatie/laravel-ray": "^1.32.4", - "symfony/yaml": "^6.0.9" + "phpunit/phpunit": "^10.1", + "symfony/process": "^6.2" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "0.4.x-dev" + "dev-master": "0.5.x-dev" } }, "autoload": { @@ -8914,9 +9008,9 @@ ], "support": { "issues": "https://github.com/orchestral/workbench/issues", - "source": "https://github.com/orchestral/workbench/tree/v0.4.1" + "source": "https://github.com/orchestral/workbench/tree/v8.2.0" }, - "time": "2023-09-26T13:04:34+00:00" + "time": "2023-12-06T02:59:43+00:00" }, { "name": "phar-io/manifest", @@ -9199,16 +9293,16 @@ }, { "name": "phpstan/phpdoc-parser", - "version": "1.24.2", + "version": "1.24.4", "source": { "type": "git", "url": "https://github.com/phpstan/phpdoc-parser.git", - "reference": "bcad8d995980440892759db0c32acae7c8e79442" + "reference": "6bd0c26f3786cd9b7c359675cb789e35a8e07496" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/bcad8d995980440892759db0c32acae7c8e79442", - "reference": "bcad8d995980440892759db0c32acae7c8e79442", + "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/6bd0c26f3786cd9b7c359675cb789e35a8e07496", + "reference": "6bd0c26f3786cd9b7c359675cb789e35a8e07496", "shasum": "" }, "require": { @@ -9240,22 +9334,22 @@ "description": "PHPDoc parser with support for nullable, intersection and generic types", "support": { "issues": "https://github.com/phpstan/phpdoc-parser/issues", - "source": "https://github.com/phpstan/phpdoc-parser/tree/1.24.2" + "source": "https://github.com/phpstan/phpdoc-parser/tree/1.24.4" }, - "time": "2023-09-26T12:28:12+00:00" + "time": "2023-11-26T18:29:22+00:00" }, { "name": "phpunit/php-code-coverage", - "version": "10.1.6", + "version": "10.1.9", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "56f33548fe522c8d82da7ff3824b42829d324364" + "reference": "a56a9ab2f680246adcf3db43f38ddf1765774735" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/56f33548fe522c8d82da7ff3824b42829d324364", - "reference": "56f33548fe522c8d82da7ff3824b42829d324364", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/a56a9ab2f680246adcf3db43f38ddf1765774735", + "reference": "a56a9ab2f680246adcf3db43f38ddf1765774735", "shasum": "" }, "require": { @@ -9312,7 +9406,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", "security": "https://github.com/sebastianbergmann/php-code-coverage/security/policy", - "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/10.1.6" + "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/10.1.9" }, "funding": [ { @@ -9320,7 +9414,7 @@ "type": "github" } ], - "time": "2023-09-19T04:59:03+00:00" + "time": "2023-11-23T12:23:20+00:00" }, { "name": "phpunit/php-file-iterator", @@ -9567,16 +9661,16 @@ }, { "name": "phpunit/phpunit", - "version": "10.3.5", + "version": "10.5.2", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "747c3b2038f1139e3dcd9886a3f5a948648b7503" + "reference": "5aedff46afba98dddecaa12349ec044d9103d4fe" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/747c3b2038f1139e3dcd9886a3f5a948648b7503", - "reference": "747c3b2038f1139e3dcd9886a3f5a948648b7503", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/5aedff46afba98dddecaa12349ec044d9103d4fe", + "reference": "5aedff46afba98dddecaa12349ec044d9103d4fe", "shasum": "" }, "require": { @@ -9616,7 +9710,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "10.3-dev" + "dev-main": "10.5-dev" } }, "autoload": { @@ -9648,7 +9742,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/phpunit/issues", "security": "https://github.com/sebastianbergmann/phpunit/security/policy", - "source": "https://github.com/sebastianbergmann/phpunit/tree/10.3.5" + "source": "https://github.com/sebastianbergmann/phpunit/tree/10.5.2" }, "funding": [ { @@ -9664,7 +9758,7 @@ "type": "tidelift" } ], - "time": "2023-09-19T05:42:37+00:00" + "time": "2023-12-05T14:54:33+00:00" }, { "name": "pimple/pimple", @@ -10038,16 +10132,16 @@ }, { "name": "sebastian/complexity", - "version": "3.0.1", + "version": "3.1.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/complexity.git", - "reference": "c70b73893e10757af9c6a48929fa6a333b56a97a" + "reference": "68cfb347a44871f01e33ab0ef8215966432f6957" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/c70b73893e10757af9c6a48929fa6a333b56a97a", - "reference": "c70b73893e10757af9c6a48929fa6a333b56a97a", + "url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/68cfb347a44871f01e33ab0ef8215966432f6957", + "reference": "68cfb347a44871f01e33ab0ef8215966432f6957", "shasum": "" }, "require": { @@ -10060,7 +10154,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "3.0-dev" + "dev-main": "3.1-dev" } }, "autoload": { @@ -10084,7 +10178,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/complexity/issues", "security": "https://github.com/sebastianbergmann/complexity/security/policy", - "source": "https://github.com/sebastianbergmann/complexity/tree/3.0.1" + "source": "https://github.com/sebastianbergmann/complexity/tree/3.1.0" }, "funding": [ { @@ -10092,7 +10186,7 @@ "type": "github" } ], - "time": "2023-08-31T09:55:53+00:00" + "time": "2023-09-28T11:50:59+00:00" }, { "name": "sebastian/diff", @@ -10709,16 +10803,16 @@ }, { "name": "spatie/array-to-xml", - "version": "3.2.0", + "version": "3.2.2", "source": { "type": "git", "url": "https://github.com/spatie/array-to-xml.git", - "reference": "f9ab39c808500c347d5a8b6b13310bd5221e39e7" + "reference": "96be97e664c87613121d073ea39af4c74e57a7f8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/spatie/array-to-xml/zipball/f9ab39c808500c347d5a8b6b13310bd5221e39e7", - "reference": "f9ab39c808500c347d5a8b6b13310bd5221e39e7", + "url": "https://api.github.com/repos/spatie/array-to-xml/zipball/96be97e664c87613121d073ea39af4c74e57a7f8", + "reference": "96be97e664c87613121d073ea39af4c74e57a7f8", "shasum": "" }, "require": { @@ -10756,7 +10850,7 @@ "xml" ], "support": { - "source": "https://github.com/spatie/array-to-xml/tree/3.2.0" + "source": "https://github.com/spatie/array-to-xml/tree/3.2.2" }, "funding": [ { @@ -10768,7 +10862,7 @@ "type": "github" } ], - "time": "2023-07-19T18:30:26+00:00" + "time": "2023-11-14T14:08:51+00:00" }, { "name": "spatie/backtrace", @@ -10969,16 +11063,16 @@ }, { "name": "spatie/ray", - "version": "1.39.0", + "version": "1.40.1", "source": { "type": "git", "url": "https://github.com/spatie/ray.git", - "reference": "7ab6bd01dc6a8ecdd836b3182d40a04308ae0c75" + "reference": "8e6547ff47aae2e4f615a5dcea1e5e4911b1dc9f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/spatie/ray/zipball/7ab6bd01dc6a8ecdd836b3182d40a04308ae0c75", - "reference": "7ab6bd01dc6a8ecdd836b3182d40a04308ae0c75", + "url": "https://api.github.com/repos/spatie/ray/zipball/8e6547ff47aae2e4f615a5dcea1e5e4911b1dc9f", + "reference": "8e6547ff47aae2e4f615a5dcea1e5e4911b1dc9f", "shasum": "" }, "require": { @@ -11029,7 +11123,7 @@ ], "support": { "issues": "https://github.com/spatie/ray/issues", - "source": "https://github.com/spatie/ray/tree/1.39.0" + "source": "https://github.com/spatie/ray/tree/1.40.1" }, "funding": [ { @@ -11041,20 +11135,20 @@ "type": "other" } ], - "time": "2023-09-18T10:36:07+00:00" + "time": "2023-11-20T08:20:15+00:00" }, { "name": "symfony/filesystem", - "version": "v6.3.1", + "version": "v6.4.0", "source": { "type": "git", "url": "https://github.com/symfony/filesystem.git", - "reference": "edd36776956f2a6fcf577edb5b05eb0e3bdc52ae" + "reference": "952a8cb588c3bc6ce76f6023000fb932f16a6e59" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/filesystem/zipball/edd36776956f2a6fcf577edb5b05eb0e3bdc52ae", - "reference": "edd36776956f2a6fcf577edb5b05eb0e3bdc52ae", + "url": "https://api.github.com/repos/symfony/filesystem/zipball/952a8cb588c3bc6ce76f6023000fb932f16a6e59", + "reference": "952a8cb588c3bc6ce76f6023000fb932f16a6e59", "shasum": "" }, "require": { @@ -11088,7 +11182,7 @@ "description": "Provides basic utilities for the filesystem", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/filesystem/tree/v6.3.1" + "source": "https://github.com/symfony/filesystem/tree/v6.4.0" }, "funding": [ { @@ -11104,20 +11198,20 @@ "type": "tidelift" } ], - "time": "2023-06-01T08:30:39+00:00" + "time": "2023-07-26T17:27:13+00:00" }, { "name": "symfony/options-resolver", - "version": "v6.3.0", + "version": "v6.4.0", "source": { "type": "git", "url": "https://github.com/symfony/options-resolver.git", - "reference": "a10f19f5198d589d5c33333cffe98dc9820332dd" + "reference": "22301f0e7fdeaacc14318928612dee79be99860e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/options-resolver/zipball/a10f19f5198d589d5c33333cffe98dc9820332dd", - "reference": "a10f19f5198d589d5c33333cffe98dc9820332dd", + "url": "https://api.github.com/repos/symfony/options-resolver/zipball/22301f0e7fdeaacc14318928612dee79be99860e", + "reference": "22301f0e7fdeaacc14318928612dee79be99860e", "shasum": "" }, "require": { @@ -11155,7 +11249,7 @@ "options" ], "support": { - "source": "https://github.com/symfony/options-resolver/tree/v6.3.0" + "source": "https://github.com/symfony/options-resolver/tree/v6.4.0" }, "funding": [ { @@ -11171,7 +11265,7 @@ "type": "tidelift" } ], - "time": "2023-05-12T14:21:09+00:00" + "time": "2023-08-08T10:16:24+00:00" }, { "name": "symfony/polyfill-iconv", @@ -11337,7 +11431,7 @@ }, { "name": "symfony/stopwatch", - "version": "v6.3.0", + "version": "v6.4.0", "source": { "type": "git", "url": "https://github.com/symfony/stopwatch.git", @@ -11379,7 +11473,7 @@ "description": "Provides a way to profile code", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/stopwatch/tree/v6.3.0" + "source": "https://github.com/symfony/stopwatch/tree/v6.4.0" }, "funding": [ { @@ -11399,16 +11493,16 @@ }, { "name": "symfony/yaml", - "version": "v6.3.3", + "version": "v6.4.0", "source": { "type": "git", "url": "https://github.com/symfony/yaml.git", - "reference": "e23292e8c07c85b971b44c1c4b87af52133e2add" + "reference": "4f9237a1bb42455d609e6687d2613dde5b41a587" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/yaml/zipball/e23292e8c07c85b971b44c1c4b87af52133e2add", - "reference": "e23292e8c07c85b971b44c1c4b87af52133e2add", + "url": "https://api.github.com/repos/symfony/yaml/zipball/4f9237a1bb42455d609e6687d2613dde5b41a587", + "reference": "4f9237a1bb42455d609e6687d2613dde5b41a587", "shasum": "" }, "require": { @@ -11420,7 +11514,7 @@ "symfony/console": "<5.4" }, "require-dev": { - "symfony/console": "^5.4|^6.0" + "symfony/console": "^5.4|^6.0|^7.0" }, "bin": [ "Resources/bin/yaml-lint" @@ -11451,7 +11545,7 @@ "description": "Loads and dumps YAML files", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/yaml/tree/v6.3.3" + "source": "https://github.com/symfony/yaml/tree/v6.4.0" }, "funding": [ { @@ -11467,20 +11561,20 @@ "type": "tidelift" } ], - "time": "2023-07-31T07:08:24+00:00" + "time": "2023-11-06T11:00:25+00:00" }, { "name": "theseer/tokenizer", - "version": "1.2.1", + "version": "1.2.2", "source": { "type": "git", "url": "https://github.com/theseer/tokenizer.git", - "reference": "34a41e998c2183e22995f158c581e7b5e755ab9e" + "reference": "b2ad5003ca10d4ee50a12da31de12a5774ba6b96" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/theseer/tokenizer/zipball/34a41e998c2183e22995f158c581e7b5e755ab9e", - "reference": "34a41e998c2183e22995f158c581e7b5e755ab9e", + "url": "https://api.github.com/repos/theseer/tokenizer/zipball/b2ad5003ca10d4ee50a12da31de12a5774ba6b96", + "reference": "b2ad5003ca10d4ee50a12da31de12a5774ba6b96", "shasum": "" }, "require": { @@ -11509,7 +11603,7 @@ "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" + "source": "https://github.com/theseer/tokenizer/tree/1.2.2" }, "funding": [ { @@ -11517,20 +11611,20 @@ "type": "github" } ], - "time": "2021-07-28T10:34:58+00:00" + "time": "2023-11-20T00:12:19+00:00" }, { "name": "vimeo/psalm", - "version": "5.15.0", + "version": "5.17.0", "source": { "type": "git", "url": "https://github.com/vimeo/psalm.git", - "reference": "5c774aca4746caf3d239d9c8cadb9f882ca29352" + "reference": "c620f6e80d0abfca532b00bda366062aaedf6e5d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/vimeo/psalm/zipball/5c774aca4746caf3d239d9c8cadb9f882ca29352", - "reference": "5c774aca4746caf3d239d9c8cadb9f882ca29352", + "url": "https://api.github.com/repos/vimeo/psalm/zipball/c620f6e80d0abfca532b00bda366062aaedf6e5d", + "reference": "c620f6e80d0abfca532b00bda366062aaedf6e5d", "shasum": "" }, "require": { @@ -11555,8 +11649,8 @@ "php": "^7.4 || ~8.0.0 || ~8.1.0 || ~8.2.0 || ~8.3.0", "sebastian/diff": "^4.0 || ^5.0", "spatie/array-to-xml": "^2.17.0 || ^3.0", - "symfony/console": "^4.1.6 || ^5.0 || ^6.0", - "symfony/filesystem": "^5.4 || ^6.0" + "symfony/console": "^4.1.6 || ^5.0 || ^6.0 || ^7.0", + "symfony/filesystem": "^5.4 || ^6.0 || ^7.0" }, "conflict": { "nikic/php-parser": "4.17.0" @@ -11578,7 +11672,7 @@ "psalm/plugin-phpunit": "^0.18", "slevomat/coding-standard": "^8.4", "squizlabs/php_codesniffer": "^3.6", - "symfony/process": "^4.4 || ^5.0 || ^6.0" + "symfony/process": "^4.4 || ^5.0 || ^6.0 || ^7.0" }, "suggest": { "ext-curl": "In order to send data to shepherd", @@ -11591,7 +11685,7 @@ "psalm-refactor", "psalter" ], - "type": "library", + "type": "project", "extra": { "branch-alias": { "dev-master": "5.x-dev", @@ -11623,10 +11717,11 @@ "static analysis" ], "support": { + "docs": "https://psalm.dev/docs", "issues": "https://github.com/vimeo/psalm/issues", - "source": "https://github.com/vimeo/psalm/tree/5.15.0" + "source": "https://github.com/vimeo/psalm" }, - "time": "2023-08-20T23:07:30+00:00" + "time": "2023-12-03T20:21:41+00:00" }, { "name": "zbateson/mail-mime-parser", @@ -11854,5 +11949,5 @@ "platform-overrides": { "php": "8.1.13" }, - "plugin-api-version": "2.3.0" + "plugin-api-version": "2.2.0" } diff --git a/config/database.php b/config/database.php index b3a9e5583..90ce98207 100644 --- a/config/database.php +++ b/config/database.php @@ -78,21 +78,6 @@ 'sslmode' => 'prefer', ], - 'pgvector' => [ - 'driver' => 'pgsql', - 'url' => env('VECTOR_DATABASE_URL'), - 'host' => env('VECTOR_DB_HOST', 'localhost'), - 'port' => env('VECTOR_DB_PORT', '5432'), - 'database' => env('VECTOR_DB_DATABASE', 'forge'), - 'username' => env('VECTOR_DB_USERNAME', 'forge'), - 'password' => env('VECTOR_DB_PASSWORD', ''), - 'charset' => 'utf8', - 'prefix' => '', - 'prefix_indexes' => true, - 'search_path' => 'public', - 'sslmode' => 'prefer', - ], - 'sqlsrv' => [ 'driver' => 'sqlsrv', 'url' => env('DATABASE_URL'), diff --git a/config/videos.php b/config/videos.php index 4cdcd6967..eea11cd55 100644 --- a/config/videos.php +++ b/config/videos.php @@ -53,20 +53,20 @@ 'track_object_max_jobs_per_user' => env('VIDEOS_TRACK_OBJECT_MAX_JOBS_PER_USER', 10), /* - | Number of max frames to generate for sprites. + | Number of max thumbnails to generate for sprites. */ - 'sprites_max_frames' => 1500, + 'sprites_max_thumbnails' => 1500, /* - | Number of min frames to generate for sprites. + | Number of min thumbnails to generate for sprites. */ - 'sprites_min_frames' => 5, + 'sprites_min_thumbnails' => 5, /* - | Number of frames per sprite. Default 5x5 = 25. + | Number of thumbnails per sprite. Default 5x5 = 25. | The square root of the number must be an integer. */ - 'frames_per_sprite' => 25, + 'sprites_thumbnails_per_sprite' => 25, /* | Dimensions of the thumbnail images to create in sprites. @@ -83,5 +83,5 @@ | Standard time interval at which thumbnails should be sampled when generating sprites. | It will be adjusted dynamically during the process. */ - 'sprites_interval_seconds' => 10, + 'sprites_thumbnail_interval' => 2.5, ]; diff --git a/database/factories/ApiTokenFactory.php b/database/factories/ApiTokenFactory.php index 8cfbf76e2..85c242576 100644 --- a/database/factories/ApiTokenFactory.php +++ b/database/factories/ApiTokenFactory.php @@ -17,8 +17,8 @@ public function definition() return [ 'owner_id' => User::factory(), 'purpose' => $this->faker->sentence(), - // 'password' - 'hash' => '$2y$10$CD13uR2iKSZ2Eyuro5H4yu9sflwe/AA2GAJsdrzRyKnkV9qaz1FaK', + // 'password', hashed with 4 rounds as defined in phpunit.xml + 'hash' => '$2y$04$aqV2XBF34eexL9ezbQZs1eM872NWgH5MhvrmD0SC9qUbhmg9EoxJq', ]; } } diff --git a/database/factories/UserFactory.php b/database/factories/UserFactory.php index 7e40765c4..e5180945a 100644 --- a/database/factories/UserFactory.php +++ b/database/factories/UserFactory.php @@ -18,8 +18,8 @@ public function definition(): array return [ 'firstname' => $this->faker->firstName(), 'lastname' => $this->faker->lastName(), - // 'password' - 'password' => '$2y$10$CD13uR2iKSZ2Eyuro5H4yu9sflwe/AA2GAJsdrzRyKnkV9qaz1FaK', + // 'password', hashed with 4 rounds as defined in phpunit.xml + 'password' => '$2y$04$aqV2XBF34eexL9ezbQZs1eM872NWgH5MhvrmD0SC9qUbhmg9EoxJq', 'email' => $this->faker->unique()->email(), 'remember_token' => Str::random(10), 'uuid' => $this->faker->unique()->uuid(), diff --git a/database/migrations/2022_08_03_000000_create_vector_extension.php b/database/migrations/2022_08_03_000000_create_vector_extension.php index a81ef7679..e785a2415 100644 --- a/database/migrations/2022_08_03_000000_create_vector_extension.php +++ b/database/migrations/2022_08_03_000000_create_vector_extension.php @@ -11,7 +11,14 @@ */ public function up() { - DB::connection('pgvector')->statement('CREATE EXTENSION IF NOT EXISTS vector'); + // The pgvector connection was removed later so it may not always be present. + // There is a second migration that enables pgvector for the default connection. + // See: https://github.com/biigle/maia/pull/150 + if (!is_null(config('database.connections-pgvector'))) { + DB::connection('pgvector') + ->statement('CREATE EXTENSION IF NOT EXISTS vector'); + + } } /** @@ -21,6 +28,10 @@ public function up() */ public function down() { - DB::connection('pgvector')->statement('DROP EXTENSION IF EXISTS vector'); + if (!is_null(config('database.connections-pgvector'))) { + DB::connection('pgvector') + ->statement('DROP EXTENSION IF NOT EXISTS vector'); + + } } }; diff --git a/database/migrations/2023_12_12_150300_create_vector_extension.php b/database/migrations/2023_12_12_150300_create_vector_extension.php new file mode 100644 index 000000000..b53387f08 --- /dev/null +++ b/database/migrations/2023_12_12_150300_create_vector_extension.php @@ -0,0 +1,26 @@ + - - - - diff --git a/resources/assets/js/videos/components/scrollStrip.vue b/resources/assets/js/videos/components/scrollStrip.vue index 4636cf5c2..a6a0fdf9f 100644 --- a/resources/assets/js/videos/components/scrollStrip.vue +++ b/resources/assets/js/videos/components/scrollStrip.vue @@ -10,10 +10,19 @@ :style="scrollerStyle" @mousemove="handleUpdateHoverTime" > +
this.initialElementWidth; }, + showThumbPreview() { + return this.showThumbnailPreview && this.showThumb; + } }, methods: { updateInitialElementWidth() { @@ -210,6 +232,14 @@ export default { this.hasOverflowTop = false; this.hasOverflowBottom = false; }, + handleVideoProgressMousemove(clientX) { + this.showThumb = true; + this.clientMouseX = clientX; + this.scrollstripTop = this.$refs.scroller.getBoundingClientRect().top; + }, + hideThumbnailPreview() { + this.showThumb = false; + }, }, watch: { hoverTime(time) { diff --git a/resources/assets/js/videos/components/settingsTab.vue b/resources/assets/js/videos/components/settingsTab.vue index 3932af765..f5d6c6d38 100644 --- a/resources/assets/js/videos/components/settingsTab.vue +++ b/resources/assets/js/videos/components/settingsTab.vue @@ -15,6 +15,7 @@ export default { 'showLabelTooltip', 'showMousePosition', 'showProgressIndicator', + 'showThumbnailPreview' ], annotationOpacity: 1, showMinimap: true, @@ -23,6 +24,7 @@ export default { showMousePosition: false, playbackRate: 1.0, showProgressIndicator: true, + showThumbnailPreview: true, }; }, methods: { @@ -50,6 +52,12 @@ export default { handleHideProgressIndicator() { this.showProgressIndicator = false; }, + handleShowThumbnailPreview() { + this.showThumbnailPreview = true; + }, + handleHideThumbnailPreview() { + this.showThumbnailPreview = false; + }, }, watch: { annotationOpacity(value) { @@ -86,6 +94,10 @@ export default { this.$emit('update', 'showProgressIndicator', show); Settings.set('showProgressIndicator', show); }, + showThumbnailPreview(show) { + this.$emit('update', 'showThumbnailPreview', show); + Settings.set('showThumbnailPreview', show); + }, }, created() { this.restoreKeys.forEach((key) => { diff --git a/resources/assets/js/videos/components/thumbnailPreview.vue b/resources/assets/js/videos/components/thumbnailPreview.vue new file mode 100644 index 000000000..4607ea889 --- /dev/null +++ b/resources/assets/js/videos/components/thumbnailPreview.vue @@ -0,0 +1,159 @@ + + + \ No newline at end of file diff --git a/resources/assets/js/videos/components/videoProgress.vue b/resources/assets/js/videos/components/videoProgress.vue index 0906a08ad..ec859d1cc 100644 --- a/resources/assets/js/videos/components/videoProgress.vue +++ b/resources/assets/js/videos/components/videoProgress.vue @@ -2,6 +2,8 @@
diff --git a/resources/assets/js/videos/components/videoScreen.vue b/resources/assets/js/videos/components/videoScreen.vue index 60a446f1e..89b6dc631 100644 --- a/resources/assets/js/videos/components/videoScreen.vue +++ b/resources/assets/js/videos/components/videoScreen.vue @@ -501,7 +501,7 @@ export default { this.$emit('next'); }, reset() { - this.setPaused(); + this.setPaused(true); this.resetInteractionMode(); }, }, diff --git a/resources/assets/js/videos/components/videoScreen/annotationPlayback.vue b/resources/assets/js/videos/components/videoScreen/annotationPlayback.vue index ac65ed8ea..fa0f65cc2 100644 --- a/resources/assets/js/videos/components/videoScreen/annotationPlayback.vue +++ b/resources/assets/js/videos/components/videoScreen/annotationPlayback.vue @@ -128,11 +128,9 @@ export default { refreshSingleAnnotation(annotation) { let source = this.annotationSource; - let newFeature = this.createFeature(annotation); - let oldFeature = source.getFeatureById(annotation.id) - - source.removeFeature(oldFeature); - source.addFeature(newFeature); + let feature = source.getFeatureById(annotation.id); + + feature.set('color', annotation.labels[0].label.color); }, createFeature(annotation) { let feature = new Feature(this.getGeometryFromPoints(annotation.shape, annotation.points[0])); diff --git a/resources/assets/js/videos/components/videoScreen/videoPlayback.vue b/resources/assets/js/videos/components/videoScreen/videoPlayback.vue index b832cd141..121bbc524 100644 --- a/resources/assets/js/videos/components/videoScreen/videoPlayback.vue +++ b/resources/assets/js/videos/components/videoScreen/videoPlayback.vue @@ -118,7 +118,7 @@ export default { this.startRenderLoop(); } }, - setPaused() { + setPaused(dontSeek = false) { this.playing = false; this.stopRenderLoop(); // Force render the video frame that belongs to currentTime. This is a @@ -126,7 +126,9 @@ export default { // currentTime (in most cases). With the workaround we can create annotations // at currentTime and be sure that the same frame can be reproduced later for // the annotations. See: https://github.com/biigle/core/issues/433 - this.$emit('seek', this.video.currentTime, true); + if (!dontSeek) { + this.$emit('seek', this.video.currentTime, true); + } }, togglePlaying() { if (this.playing) { diff --git a/resources/assets/js/videos/components/videoTimeline.vue b/resources/assets/js/videos/components/videoTimeline.vue index d0329d8d2..fef6867d2 100644 --- a/resources/assets/js/videos/components/videoTimeline.vue +++ b/resources/assets/js/videos/components/videoTimeline.vue @@ -20,6 +20,7 @@ :duration="duration" :current-time="currentTime" :seeking="seeking" + :showThumbnailPreview="showThumbnailPreview" @seek="emitSeek" @select="emitSelect" @deselect="emitDeselect" @@ -65,6 +66,10 @@ export default { return null; }, }, + showThumbnailPreview: { + type: Boolean, + default: true, + }, }, data() { return { diff --git a/resources/assets/js/videos/main.js b/resources/assets/js/videos/main.js index 414c9ea6b..fee4837c8 100644 --- a/resources/assets/js/videos/main.js +++ b/resources/assets/js/videos/main.js @@ -2,7 +2,6 @@ import './filters/videoTime'; import Navbar from './navbar'; import SearchResults from './searchResults'; import VideoContainer from './videoContainer'; - biigle.$mount('search-results', SearchResults); biigle.$mount('video-annotations-navbar', Navbar); -biigle.$mount('video-container', VideoContainer); +biigle.$mount('video-container', VideoContainer); \ No newline at end of file diff --git a/resources/assets/js/videos/models/Annotation.vue b/resources/assets/js/videos/models/Annotation.vue index bf014ff2b..a300e8bab 100644 --- a/resources/assets/js/videos/models/Annotation.vue +++ b/resources/assets/js/videos/models/Annotation.vue @@ -282,6 +282,16 @@ export default Vue.extend({ this.frames.splice(index, 1); this.points.splice(index, 1); + // Remove "null" elements of adjacent gaps to + // avoid multiple consecutive "null"s. + if (index === 0 && this.frames[0] === null) { + this.frames.splice(0, 1); + this.points.splice(0, 1); + } else if (this.frames[index - 1] === null) { + this.frames.splice(index - 1, 1); + this.points.splice(index - 1, 1); + } + return VideoAnnotationApi.update({id: this.id}, { frames: this.frames, points: this.points diff --git a/resources/assets/js/videos/stores/settings.js b/resources/assets/js/videos/stores/settings.js index 5a88bd2c4..589880ac3 100644 --- a/resources/assets/js/videos/stores/settings.js +++ b/resources/assets/js/videos/stores/settings.js @@ -7,6 +7,7 @@ let defaults = { showLabelTooltip: false, showMousePosition: false, showProgressIndicator: true, + showThumbnailPreview: true, }; export default new Settings({ diff --git a/resources/assets/js/videos/videoContainer.vue b/resources/assets/js/videos/videoContainer.vue index b1c905813..61479fdcc 100644 --- a/resources/assets/js/videos/videoContainer.vue +++ b/resources/assets/js/videos/videoContainer.vue @@ -68,6 +68,7 @@ export default { showMousePosition: false, playbackRate: 1.0, showProgressIndicator: true, + showThumbnailPreview: true, }, openTab: '', urlParams: { @@ -553,7 +554,11 @@ export default { .then(this.handleVideoInformationResponse) .then(this.fetchVideoContent) .catch(this.handleVideoError) - .finally(this.finishLoading); + .finally(() => { + this.finishLoading(); + // Avoid spinning wheel continuing to be displayed after moving fast through videos + this.seeking = false; + }); return promise; }, diff --git a/resources/assets/js/volumes/components/filterListComponent.vue b/resources/assets/js/volumes/components/filterListComponent.vue index eb84345a4..24ad1315c 100644 --- a/resources/assets/js/volumes/components/filterListComponent.vue +++ b/resources/assets/js/volumes/components/filterListComponent.vue @@ -3,6 +3,7 @@ without + @@ -18,6 +19,10 @@ export default { type: Object, required: true, }, + type: { + type: String, + required: true, + }, }, data() { return { @@ -25,11 +30,17 @@ export default { }; }, computed: { + fileCount() { + let typeForm = this.rule.sequence.length === 1 ? `${this.type}` : `${this.type}s`; + return `(${this.rule.sequence.length} ${typeForm})`; + }, dataName() { if (this.rule.data) { - return this.rule.data.name; + if(this.rule.data.name) { + return this.rule.data.name; + } } - + return ''; }, }, diff --git a/resources/assets/js/volumes/components/filterTab.vue b/resources/assets/js/volumes/components/filterTab.vue index 572f8bcd8..8e1d6f4cd 100644 --- a/resources/assets/js/volumes/components/filterTab.vue +++ b/resources/assets/js/volumes/components/filterTab.vue @@ -161,11 +161,22 @@ export default { return null; }, + itemsAreEqual(itemData, ruleData) { + // handle Array + if (itemData !== null && ruleData !== null) { + if (itemData instanceof Array) { + return itemData.length === ruleData.length && + itemData.every((val, index) => val === ruleData[index]); + } + } + // handle all other types (Objects, null) + return itemData === ruleData; + }, hasRule(rule) { - return this.rules.findIndex(function (item) { + return this.rules.findIndex((item) => { return item.id === rule.id && item.negate === rule.negate && - item.data === rule.data; + this.itemsAreEqual(item.data, rule.data); }) !== -1; }, addRule(data) { @@ -176,7 +187,6 @@ export default { data: data, negate: this.negate, }; - if (this.hasRule(rule)) return; this.startLoading(); diff --git a/resources/assets/sass/videos/components/_thumbnail.scss b/resources/assets/sass/videos/components/_thumbnail.scss new file mode 100644 index 000000000..22d485b7d --- /dev/null +++ b/resources/assets/sass/videos/components/_thumbnail.scss @@ -0,0 +1,12 @@ +.thumbnail-preview { + position: fixed; + top: 0; + left: 0; + z-index: 1; +} + +.thumbnail-canvas { + @extend %info-box; + padding: 0; + box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.25); +} \ No newline at end of file diff --git a/resources/assets/sass/videos/main.scss b/resources/assets/sass/videos/main.scss index 35aade99b..51c588646 100644 --- a/resources/assets/sass/videos/main.scss +++ b/resources/assets/sass/videos/main.scss @@ -53,3 +53,4 @@ @import 'components/annotationClip'; @import 'components/annotationSegment'; @import 'components/annotationKeyframe'; +@import 'components/thumbnail'; \ No newline at end of file diff --git a/resources/assets/sass/volumes/components/_volume-image-grid-image.scss b/resources/assets/sass/volumes/components/_volume-image-grid-image.scss index 34a2d430a..1cf6be64f 100644 --- a/resources/assets/sass/volumes/components/_volume-image-grid-image.scss +++ b/resources/assets/sass/volumes/components/_volume-image-grid-image.scss @@ -2,7 +2,7 @@ position: relative; &.image-grid__image--selected { - &:before { + &:after { position: absolute; content: ''; top: $padding-base-horizontal; diff --git a/resources/views/manual/tutorials/videos/sidebar.blade.php b/resources/views/manual/tutorials/videos/sidebar.blade.php index a2f628dc4..ce74e42f2 100644 --- a/resources/views/manual/tutorials/videos/sidebar.blade.php +++ b/resources/views/manual/tutorials/videos/sidebar.blade.php @@ -71,5 +71,10 @@

The mouse position switch controls the display of an additional map overlay that shows the current position of the cursor on the video in pixels.

+ +

+ The thumbnail switch controls the display of a thumbnail preview that appears when you hover your cursor over the video progress bar. The thumbnail shows a preview of the video frame at the hovered time position. +

+
@endsection diff --git a/resources/views/videos/show.blade.php b/resources/views/videos/show.blade.php index 09e3164a5..5d666ce6e 100644 --- a/resources/views/videos/show.blade.php +++ b/resources/views/videos/show.blade.php @@ -69,5 +69,13 @@ class="sidebar-container__content" biigle.$declare('videos.videoFilenames', {!! $videos->values() !!}); biigle.$declare('videos.user', {!! $user !!}); biigle.$declare('videos.isAdmin', @can('update', $volume) true @else false @endcan); + biigle.$declare('videos.fileUuids', {!! $fileIds !!}); + biigle.$declare('videos.thumbUri', '{{ $thumbUriTemplate }}'); + biigle.$declare('videos.spritesThumbnailsPerSprite', {!! $spritesThumbnailsPerSprite !!}); + biigle.$declare('videos.spritesThumbnailInterval', {!! $spritesThumbnailInterval !!}); + biigle.$declare('videos.spritesMaxThumbnails', {!! $spritesMaxThumbnails !!}); + biigle.$declare('videos.spritesMinThumbnails', {!! $spritesMinThumbnails !!}); + biigle.$declare('videos.spritesThumbnailWidth', {!! $spritesThumbnailWidth !!}); + biigle.$declare('videos.spritesThumbnailHeight', {!! $spritesThumbnailHeight !!}); @endpush diff --git a/resources/views/videos/show/content.blade.php b/resources/views/videos/show/content.blade.php index b6cf7a816..9f9f15d79 100644 --- a/resources/views/videos/show/content.blade.php +++ b/resources/views/videos/show/content.blade.php @@ -69,6 +69,7 @@ :seeking="seeking" :height-offset="timelineHeightOffset" :pending-annotation="pendingAnnotation" + :show-thumbnail-preview="settings.showThumbnailPreview" v-on:seek="seek" v-on:select="selectAnnotation" v-on:deselect="deselectAnnotation" diff --git a/resources/views/videos/show/sidebar-settings.blade.php b/resources/views/videos/show/sidebar-settings.blade.php index f77eb6e4c..dec80fe3c 100644 --- a/resources/views/videos/show/sidebar-settings.blade.php +++ b/resources/views/videos/show/sidebar-settings.blade.php @@ -35,6 +35,9 @@ Mouse Position
+ diff --git a/resources/views/volumes/show/filters.blade.php b/resources/views/volumes/show/filters.blade.php index e51978ecd..53dc68fb5 100644 --- a/resources/views/volumes/show/filters.blade.php +++ b/resources/views/volumes/show/filters.blade.php @@ -36,7 +36,7 @@
  • - +
  • No filter rules
diff --git a/tests/TestCase.php b/tests/TestCase.php index ca99c5317..dd25deb8c 100644 --- a/tests/TestCase.php +++ b/tests/TestCase.php @@ -2,7 +2,6 @@ use Biigle\Tests\CreatesApplication; use Illuminate\Foundation\Testing\RefreshDatabase; -use Illuminate\Foundation\Testing\RefreshDatabaseState; use Illuminate\Foundation\Testing\TestCase as BaseTestCase; use Illuminate\Support\Facades\Queue; use Mockery\Adapter\Phpunit\MockeryPHPUnitIntegration; @@ -10,20 +9,10 @@ class TestCase extends BaseTestCase { use CreatesApplication, MockeryPHPUnitIntegration, RefreshDatabase; - use RefreshDatabase { - refreshTestDatabase as protected originalRefreshTestDatabase; - } public static $cachedPdo; - public static $cachedVectorPdo; - protected $baseUrl = 'http://localhost'; - protected $connectionsToTransact = [ - 'pgsql', - 'pgvector', - ]; - /** * Default preparation for each test. */ @@ -54,21 +43,5 @@ protected function beforeRefreshingDatabase() } else { static::$cachedPdo = DB::getPdo(); } - - if (static::$cachedVectorPdo) { - DB::connection('pgvector')->setPdo(static::$cachedVectorPdo); - } else { - static::$cachedVectorPdo = DB::connection('pgvector')->getPdo(); - } - } - - // Custom implementation to wipe the vector database, too. - protected function refreshTestDatabase() - { - if (!RefreshDatabaseState::$migrated) { - $this->artisan('db:wipe', ['--database' => 'pgvector']); - } - - $this->originalRefreshTestDatabase(); } } diff --git a/tests/php/Http/Controllers/Api/ApiTokenControllerTest.php b/tests/php/Http/Controllers/Api/ApiTokenControllerTest.php index 5d4bc1f66..04ac07497 100644 --- a/tests/php/Http/Controllers/Api/ApiTokenControllerTest.php +++ b/tests/php/Http/Controllers/Api/ApiTokenControllerTest.php @@ -30,8 +30,8 @@ public function testIndex() public function testStoreWithToken() { $token = ApiTokenTest::create([ - // 'test_token' - 'hash' => '$2y$10$.rR7YrU9K2ZR4xgPbKs1x.AGUUKIA733CT72eC6I2piTiPY59V7.O', + // 'test_token', hashed with 4 rounds as defined in phpunit.xml + 'hash' => '$2y$04$9Ncj6qJVqenJ13VtdtV5yOca8rQyN1UwATdGpAQ80FeRjS67.Efaq', ]); $response = $this->call('POST', '/api/v1/api-tokens', [], [], [], [ 'PHP_AUTH_USER' => $token->owner->email, @@ -46,8 +46,8 @@ public function testStore() $this->doTestApiRoute('POST', '/api/v1/api-tokens'); $token = ApiTokenTest::create([ - // 'test_token' - 'hash' => '$2y$10$.rR7YrU9K2ZR4xgPbKs1x.AGUUKIA733CT72eC6I2piTiPY59V7.O', + // 'test_token', hashed with 4 rounds as defined in phpunit.xml + 'hash' => '$2y$04$9Ncj6qJVqenJ13VtdtV5yOca8rQyN1UwATdGpAQ80FeRjS67.Efaq', ]); $this->be($token->owner); diff --git a/tests/php/Http/Controllers/Api/ImageAnnotationLabelControllerTest.php b/tests/php/Http/Controllers/Api/ImageAnnotationLabelControllerTest.php index 1f40b3137..dba26c170 100644 --- a/tests/php/Http/Controllers/Api/ImageAnnotationLabelControllerTest.php +++ b/tests/php/Http/Controllers/Api/ImageAnnotationLabelControllerTest.php @@ -3,11 +3,13 @@ namespace Biigle\Tests\Http\Controllers\Api; use ApiTestCase; +use Biigle\Events\AnnotationLabelAttached; use Biigle\Tests\AnnotationSessionTest; use Biigle\Tests\ImageAnnotationLabelTest; use Biigle\Tests\ImageAnnotationTest; use Cache; use Carbon\Carbon; +use Illuminate\Support\Facades\Event; use Session; class ImageAnnotationLabelControllerTest extends ApiTestCase @@ -115,6 +117,7 @@ public function testStoreLegacy() public function store($url) { + Event::fake(); $id = $this->annotation->id; $this->doTestApiRoute('POST', "{$url}/{$id}/labels"); @@ -150,12 +153,16 @@ public function store($url) $response->assertStatus(201); $this->assertEquals(1, $this->annotation->labels()->count()); + Event::assertDispatched(AnnotationLabelAttached::class); + $this->beAdmin(); $response = $this->json('POST', "{$url}/{$id}/labels", [ 'label_id' => $this->labelRoot()->id, 'confidence' => 0.1, ]); $response->assertStatus(201); + + Event::assertDispatched(AnnotationLabelAttached::class); $this->assertEquals(2, $this->annotation->labels()->count()); $response->assertJsonFragment([ 'id' => $this->labelRoot()->id, diff --git a/tests/php/Http/Controllers/Api/UserControllerTest.php b/tests/php/Http/Controllers/Api/UserControllerTest.php index 70d10267b..642ce3de5 100644 --- a/tests/php/Http/Controllers/Api/UserControllerTest.php +++ b/tests/php/Http/Controllers/Api/UserControllerTest.php @@ -16,8 +16,8 @@ class UserControllerTest extends ApiTestCase private function callToken($verb, $route, $user) { $token = ApiTokenTest::create([ - // 'test_token' - 'hash' => '$2y$10$.rR7YrU9K2ZR4xgPbKs1x.AGUUKIA733CT72eC6I2piTiPY59V7.O', + // 'test_token', hashed with 4 rounds as defined in phpunit.xml + 'hash' => '$2y$04$9Ncj6qJVqenJ13VtdtV5yOca8rQyN1UwATdGpAQ80FeRjS67.Efaq', 'owner_id' => $user->id, ]); @@ -116,8 +116,8 @@ public function testUpdate() $response = $this->put('/api/v1/users/'.$this->guest()->id); $response->assertStatus(403); - // 'adminpassword' - $this->globalAdmin()->password = '$2y$10$O/OuPUHuswXD.6LRVUeHueY5hbiFkHVFaPLcdOd.sp3U9C8H9dcJS'; + // 'adminpassword', hashed with 4 rounds as defined in phpunit.xml + $this->globalAdmin()->password = '$2y$04$Cwx.818Z0GgxhFxF3JN4Rejpuu9M0vBChtZTRCcgSASN.xl0TmM8a'; $this->globalAdmin()->save(); $this->beGlobalAdmin(); @@ -234,8 +234,8 @@ public function testUpdate() public function testUpdateEmailCaseInsensitive() { - // 'adminpassword' - $this->globalAdmin()->password = '$2y$10$O/OuPUHuswXD.6LRVUeHueY5hbiFkHVFaPLcdOd.sp3U9C8H9dcJS'; + // 'adminpassword', hashed with 4 rounds as defined in phpunit.xml + $this->globalAdmin()->password = '$2y$04$Cwx.818Z0GgxhFxF3JN4Rejpuu9M0vBChtZTRCcgSASN.xl0TmM8a'; $this->globalAdmin()->save(); $this->beGlobalAdmin(); @@ -274,8 +274,8 @@ public function testUpdateAffiliation() public function testUpdateRole() { $user = $this->guest(); - // 'adminpassword' - $this->globalAdmin()->password = '$2y$10$O/OuPUHuswXD.6LRVUeHueY5hbiFkHVFaPLcdOd.sp3U9C8H9dcJS'; + // 'adminpassword', hashed with 4 rounds as defined in phpunit.xml + $this->globalAdmin()->password = '$2y$04$Cwx.818Z0GgxhFxF3JN4Rejpuu9M0vBChtZTRCcgSASN.xl0TmM8a'; $this->globalAdmin()->save(); $this->beGlobalAdmin(); $this @@ -308,8 +308,8 @@ public function testUpdateRole() public function testUpdateCanReview() { - // 'adminpassword' - $this->globalAdmin()->password = '$2y$10$O/OuPUHuswXD.6LRVUeHueY5hbiFkHVFaPLcdOd.sp3U9C8H9dcJS'; + // 'adminpassword', hashed with 4 rounds as defined in phpunit.xml + $this->globalAdmin()->password = '$2y$04$Cwx.818Z0GgxhFxF3JN4Rejpuu9M0vBChtZTRCcgSASN.xl0TmM8a'; $this->globalAdmin()->save(); $this->beGlobalAdmin(); @@ -344,8 +344,8 @@ public function testUpdateCanReview() public function testDowngradeRoleWithCanReview() { - // 'adminpassword' - $this->globalAdmin()->password = '$2y$10$O/OuPUHuswXD.6LRVUeHueY5hbiFkHVFaPLcdOd.sp3U9C8H9dcJS'; + // 'adminpassword', hashed with 4 rounds as defined in phpunit.xml + $this->globalAdmin()->password = '$2y$04$Cwx.818Z0GgxhFxF3JN4Rejpuu9M0vBChtZTRCcgSASN.xl0TmM8a'; $this->globalAdmin()->save(); $this->beGlobalAdmin(); $user = $this->user(); @@ -378,8 +378,8 @@ public function testUpdateOwnWithToken() public function testUpdateOwn() { - // 'guest-password' - $this->guest()->password = '$2y$10$X/s/ecsLboxkL7T/WQzI.emOeMDXIFjj2jVXEMAK1im.7IHwT0VWi'; + // 'guest-password', hashed with 4 rounds as defined in phpunit.xml + $this->guest()->password = '$2y$04$j3f9h84KswH3h30Q1CnXZuthgMt569YJdOo2NCWpS4AdLlj3emupO'; $this->guest()->save(); $this->doTestApiRoute('PUT', '/api/v1/users/my'); @@ -428,8 +428,8 @@ public function testUpdateOwn() public function testUpdateOwnEmailCaseInsensitive() { - // 'guest-password' - $this->guest()->password = '$2y$10$X/s/ecsLboxkL7T/WQzI.emOeMDXIFjj2jVXEMAK1im.7IHwT0VWi'; + // 'guest-password', hashed with 4 rounds as defined in phpunit.xml + $this->guest()->password = '$2y$04$j3f9h84KswH3h30Q1CnXZuthgMt569YJdOo2NCWpS4AdLlj3emupO'; $this->guest()->save(); $this->beGuest(); @@ -600,8 +600,8 @@ public function testDestroyWithToken() public function testDestroy() { - // 'globalAdmin-password' - $this->globalAdmin()->password = '$2y$10$44FMBIkBS2hNhI09ep6UMen7fDT4/RuQKNtDTOPRCvhQxg2H0TXIm'; + // 'globalAdmin-password', hashed with 4 rounds as defined in phpunit.xml + $this->globalAdmin()->password = '$2y$04$RQljsDh/mpnnPcYMAR622ueuqmNEvucy9vMT/nQyJ.jPnFWpErzIS'; $this->globalAdmin()->save(); $id = $this->guest()->id; @@ -664,11 +664,11 @@ public function testDestroyOwnWithToken() public function testDestroyOwn() { - // 'guest-password' - $this->guest()->password = '$2y$10$X/s/ecsLboxkL7T/WQzI.emOeMDXIFjj2jVXEMAK1im.7IHwT0VWi'; + // 'guest-password', hashed with 4 rounds as defined in phpunit.xml + $this->guest()->password = '$2y$04$j3f9h84KswH3h30Q1CnXZuthgMt569YJdOo2NCWpS4AdLlj3emupO'; $this->guest()->save(); - // 'editor-password' - $this->editor()->password = '$2y$10$2BwVwEw1AOzWx01twMmHg.FHp5N/TrK1X0KtHxRH0MN5CRrpc6k46'; + // 'editor-password', hashed with 4 rounds as defined in phpunit.xml + $this->editor()->password = '$2y$04$TwIgO65v19BE9x9osMl9zeV.FX4.ZnJ/Tm9.nd.vrozYIoKMmfWme'; $this->guest()->save(); $this->doTestApiRoute('DELETE', '/api/v1/users/my'); diff --git a/tests/php/Http/Controllers/Api/VideoAnnotationLabelControllerTest.php b/tests/php/Http/Controllers/Api/VideoAnnotationLabelControllerTest.php index 055e8f1b9..353d7e04d 100644 --- a/tests/php/Http/Controllers/Api/VideoAnnotationLabelControllerTest.php +++ b/tests/php/Http/Controllers/Api/VideoAnnotationLabelControllerTest.php @@ -3,11 +3,13 @@ namespace Biigle\Tests\Http\Controllers\Api; use ApiTestCase; +use Biigle\Events\AnnotationLabelAttached; use Biigle\MediaType; use Biigle\Tests\LabelTest; use Biigle\Tests\VideoAnnotationLabelTest; use Biigle\Tests\VideoAnnotationTest; use Biigle\Tests\VideoTest; +use Illuminate\Support\Facades\Event; class VideoAnnotationLabelControllerTest extends ApiTestCase { @@ -20,6 +22,7 @@ public function setUp(): void public function testStore() { + Event::fake(); $annotation = VideoAnnotationTest::create(['video_id' => $this->video->id]); $id = $annotation->id; @@ -51,6 +54,7 @@ public function testStore() $this->assertNotNull($label); $this->assertEquals($this->labelRoot()->id, $label->label_id); $this->assertEquals($this->editor()->id, $label->user_id); + Event::assertDispatched(AnnotationLabelAttached::class); $this ->postJson("api/v1/video-annotations/{$id}/labels", [ diff --git a/tests/php/Http/Controllers/Api/VolumeControllerTest.php b/tests/php/Http/Controllers/Api/VolumeControllerTest.php index e3c59b237..44c8cdc43 100644 --- a/tests/php/Http/Controllers/Api/VolumeControllerTest.php +++ b/tests/php/Http/Controllers/Api/VolumeControllerTest.php @@ -186,6 +186,25 @@ public function testUpdateUrl() Queue::assertPushed(ProcessNewVolumeFiles::class); } + public function testUpdateInvalidUrl() + { + $volume = $this->volume(); + + config(['volumes.admin_storage_disks' => ['admin-test']]); + $disk = Storage::fake('admin-test'); + $disk->put('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/file.txt', 'abc'); + + $this->beGlobalAdmin(); + + // invalid url (>256 characters) + $response = $this->json('PUT', '/api/v1/volumes/'.$volume->id, [ + 'url' => 'admin-test://aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', + ])->assertStatus(422); + + $this->assertEquals('The url must not be greater than 256 characters.', $response->exception->getMessage()); + Queue::assertNothingPushed(); + } + public function testUpdateUrlProviderDenylist() { $this->beAdmin(); diff --git a/tests/php/Http/Controllers/Auth/ControllerTest.php b/tests/php/Http/Controllers/Auth/ControllerTest.php index 01dc486e8..b35eaec64 100644 --- a/tests/php/Http/Controllers/Auth/ControllerTest.php +++ b/tests/php/Http/Controllers/Auth/ControllerTest.php @@ -56,8 +56,8 @@ public function testLoginSuccess() { $user = UserTest::create([ 'email' => 'test@test.com', - // 'password' - 'password' => '$2y$10$EEcVvtsqcG3cscQC9UE5.uLkWRM7IrsqPBiSPhtbslfnx9KdJtVMG', + // 'password', hashed with 4 rounds as defined in phpunit.xml + 'password' => '$2y$04$aqV2XBF34eexL9ezbQZs1eM872NWgH5MhvrmD0SC9qUbhmg9EoxJq', ]); // login_at attribute should be null after creation $this->assertNull($user->login_at); @@ -78,8 +78,8 @@ public function testLoginCaseInsensitive() { $user = UserTest::create([ 'email' => 'test@test.com', - // 'password' - 'password' => '$2y$10$EEcVvtsqcG3cscQC9UE5.uLkWRM7IrsqPBiSPhtbslfnx9KdJtVMG', + // 'password', hashed with 4 rounds as defined in phpunit.xml + 'password' => '$2y$04$aqV2XBF34eexL9ezbQZs1eM872NWgH5MhvrmD0SC9qUbhmg9EoxJq', ]); $response = $response = $this->post('/login', [ diff --git a/tests/php/Http/Middleware/VerifyCsrfTokenTest.php b/tests/php/Http/Middleware/VerifyCsrfTokenTest.php index bcff25582..22caf925d 100644 --- a/tests/php/Http/Middleware/VerifyCsrfTokenTest.php +++ b/tests/php/Http/Middleware/VerifyCsrfTokenTest.php @@ -19,8 +19,8 @@ public function setUp(): void App::bind(VerifyCsrfToken::class, VerifyCsrfTokenStub::class); $this->token = ApiTokenTest::create([ - // 'test_token' - 'hash' => '$2y$10$.rR7YrU9K2ZR4xgPbKs1x.AGUUKIA733CT72eC6I2piTiPY59V7.O', + // 'test_token', hashed with 4 rounds as defined in phpunit.xml + 'hash' => '$2y$04$9Ncj6qJVqenJ13VtdtV5yOca8rQyN1UwATdGpAQ80FeRjS67.Efaq', 'owner_id' => $this->globalAdmin()->id, ]); } diff --git a/tests/php/Jobs/CloneImagesOrVideosTest.php b/tests/php/Jobs/CloneImagesOrVideosTest.php index 8da61a120..568bdd8f0 100644 --- a/tests/php/Jobs/CloneImagesOrVideosTest.php +++ b/tests/php/Jobs/CloneImagesOrVideosTest.php @@ -5,8 +5,8 @@ use Biigle\Jobs\CloneImagesOrVideos; use Biigle\Jobs\ProcessNewVolumeFiles; use Biigle\MediaType; -use Biigle\Modules\Largo\Jobs\GenerateImageAnnotationPatch; -use Biigle\Modules\Largo\Jobs\GenerateVideoAnnotationPatch; +use Biigle\Modules\Largo\Jobs\ProcessAnnotatedImage; +use Biigle\Modules\Largo\Jobs\ProcessAnnotatedVideo; use Biigle\Tests\ImageAnnotationLabelTest; use Biigle\Tests\ImageAnnotationTest; use Biigle\Tests\ImageLabelTest; @@ -32,6 +32,9 @@ public function testCloneImageVolume() $volume = $this->volume([ 'created_at' => '2022-11-09 14:37:00', 'updated_at' => '2022-11-09 14:37:00', + 'attrs' => [ + 'creating_async' => true, + ], ])->fresh(); // Use fresh() to load even the null fields. $copy = $volume->replicate(); @@ -63,6 +66,7 @@ public function testCloneImageVolume() $this->assertNotEquals($volume->created_at, $copy->created_at); $this->assertNotEquals($volume->updated_at, $copy->updated_at); $this->assertEmpty($copy->images()->first()->labels()->get()); + $this->assertFalse($copy->creating_async); $ignore = ['id', 'created_at', 'updated_at']; $this->assertEquals( @@ -78,6 +82,9 @@ public function testCloneVideoVolume() 'created_at' => '2022-01-09 14:37:00', 'updated_at' => '2022-01-09 14:37:00', 'media_type_id' => MediaType::videoId(), + 'attrs' => [ + 'creating_async' => true, + ], ])->fresh(); // Use fresh() to load even the null fields. $copy = $volume->replicate(); $copy->save(); @@ -104,6 +111,7 @@ public function testCloneVideoVolume() $copy = $project->volumes()->first(); $this->assertEmpty($copy->videos()->first()->labels()->get()); + $this->assertFalse($copy->creating_async); } public function testCloneVolumeImages() @@ -616,13 +624,13 @@ public function testHandleVolumeImages() (new CloneImagesOrVideos($request, $copy))->handle(); Queue::assertPushed(ProcessNewVolumeFiles::class); - Queue::assertNotPushed(GenerateImageAnnotationPatch::class); + Queue::assertNotPushed(ProcessAnnotatedImage::class); } public function testHandleImageAnnotationPatches() { - if (!class_exists(GenerateImageAnnotationPatch::class)) { - $this->markTestSkipped('Requires '.GenerateImageAnnotationPatch::class); + if (!class_exists(ProcessAnnotatedImage::class)) { + $this->markTestSkipped('Requires '.ProcessAnnotatedImage::class); } // The target project. @@ -647,15 +655,15 @@ public function testHandleImageAnnotationPatches() ]); (new CloneImagesOrVideos($request, $copy))->handle(); - // One job for the creation of the annotation and one job for GenerateImageAnnotationPatch + // One job for the creation of the annotation and one job for ProcessAnnotatedImage Queue::assertPushed(ProcessNewVolumeFiles::class); - Queue::assertPushed(GenerateImageAnnotationPatch::class); + Queue::assertPushed(ProcessAnnotatedImage::class); } public function testHandleVideoAnnotationPatches() { - if (!class_exists(GenerateVideoAnnotationPatch::class)) { - $this->markTestSkipped('Requires '.GenerateVideoAnnotationPatch::class); + if (!class_exists(ProcessAnnotatedVideo::class)) { + $this->markTestSkipped('Requires '.ProcessAnnotatedVideo::class); } // The target project. @@ -680,8 +688,8 @@ public function testHandleVideoAnnotationPatches() ]); (new CloneImagesOrVideos($request, $copy))->handle(); - // One job for the creation of the annotation and one job for GenerateVideoAnnotationPatch + // One job for the creation of the annotation and one job for ProcessAnnotatedVideo Queue::assertPushed(ProcessNewVolumeFiles::class); - Queue::assertPushed(GenerateVideoAnnotationPatch::class); + Queue::assertPushed(ProcessAnnotatedVideo::class); } } diff --git a/tests/php/Jobs/ProcessNewVideoTest.php b/tests/php/Jobs/ProcessNewVideoTest.php index c7c76d957..c5dfc2627 100644 --- a/tests/php/Jobs/ProcessNewVideoTest.php +++ b/tests/php/Jobs/ProcessNewVideoTest.php @@ -36,20 +36,18 @@ public function testHandleThumbnails() public function testGenerateSprites() { Storage::fake('video-thumbs'); - config(['videos.frames_per_sprite' => 9]); $video = VideoTest::create(['filename' => 'test.mp4']); $job = new ProcessNewVideoStub($video); $job->duration = 180; $job->handle(); $this->assertEquals(180, $video->fresh()->duration); - $expected_frames = 18; - // additional frames caused by generating regular thumbnails - $additional_frames = $job->frames - $expected_frames; - $this->assertEquals($expected_frames, $job->frames - $additional_frames); - $this->assertEquals([0.0, 10.0, 20.0, 30.0, 40.0, 50.0, - 60.0, 70.0, 80.0, 90.0, 100.0, 110.0, 120.0, 130.0, - 140.0, 150.0, 160.0, 170.0], array_slice($job->times, $additional_frames, $job->frames)); + $expectedThumbnails = 72; + $expectedIntervals = range(0, 177.5, 2.5); + // additional thumbnails caused by generating regular thumbnails + $additionalThumbnails = $job->thumbnails - $expectedThumbnails; + $this->assertEquals($expectedThumbnails, $job->thumbnails - $additionalThumbnails); + $this->assertEquals($expectedIntervals, array_slice($job->times, $additionalThumbnails, $job->thumbnails)); $disk = Storage::disk('video-thumbs'); $fragment = fragment_uuid_path($video->uuid); @@ -65,11 +63,11 @@ public function testGenerateSpritesZeroDuration() $job->duration = 0; $job->handle(); - $expected_frames = 0; - // additional frames caused by generating regular thumbnails - $additional_frames = $job->frames - $expected_frames; - $this->assertEquals($expected_frames, $job->frames - $additional_frames); - $this->assertEquals([], array_slice($job->times, $additional_frames, $job->frames)); + $expectedThumbnails = 0; + // additional thumbnails caused by generating regular thumbnails + $additionalThumbnails = $job->thumbnails - $expectedThumbnails; + $this->assertEquals($expectedThumbnails, $job->thumbnails - $additionalThumbnails); + $this->assertEquals([], array_slice($job->times, $additionalThumbnails, $job->thumbnails)); $disk = Storage::disk('video-thumbs'); $fragment = fragment_uuid_path($video->uuid); @@ -85,11 +83,11 @@ public function testGenerateSpritesOneSecondDuration() $job->handle(); $this->assertEquals(1, $video->fresh()->duration); - $expected_frames = 5; - // additional frames caused by generating regular thumbnails - $additional_frames = $job->frames - $expected_frames; - $this->assertEquals($expected_frames, $job->frames - $additional_frames); - $this->assertEquals([0.0, 0.2, 0.4, 0.6, 0.8], array_slice($job->times, $additional_frames, $job->frames)); + $expectedThumbnails = 5; + // additional thumbnails caused by generating regular thumbnails + $additionalThumbnails = $job->thumbnails - $expectedThumbnails; + $this->assertEquals($expectedThumbnails, $job->thumbnails - $additionalThumbnails); + $this->assertEquals([0.0, 0.2, 0.4, 0.6, 0.8], array_slice($job->times, $additionalThumbnails, $job->thumbnails)); $disk = Storage::disk('video-thumbs'); $fragment = fragment_uuid_path($video->uuid); @@ -97,45 +95,43 @@ public function testGenerateSpritesOneSecondDuration() } - public function testGenerateSpritesExceedsMaxFrames() + public function testGenerateSpritesExceedsMaxThumbnails() { Storage::fake('video-thumbs'); - config(['videos.sprites_max_frames' => 25]); - config(['videos.sprites_interval_seconds' => 5]); + config(['videos.sprites_max_thumbnails' => 50]); $video = VideoTest::create(['filename' => 'test.mp4']); $job = new ProcessNewVideoStub($video); $job->duration = 130; $job->handle(); $this->assertEquals(130, $video->fresh()->duration); - $expected_frames = 25; + $expectedThumbnails = 50; + $expectedIntervals = array_map(fn ($value) => round($value, 2), range(0, 127.4, 2.6)); // additional frames caused by generating regular thumbnails - $additional_frames = $job->frames - $expected_frames; - $this->assertEquals($expected_frames, $job->frames - $additional_frames); - $this->assertEquals([0.0, 5.2, 10.4, 15.6, 20.8, 26.0, 31.2, 36.4, - 41.6, 46.8, 52.0, 57.2, 62.4, 67.6, 72.8, 78.0, 83.2, 88.4, - 93.6, 98.8, 104.0, 109.2, 114.4, 119.6, 124.8], array_slice($job->times, $additional_frames, $job->frames)); + $additionalThumbnails = $job->thumbnails - $expectedThumbnails; + $this->assertEquals($expectedThumbnails, $job->thumbnails - $additionalThumbnails); + $this->assertEquals($expectedIntervals, array_slice($job->times, $additionalThumbnails, $job->thumbnails)); $disk = Storage::disk('video-thumbs'); $fragment = fragment_uuid_path($video->uuid); $this->assertTrue($disk->exists("{$fragment}/sprite_0.webp")); + $this->assertTrue($disk->exists("{$fragment}/sprite_1.webp")); } - public function testGenerateSpritesFallsBelowMinFrames() + public function testGenerateSpritesFallsBelowMinThumbnails() { Storage::fake('video-thumbs'); $video = VideoTest::create(['filename' => 'test.mp4']); $job = new ProcessNewVideoStub($video); - $job->duration = 20; + $job->duration = 5; $job->handle(); - $this->assertEquals(20, $video->fresh()->duration); - $expected_frames = 5; + $this->assertEquals(5, $video->fresh()->duration); + $expectedThumbnails = 5; // additional frames caused by generating regular thumbnails - $additional_frames = $job->frames - $expected_frames; - $this->assertEquals($expected_frames, $job->frames - $additional_frames); - $this->assertEquals([0.0, 4.0, 8.0, 12.0, 16.0], array_slice($job->times, $additional_frames, $job->frames)); - + $additionalThumbnails = $job->thumbnails - $expectedThumbnails; + $this->assertEquals($expectedThumbnails, $job->thumbnails - $additionalThumbnails); + $this->assertEquals([0.0, 1.0, 2.0, 3.0, 4.0], array_slice($job->times, $additionalThumbnails, $job->thumbnails)); $disk = Storage::disk('video-thumbs'); $fragment = fragment_uuid_path($video->uuid); @@ -268,7 +264,7 @@ class ProcessNewVideoStub extends ProcessNewVideo public $duration = 0; public $codec = ''; public $times = []; - public $frames = 0; + public $thumbnails = 0; protected function getCodec($path) { @@ -283,7 +279,7 @@ protected function getVideoDuration($path) protected function generateVideoThumbnail($path, $time, $width, $height) { $this->times[] = $time; - $this->frames += 1; + $this->thumbnails += 1; return VipsImage::black(240, 138) ->embed(30, 40, 240, 138, ['extend' => Extend::WHITE]) // Extend left & top edges with white color diff --git a/tests/php/Services/Auth/ApiGuardTest.php b/tests/php/Services/Auth/ApiGuardTest.php index 6e29895b4..898331380 100644 --- a/tests/php/Services/Auth/ApiGuardTest.php +++ b/tests/php/Services/Auth/ApiGuardTest.php @@ -24,8 +24,8 @@ public function testNoCredentialsJson() public function testWrongCredentials() { $token = ApiTokenTest::create([ - // 'test_token' - 'hash' => '$2y$10$.rR7YrU9K2ZR4xgPbKs1x.AGUUKIA733CT72eC6I2piTiPY59V7.O', + // 'test_token', hashed with 4 rounds as defined in phpunit.xml + 'hash' => '$2y$04$9Ncj6qJVqenJ13VtdtV5yOca8rQyN1UwATdGpAQ80FeRjS67.Efaq', ]); $response = $this->json('GET', '/api/v1/users', [], [ 'PHP_AUTH_USER' => $token->owner->email, @@ -53,8 +53,8 @@ public function testNoToken() public function testSuccess() { $token = ApiTokenTest::create([ - // 'test_token' - 'hash' => '$2y$10$.rR7YrU9K2ZR4xgPbKs1x.AGUUKIA733CT72eC6I2piTiPY59V7.O', + // 'test_token', hashed with 4 rounds as defined in phpunit.xml + 'hash' => '$2y$04$9Ncj6qJVqenJ13VtdtV5yOca8rQyN1UwATdGpAQ80FeRjS67.Efaq', ]); $response = $this->call('GET', '/api/v1/users', [], [], [], [ 'PHP_AUTH_USER' => $token->owner->email, @@ -64,8 +64,8 @@ public function testSuccess() $token2 = ApiTokenTest::create([ 'owner_id' => $token->owner->id, - // 'test_token2' - 'hash' => '$2y$10$bqKeHzuH0hf9gIOUBnzd0ezQkVkUU12faCOu2twnBguONfx8.XhlO', + // 'test_token2', hashed with 4 rounds as defined in phpunit.xml + 'hash' => '$2y$04$YO8JZPK35rlk48cFprp8luo9lN/SPZaKeYjnhM2IpLMWpP8anC08e', ]); $response = $this->json('GET', '/api/v1/users', [], [ @@ -78,8 +78,8 @@ public function testSuccess() public function testEmailCaseInsensitive() { $token = ApiTokenTest::create([ - // 'test_token' - 'hash' => '$2y$10$.rR7YrU9K2ZR4xgPbKs1x.AGUUKIA733CT72eC6I2piTiPY59V7.O', + // 'test_token', hashed with 4 rounds as defined in phpunit.xml + 'hash' => '$2y$04$9Ncj6qJVqenJ13VtdtV5yOca8rQyN1UwATdGpAQ80FeRjS67.Efaq', ]); $token->owner->email = 'test@test.com'; @@ -95,8 +95,8 @@ public function testEmailCaseInsensitive() public function testTouchToken() { $token = ApiTokenTest::create([ - // 'test_token' - 'hash' => '$2y$10$.rR7YrU9K2ZR4xgPbKs1x.AGUUKIA733CT72eC6I2piTiPY59V7.O', + // 'test_token', hashed with 4 rounds as defined in phpunit.xml + 'hash' => '$2y$04$9Ncj6qJVqenJ13VtdtV5yOca8rQyN1UwATdGpAQ80FeRjS67.Efaq', ]); $token->updated_at = Carbon::now(-5); $token->save(); diff --git a/tests/php/VideoAnnotationTest.php b/tests/php/VideoAnnotationTest.php index 2c2aac66e..d2339cb3a 100644 --- a/tests/php/VideoAnnotationTest.php +++ b/tests/php/VideoAnnotationTest.php @@ -49,6 +49,14 @@ public function testValidatePointsFramesMismatch() $this->model->validatePoints(); } + public function testValidatePointsWithGap() + { + $this->expectNotToPerformAssertions(); + $this->model->points = [[10, 10], [], [20, 20]]; + $this->model->frames = [0.0, null, 1.0]; + $this->model->validatePoints(); + } + public function testValidatePointsPoint() { $this->model->shape_id = Shape::pointId();