Skip to content

Commit

Permalink
initial search filter implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
skie committed Sep 10, 2024
0 parents commit d6c3d0a
Show file tree
Hide file tree
Showing 80 changed files with 9,980 additions and 0 deletions.
7 changes: 7 additions & 0 deletions .github/codecov.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
codecov:
require_ci_to_pass: yes

coverage:
range: "50...100"

comment: false
121 changes: 121 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
name: CI

on:
push:

pull_request:
branches:
- '*'

jobs:
testsuite:
runs-on: ubuntu-22.04
strategy:
fail-fast: false
matrix:
php-version: ['8.1', '8.2', '8.3']
db-type: [sqlite, mysql, pgsql]
prefer-lowest: ['']

steps:
- name: Setup MySQL latest
if: matrix.db-type == 'mysql'
run: |
docker run --rm --name=mysqld -e MYSQL_ROOT_PASSWORD=root -e MYSQL_DATABASE=cakephp -p 3306:3306 -d mysql:8.2 --default-authentication-plugin=mysql_native_password --disable-log-bin
until docker exec mysqld mysqladmin ping --host=127.0.0.1 --password=root --silent; do
echo "Waiting for MySQL..."
sleep 2
done
- name: Setup PostgreSQL latest
if: matrix.db-type == 'pgsql'
run: docker run --rm --name=postgres -e POSTGRES_PASSWORD=postgres -e POSTGRES_DB=cakephp -p 5432:5432 -d postgres

- uses: actions/checkout@v2

- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php-version }}
extensions: mbstring, intl, apcu, sqlite, pdo_sqlite, pdo_${{ matrix.db-type }}, ${{ matrix.db-type }}
ini-values: apc.enable_cli = 1
coverage: pcov

- name: Get composer cache directory
id: composer-cache
run: echo "::set-output name=dir::$(composer config cache-files-dir)"

- name: Get date part for cache key
id: key-date
run: echo "::set-output name=date::$(date +'%Y-%m')"

- name: Cache composer dependencies
uses: actions/cache@v1
with:
path: ${{ steps.composer-cache.outputs.dir }}
key: ${{ runner.os }}-composer-${{ steps.key-date.outputs.date }}-${{ hashFiles('composer.json') }}-${{ matrix.prefer-lowest }}

- name: composer install
run: |
if ${{ matrix.prefer-lowest == 'prefer-lowest' }}; then
composer update --prefer-lowest --prefer-stable
else
composer update
fi
- name: Setup problem matchers for PHPUnit
if: matrix.php-version == '8.1' && matrix.db-type == 'mysql'
run: echo "::add-matcher::${{ runner.tool_cache }}/phpunit.json"

- name: Run PHPUnit
run: |
if [[ ${{ matrix.db-type }} == 'sqlite' ]]; then export DB_URL='sqlite:///:memory:'; fi
if [[ ${{ matrix.db-type }} == 'mysql' ]]; then export DB_URL='mysql://root:[email protected]/cakephp?encoding=utf8'; fi
if [[ ${{ matrix.db-type }} == 'pgsql' ]]; then export DB_URL='postgres://postgres:[email protected]/postgres'; fi
if [[ ${{ matrix.php-version }} == '8.1' ]]; then
export CODECOVERAGE=1 && vendor/bin/phpunit --verbose --coverage-clover=coverage.xml
else
vendor/bin/phpunit
fi
- name: Submit code coverage
if: matrix.php-version == '8.1'
uses: codecov/codecov-action@v1

cs-stan:
name: Coding Standard & Static Analysis
runs-on: ubuntu-22.04

steps:
- uses: actions/checkout@v2

- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: '8.1'
extensions: mbstring, intl, apcu
coverage: none

- name: Get composer cache directory
id: composer-cache
run: echo "::set-output name=dir::$(composer config cache-files-dir)"

- name: Get date part for cache key
id: key-date
run: echo "::set-output name=date::$(date +'%Y-%m')"

