diff --git a/.github/workflows/php80.yml b/.github/workflows/php80.yml deleted file mode 100644 index 7be2df5..0000000 --- a/.github/workflows/php80.yml +++ /dev/null @@ -1,41 +0,0 @@ -name: Build PHP 8.0 - -on: - push: - branches: [ master ] - pull_request: - branches: [ master ] - -jobs: - test: - runs-on: ${{ matrix.os }} - - strategy: - fail-fast: true - matrix: - os: [ ubuntu-latest ] - php: [ 8.0 ] - - name: PHP${{matrix.php}} - ${{matrix.os}} - - steps: - - name: Clone Repo - uses: actions/checkout@v4 - - - name: Setup PHP - uses: shivammathur/setup-php@v2 - with: - php-version: ${{ matrix.php }} - extensions: mysqli, mbstring, sqlsrv - tools: phpunit:8.5.13 - - - name: Install Dependencies - run: composer install --prefer-dist --no-interaction --no-dev - - - name: Execute Tests - run: phpunit --configuration tests/phpunit.xml - - - name: CodeCov - uses: codecov/codecov-action@v4 - with: - token: ${{ secrets.CODECOV_TOKEN }} diff --git a/.github/workflows/php81.yaml b/.github/workflows/php81.yaml new file mode 100644 index 0000000..fead114 --- /dev/null +++ b/.github/workflows/php81.yaml @@ -0,0 +1,26 @@ +name: Build PHP 8.1 + +on: + push: + branches: [ main ] + pull_request: + branches: [ main ] +jobs: + test: + name: Run Tests + uses: WebFiori/workflows/.github/workflows/test-php.yaml@main + with: + php-version: '8.1' + + code-coverage: + name: Coverage + needs: test + uses: WebFiori/workflows/.github/workflows/coverage-codecov.yaml@main + with: + php-version: '8.1' + coverage-file: 'php-8.1-coverage.xml' + secrets: + CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} + + + diff --git a/.github/workflows/php81.yml b/.github/workflows/php81.yml deleted file mode 100644 index 4348d47..0000000 --- a/.github/workflows/php81.yml +++ /dev/null @@ -1,41 +0,0 @@ -name: Build PHP 8.1 - -on: - push: - branches: [ master ] - pull_request: - branches: [ master ] - -jobs: - test: - runs-on: ${{ matrix.os }} - - strategy: - fail-fast: true - matrix: - os: [ ubuntu-latest ] - php: [8.1] - - name: PHP${{matrix.php}} - ${{matrix.os}} - - steps: - - name: Clone Repo - uses: actions/checkout@v4 - - - name: Setup PHP - uses: shivammathur/setup-php@v2 - with: - php-version: ${{ matrix.php }} - extensions: mysqli, mbstring, sqlsrv - tools: phpunit:9.5.20, composer - - - name: Install Dependencies - run: composer install --prefer-dist --no-interaction --no-dev - - - name: Execute Tests - run: phpunit --configuration tests/phpunit.xml - - - name: CodeCov - uses: codecov/codecov-action@v4 - with: - token: ${{ secrets.CODECOV_TOKEN }} diff --git a/.github/workflows/php82.yaml b/.github/workflows/php82.yaml new file mode 100644 index 0000000..978033a --- /dev/null +++ b/.github/workflows/php82.yaml @@ -0,0 +1,27 @@ +name: Build PHP 8.2 + +on: + push: + branches: [ main ] + pull_request: + branches: [ main ] +jobs: + test: + name: Run Tests + uses: WebFiori/workflows/.github/workflows/test-php.yaml@main + with: + php-version: '8.2' + phpunit-config: "tests/phpunit10.xml" + + code-coverage: + name: Coverage + needs: test + uses: WebFiori/workflows/.github/workflows/coverage-codecov.yaml@main + with: + php-version: '8.2' + coverage-file: 'php-8.2-coverage.xml' + secrets: + CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} + + + diff --git a/.github/workflows/php82.yml b/.github/workflows/php82.yml deleted file mode 100644 index 88753ce..0000000 --- a/.github/workflows/php82.yml +++ /dev/null @@ -1,44 +0,0 @@ -name: Build PHP 8.2 - -on: - push: - branches: [ master, dev ] - pull_request: - branches: [ master ] - -jobs: - - test: - runs-on: ${{ matrix.os }} - - strategy: - fail-fast: true - matrix: - os: [ ubuntu-latest ] - php: [8.2] - - name: PHP${{matrix.php}} - ${{matrix.os}} - - steps: - - name: Clone Repo - uses: actions/checkout@v3 - - - name: Setup PHP - uses: shivammathur/setup-php@v2 - with: - php-version: ${{ matrix.php }} - extensions: mysqli, mbstring, sqlsrv - tools: phpunit:9.5.20, composer, symplify/easy-coding-standard:12.0.6, phpbench/phpbench:1.2.14 - - - name: Install Dependencies - run: composer install --prefer-dist --no-interaction --no-dev - - - name: Execute Tests - run: phpunit --configuration tests/phpunit.xml - - - name: CodeCov - uses: codecov/codecov-action@v4 - with: - token: ${{ secrets.CODECOV_TOKEN }} - - diff --git a/.github/workflows/php83.yaml b/.github/workflows/php83.yaml new file mode 100644 index 0000000..8ecb808 --- /dev/null +++ b/.github/workflows/php83.yaml @@ -0,0 +1,45 @@ +name: Build PHP 8.3 + +on: + push: + branches: [ main, dev ] + pull_request: + branches: [ main, dev ] +env: + OPERATING_SYS: ubuntu-latest + PHP_VERSION: 8.3 +jobs: + + test: + name: Run Tests + uses: WebFiori/workflows/.github/workflows/test-php.yaml@main + with: + php-version: '8.3' + phpunit-config: 'tests/phpunit10.xml' + + + code-coverage: + name: Coverage + needs: test + uses: WebFiori/workflows/.github/workflows/coverage-codecov.yaml@main + with: + php-version: '8.3' + coverage-file: 'php-8.3-coverage.xml' + secrets: + CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} + + code-quality: + name: Code Quality + needs: test + uses: WebFiori/workflows/.github/workflows/quality-sonarcloud.yaml@main + with: + coverage-file: 'php-8.3-coverage.xml' + secrets: + SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} + + release-prod: + name: Prepare Production Release Branch / Publish Release + needs: [code-coverage, code-quality] + uses: WebFiori/workflows/.github/workflows/release-php.yaml@main + with: + branch: 'main' diff --git a/.github/workflows/php83.yml b/.github/workflows/php83.yml deleted file mode 100644 index 31ae4a6..0000000 --- a/.github/workflows/php83.yml +++ /dev/null @@ -1,65 +0,0 @@ -name: Build PHP 8.3 - -on: - push: - branches: [ master, dev ] - pull_request: - branches: [ master ] - -jobs: - - test: - runs-on: ${{ matrix.os }} - - strategy: - fail-fast: true - matrix: - os: [ ubuntu-latest ] - php: [8.3] - - name: PHP${{matrix.php}} - ${{matrix.os}} - - steps: - - name: Clone Repo - uses: actions/checkout@v4 - - - name: Setup PHP - uses: shivammathur/setup-php@v2 - with: - php-version: ${{ matrix.php }} - extensions: mysqli, mbstring, sqlsrv - tools: phpunit:9.5.20, composer, symplify/easy-coding-standard:12.0.6, phpbench/phpbench:1.2.14 - - - - - name: Install Dependencies - run: composer install --prefer-dist --no-interaction --no-dev - - - name: Execute Tests - run: phpunit --configuration tests/phpunit.xml - - - name: CodeCov - uses: codecov/codecov-action@v4 - with: - token: ${{ secrets.CODECOV_TOKEN }} - - - name: SonarCloud Code Scan - uses: sonarsource/sonarqube-scan-action@v4 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} - - - release_prod: - name: Prepare Production Release Branch / Publish Release - needs: - - "test" - runs-on: ubuntu-latest - if: github.ref == 'refs/heads/main' - steps: - - uses: actions/checkout@v4 - - uses: google-github-actions/release-please-action@v3 - with: - release-type: php - config-file: release-please-config.json - token: ${{ secrets.GITHUB_TOKEN }} \ No newline at end of file diff --git a/.github/workflows/php84.yaml b/.github/workflows/php84.yaml new file mode 100644 index 0000000..1ce3097 --- /dev/null +++ b/.github/workflows/php84.yaml @@ -0,0 +1,27 @@ +name: Build PHP 8.4 + +on: + push: + branches: [ main ] + pull_request: + branches: [ main ] +jobs: + test: + name: Run Tests + uses: WebFiori/workflows/.github/workflows/test-php.yaml@main + with: + php-version: '8.4' + phpunit-config: "tests/phpunit10.xml" + + code-coverage: + name: Coverage + needs: test + uses: WebFiori/workflows/.github/workflows/coverage-codecov.yaml@main + with: + php-version: '8.4' + coverage-file: 'php-8.4-coverage.xml' + secrets: + CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} + + + diff --git a/.github/workflows/php84.yml b/.github/workflows/php84.yml deleted file mode 100644 index deda301..0000000 --- a/.github/workflows/php84.yml +++ /dev/null @@ -1,61 +0,0 @@ -name: Build PHP 8.4 - -on: - push: - branches: [ master, dev ] - pull_request: - branches: [ master, dev ] - -jobs: - - test: - runs-on: ${{ matrix.os }} - - strategy: - fail-fast: true - matrix: - os: [ ubuntu-latest ] - php: [8.4] - - name: PHP${{matrix.php}} - ${{matrix.os}} - - steps: - - name: Clone Repo - uses: actions/checkout@v4 - - - name: Setup PHP - uses: shivammathur/setup-php@v2 - with: - php-version: ${{ matrix.php }} - extensions: mysqli, mbstring, sqlsrv - tools: phpunit:9.5.20, composer, symplify/easy-coding-standard:12.0.6, phpbench/phpbench:1.2.14 - - - - - name: Install Dependencies - run: composer install --prefer-dist --no-interaction --no-dev - - - name: Execute Tests - run: phpunit --configuration tests/phpunit.xml - - - name: CodeCov - uses: codecov/codecov-action@v4 - with: - token: ${{ secrets.CODECOV_TOKEN }} - - - release_prod: - name: Prepare Production Release Branch / Publish Release - needs: - - "test" - runs-on: ubuntu-latest - if: github.ref == 'refs/heads/master' - steps: - - uses: actions/checkout@v4 - - uses: google-github-actions/release-please-action@v3 - with: - release-type: php - config-file: release-please-config.json - token: ${{ secrets.GITHUB_TOKEN }} - - diff --git a/.gitignore b/.gitignore index b431711..4a838c8 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,4 @@ clover.xml composer.lock vendor/* .idea/* +*.Identifier diff --git a/README.md b/README.md index d9cfe96..b0ab0b6 100644 --- a/README.md +++ b/README.md @@ -4,10 +4,10 @@ Basic data structures used by WebFiori framework.

- + - + @@ -23,13 +23,287 @@ Basic data structures used by WebFiori framework. ## Supported PHP Versions | Build Status | |:---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------:| -| | -| | -| | -| | -| | +| | +| | +| | +| | ## Supported Collections * Linked List * Stack * Queue + +## Installation + +You can install the library through Composer: + +```bash +composer require webfiori/collections +``` + +## Usage + +### LinkedList + +The `LinkedList` class provides a doubly-linked list implementation with full iterator support. + +```php +add("First"); +$list->add("Second"); +$list->add("Third"); + +// Access elements by index +echo $list->get(0); // "First" +echo $list->get(1); // "Second" + +// Insert at specific position +$list->insert("Inserted", 1); // Insert at index 1 + +// Remove elements +$removed = $list->remove(0); // Remove first element +$removed = $list->removeElement("Second"); // Remove by value + +// Check if element exists +if ($list->contains("Third")) { + echo "Found Third!"; +} + +// Get element index +$index = $list->indexOf("Third"); + +// Iterate through the list +foreach ($list as $item) { + echo $item . "\n"; +} + +// Convert to array +$array = $list->toArray(); + +// Sort the list (works with strings, numbers, and Comparable objects) +$list->insertionSort(); // Ascending +$list->insertionSort(false); // Descending + +// Get list size +echo "Size: " . $list->size(); + +// Clear all elements +$list->clear(); +``` + +#### LinkedList with Size Limit + +```php +// Create a list with maximum 5 elements +$limitedList = new LinkedList(5); + +// This will return false if limit is reached +$success = $limitedList->add("Item"); +``` + +### Stack + +The `Stack` class implements a Last-In-First-Out (LIFO) data structure. + +```php +push("Bottom"); +$stack->push("Middle"); +$stack->push("Top"); + +// Peek at the top element without removing it +echo $stack->peek(); // "Top" + +// Pop elements from the stack +$top = $stack->pop(); // "Top" +$middle = $stack->pop(); // "Middle" + +// Check stack size +echo "Size: " . $stack->size(); + +// Convert to array +$array = $stack->toArray(); + +// You can also use add() method (alias for push) +$stack->add("New Top"); +``` + +#### Stack with Size Limit + +```php +// Create a stack with maximum 10 elements +$limitedStack = new Stack(10); + +// This will return false if limit is reached +$success = $limitedStack->push("Item"); +``` + +### Queue + +The `Queue` class implements a First-In-First-Out (FIFO) data structure. + +```php +enqueue("First"); +$queue->enqueue("Second"); +$queue->enqueue("Third"); + +// Peek at the front element without removing it +echo $queue->peek(); // "First" + +// Dequeue elements +$first = $queue->dequeue(); // "First" +$second = $queue->dequeue(); // "Second" + +// Check queue size +echo "Size: " . $queue->size(); + +// Convert to array +$array = $queue->toArray(); + +// You can also use add() method (alias for enqueue) +$queue->add("Fourth"); +``` + +#### Queue with Size Limit + +```php +// Create a queue with maximum 100 elements +$limitedQueue = new Queue(100); + +// This will return false if limit is reached +$success = $limitedQueue->enqueue("Item"); +``` + +## Advanced Usage + +### Custom Object Sorting + +To sort custom objects in a LinkedList, implement the `Comparable` interface: + +```php +name = $name; + $this->age = $age; + } + + public function compare($other): int { + if (!($other instanceof Person)) { + return 1; + } + + // Compare by age + if ($this->age == $other->age) { + return 0; + } + + return $this->age > $other->age ? 1 : -1; + } + + public function getName() { + return $this->name; + } + + public function getAge() { + return $this->age; + } +} + +// Usage +$list = new LinkedList(); +$list->add(new Person("Alice", 30)); +$list->add(new Person("Bob", 25)); +$list->add(new Person("Charlie", 35)); + +// Sort by age +$list->insertionSort(); // Ascending by age +``` + +### Working with References + +All collections work with references, allowing you to modify objects after adding them: + +```php +$data = ["key" => "value"]; +$list = new LinkedList(); +$list->add($data); + +// Modify the original data +$data["key"] = "modified"; + +// The list contains the modified data +$retrieved = $list->get(0); +echo $retrieved["key"]; // "modified" +``` + +## API Reference + +### Common Methods (All Collections) + +- `add(&$element): bool` - Add an element to the collection +- `size(): int` - Get the number of elements +- `toArray(): array` - Convert collection to array +- `count(): int` - Get element count (implements Countable) + +### LinkedList Specific Methods + +- `get($index): mixed` - Get element at index +- `getFirst(): mixed` - Get first element +- `getLast(): mixed` - Get last element +- `remove($index): mixed` - Remove element at index +- `removeFirst(): mixed` - Remove first element +- `removeLast(): mixed` - Remove last element +- `removeElement(&$element): mixed` - Remove specific element +- `insert(&$element, $position): bool` - Insert at position +- `indexOf($element): int` - Find element index +- `contains(&$element): bool` - Check if element exists +- `countElement(&$element): int` - Count occurrences +- `replace(&$old, &$new): bool` - Replace element +- `insertionSort($ascending = true): bool` - Sort elements +- `clear(): void` - Remove all elements +- `max(): int` - Get maximum capacity (-1 for unlimited) + +### Stack Specific Methods + +- `push($element): bool` - Add element to top +- `pop(): mixed` - Remove and return top element +- `peek(): mixed` - View top element without removing +- `max(): int` - Get maximum capacity (-1 for unlimited) + +### Queue Specific Methods + +- `enqueue($element): bool` - Add element to rear +- `dequeue(): mixed` - Remove and return front element +- `peek(): mixed` - View front element without removing +- `max(): int` - Get maximum capacity (-1 for unlimited) + + +## License + +This library is licensed under the MIT License. See the [LICENSE](LICENSE) file for details. diff --git a/webfiori/collections/AbstractCollection.php b/WebFiori/Collections/AbstractCollection.php similarity index 90% rename from webfiori/collections/AbstractCollection.php rename to WebFiori/Collections/AbstractCollection.php index 87a5057..f05612d 100644 --- a/webfiori/collections/AbstractCollection.php +++ b/WebFiori/Collections/AbstractCollection.php @@ -8,14 +8,13 @@ * https://github.com/WebFiori/.github/blob/main/LICENSE * */ -namespace webfiori\collections; +namespace WebFiori\Collections; use Countable; /** * A base class that can be used to create different collections. * * @author Ibrahim - * @version 1.0 */ abstract class AbstractCollection implements Countable { public static $NULL = null; @@ -55,18 +54,14 @@ public function __toString() { * * @return bool The method should be implemented in a way that it returns * true if the element is added and returns false otherwise. - * - * @since 1.0 */ public abstract function add(&$el); /** * Returns the number of elements in the collection. * - * This one is similar to calling the method "AbstractCollection::size()". + * This one is similar to calling the method AbstractCollection::size(). * * @return int Number of elements in the collection. - * - * @since 1.0 */ public function count() : int { return $this->size(); @@ -75,16 +70,12 @@ public function count() : int { * Returns the number of elements in the collection. * * @return int The number of elements in the collection. - * - * @since 1.0 */ public abstract function size() : int ; /** * Returns an array that contains the elements of the collection. * * @return array An array that contains the elements of the collection. - * - * @since 1.0 */ public abstract function toArray() : array; } diff --git a/webfiori/collections/Comparable.php b/WebFiori/Collections/Comparable.php similarity index 92% rename from webfiori/collections/Comparable.php rename to WebFiori/Collections/Comparable.php index 508f1e6..0bd4c8c 100644 --- a/webfiori/collections/Comparable.php +++ b/WebFiori/Collections/Comparable.php @@ -8,15 +8,13 @@ * https://github.com/WebFiori/.github/blob/main/LICENSE * */ -namespace webfiori\collections; +namespace WebFiori\Collections; /** * An interface that is used to compare objects. It is used by the class * LinkedList's sorting method in order to compare objects. * * @author Ibrahim - * - * @version 1.0 */ interface Comparable { /** @@ -31,8 +29,6 @@ interface Comparable { * with. * * @return int Negative value, 0 or positive value. - * - * @since 1.0 */ public function compare($other) : int; } diff --git a/webfiori/collections/LinkedList.php b/WebFiori/Collections/LinkedList.php similarity index 96% rename from webfiori/collections/LinkedList.php rename to WebFiori/Collections/LinkedList.php index c1c22c4..2b8c11f 100644 --- a/webfiori/collections/LinkedList.php +++ b/WebFiori/Collections/LinkedList.php @@ -9,60 +9,47 @@ * */ -namespace webfiori\collections; +namespace WebFiori\Collections; use Iterator; /** * A class that represents a linked list data structure. * * @author Ibrahim - * @version 1.4.3 */ class LinkedList extends AbstractCollection implements Iterator { /** * The first node in the list. * - * @var Node - * - * @since 1.0 + * @var Node|null */ private $head; /** * A node which is used for iterator related methods. * - * @var Node - * - * @since 1.4.3 + * @var Node|null */ private $iteratorEl; /** * The maximum number of elements the list can have. * * @var int - * - * @since 1.4.1 */ private $maxEls; /** * A null guard for the methods that return null reference. - * - * @since 1.4 */ private $null; /** * The number of elements in the node. * * @var int - * - * @since 1.0 */ private $size; /** * The last node in the list. * - * @var Node - * - * @since 1.0 + * @var Node|null */ private $tail; /** @@ -71,7 +58,6 @@ class LinkedList extends AbstractCollection implements Iterator { * @param int $max The maximum number of elements that the list can hold. * If 0 or a negative number is given, the list will be able to hold * unlimited number of elements. - * */ public function __construct($max = 0) { $this->null = null; @@ -88,11 +74,11 @@ public function __construct($max = 0) { /** * Returns the element at the specified index. * + * @param int $index The index of the element to retrieve. + * * @return mixed The element at the specified index. If the list * is empty or the given index is out of list bounds, The method will * return null. - * - * @since 1.1 */ public function &get($index) { if (gettype($index) == 'integer' && $index < $this->size() && $index > -1) { @@ -127,8 +113,6 @@ public function &get($index) { * * @return mixed The method will return The element after removal if the given element * is removed. Other than that, the method will return null. - * - * @since 1.0 */ public function &removeElement(&$val) { if ($this->size() == 1) { @@ -152,8 +136,6 @@ public function &removeElement(&$val) { * * @return mixed If the list has elements, the last element is returned. * If the list is empty, the method will return null. - * - * @since 1.0 */ public function &removeLast() { if ($this->size() == 1) { @@ -181,8 +163,6 @@ public function &removeLast() { * * @return mixed If the list has elements, the first element is returned. * If the list is empty, the method will return null. - * - * @since 1.0 */ public function &removeFirst() { if ($this->size() == 1) { @@ -213,8 +193,6 @@ public function &removeFirst() { * @param int $index The index of the element. * * @return mixed The element that was removed. null if no element is removed. - * - * @since 1.0 */ public function &remove($index) { if (gettype($index) == 'integer' && $index < $this->size() && $index > -1) { @@ -249,8 +227,6 @@ public function &remove($index) { * * @return mixed The first element that was added to the list. If the list * is empty, The method will return null. - * - * @since 1.1 */ public function &getFirst() { if ($this->size() >= 1) { @@ -265,8 +241,6 @@ public function &getFirst() { * * @return mixed The last element that was added to the list. If the list * is empty, The method will return null. - * - * @since 1.1 */ public function &getLast() { if ($this->size() == 1) { @@ -287,8 +261,6 @@ public function &getLast() { * @return bool true if the element is added. The method will return * false only if the list accepts a limited number of elements and that * number has been reached. - * - * @since 1.0 */ public function add(&$el) : bool { if ($this->validateSize()) { @@ -321,8 +293,6 @@ public function add(&$el) : bool { } /** * Removes all the elements from the list. - * - * @since 1.1 */ public function clear() { $this->head = null; @@ -339,8 +309,6 @@ public function clear() { * * @return bool true if the element is on the list. Other than that, * the method will return false. - * - * @since 1.0 */ public function contains(&$el) : bool { if ($this->size() == 0) { @@ -367,8 +335,6 @@ public function contains(&$el) : bool { * * @return int The number of times the element has appeared on the list. If * the element does not exist, 0 is returned. - * - * @since 1.0 */ public function countElement(&$el) : int { $count = 0; @@ -397,8 +363,6 @@ public function countElement(&$el) : int { * is doing. * * @return mixed The element that the iterator is currently is pointing to. - * - * @since 1.4.3 */ public function current() { if ($this->iteratorEl !== null) { @@ -418,8 +382,6 @@ public function current() { * * @return int The index of the element if found. If the list does not contain * the element or is empty, the method will return -1. - * - * @since 1.2 */ public function indexOf($el) : int { if ($this->size() == 1) { @@ -515,7 +477,7 @@ public function insert(&$el,$position) : bool { *

* * @param bool $ascending If set to true, list elements @@ -529,8 +491,6 @@ public function insert(&$el,$position) : bool { * not implement the interface Comparable or it has a mix of objects * and primitive types. Also, the method will return false if not * all elements of the same primitive type. - * - * @since 1.3 */ public function insertionSort(bool $ascending = true) : bool { $array = $this->toArray(); @@ -579,6 +539,12 @@ public function insertionSort(bool $ascending = true) : bool { return true; } + /** + * Helper method for insertion sort. + * + * @param bool $ascending Sort order. + * @param array $array Sorted array. + */ private function _insertionSortHelper($ascending, $array) { while ($this->size() != 0) { $this->remove(0); @@ -606,8 +572,6 @@ private function _insertionSortHelper($ascending, $array) { * * @return Node|null An object of type 'Node' or null if the list is empty or * the iterator is finished. - * - * @since 1.4.3 */ public function key() { return $this->iteratorEl; @@ -619,8 +583,6 @@ public function key() { * negative number, the method will return -1 which indicates * that the list can have any number of elements. Other than that, * the method will return the maximum number of elements. - * - * @since 1.4.1 */ public function max() : int { if ($this->maxEls <= 0) { @@ -639,8 +601,6 @@ public function max() : int { * * @return mixed|null The next element in the iterator. If the iterator is * finished or the list is empty, the method will return null. - * - * @since 1.4.3 */ public function next() { $this->iteratorEl = $this->iteratorEl !== null ? $this->iteratorEl->next() : null; @@ -660,8 +620,6 @@ public function next() { * * @return bool The method will return true if replaced. * if the element is not replaced, the method will return false. - * - * @since 1.2 */ public function replace(&$oldEl,&$newEl) : bool { if($this->size() == 0){ @@ -694,8 +652,6 @@ public function replace(&$oldEl,&$newEl) : bool { * This method is only used if the list is used in a 'foreach' loop. * The developer should not call it manually unless he knows what he * is doing. - * - * @since 1.4.3 */ public function rewind() { $this->iteratorEl = $this->head; @@ -704,8 +660,6 @@ public function rewind() { * Returns the number of elements in the list. * * @return int The number of elements in the list. - * - * @since 1.0 */ public function size() : int { return $this->size; @@ -714,8 +668,6 @@ public function size() : int { * Returns an array that contains the elements of the list. * * @return array An array that contains the elements of the list. - * - * @since 1.3 */ public function toArray() : array { $array = []; @@ -743,12 +695,17 @@ public function toArray() : array { * * @return bool If there is a next element, the method * will return true. False otherwise. - * - * @since 1.4.3 */ public function valid() : bool { return $this->iteratorEl !== null; } + /** + * Helper method to remove an element from the list. + * + * @param mixed $val The value to remove. + * + * @return mixed The removed element or null. + */ private function &_removeElementHelper(&$val) { $node = $this->head; $nextNode = &$this->head->next(); @@ -768,6 +725,14 @@ private function &_removeElementHelper(&$val) { return $this->null; } + /** + * Helper method to insert element in the middle of the list. + * + * @param mixed $el The element to insert. + * @param int $position The position to insert at. + * + * @return bool True if inserted successfully. + */ private function _insertMiddle(&$el,&$position) { $pointer = 1; $currentNode = $this->head; @@ -793,6 +758,12 @@ private function _insertMiddle(&$el,&$position) { return $retVal; } + /** + * Helper method to insert element at the start of the list. + * + * @param mixed $el The element to insert. + * @param bool $noTail Whether to update tail pointer. + */ private function _insertStart(&$el, $noTail = true) { $newNode = new Node($el, $this->head); $this->head = $newNode; @@ -806,8 +777,6 @@ private function _insertStart(&$el, $noTail = true) { * Reduce the size of the list. * * called after removing an element. - * - * @since 1.3 */ private function _reduceSize() { if ($this->size > 0) { @@ -818,8 +787,6 @@ private function _reduceSize() { * Checks if the list can hold more elements or not. * * @return bool true if the list can hold more elements. - * - * @since 1.4.1 */ private function validateSize() : bool { $max = $this->max(); diff --git a/webfiori/collections/Node.php b/WebFiori/Collections/Node.php similarity index 82% rename from webfiori/collections/Node.php rename to WebFiori/Collections/Node.php index 2c37c2f..8541044 100644 --- a/webfiori/collections/Node.php +++ b/WebFiori/Collections/Node.php @@ -10,7 +10,7 @@ */ -namespace webfiori\collections; +namespace WebFiori\Collections; /** * A singly linked node that can be used to construct different data structures. @@ -18,24 +18,18 @@ * It is somehow the core class of this library. * * @author Ibrahim - * - * @version 1.1 */ class Node { /** * The data that the node is holding. * * @var mixed - * - * @since 1.0 */ private $data; /** * The next node. * - * @var Node - * - * @since 1.0 + * @var Node|null */ private $next; /** @@ -45,11 +39,9 @@ class Node { * * @param mixed $data The data that the node will hold. * - * @param Node $next The next node. If null is given or the given + * @param Node|null $next The next node. If null is given or the given * value is not an instance of Node, the next node will be set to * null. - * - * @since 1.0 */ public function __construct(mixed &$data, ?Node &$next) { $this->setData($data); @@ -59,8 +51,6 @@ public function __construct(mixed &$data, ?Node &$next) { * Returns the data that is stored in the node. * * @return mixed The data that is stored in the node. - * - * @since 1.0 */ public function &data() { return $this->data; @@ -68,10 +58,8 @@ public function &data() { /** * Returns a reference to the next linked node. * - * @return null|Node If no linked node is set, null is returned. Else, + * @return Node|null If no linked node is set, null is returned. Else, * an instance of Node is returned. - * - * @since 1.0 */ public function &next() : ?Node { return $this->next; @@ -82,8 +70,6 @@ public function &next() : ?Node { * Note that the method will only accept a reference to the data. * * @param mixed $data A reference to the data that the node will hold. - * - * @since 1.0 */ public function setData(mixed &$data) { $this->data = $data; @@ -93,11 +79,9 @@ public function setData(mixed &$data) { * * Note that the method can only accept a reference to the next node. * - * @param Node $next The next node. If null is given, the next node + * @param Node|null $next The next node. If null is given, the next node * will be set to null. If the given value is not an instance of Node, * it will be not set. - * - * @since 1.0 */ public function setNext(?Node &$next) { if ($next instanceof Node) { diff --git a/webfiori/collections/Queue.php b/WebFiori/Collections/Queue.php similarity index 93% rename from webfiori/collections/Queue.php rename to WebFiori/Collections/Queue.php index 96144ce..09681a3 100644 --- a/webfiori/collections/Queue.php +++ b/WebFiori/Collections/Queue.php @@ -10,7 +10,7 @@ */ -namespace webfiori\collections; +namespace WebFiori\Collections; /** * A class that represents a queue data structure. @@ -19,14 +19,11 @@ * be the first element to come out (FIFO queue). * * @author Ibrahim - * - * @version 1.1.2 */ class Queue extends AbstractCollection { /** * The first element in the queue. - * @var Node - * @since 1.0 + * @var Node|null */ private $head; /** @@ -34,30 +31,22 @@ class Queue extends AbstractCollection { * * @var int If the value is 0 or a negative number, the maximum number of * in the queue will be unlimited. - * - * @since 1.0 */ private $max; /** * A null guard for the methods that return null reference. - * - * @since 1.1 */ private $null; /** * The number of elements in the queue. * * @var int - * - * @since 1.0 */ private $size; /** * The last queued element. * - * @var Node - * - * @since 1.0 + * @var Node|null */ private $tail; @@ -68,8 +57,6 @@ class Queue extends AbstractCollection { * if a negative number is given or 0, the queue will have unlimited number * of elements. Also, if the given value is not an integer, the maximum will be set * to unlimited. Default is 0. - * - * @since 1.0 */ public function __construct(int $max = 0) { $this->head = null; @@ -90,8 +77,6 @@ public function __construct(int $max = 0) { * * @return mixed The element at the top. If the queue is empty, the method * will return null. - * - * @since 1.0 */ public function &peek() { if ($this->size() >= 1) { @@ -105,8 +90,6 @@ public function &peek() { * * @return mixed The element after removal from the queue. If the queue is * empty, the method will return null. - * - * @since 1.0 */ public function &dequeue() { if ($this->size > 1) { @@ -136,8 +119,6 @@ public function &dequeue() { * The method will return false only in two cases, If the maximum * number of elements is reached and trying to add new one or the given element * is null. - * - * @since 1.1.2 */ public function add(&$el) : bool { return $this->enqueue($el); @@ -152,8 +133,6 @@ public function add(&$el) : bool { * The method will return false only in two cases, If the maximum * number of elements is reached and trying to add new one or the given element * is null. - * - * @since 1.0 */ public function enqueue($el) : bool { if ($this->validateSize() && $el !== null) { @@ -191,8 +170,6 @@ public function enqueue($el) : bool { * negative number, the method will return -1 which indicates * that the queue can have any number of elements. Other than that, * the method will return the maximum number of elements. - * - * @since 1.0 */ public function max() : int { if ($this->max <= 0) { @@ -205,8 +182,6 @@ public function max() : int { * Returns the number of elements in the queue. * * @return int The number of elements in the queue. - * - * @since 1.0 */ public function size() : int { return $this->size; @@ -215,8 +190,6 @@ public function size() : int { * Returns an indexed array that contains the elements of the queue. * * @return array An indexed array that contains the elements of the queue. - * - * @since 1.1.2 */ public function toArray() : array { $array = []; @@ -241,8 +214,6 @@ public function toArray() : array { * Checks if the queue can hold more elements or not. * * @return bool true if the queue can hold more elements. - * - * @since 1.0 */ private function validateSize() : bool { $maxEls = $this->max(); diff --git a/webfiori/collections/Stack.php b/WebFiori/Collections/Stack.php similarity index 94% rename from webfiori/collections/Stack.php rename to WebFiori/Collections/Stack.php index 0834caf..6535031 100644 --- a/webfiori/collections/Stack.php +++ b/WebFiori/Collections/Stack.php @@ -9,42 +9,36 @@ * */ -namespace webfiori\collections; +namespace WebFiori\Collections; /** * A class that represents a stack data structure. * * @author Ibrahim - * @version 1.1.2 */ class Stack extends AbstractCollection { /** * The bottom node of the stack. - * @var Node - * @since 1.0 + * @var Node|null */ private $head; /** * The maximum number of elements the stack can hold. * @var int - * @since 1.0 */ private $max; /** * A null guard for the methods that return null reference. - * @since 1.1 */ private $null; /** * The number of elements in the stack. - * @var Node - * @since 1.0 + * @var int */ private $size; /** * The top node of the stack. - * @var Node - * @since 1.0 + * @var Node|null */ private $tail; /** @@ -74,8 +68,6 @@ public function __construct(int $max = 0) { * * @return mixed The element at the top. If the stack is empty, the method * will return null. - * - * @since 1.0 */ public function &peek() { if ($this->size() == 1) { @@ -93,8 +85,6 @@ public function &peek() { * * @return mixed The element after removal from the stack. If the stack is * empty, the method will return null. - * - * @since 1.0 */ public function &pop() { if ($this->size() == 0) { @@ -129,8 +119,6 @@ public function &pop() { * negative number, the method will return -1 which indicates that * the stack can have infinite number of elements. Other than that, * the method will return the maximum number of elements. - * - * @since 1.0 */ public function max() : int { if ($this->max <= 0) { @@ -149,8 +137,6 @@ public function max() : int { * The method will return false only in two cases, If the maximum * number of elements is reached and trying to add new one or the given element * is null. - * - * @since 1.0 */ public function add(&$el) : bool { return $this->push($el); @@ -165,8 +151,6 @@ public function add(&$el) : bool { * The method will return false only in two cases, If the maximum * number of elements is reached and trying to add new one or the given element * is null. - * - * @since 1.0 */ public function push($el) : bool { if ($el !== null && $this->validateSize()) { @@ -198,8 +182,6 @@ public function push($el) : bool { * Returns the number of elements in the stack. * * @return int The number of elements in the stack. - * - * @since 1.0 */ public function size() : int { return $this->size; @@ -209,8 +191,6 @@ public function size() : int { * Returns an indexed array that contains the elements of the stack. * * @return array An indexed array that contains the elements of the stack. - * - * @since 1.1.2 */ public function toArray() : array { $elsArray = []; @@ -235,8 +215,6 @@ public function toArray() : array { * Checks if the stack can hold more elements or not. * * @return bool true if the stack can hold more elements. - * - * @since 1.0 */ private function validateSize() : bool { $maxSize = $this->max(); diff --git a/composer.json b/composer.json index c0a95bc..8a72f7b 100644 --- a/composer.json +++ b/composer.json @@ -4,7 +4,7 @@ "type": "library", "version": "1.1.5", "require": { - "php": ">=7.0" + "php": ">=8.1" }, "keywords": [ "library", @@ -13,13 +13,18 @@ "collections", "data structures" ], - "autoload": { - "psr-4": { - "webfiori\\collections\\": "webfiori/collections/" + "autoload" :{ + "psr-4":{ + "WebFiori\\Collections\\":"WebFiori/Collections/" } }, + "require-dev": { - "phpunit/phpunit": "^5" + "phpunit/phpunit": "^10" + }, + "scripts":{ + "test": "vendor/bin/phpunit -c tests/phpunit.xml", + "test10": "vendor/bin/phpunit -c tests/phpunit10.xml" }, "license": "MIT" } diff --git a/sonar-project.properties b/sonar-project.properties index 95952bc..9490560 100644 --- a/sonar-project.properties +++ b/sonar-project.properties @@ -4,7 +4,7 @@ sonar.organization=webfiori # This is the name and version displayed in the SonarCloud UI. sonar.projectName=collections sonar.projectVersion=1.0 -sonar.sources=webfiori/ +sonar.sources=WebFiori/ sonar.test=tests/ sonar.test.exclusions=tests/** sonar.php.coverage.reportPaths=clover.xml diff --git a/tests/AnyObject.php b/tests/AnyObject.php index 34ad0f1..7c35b02 100644 --- a/tests/AnyObject.php +++ b/tests/AnyObject.php @@ -22,9 +22,9 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -namespace webfiori\collections\tests; +namespace WebFiori\Collections\Tests; -use webfiori\collections\Comparable; +use WebFiori\Collections\Comparable; /** * An object for testing some of data structures functionality. * diff --git a/tests/data-structures/LinkedListTest.php b/tests/WebFiori/Collections/LinkedListTest.php similarity index 98% rename from tests/data-structures/LinkedListTest.php rename to tests/WebFiori/Collections/LinkedListTest.php index 96353b2..b6b102a 100644 --- a/tests/data-structures/LinkedListTest.php +++ b/tests/WebFiori/Collections/LinkedListTest.php @@ -1,9 +1,9 @@ assertEquals("webfiori\collections\LinkedList[\n]",$list.''); + $this->assertEquals("WebFiori\Collections\LinkedList[\n]",$list.''); } /** * @test @@ -1640,21 +1640,21 @@ public function testToString01() { $list = new LinkedList(); $el00 = 'EL #00'; $list->add($el00); - $this->assertEquals("webfiori\collections\LinkedList[\n [0]=>EL #00(string)\n]",$list.''); + $this->assertEquals("WebFiori\Collections\LinkedList[\n [0]=>EL #00(string)\n]",$list.''); $el01 = 55; $list->add($el01); - $this->assertEquals("webfiori\collections\LinkedList[\n [0]=>EL #00(string),\n [1]=>55(integer)\n]",$list.''); + $this->assertEquals("WebFiori\Collections\LinkedList[\n [0]=>EL #00(string),\n [1]=>55(integer)\n]",$list.''); $obj00 = new AnyObject(0, 'Obj 00'); $list->add($obj00); - $this->assertEquals("webfiori\collections\LinkedList[\n [0]=>EL #00(string),\n [1]=>55(integer),\n [2]=>(object)\n]",$list.''); + $this->assertEquals("WebFiori\Collections\LinkedList[\n [0]=>EL #00(string),\n [1]=>55(integer),\n [2]=>(object)\n]",$list.''); $list->add($obj00); - $this->assertEquals("webfiori\collections\LinkedList[\n [0]=>EL #00(string),\n [1]=>55(integer),\n [2]=>(object),\n [3]=>(object)\n]",$list.''); + $this->assertEquals("WebFiori\Collections\LinkedList[\n [0]=>EL #00(string),\n [1]=>55(integer),\n [2]=>(object),\n [3]=>(object)\n]",$list.''); $arr00 = []; $list->add($arr00); $list->remove(1); $list->removeFirst(); - //$this->assertEquals("webfiori\collections\LinkedList[\n [0]=>(object),\n [1]=>(object),\n [2]=>(array)\n]",$list.''); + //$this->assertEquals("WebFiori\Collections\LinkedList[\n [0]=>(object),\n [1]=>(object),\n [2]=>(array)\n]",$list.''); $list->add($arr00); - //$this->assertEquals("webfiori\collections\LinkedList[\n [0]=>(object),\n [1]=>(object),\n [2]=>(array),\n [3]=>(array)\n]",$list.''); + //$this->assertEquals("WebFiori\Collections\LinkedList[\n [0]=>(object),\n [1]=>(object),\n [2]=>(array),\n [3]=>(array)\n]",$list.''); } } diff --git a/tests/data-structures/NodeTest.php b/tests/WebFiori/Collections/NodeTest.php similarity index 97% rename from tests/data-structures/NodeTest.php rename to tests/WebFiori/Collections/NodeTest.php index 3ab33f7..03c08ad 100644 --- a/tests/data-structures/NodeTest.php +++ b/tests/WebFiori/Collections/NodeTest.php @@ -22,10 +22,10 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -namespace webfiori\collections\tests;; +namespace WebFiori\Collections\Tests; -use webfiori\collections\Node; -use webfiori\collections\tests\AnyObject; +use WebFiori\Collections\Node; +use WebFiori\Collections\Tests\AnyObject; use PHPUnit\Framework\TestCase; /** * A test class for the class 'Node' diff --git a/tests/data-structures/QueueTest.php b/tests/WebFiori/Collections/QueueTest.php similarity index 91% rename from tests/data-structures/QueueTest.php rename to tests/WebFiori/Collections/QueueTest.php index 4bcc956..e6e6183 100644 --- a/tests/data-structures/QueueTest.php +++ b/tests/WebFiori/Collections/QueueTest.php @@ -1,8 +1,8 @@ assertEquals("webfiori\collections\Queue[\n" + $this->assertEquals("WebFiori\Collections\Queue[\n" ."]" ."",$queue.''); $queue->enqueue('Hello'); - $this->assertEquals("webfiori\collections\Queue[\n" + $this->assertEquals("WebFiori\Collections\Queue[\n" ." [0]=>Hello(string)\n" ."]" ."",$queue.''); $queue->enqueue(new \Exception()); - $this->assertEquals("webfiori\collections\Queue[\n" + $this->assertEquals("WebFiori\Collections\Queue[\n" ." [0]=>Hello(string),\n" ." [1]=>(object)\n" ."]" ."",$queue.''); $queue->enqueue([]); - $this->assertEquals("webfiori\collections\Queue[\n" + $this->assertEquals("WebFiori\Collections\Queue[\n" ." [0]=>Hello(string),\n" ." [1]=>(object),\n" ." [2]=>(array)\n" ."]" ."",$queue.''); $queue->enqueue(88.08); - $this->assertEquals("webfiori\collections\Queue[\n" + $this->assertEquals("WebFiori\Collections\Queue[\n" ." [0]=>Hello(string),\n" ." [1]=>(object),\n" ." [2]=>(array),\n" @@ -224,7 +224,7 @@ public function testToString() { ."]" ."",$queue.''); $queue->enqueue('Another String.'); - $this->assertEquals("webfiori\collections\Queue[\n" + $this->assertEquals("WebFiori\Collections\Queue[\n" ." [0]=>Hello(string),\n" ." [1]=>(object),\n" ." [2]=>(array),\n" @@ -233,7 +233,7 @@ public function testToString() { ."]" ."",$queue.''); $queue->dequeue(); - $this->assertEquals("webfiori\collections\Queue[\n" + $this->assertEquals("WebFiori\Collections\Queue[\n" ." [0]=>(object),\n" ." [1]=>(array),\n" ." [2]=>88.08(double),\n" @@ -241,25 +241,25 @@ public function testToString() { ."]" ."",$queue.''); $queue->dequeue(); - $this->assertEquals("webfiori\collections\Queue[\n" + $this->assertEquals("WebFiori\Collections\Queue[\n" ." [0]=>(array),\n" ." [1]=>88.08(double),\n" ." [2]=>Another String.(string)\n" ."]" ."",$queue.''); $queue->dequeue(); - $this->assertEquals("webfiori\collections\Queue[\n" + $this->assertEquals("WebFiori\Collections\Queue[\n" ." [0]=>88.08(double),\n" ." [1]=>Another String.(string)\n" ."]" ."",$queue.''); $queue->dequeue(); - $this->assertEquals("webfiori\collections\Queue[\n" + $this->assertEquals("WebFiori\Collections\Queue[\n" ." [0]=>Another String.(string)\n" ."]" ."",$queue.''); $queue->dequeue(); - $this->assertEquals("webfiori\collections\Queue[\n" + $this->assertEquals("WebFiori\Collections\Queue[\n" ."]" ."",$queue.''); } diff --git a/tests/data-structures/StackTest.php b/tests/WebFiori/Collections/StackTest.php similarity index 91% rename from tests/data-structures/StackTest.php rename to tests/WebFiori/Collections/StackTest.php index ff33fdd..2d04cf6 100644 --- a/tests/data-structures/StackTest.php +++ b/tests/WebFiori/Collections/StackTest.php @@ -1,8 +1,8 @@ assertEquals("webfiori\collections\Stack[\n" + $this->assertEquals("WebFiori\Collections\Stack[\n" ."]" ."",$stack.''); $stack->push('Hello'); - $this->assertEquals("webfiori\collections\Stack[\n" + $this->assertEquals("WebFiori\Collections\Stack[\n" ." [0]=>Hello(string)\n" ."]" ."",$stack.''); $stack->push(new \Exception()); - $this->assertEquals("webfiori\collections\Stack[\n" + $this->assertEquals("WebFiori\Collections\Stack[\n" ." [0]=>Hello(string),\n" ." [1]=>(object)\n" ."]" ."",$stack.''); $stack->push([]); - $this->assertEquals("webfiori\collections\Stack[\n" + $this->assertEquals("WebFiori\Collections\Stack[\n" ." [0]=>Hello(string),\n" ." [1]=>(object),\n" ." [2]=>(array)\n" ."]" ."",$stack.''); $stack->push(88.08); - $this->assertEquals("webfiori\collections\Stack[\n" + $this->assertEquals("WebFiori\Collections\Stack[\n" ." [0]=>Hello(string),\n" ." [1]=>(object),\n" ." [2]=>(array),\n" @@ -218,7 +218,7 @@ public function testToString() { ."]" ."",$stack.''); $stack->push('Another String.'); - $this->assertEquals("webfiori\collections\Stack[\n" + $this->assertEquals("WebFiori\Collections\Stack[\n" ." [0]=>Hello(string),\n" ." [1]=>(object),\n" ." [2]=>(array),\n" @@ -227,7 +227,7 @@ public function testToString() { ."]" ."",$stack.''); $stack->pop(); - $this->assertEquals("webfiori\collections\Stack[\n" + $this->assertEquals("WebFiori\Collections\Stack[\n" ." [0]=>Hello(string),\n" ." [1]=>(object),\n" ." [2]=>(array),\n" @@ -235,25 +235,25 @@ public function testToString() { ."]" ."",$stack.''); $stack->pop(); - $this->assertEquals("webfiori\collections\Stack[\n" + $this->assertEquals("WebFiori\Collections\Stack[\n" ." [0]=>Hello(string),\n" ." [1]=>(object),\n" ." [2]=>(array)\n" ."]" ."",$stack.''); $stack->pop(); - $this->assertEquals("webfiori\collections\Stack[\n" + $this->assertEquals("WebFiori\Collections\Stack[\n" ." [0]=>Hello(string),\n" ." [1]=>(object)\n" ."]" ."",$stack.''); $stack->pop(); - $this->assertEquals("webfiori\collections\Stack[\n" + $this->assertEquals("WebFiori\Collections\Stack[\n" ." [0]=>Hello(string)\n" ."]" ."",$stack.''); $stack->pop(); - $this->assertEquals("webfiori\collections\Stack[\n" + $this->assertEquals("WebFiori\Collections\Stack[\n" ."]" ."",$stack.''); } diff --git a/tests/phpunit.xml b/tests/phpunit.xml index 4c22f50..cd2efe7 100644 --- a/tests/phpunit.xml +++ b/tests/phpunit.xml @@ -4,10 +4,10 @@ - ../webfiori/collections/LinkedList.php - ../webfiori/collections/Node.php - ../webfiori/collections/Stack.php - ../webfiori/collections/Queue.php + ../WebFiori/Collections/LinkedList.php + ../WebFiori/Collections/Node.php + ../WebFiori/Collections/Stack.php + ../WebFiori/Collections/Queue.php @@ -15,7 +15,7 @@ - ./data-structures + ./WebFiori/Collections \ No newline at end of file diff --git a/tests/phpunit10.xml b/tests/phpunit10.xml new file mode 100644 index 0000000..484bd1e --- /dev/null +++ b/tests/phpunit10.xml @@ -0,0 +1,28 @@ + + + + + + + + + ./WebFiori/Collections + + + + + + ../WebFiori/Collections + + + + + + + + + +