GitHub
Tests: 12 • Commercial: 2 • Pet projects: 4 • Legacy: 4
Total: 22

.NET Framework

Test
2021

Project Request

ASP.NET MVC • C# • SQL Server
Idea of the project: if someone wants to order a project development, here you can send an application.
Test
2020

ProjectC

ASP.NET MVC • C# • JSON • jQuery
JSON data processing.
Test
2020

Vehicle Maintenance

ASP.NET MVC • VB.NET • JSON
Idea of the project: if someone wants to order a project development, here you can send an application.
Test
2019

Movie Navigator

ASP.NET MVC • VB.NET
Request information about movie from IMDB.
Test
2018

Customers Exchange

ASP.NET MVC • C# • SQL Server
Automated teller machine emulation.
Test
2016

ATM

ASP.NET MVC • C#
Automated teller machine emulation.

.NET Core

Pet project
2022

Mail Daemon

.NET 9 • Console • JSON
Utility to send mails with customizable settings.

Custom

Code
2024

Buns of code

.NET Framework • C# • JavaScript
Code snippets from my projects, ready to use; tiny tests; code examples.

PHP

Test
2024

Mediabox

PHP 8 • Laravel 11 • Vue.js • Composer • SQLite
Test project for media files management.
Test
2020

Loan Castle

PHP • MariaDB
Jums jāizstrādā kāda lielāk projekta prototips. Izstrādājot prototipu, paturiet prātā, ka projektam attīstoties, šo prototipu varētu vajadzēt pilnveidot.
Test
2020

Content Management

PHP • MySQL • AJAX
Создать простой сайт, где будет страница с формой для авторизации и страница для авторизованного пользователя.
Test
2019

Laravel

PHP • Laravel • Vue.js • Composer • SQLite
Izveidot aplikāciju, kura ik pēc noteikta intervāla (60 sekundes) veic ierakstu datubāzē izmantojot Laravel freimworka iebūvēto funkcionalitāti.
Test
2019

Phone Check

PHP • JavaScript • JSON • Docker
Implement application to detect country by phone number.

Frontend

Test
2021

Forex Wall

npm • React
For this exercise, what we need is a simple live wall for tracking currencies.

Business projects

Commercial
2008

Certification Center

.NET Framework 4.8 • ASP.NET Web Forms • C# • LINQ • SQL Server • ADO.NET • Dapper • JavaScript • jQuery • Git
Transport registration and certification services in Latvia, Customer Relationship Management.
Commercial
2000

Amerikas Auto

.NET Framework 4.8 • ASP.NET Web Forms • C# • LINQ • SQL Server • ADO.NET • Entity Framework • JavaScript • jQuery • Git
Car service and spare parts for all USA and European car models, Customer Relationship Management.

Pet projects

Pet project
2023

Geolocation Assistant

.NET 8 • ASP.NET Core • C# • Web API • JSON • Git
Website for determining geolocation by IP or geotagged photo.
Pet project
2008

Web Dynamics

.NET Framework 4.8 • ASP.NET Web Forms • C# • LINQ • Web API • JSON • SQL Server • Dapper • JavaScript • jQuery • SVG • Git
Software development blog. Articles, books, videos, content management.
Pet project
2000

Blackball

.NET Framework 4.8 • ASP.NET Web Forms • C# • LINQ • Web API • JSON • XML • SQL Server • Dapper • JavaScript • jQuery • SVG • Git
My entertainment portal created from scratch.

Good old times

Legacy
2000

DOS Clock

Turbo Pascal • Assembler
Digital clock.
Legacy
2000

BrainOut

Turbo Pascal • Assembler
Tank battle game.
Legacy
1999

Airport Administrator

Turbo Pascal
Курсовая работа в институте.
Legacy
1998

Atomizer

Turbo Pascal • Assembler
Atomizer, aka «Studio2D». Graphic raster editor. AGI is my own «Atomizer Generated Image» file format.

Mediabox

2024 Test

Test project for media files management.

PHP 8 Laravel 11 Vue.js Composer SQLite
Information
Source code
  app
  Http
  .bin
  vite
  lib
  dist
  esm
  node
  lib
  core
  env
  node
  lib
  lib
  lib
  lib
  dist
  lib
  lib
  dist
  es
  lib
  vite
  dist
  node
  dist
  css
  js
  app
  data
  logs
  Unit
  math
  src
  src
  src
  docs
  en
  lib
  src
  src
  Cron
  src
  src
  Core
  ORM
  Spot
  filp
  src
  css
  js
  Util
  src
  src
  src
  src
  psr7
  src
  src
  Core
  Text
  Type
  Xml
  Core
  Text
  Type
  Xml
  src
  Auth
  make
  Bus
  View
  Auth
  Bus
  Http
  Mail
  View
  Auth
  Bus
  Http
  dist
  Http
  Json
  Log
  Mail
  html
  text
  Jobs
  lang
  en
  View
  pint
  pint
  src
  sail
  8.0
  8.1
  8.2
  8.3
  src
  src
  src
  src
  Node
  Util
  Node
  Node
  Node
  Data
  Node
  Node
  Util
  Xml
  src
  src
  src
  docs
  Pass
  src
  Curl
  Test
  src
  Date
  Spl
  lazy
  src
  Cli
  Lang
  List
  src
  src
  lib
  Node
  Expr
  Cast
  Name
  Stmt
  src
  src
  Html
  src
  xml
  src
  src
  src
  Data
  Node
  Html
  css
  js
  Xml
  Util
  src
  src
  src
  src
  src
  Test
  Test
  Math
  Type
  Api
  Rule
  Stub
  Api
  PHPT
  Cli
  Xml
  Util
  PHP
  Xml
  psr
  src
  src
  src
  src
  src
  docs
  src
  log
  src
  src
  psy
  src
  Hoa
  77
  78
  Sudo
  Util
  src
  src
  Map
  Tool
  uuid
  src
  Time
  Guid
  Lazy
  Math
  Dce
  Node
  Time
  Type
  src
  src
  src
  src
  src
  diff
  src
  src
  src
  src
  src
  src
  src
  src
  type
  src
  type
  src
  Test
  CI
  Node
  css
  js
  File
  Test
  Log
  Test
  Smtp
  Auth
  mime
  Part
  Test
  Test
  data
  data
  Test
  Util
  Test
  uid
  css
  js
  Test
  yaml
  Tag
  src
  src
  Css
  Rule
  src
  File
  Util
  voku
  src
  voku
  data
  src
  .env