- name: Cache composer dependencies
uses: actions/cache@v1
with:
path: ${{ steps.composer-cache.outputs.dir }}
key: ${{ runner.os }}-composer-${{ steps.key-date.outputs.date }}-${{ hashFiles('composer.json') }}-${{ matrix.prefer-lowest }}

- name: composer install
run: composer stan-setup

- name: Run PHP CodeSniffer
run: composer cs-check

- name: Run phpstan
if: success() || failure()
run: composer stan
10 changes: 10 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
/composer.lock
/composer.phar
/phpunit.xml
/.phpunit.result.cache
/phpunit.phar
/config/Migrations/schema-dump-default.lock
/vendor/
/.idea/
/.vscode/
/tmp
26 changes: 26 additions & 0 deletions LICENSE.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
The MIT License

Copyright 2009-2018
Cake Development Corporation
1785 E. Sahara Avenue, Suite 490-423
Las Vegas, Nevada 89104
Phone: +1 702 425 5085
https://www.cakedc.com

Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
159 changes: 159 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
CakeDC SearchFilter Plugin for CakePHP
===================

[![Build Status](https://img.shields.io/github/actions/workflow/status/CakeDC/search-filter/ci.yml?branch=main&style=flat-square)](https://github.com/CakeDC/search-filter/actions?query=workflow%3ACI+branch%3Amain)
[![Coverage Status](https://img.shields.io/codecov/c/gh/CakeDC/search-filter.svg?style=flat-square)](https://codecov.io/gh/CakeDC/search-filter)
[![Downloads](https://poser.pugx.org/CakeDC/search-filter/d/total.png)](https://packagist.org/packages/CakeDC/search-filter)
[![License](https://poser.pugx.org/CakeDC/search-filter/license.svg)](https://packagist.org/packages/CakeDC/search-filter)

## Overview

The SearchFilter plugin is a powerful and flexible solution for implementing advanced search functionality in CakePHP applications. It provides a robust set of tools for creating dynamic, user-friendly search interfaces with minimal effort.

## Features

- Dynamic filter generation based on database schema
- Support for various filter types: string, numeric, date, datetime, boolean, and lookup (autocomplete)
- Customizable filter conditions (equals, not equals, greater than, less than, between, etc.)
- Vue.js based frontend for an interactive user experience
- AJAX-powered autocomplete functionality for lookup filters
- Easy integration with CakePHP's ORM for efficient query building
- Extensible architecture allowing for custom filter types and conditions

## Installation

You can install this plugin into your CakePHP application using [composer](https://getcomposer.org):

```
composer require cakedc/search-filter
```

Then, add the following line to your application's `src/Application.php` file:

```php
$this->addPlugin('CakeDC.SearchFilter');
```

## Configuration

* [Criteria List](docs/Criteria.md)
* [Filters List](docs/Filters.md)

## Basic Usage

### Controller

In your controller, you can set up the search functionality like this:

```php
use CakeDC\SearchFilter\Manager;

class PostsController extends AppController
{
public function index()
{
$query = $this->Posts->find();

$manager = new Manager($this->request);
$collection = $manager->newCollection();

// Add a general search filter
$collection->add('search', $manager->filters()
->getNew('string')
->setConditions(new \stdClass())
->setLabel('Search...')
);

// Add a complex name filter that searches across multiple fields
$collection->add('name', $manager->filters()
->getNew('string')
->setLabel('Name')
->setCriterion(
new OrCriterion([
$manager->buildCriterion('title', 'string', $this->Posts),
$manager->buildCriterion('body', 'string', $this->Posts),
$manager->buildCriterion('author', 'string', $this->Posts),
])
)
);

// Add a datetime filter for the 'created' field
$collection->add('created', $manager->filters()
->getNew('datetime')
->setLabel('Created')
->setCriterion($manager->buildCriterion('created', 'datetime', $this->Posts))
);

// Automatically add filters based on the table schema
$manager->appendFromSchema($collection, $this->Posts);

// Get the view configuration for the filters
$viewFields = $collection->getViewConfig();
$this->set('viewFields', $viewFields);

// Apply filters if search parameters are present in the request
if (!empty($this->getRequest()->getQuery()) && !empty($this->getRequest()->getQuery('f'))) {
$search = $manager->formatSearchData();
$this->set('values', $search);

// Add a custom 'multiple' filter using the CriteriaFilter
$this->Posts->addFilter('multiple', [
'className' => 'CakeDC/SearchFilter.Criteria',
'criteria' => $collection->getCriteria(),
]);

$filters = $manager->formatFinders($search);
$query = $query->find('filters', $filters);
}

// Paginate the results
$posts = $this->paginate($this->Filter->prg($query));
$this->set(compact('posts'));
}
}
```

This example demonstrates several key features of the SearchFilter plugin:

1. Creating a new `Manager` instance and filter collection.
2. Adding a general search filter that can be used for quick searches.
3. Creating a complex filter that searches across multiple fields using `OrCriterion`.
4. Adding a datetime filter for a specific field.
5. Automatically generating filters based on the table schema.
6. Applying filters when search parameters are present in the request.
7. Using the `CriteriaFilter` for handling multiple filter criteria.

### View

In your view, you can render the search component inside search form like this:

```php
<?= $this->element('CakeDC/SearchFilter.Search/v_search'); ?>
```

```html
<script>
window._search.createMyApp(window._search.rootElemId)
</script>
```

## Advanced Usage

### Custom Filter Types

[Custom Range Filter implementation and integration](docs/CustomFilter.md)

## Frontend Customization

The plugin uses Vue.js for the frontend. You can customize the look and feel by overriding the templates in your application:

1. Copy the `templates/element/Search/v_templates.php` file from the plugin to your application's `templates/element/Search/` directory.
2. Modify the templates as needed.

## Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

## License

This plugin is licensed under the [MIT License](LICENSE).
55 changes: 55 additions & 0 deletions composer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
{
"name": "cakedc/search-filter",
"description": "SearchFilter plugin for CakePHP",
"type": "cakephp-plugin",
"license": "MIT",
"require": {
"php": ">=8.1",
"cakephp/cakephp": "^4.4",
"skie/cakephp-search": "^4.0"
},
"require-dev": {
"cakephp/cakephp-codesniffer": "^4.0",
"slevomat/coding-standard": "^8.0",
"phpunit/phpunit": "^9.5"
},
"scripts": {
"fixcode": [
"bin/cake code_completion generate || echo 'FAILED'",
"bin/cake phpstorm generate || echo 'FAILED'",
"bin/cake annotate all || echo 'FAILED'",
"phpcbf --standard=vendor/cakephp/cakephp-codesniffer/CakePHP src/ tests/ || echo 'FAILED'"
],
"check": [
"@cs-check",
"@stan",
"@psalm",
"@test"
],
"test": "phpunit --stderr",
"coverage-test": "phpunit --stderr --coverage-clover=clover.xml",
"stan": "phpstan.phar analyse --memory-limit=-1 src/",
"stan-setup": "cp composer.json composer.backup && composer require --dev phpstan/phpstan:0.12.94 psalm/phar:~4.9.2 && mv composer.backup composer.json",
"psalm": "psalm.phar --show-info=false",
"stan-rebuild-baseline": "phpstan.phar analyse ./src/ --generate-baseline",
"cs-check": "phpcs -n -p ./src ./tests",
"cs-fix": "phpcbf -n -p ./src ./tests "
},
"autoload": {
"psr-4": {
"CakeDC\\SearchFilter\\": "src/"
}
},
"autoload-dev": {
"psr-4": {
"CakeDC\\SearchFilter\\Test\\": "tests/",
"Cake\\Test\\": "vendor/cakephp/cakephp/tests/"
}
},
"config": {
"allow-plugins": {
"dealerdirect/phpcodesniffer-composer-installer": false,
"cakephp/plugin-installer": true
}
}
}
Loading

0 comments on commit d6c3d0a

Please sign in to comment.