Root / vendor / laravel / framework / src / Illuminate / Collections / LazyCollection.php
<?php namespace Illuminate\Support; use ArrayIterator; use Closure; use DateTimeInterface; use Generator; use Illuminate\Contracts\Support\CanBeEscapedWhenCastToString; use Illuminate\Support\Traits\EnumeratesValues; use Illuminate\Support\Traits\Macroable; use InvalidArgumentException; use IteratorAggregate; use stdClass; use Traversable; /** * @template TKey of array-key * * @template-covariant TValue * * @implements \Illuminate\Support\Enumerable<TKey, TValue> */ class LazyCollection implements CanBeEscapedWhenCastToString, Enumerable { /** * @use \Illuminate\Support\Traits\EnumeratesValues<TKey, TValue> */ use EnumeratesValues, Macroable; /** * The source from which to generate items. * * @var (Closure(): \Generator<TKey, TValue, mixed, void>)|static|array<TKey, TValue> */ public $source; /** * Create a new lazy collection instance. * * @param \Illuminate\Contracts\Support\Arrayable<TKey, TValue>|iterable<TKey, TValue>|(Closure(): \Generator<TKey, TValue, mixed, void>)|self<TKey, TValue>|array<TKey, TValue>|null $source * @return void */ public function __construct($source = null) { if ($source instanceof Closure || $source instanceof self) { $this->source = $source; } elseif (is_null($source)) { $this->source = static::empty(); } elseif ($source instanceof Generator) { throw new InvalidArgumentException( 'Generators should not be passed directly to LazyCollection. Instead, pass a generator function.' ); } else { $this->source = $this->getArrayableItems($source); } } /** * Create a new collection instance if the value isn't one already. * * @template TMakeKey of array-key * @template TMakeValue * * @param \Illuminate\Contracts\Support\Arrayable<TMakeKey, TMakeValue>|iterable<TMakeKey, TMakeValue>|(Closure(): \Generator<TMakeKey, TMakeValue, mixed, void>)|self<TMakeKey, TMakeValue>|array<TMakeKey, TMakeValue>|null $items * @return static<TMakeKey, TMakeValue> */ public static function make($items = []) { return new static($items); } /** * Create a collection with the given range. * * @param int $from * @param int $to * @return static<int, int> */ public static function range($from, $to) { return new static(function () use ($from, $to) { if ($from <= $to) { for (; $from <= $to; $from++) { yield $from; } } else { for (; $from >= $to; $from--) { yield $from; } } }); } /** * Get all items in the enumerable. * * @return array<TKey, TValue> */ public function all() { if (is_array($this->source)) { return $this->source; } return iterator_to_array($this->getIterator()); } /** * Eager load all items into a new lazy collection backed by an array. * * @return static */ public function eager() { return new static($this->all()); } /** * Cache values as they're enumerated. * * @return static */ public function remember() { $iterator = $this->getIterator(); $iteratorIndex = 0; $cache = []; return new static(function () use ($iterator, &$iteratorIndex, &$cache) { for ($index = 0; true; $index++) { if (array_key_exists($index, $cache)) { yield $cache[$index][0] => $cache[$index][1]; continue; } if ($iteratorIndex < $index) { $iterator->next(); $iteratorIndex++; } if (! $iterator->valid()) { break; } $cache[$index] = [$iterator->key(), $iterator->current()]; yield $cache[$index][0] => $cache[$index][1]; } }); } /** * Get the median of a given key. * * @param string|array<array-key, string>|null $key * @return float|int|null */ public function median($key = null) { return $this->collect()->median($key); } /** * Get the mode of a given key. * * @param string|array<string>|null $key * @return array<int, float|int>|null */ public function mode($key = null) { return $this->collect()->mode($key); } /** * Collapse the collection of items into a single array. * * @return static<int, mixed> */ public function collapse() { return new static(function () { foreach ($this as $values) { if (is_array($values) || $values instanceof Enumerable) { foreach ($values as $value) { yield $value; } } } }); } /** * Collapse the collection of items into a single array while preserving its keys. * * @return static<mixed, mixed> */ public function collapseWithKeys() { return new static(function () { foreach ($this as $values) { if (is_array($values) || $values instanceof Enumerable) { foreach ($values as $key => $value) { yield $key => $value; } } } }); } /** * Determine if an item exists in the enumerable. * * @param (callable(TValue, TKey): bool)|TValue|string $key * @param mixed $operator * @param mixed $value * @return bool */ public function contains($key, $operator = null, $value = null) { if (func_num_args() === 1 && $this->useAsCallable($key)) { $placeholder = new stdClass; /** @var callable $key */ return $this->first($key, $placeholder) !== $placeholder; } if (func_num_args() === 1) { $needle = $key; foreach ($this as $value) { if ($value == $needle) { return true; } } return false; } return $this->contains($this->operatorForWhere(...func_get_args())); } /** * Determine if an item exists, using strict comparison. * * @param (callable(TValue): bool)|TValue|array-key $key * @param TValue|null $value * @return bool */ public function containsStrict($key, $value = null) { if (func_num_args() === 2) { return $this->contains(fn ($item) => data_get($item, $key) === $value); } if ($this->useAsCallable($key)) { return ! is_null($this->first($key)); } foreach ($this as $item) { if ($item === $key) { return true; } } return false; } /** * Determine if an item is not contained in the enumerable. * * @param mixed $key * @param mixed $operator * @param mixed $value * @return bool */ public function doesntContain($key, $operator = null, $value = null) { return ! $this->contains(...func_get_args()); } /** * Cross join the given iterables, returning all possible permutations. * * @template TCrossJoinKey * @template TCrossJoinValue * * @param \Illuminate\Contracts\Support\Arrayable<TCrossJoinKey, TCrossJoinValue>|iterable<TCrossJoinKey, TCrossJoinValue> ...$arrays * @return static<int, array<int, TValue|TCrossJoinValue>> */ public function crossJoin(...$arrays) { return $this->passthru('crossJoin', func_get_args()); } /** * Count the number of items in the collection by a field or using a callback. * * @param (callable(TValue, TKey): array-key)|string|null $countBy * @return static<array-key, int> */ public function countBy($countBy = null) { $countBy = is_null($countBy) ? $this->identity() : $this->valueRetriever($countBy); return new static(function () use ($countBy) { $counts = []; foreach ($this as $key => $value) { $group = $countBy($value, $key); if (empty($counts[$group])) { $counts[$group] = 0; } $counts[$group]++; } yield from $counts; }); } /** * Get the items that are not present in the given items. * * @param \Illuminate\Contracts\Support\Arrayable<array-key, TValue>|iterable<array-key, TValue> $items * @return static */ public function diff($items) { return $this->passthru('diff', func_get_args()); } /** * Get the items that are not present in the given items, using the callback. * * @param \Illuminate\Contracts\Support\Arrayable<array-key, TValue>|iterable<array-key, TValue> $items * @param callable(TValue, TValue): int $callback * @return static */ public function diffUsing($items, callable $callback) { return $this->passthru('diffUsing', func_get_args()); } /** * Get the items whose keys and values are not present in the given items. * * @param \Illuminate\Contracts\Support\Arrayable<TKey, TValue>|iterable<TKey, TValue> $items * @return static */ public function diffAssoc($items) { return $this->passthru('diffAssoc', func_get_args()); } /** * Get the items whose keys and values are not present in the given items, using the callback. * * @param \Illuminate\Contracts\Support\Arrayable<TKey, TValue>|iterable<TKey, TValue> $items * @param callable(TKey, TKey): int $callback * @return static */ public function diffAssocUsing($items, callable $callback) { return $this->passthru('diffAssocUsing', func_get_args()); } /** * Get the items whose keys are not present in the given items. * * @param \Illuminate\Contracts\Support\Arrayable<TKey, TValue>|iterable<TKey, TValue> $items * @return static */ public function diffKeys($items) { return $this->passthru('diffKeys', func_get_args()); } /** * Get the items whose keys are not present in the given items, using the callback. * * @param \Illuminate\Contracts\Support\Arrayable<TKey, TValue>|iterable<TKey, TValue> $items * @param callable(TKey, TKey): int $callback * @return static */ public function diffKeysUsing($items, callable $callback) { return $this->passthru('diffKeysUsing', func_get_args()); } /** * Retrieve duplicate items. * * @param (callable(TValue): bool)|string|null $callback * @param bool $strict * @return static */ public function duplicates($callback = null, $strict = false) { return $this->passthru('duplicates', func_get_args()); } /** * Retrieve duplicate items using strict comparison. * * @param (callable(TValue): bool)|string|null $callback * @return static */ public function duplicatesStrict($callback = null) { return $this->passthru('duplicatesStrict', func_get_args()); } /** * Get all items except for those with the specified keys. * * @param \Illuminate\Support\Enumerable<array-key, TKey>|array<array-key, TKey> $keys * @return static */ public function except($keys) { return $this->passthru('except', func_get_args()); } /** * Run a filter over each of the items. * * @param (callable(TValue, TKey): bool)|null $callback * @return static */ public function filter(?callable $callback = null) { if (is_null($callback)) { $callback = fn ($value) => (bool) $value; } return new static(function () use ($callback) { foreach ($this as $key => $value) { if ($callback($value, $key)) { yield $key => $value; } } }); } /** * Get the first item from the enumerable passing the given truth test. * * @template TFirstDefault * * @param (callable(TValue): bool)|null $callback * @param TFirstDefault|(\Closure(): TFirstDefault) $default * @return TValue|TFirstDefault */ public function first(?callable $callback = null, $default = null) { $iterator = $this->getIterator(); if (is_null($callback)) { if (! $iterator->valid()) { return value($default); } return $iterator->current(); } foreach ($iterator as $key => $value) { if ($callback($value, $key)) { return $value; } } return value($default); } /** * Get a flattened list of the items in the collection. * * @param int $depth * @return static<int, mixed> */ public function flatten($depth = INF) { $instance = new static(function () use ($depth) { foreach ($this as $item) { if (! is_array($item) && ! $item instanceof Enumerable) { yield $item; } elseif ($depth === 1) { yield from $item; } else { yield from (new static($item))->flatten($depth - 1); } } }); return $instance->values(); } /** * Flip the items in the collection. * * @return static<TValue, TKey> */ public function flip() { return new static(function () { foreach ($this as $key => $value) { yield $value => $key; } }); } /** * Get an item by key. * * @template TGetDefault * * @param TKey|null $key * @param TGetDefault|(\Closure(): TGetDefault) $default * @return TValue|TGetDefault */ public function get($key, $default = null) { if (is_null($key)) { return; } foreach ($this as $outerKey => $outerValue) { if ($outerKey == $key) { return $outerValue; } } return value($default); } /** * Group an associative array by a field or using a callback. * * @param (callable(TValue, TKey): array-key)|array|string $groupBy * @param bool $preserveKeys * @return static<array-key, static<array-key, TValue>> */ public function groupBy($groupBy, $preserveKeys = false) { return $this->passthru('groupBy', func_get_args()); } /** * Key an associative array by a field or using a callback. * * @param (callable(TValue, TKey): array-key)|array|string $keyBy * @return static<array-key, TValue> */ public function keyBy($keyBy) { return new static(function () use ($keyBy) { $keyBy = $this->valueRetriever($keyBy); foreach ($this as $key => $item) { $resolvedKey = $keyBy($item, $key); if (is_object($resolvedKey)) { $resolvedKey = (string) $resolvedKey; } yield $resolvedKey => $item; } }); } /** * Determine if an item exists in the collection by key. * * @param mixed $key * @return bool */ public function has($key) { $keys = array_flip(is_array($key) ? $key : func_get_args()); $count = count($keys); foreach ($this as $key => $value) { if (array_key_exists($key, $keys) && --$count == 0) { return true; } } return false; } /** * Determine if any of the keys exist in the collection. * * @param mixed $key * @return bool */ public function hasAny($key) { $keys = array_flip(is_array($key) ? $key : func_get_args()); foreach ($this as $key => $value) { if (array_key_exists($key, $keys)) { return true; } } return false; } /** * Concatenate values of a given key as a string. * * @param callable|string $value * @param string|null $glue * @return string */ public function implode($value, $glue = null) { return $this->collect()->implode(...func_get_args()); } /** * Intersect the collection with the given items. * * @param \Illuminate\Contracts\Support\Arrayable<TKey, TValue>|iterable<TKey, TValue> $items * @return static */ public function intersect($items) { return $this->passthru('intersect', func_get_args()); } /** * Intersect the collection with the given items, using the callback. * * @param \Illuminate\Contracts\Support\Arrayable<array-key, TValue>|iterable<array-key, TValue> $items * @param callable(TValue, TValue): int $callback * @return static */ public function intersectUsing($items, callable $callback) { return $this->passthru('intersectUsing', func_get_args()); } /** * Intersect the collection with the given items with additional index check. * * @param \Illuminate\Contracts\Support\Arrayable<TKey, TValue>|iterable<TKey, TValue> $items * @return static */ public function intersectAssoc($items) { return $this->passthru('intersectAssoc', func_get_args()); } /** * Intersect the collection with the given items with additional index check, using the callback. * * @param \Illuminate\Contracts\Support\Arrayable<array-key, TValue>|iterable<array-key, TValue> $items * @param callable(TValue, TValue): int $callback * @return static */ public function intersectAssocUsing($items, callable $callback) { return $this->passthru('intersectAssocUsing', func_get_args()); } /** * Intersect the collection with the given items by key. * * @param \Illuminate\Contracts\Support\Arrayable<TKey, TValue>|iterable<TKey, TValue> $items * @return static */ public function intersectByKeys($items) { return $this->passthru('intersectByKeys', func_get_args()); } /** * Determine if the items are empty or not. * * @return bool */ public function isEmpty() { return ! $this->getIterator()->valid(); } /** * Determine if the collection contains a single item. * * @return bool */ public function containsOneItem() { return $this->take(2)->count() === 1; } /** * Join all items from the collection using a string. The final items can use a separate glue string. * * @param string $glue * @param string $finalGlue * @return string */ public function join($glue, $finalGlue = '') { return $this->collect()->join(...func_get_args()); } /** * Get the keys of the collection items. * * @return static<int, TKey> */ public function keys() { return new static(function () { foreach ($this as $key => $value) { yield $key; } }); } /** * Get the last item from the collection. * * @template TLastDefault * * @param (callable(TValue, TKey): bool)|null $callback * @param TLastDefault|(\Closure(): TLastDefault) $default * @return TValue|TLastDefault */ public function last(?callable $callback = null, $default = null) { $needle = $placeholder = new stdClass; foreach ($this as $key => $value) { if (is_null($callback) || $callback($value, $key)) { $needle = $value; } } return $needle === $placeholder ? value($default) : $needle; } /** * Get the values of a given key. * * @param string|array<array-key, string> $value * @param string|null $key * @return static<array-key, mixed> */ public function pluck($value, $key = null) { return new static(function () use ($value, $key) { [$value, $key] = $this->explodePluckParameters($value, $key); foreach ($this as $item) { $itemValue = data_get($item, $value); if (is_null($key)) { yield $itemValue; } else { $itemKey = data_get($item, $key); if (is_object($itemKey) && method_exists($itemKey, '__toString')) { $itemKey = (string) $itemKey; } yield $itemKey => $itemValue; } } }); } /** * Run a map over each of the items. * * @template TMapValue * * @param callable(TValue, TKey): TMapValue $callback * @return static<TKey, TMapValue> */ public function map(callable $callback) { return new static(function () use ($callback) { foreach ($this as $key => $value) { yield $key => $callback($value, $key); } }); } /** * Run a dictionary map over the items. * * The callback should return an associative array with a single key/value pair. * * @template TMapToDictionaryKey of array-key * @template TMapToDictionaryValue * * @param callable(TValue, TKey): array<TMapToDictionaryKey, TMapToDictionaryValue> $callback * @return static<TMapToDictionaryKey, array<int, TMapToDictionaryValue>> */ public function mapToDictionary(callable $callback) { return $this->passthru('mapToDictionary', func_get_args()); } /** * Run an associative map over each of the items. * * The callback should return an associative array with a single key/value pair. * * @template TMapWithKeysKey of array-key * @template TMapWithKeysValue * * @param callable(TValue, TKey): array<TMapWithKeysKey, TMapWithKeysValue> $callback * @return static<TMapWithKeysKey, TMapWithKeysValue> */ public function mapWithKeys(callable $callback) { return new static(function () use ($callback) { foreach ($this as $key => $value) { yield from $callback($value, $key); } }); } /** * Merge the collection with the given items. * * @param \Illuminate\Contracts\Support\Arrayable<TKey, TValue>|iterable<TKey, TValue> $items * @return static */ public function merge($items) { return $this->passthru('merge', func_get_args()); } /** * Recursively merge the collection with the given items. * * @template TMergeRecursiveValue * * @param \Illuminate\Contracts\Support\Arrayable<TKey, TMergeRecursiveValue>|iterable<TKey, TMergeRecursiveValue> $items * @return static<TKey, TValue|TMergeRecursiveValue> */ public function mergeRecursive($items) { return $this->passthru('mergeRecursive', func_get_args()); } /** * Multiply the items in the collection by the multiplier. * * @param int $multiplier * @return static */ public function multiply(int $multiplier) { return $this->passthru('multiply', func_get_args()); } /** * Create a collection by using this collection for keys and another for its values. * * @template TCombineValue * * @param \IteratorAggregate<array-key, TCombineValue>|array<array-key, TCombineValue>|(callable(): \Generator<array-key, TCombineValue>) $values * @return static<TValue, TCombineValue> */ public function combine($values) { return new static(function () use ($values) { $values = $this->makeIterator($values); $errorMessage = 'Both parameters should have an equal number of elements'; foreach ($this as $key) { if (! $values->valid()) { trigger_error($errorMessage, E_USER_WARNING); break; } yield $key => $values->current(); $values->next(); } if ($values->valid()) { trigger_error($errorMessage, E_USER_WARNING); } }); } /** * Union the collection with the given items. * * @param \Illuminate\Contracts\Support\Arrayable<TKey, TValue>|iterable<TKey, TValue> $items * @return static */ public function union($items) { return $this->passthru('union', func_get_args()); } /** * Create a new collection consisting of every n-th element. * * @param int $step * @param int $offset * @return static */ public function nth($step, $offset = 0) { return new static(function () use ($step, $offset) { $position = 0; foreach ($this->slice($offset) as $item) { if ($position % $step === 0) { yield $item; } $position++; } }); } /** * Get the items with the specified keys. * * @param \Illuminate\Support\Enumerable<array-key, TKey>|array<array-key, TKey>|string $keys * @return static */ public function only($keys) { if ($keys instanceof Enumerable) { $keys = $keys->all(); } elseif (! is_null($keys)) { $keys = is_array($keys) ? $keys : func_get_args(); } return new static(function () use ($keys) { if (is_null($keys)) { yield from $this; } else { $keys = array_flip($keys); foreach ($this as $key => $value) { if (array_key_exists($key, $keys)) { yield $key => $value; unset($keys[$key]); if (empty($keys)) { break; } } } } }); } /** * Select specific values from the items within the collection. * * @param \Illuminate\Support\Enumerable<array-key, TKey>|array<array-key, TKey>|string $keys * @return static */ public function select($keys) { if ($keys instanceof Enumerable) { $keys = $keys->all(); } elseif (! is_null($keys)) { $keys = is_array($keys) ? $keys : func_get_args(); } return new static(function () use ($keys) { if (is_null($keys)) { yield from $this; } else { foreach ($this as $item) { $result = []; foreach ($keys as $key) { if (Arr::accessible($item) && Arr::exists($item, $key)) { $result[$key] = $item[$key]; } elseif (is_object($item) && isset($item->{$key})) { $result[$key] = $item->{$key}; } } yield $result; } } }); } /** * Push all of the given items onto the collection. * * @template TConcatKey of array-key * @template TConcatValue * * @param iterable<TConcatKey, TConcatValue> $source * @return static<TKey|TConcatKey, TValue|TConcatValue> */ public function concat($source) { return (new static(function () use ($source) { yield from $this; yield from $source; }))->values(); } /** * Get one or a specified number of items randomly from the collection. * * @param int|null $number * @return static<int, TValue>|TValue * * @throws \InvalidArgumentException */ public function random($number = null) { $result = $this->collect()->random(...func_get_args()); return is_null($number) ? $result : new static($result); } /** * Replace the collection items with the given items. * * @param \Illuminate\Contracts\Support\Arrayable<TKey, TValue>|iterable<TKey, TValue> $items * @return static */ public function replace($items) { return new static(function () use ($items) { $items = $this->getArrayableItems($items); foreach ($this as $key => $value) { if (array_key_exists($key, $items)) { yield $key => $items[$key]; unset($items[$key]); } else { yield $key => $value; } } foreach ($items as $key => $value) { yield $key => $value; } }); } /** * Recursively replace the collection items with the given items. * * @param \Illuminate\Contracts\Support\Arrayable<TKey, TValue>|iterable<TKey, TValue> $items * @return static */ public function replaceRecursive($items) { return $this->passthru('replaceRecursive', func_get_args()); } /** * Reverse items order. * * @return static */ public function reverse() { return $this->passthru('reverse', func_get_args()); } /** * Search the collection for a given value and return the corresponding key if successful. * * @param TValue|(callable(TValue,TKey): bool) $value * @param bool $strict * @return TKey|false */ public function search($value, $strict = false) { /** @var (callable(TValue,TKey): bool) $predicate */ $predicate = $this->useAsCallable($value) ? $value : function ($item) use ($value, $strict) { return $strict ? $item === $value : $item == $value; }; foreach ($this as $key => $item) { if ($predicate($item, $key)) { return $key; } } return false; } /** * Get the item before the given item. * * @param TValue|(callable(TValue,TKey): bool) $value * @param bool $strict * @return TValue|null */ public function before($value, $strict = false) { $previous = null; /** @var (callable(TValue,TKey): bool) $predicate */ $predicate = $this->useAsCallable($value) ? $value : function ($item) use ($value, $strict) { return $strict ? $item === $value : $item == $value; }; foreach ($this as $key => $item) { if ($predicate($item, $key)) { return $previous; } $previous = $item; } return null; } /** * Get the item after the given item. * * @param TValue|(callable(TValue,TKey): bool) $value * @param bool $strict * @return TValue|null */ public function after($value, $strict = false) { $found = false; /** @var (callable(TValue,TKey): bool) $predicate */ $predicate = $this->useAsCallable($value) ? $value : function ($item) use ($value, $strict) { return $strict ? $item === $value : $item == $value; }; foreach ($this as $key => $item) { if ($found) { return $item; } if ($predicate($item, $key)) { $found = true; } } return null; } /** * Shuffle the items in the collection. * * @return static */ public function shuffle() { return $this->passthru('shuffle', []); } /** * Create chunks representing a "sliding window" view of the items in the collection. * * @param int $size * @param int $step * @return static<int, static> */ public function sliding($size = 2, $step = 1) { return new static(function () use ($size, $step) { $iterator = $this->getIterator(); $chunk = []; while ($iterator->valid()) { $chunk[$iterator->key()] = $iterator->current(); if (count($chunk) == $size) { yield (new static($chunk))->tap(function () use (&$chunk, $step) { $chunk = array_slice($chunk, $step, null, true); }); // If the $step between chunks is bigger than each chunk's $size // we will skip the extra items (which should never be in any // chunk) before we continue to the next chunk in the loop. if ($step > $size) { $skip = $step - $size; for ($i = 0; $i < $skip && $iterator->valid(); $i++) { $iterator->next(); } } } $iterator->next(); } }); } /** * Skip the first {$count} items. * * @param int $count * @return static */ public function skip($count) { return new static(function () use ($count) { $iterator = $this->getIterator(); while ($iterator->valid() && $count--) { $iterator->next(); } while ($iterator->valid()) { yield $iterator->key() => $iterator->current(); $iterator->next(); } }); } /** * Skip items in the collection until the given condition is met. * * @param TValue|callable(TValue,TKey): bool $value * @return static */ public function skipUntil($value) { $callback = $this->useAsCallable($value) ? $value : $this->equality($value); return $this->skipWhile($this->negate($callback)); } /** * Skip items in the collection while the given condition is met. * * @param TValue|callable(TValue,TKey): bool $value * @return static */ public function skipWhile($value) { $callback = $this->useAsCallable($value) ? $value : $this->equality($value); return new static(function () use ($callback) { $iterator = $this->getIterator(); while ($iterator->valid() && $callback($iterator->current(), $iterator->key())) { $iterator->next(); } while ($iterator->valid()) { yield $iterator->key() => $iterator->current(); $iterator->next(); } }); } /** * Get a slice of items from the enumerable. * * @param int $offset * @param int|null $length * @return static */ public function slice($offset, $length = null) { if ($offset < 0 || $length < 0) { return $this->passthru('slice', func_get_args()); } $instance = $this->skip($offset); return is_null($length) ? $instance : $instance->take($length); } /** * Split a collection into a certain number of groups. * * @param int $numberOfGroups * @return static<int, static> */ public function split($numberOfGroups) { return $this->passthru('split', func_get_args()); } /** * Get the first item in the collection, but only if exactly one item exists. Otherwise, throw an exception. * * @param (callable(TValue, TKey): bool)|string $key * @param mixed $operator * @param mixed $value * @return TValue * * @throws \Illuminate\Support\ItemNotFoundException * @throws \Illuminate\Support\MultipleItemsFoundException */ public function sole($key = null, $operator = null, $value = null) { $filter = func_num_args() > 1 ? $this->operatorForWhere(...func_get_args()) : $key; return $this ->unless($filter == null) ->filter($filter) ->take(2) ->collect() ->sole(); } /** * Get the first item in the collection but throw an exception if no matching items exist. * * @param (callable(TValue, TKey): bool)|string $key * @param mixed $operator * @param mixed $value * @return TValue * * @throws \Illuminate\Support\ItemNotFoundException */ public function firstOrFail($key = null, $operator = null, $value = null) { $filter = func_num_args() > 1 ? $this->operatorForWhere(...func_get_args()) : $key; return $this ->unless($filter == null) ->filter($filter) ->take(1) ->collect() ->firstOrFail(); } /** * Chunk the collection into chunks of the given size. * * @param int $size * @return static<int, static> */ public function chunk($size) { if ($size <= 0) { return static::empty(); } return new static(function () use ($size) { $iterator = $this->getIterator(); while ($iterator->valid()) { $chunk = []; while (true) { $chunk[$iterator->key()] = $iterator->current(); if (count($chunk) < $size) { $iterator->next(); if (! $iterator->valid()) { break; } } else { break; } } yield new static($chunk); $iterator->next(); } }); } /** * Split a collection into a certain number of groups, and fill the first groups completely. * * @param int $numberOfGroups * @return static<int, static> */ public function splitIn($numberOfGroups) { return $this->chunk((int) ceil($this->count() / $numberOfGroups)); } /** * Chunk the collection into chunks with a callback. * * @param callable(TValue, TKey, Collection<TKey, TValue>): bool $callback * @return static<int, static<int, TValue>> */ public function chunkWhile(callable $callback) { return new static(function () use ($callback) { $iterator = $this->getIterator(); $chunk = new Collection; if ($iterator->valid()) { $chunk[$iterator->key()] = $iterator->current(); $iterator->next(); } while ($iterator->valid()) { if (! $callback($iterator->current(), $iterator->key(), $chunk)) { yield new static($chunk); $chunk = new Collection; } $chunk[$iterator->key()] = $iterator->current(); $iterator->next(); } if ($chunk->isNotEmpty()) { yield new static($chunk); } }); } /** * Sort through each item with a callback. * * @param (callable(TValue, TValue): int)|null|int $callback * @return static */ public function sort($callback = null) { return $this->passthru('sort', func_get_args()); } /** * Sort items in descending order. * * @param int $options * @return static */ public function sortDesc($options = SORT_REGULAR) { return $this->passthru('sortDesc', func_get_args()); } /** * Sort the collection using the given callback. * * @param array<array-key, (callable(TValue, TValue): mixed)|(callable(TValue, TKey): mixed)|string|array{string, string}>|(callable(TValue, TKey): mixed)|string $callback * @param int $options * @param bool $descending * @return static */ public function sortBy($callback, $options = SORT_REGULAR, $descending = false) { return $this->passthru('sortBy', func_get_args()); } /** * Sort the collection in descending order using the given callback. * * @param array<array-key, (callable(TValue, TValue): mixed)|(callable(TValue, TKey): mixed)|string|array{string, string}>|(callable(TValue, TKey): mixed)|string $callback * @param int $options * @return static */ public function sortByDesc($callback, $options = SORT_REGULAR) { return $this->passthru('sortByDesc', func_get_args()); } /** * Sort the collection keys. * * @param int $options * @param bool $descending * @return static */ public function sortKeys($options = SORT_REGULAR, $descending = false) { return $this->passthru('sortKeys', func_get_args()); } /** * Sort the collection keys in descending order. * * @param int $options * @return static */ public function sortKeysDesc($options = SORT_REGULAR) { return $this->passthru('sortKeysDesc', func_get_args()); } /** * Sort the collection keys using a callback. * * @param callable(TKey, TKey): int $callback * @return static */ public function sortKeysUsing(callable $callback) { return $this->passthru('sortKeysUsing', func_get_args()); } /** * Take the first or last {$limit} items. * * @param int $limit * @return static */ public function take($limit) { if ($limit < 0) { return new static(function () use ($limit) { $limit = abs($limit); $ringBuffer = []; $position = 0; foreach ($this as $key => $value) { $ringBuffer[$position] = [$key, $value]; $position = ($position + 1) % $limit; } for ($i = 0, $end = min($limit, count($ringBuffer)); $i < $end; $i++) { $pointer = ($position + $i) % $limit; yield $ringBuffer[$pointer][0] => $ringBuffer[$pointer][1]; } }); } return new static(function () use ($limit) { $iterator = $this->getIterator(); while ($limit--) { if (! $iterator->valid()) { break; } yield $iterator->key() => $iterator->current(); if ($limit) { $iterator->next(); } } }); } /** * Take items in the collection until the given condition is met. * * @param TValue|callable(TValue,TKey): bool $value * @return static */ public function takeUntil($value) { /** @var callable(TValue, TKey): bool $callback */ $callback = $this->useAsCallable($value) ? $value : $this->equality($value); return new static(function () use ($callback) { foreach ($this as $key => $item) { if ($callback($item, $key)) { break; } yield $key => $item; } }); } /** * Take items in the collection until a given point in time. * * @param \DateTimeInterface $timeout * @return static */ public function takeUntilTimeout(DateTimeInterface $timeout) { $timeout = $timeout->getTimestamp(); return new static(function () use ($timeout) { if ($this->now() >= $timeout) { return; } foreach ($this as $key => $value) { yield $key => $value; if ($this->now() >= $timeout) { break; } } }); } /** * Take items in the collection while the given condition is met. * * @param TValue|callable(TValue,TKey): bool $value * @return static */ public function takeWhile($value) { /** @var callable(TValue, TKey): bool $callback */ $callback = $this->useAsCallable($value) ? $value : $this->equality($value); return $this->takeUntil(fn ($item, $key) => ! $callback($item, $key)); } /** * Pass each item in the collection to the given callback, lazily. * * @param callable(TValue, TKey): mixed $callback * @return static */ public function tapEach(callable $callback) { return new static(function () use ($callback) { foreach ($this as $key => $value) { $callback($value, $key); yield $key => $value; } }); } /** * Throttle the values, releasing them at most once per the given seconds. * * @return static<TKey, TValue> */ public function throttle(float $seconds) { return new static(function () use ($seconds) { $microseconds = $seconds * 1_000_000; foreach ($this as $key => $value) { $fetchedAt = $this->preciseNow(); yield $key => $value; $sleep = $microseconds - ($this->preciseNow() - $fetchedAt); $this->usleep((int) $sleep); } }); } /** * Flatten a multi-dimensional associative array with dots. * * @return static */ public function dot() { return $this->passthru('dot', []); } /** * Convert a flatten "dot" notation array into an expanded array. * * @return static */ public function undot() { return $this->passthru('undot', []); } /** * Return only unique items from the collection array. * * @param (callable(TValue, TKey): mixed)|string|null $key * @param bool $strict * @return static */ public function unique($key = null, $strict = false) { $callback = $this->valueRetriever($key); return new static(function () use ($callback, $strict) { $exists = []; foreach ($this as $key => $item) { if (! in_array($id = $callback($item, $key), $exists, $strict)) { yield $key => $item; $exists[] = $id; } } }); } /** * Reset the keys on the underlying array. * * @return static<int, TValue> */ public function values() { return new static(function () { foreach ($this as $item) { yield $item; } }); } /** * Zip the collection together with one or more arrays. * * e.g. new LazyCollection([1, 2, 3])->zip([4, 5, 6]); * => [[1, 4], [2, 5], [3, 6]] * * @template TZipValue * * @param \Illuminate\Contracts\Support\Arrayable<array-key, TZipValue>|iterable<array-key, TZipValue> ...$items * @return static<int, static<int, TValue|TZipValue>> */ public function zip($items) { $iterables = func_get_args(); return new static(function () use ($iterables) { $iterators = Collection::make($iterables)->map(function ($iterable) { return $this->makeIterator($iterable); })->prepend($this->getIterator()); while ($iterators->contains->valid()) { yield new static($iterators->map->current()); $iterators->each->next(); } }); } /** * Pad collection to the specified length with a value. * * @template TPadValue * * @param int $size * @param TPadValue $value * @return static<int, TValue|TPadValue> */ public function pad($size, $value) { if ($size < 0) { return $this->passthru('pad', func_get_args()); } return new static(function () use ($size, $value) { $yielded = 0; foreach ($this as $index => $item) { yield $index => $item; $yielded++; } while ($yielded++ < $size) { yield $value; } }); } /** * Get the values iterator. * * @return \Traversable<TKey, TValue> */ public function getIterator(): Traversable { return $this->makeIterator($this->source); } /** * Count the number of items in the collection. * * @return int */ public function count(): int { if (is_array($this->source)) { return count($this->source); } return iterator_count($this->getIterator()); } /** * Make an iterator from the given source. * * @template TIteratorKey of array-key * @template TIteratorValue * * @param \IteratorAggregate<TIteratorKey, TIteratorValue>|array<TIteratorKey, TIteratorValue>|(callable(): \Generator<TIteratorKey, TIteratorValue>) $source * @return \Traversable<TIteratorKey, TIteratorValue> */ protected function makeIterator($source) { if ($source instanceof IteratorAggregate) { return $source->getIterator(); } if (is_array($source)) { return new ArrayIterator($source); } if (is_callable($source)) { $maybeTraversable = $source(); return $maybeTraversable instanceof Traversable ? $maybeTraversable : new ArrayIterator(Arr::wrap($maybeTraversable)); } return new ArrayIterator((array) $source); } /** * Explode the "value" and "key" arguments passed to "pluck". * * @param string|string[] $value * @param string|string[]|null $key * @return array{string[],string[]|null} */ protected function explodePluckParameters($value, $key) { $value = is_string($value) ? explode('.', $value) : $value; $key = is_null($key) || is_array($key) ? $key : explode('.', $key); return [$value, $key]; } /** * Pass this lazy collection through a method on the collection class. * * @param string $method * @param array<mixed> $params * @return static */ protected function passthru($method, array $params) { return new static(function () use ($method, $params) { yield from $this->collect()->$method(...$params); }); } /** * Get the current time. * * @return int */ protected function now() { return class_exists(Carbon::class) ? Carbon::now()->timestamp : time(); } /** * Get the precise current time. * * @return float */ protected function preciseNow() { return class_exists(Carbon::class) ? Carbon::now()->getPreciseTimestamp() : microtime(true) * 1_000_000; } /** * Sleep for the given amount of microseconds. * * @return void */ protected function usleep(int $microseconds) { if ($microseconds <= 0) { return; } class_exists(Sleep::class) ? Sleep::usleep($microseconds) : usleep($microseconds); } }