Code Monkey home page Code Monkey logo

aura.filter's Introduction

Aura.Filter

This package provides tools to validate and sanitize objects and arrays.

Foreword

Installation

This library requires PHP 7.2 or later; we recommend using the latest available version of PHP as a matter of principle. It has no userland dependencies.

It is installable and autoloadable via Composer as aura/filter.

Alternatively, download a release or clone this repository, then require or include its autoload.php file.

Quality

Scrutinizer Code Quality codecov Continuous Integration

To run the unit tests at the command line, issue composer install and then vendor/bin/phpunit at the package root. This requires Composer to be available as composer.

This library attempts to comply with PSR-1, PSR-2, and PSR-4. If you notice compliance oversights, please send a patch via pull request.

Community

To ask questions, provide feedback, or otherwise communicate with the Aura community, please join our Google Group, follow @auraphp on Twitter, or chat with us on #auraphp on Freenode.

Documentation

This package is fully documented here.

aura.filter's People

Contributors

auroraeosrose avatar chrissound avatar cordoval avatar designermonkey avatar dg avatar dhaaker avatar dperjar avatar geissler avatar harikt avatar jakejohns avatar koriym avatar mivanov93 avatar pborreli avatar rayne avatar taiiiraaa avatar thomaswunderlich avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

aura.filter's Issues

Notice: Undefined index: in addMessages

Even we have the field the addMessages throws notices

email in vendor/aura/filter/src/Aura/Filter/RuleCollection.php on line 460

if (! $this->messages[$field]) {
    $this->messages[$field] = [];
}

Good to check isset($this->messages[$field])

Filter should use exceptions

Validating code ends up requiring lots of if statements. Filter should be callable without worrying about its response, with exceptions throw to halt execution, when necessary.

for example:
Boilerplate:

$this->filter(...);
$data = ['foo' => 'bar'];

Before:

$success = $filter->values($data);
if (! $success) {
    $messages = $filter->getMessages();
    // do something with $messages;
}

After:

// exceptions can be caught anywhere in the stack
$filter->values($data);

Discuss here the bugfix about the missing properties

Quoting the new function from my commit(waiting for merge)

protected function applyRule($subject)
{
        $added = false;
        $rule = $this->locator->get($this->rule);
        $args = $this->args;
        array_unshift($args, $this->field);
        array_unshift($args, $subject);
        if(!isset($subject->{$this->field}) && !property_exists($subject,$this->field))
        {
                 $subject->{$this->field} = null;
                 $added = true;
        }

        $result = call_user_func_array($rule, $args);
        if($added && property_exists($subject,$this->field) && $subject->{$this->field} === null) {
            unset($subject->{$this->field});
        }
        return $result;
    }

Cons: it will fail if you depend on it for add for example null to an array=>say we have $a=[];
and you expect to get $a=[b=>null]; out of it.

and the other options:

  1. just return false in applyRule on missing property(not good imho), since the property could be allowed to be null. Hence obj={a:null} would be the same as obj={};(sorry for the json notation). So if obj->a can be null, then why can't obj->a be missing? Also if we for example want a remove rule, we should not get an error if it's already removed, right?

  2. in all rules which don't allow null values=>do explicit isset/has_property(also those two are different) checks (too time consuming for me to do right now, but perhaps the best solution).

Sorry to ask for a release, but

Hi Paul,

I do understand that the v1 is EOL. But as v2 is not yet released also can you make one last release with the fix having the set message on the Translator.php ?

Configuring RuleCollection for use with Aura.Di

How would you recommend configuring the dependency injection container in the Aura.Di package for use with Aura.Filter's RuleCollection and RuleLocator classes? I've been trying to work it out for a few days and keep getting stuck. Are you able to provide an example?

Arise PHP Notice when I try to sanitize

$filter->sanitize('value')->to('int')->useBlankValue(0);
$subject = ['value' => 'abc'];
$filter->apply($subject);
PHP Notice: Uninitialized string offset: 0 in aura\filter\src\Rule\Sanitize\Integer.php on line 66

Translator error on inValues filter fail

Translator triggers an error with message "PHP Notice: Array to string conversion in vendor/aura/filter/src/Aura/Filter/Translator.php on line 72" when the "inValues" filter fails to pass.

Test case:

$values = range(0, 9);
$object = (object) [
    'field' =>11
];

$filter = require 'vendor/aura/filter/scripts/instance.php';
$filter->addSoftRule('field', $filter::IS, 'inValues', $values);
$filter->values($object);

Full error:

Notice: Array to string conversion in vendor/aura/filter/src/Aura/Filter/Translator.php on line 72

Call Stack:
    0.0001     227464   1. {main}() test.php:0
    0.0045    1053584   2. Aura\Filter\RuleCollection->values() test.php:12
    0.0046    1056192   3. Aura\Filter\RuleCollection->addMessage() vendor/aura/filter/src/Aura/Filter/RuleCollection.php:365
    0.0046    1056520   4. Aura\Filter\Translator->translate() vendor/aura/filter/src/Aura/Filter/RuleCollection.php:418
    0.0046    1057088   5. str_replace() vendor/aura/filter/src/Aura/Filter/Translator.php:72

"Advanced Usage" section is missing

README.md says

(Note that if we instantiate it manually, we will need to configure the RuleLocator manually to add rule services. See the "Advanced Usage" section near the end of this page for more information.)

But there is no "Advanced Usage" section in README.

can't use validate rule 'blank' at "2.0.0"

Hi, my name is Satomi. I'm using aurafilter, but upon doing composer update, I updated from "2.0.0-beta2" to "2.0.0", and it seems like the "blank" validation rule went away. I'm getting this error: Aura\Filter\Exception\RuleNotMapped: blank. Did the name of this validation rule change? Thank very much!

Closure filtering should allow any callable instead

The closure filtering is typehinting using Closure, this means that callable methods or functions from elsewhere cannot be used

Using the Callable typehint instead (available since 5.4) would allow any legal callable to be used instead (and would require no code changes except the typehint)

Email validation

Currently, it's acceptable to have numbers in the top level domain. Which should only be used for internationalized domains(starting with xn-- as stated in https://en.wikipedia.org/wiki/List_of_Internet_top-level_domains

Ex. [email protected] should be invalid, but it's not.

Com1 doesn't start with xn and is not an internationalized domain either.

It's okay to be able to use an IP instead of a domain name(ex. [email protected]), but not a mix of both.

Also, as far as I know domains must be at least 2 symbols long(did a search). Hence:
[email protected] should be invalid as well.

Another thing is - what about strong email validation using https://secure.php.net/manual/en/function.checkdnsrr.php

Since it makes a network call, maybe it should be in another rule, EmailMX or something.

JsonSerializable

I've just come across a great scenario where I need to get all of the failure data as json for a vue.js component to take over.

Would it be a good idea to implement JsonSerializable in the Failure class?

PHP7 support

Hey,

A great package, but wondered what the timeline is for supporting php 7? There is a class Bool which is now a reserved keyword in php7.

Improvement : We need to get the parameters

Its good to say the field needs a minimum of 9 characters or what ever . Currently in the error we will not be getting all the details like what is the minimum length and stuffs.

array(3) {
  'userid' =>
  array(1) {
    [0] =>
    array(6) {
      'field' =>
      string(6) "userid"
      'method' =>
      string(2) "is"
      'name' =>
      string(5) "email"
      'params' =>
      array(0) {
        ...
      }
      'message' =>
      string(12) "FILTER_EMAIL"
      'type' =>
      string(9) "HARD_RULE"
    }
  }
  'password' =>
  array(1) {
    [0] =>
    array(6) {
      'field' =>
      string(8) "password"
      'method' =>
      string(2) "is"
      'name' =>
      string(9) "strlenMin"
      'params' =>
      array(1) {
        ...
      }
      'message' =>
      string(17) "FILTER_STRLEN_MIN"
      'type' =>
      string(9) "HARD_RULE"
    }
  }
  'confirm_password' =>
  array(1) {
    [0] =>
    array(6) {
      'field' =>
      string(16) "confirm_password"
      'method' =>
      string(2) "is"
      'name' =>
      string(12) "equalToField"
      'params' =>
      array(1) {
        ...
      }
      'message' =>
      string(21) "FILTER_EQUAL_TO_FIELD"
      'type' =>
      string(9) "SOFT_RULE"
    }
  }
}

Stop rule does not stop processing

I have a set of rules that I have configured:

        $filter->validate('first_name')->isNotBlank();
        $filter->validate('last_name')->isNotBlank();
        $filter->validate('email')->is('email');
        $filter->validate('cell_number')->isNotBlank();
        $filter->validate('cell_number')->is('phoneNumber')->asStopRule();
        $filter->validate('password')->isNotBlank();

When I pass an invalid phone number, and a blank password, I expect that the phone number stop rule will prevent processing of the password check. This does not happen. I'm using 2.3.1.

Multidimensional Subjects and Variable Length Members

Multidimensional Subjects, Variable Length Members, and the possible case for
injecting a factory into a subject filter?

I have a couple use cases which I have solved in various hacky ways and am
curious if others have insight into better solutions, or if a PR is in order.

Multi dimensional

I think it might be useful if the SubjectFilter had the FilterFactory
injected into it, so that I could create new 'subfilters' (probably just another
SubjectFilter) to validate members of the subject which are themselves data
structures (array/objects) which have their own criteria.

// Given something like this:
$data = [
    'id' => 1,
    'user' => [
        'name' => 'Foo',
        'age' => 42,
    ],
    'url' => 'http://example.com'
];

// I want to be able to do something like this:
$subject = $factory->newSubjectFilter('My\Filter');

// .. in My\Filter::init()
$this->validate('id')->is('int');
$this->validate('url')->is('url');

$user = $this->subfilter('user'); // create a "sub-filter" ?
// $user = $this->subfilter('user', 'My\Filter\User'); // maybe pass class
$user->validate('given-name')->isNotBlank();
$user->validate('age')->is('int');

// or if not injecting the factory, and providing a method, perhaps a way to
// just inject a filter to a spec? but I don't think I like this as much.
$subject = $factory->newSubjectFilter('My\Filter');
$name = $factory->newSubjectFilter('My\Filter\Name');
$subject->setSubFilter('name', $name);

Variable length arrays

Additionally, I often have a situation where user fills out a HTML form with
some JS crap to add additional fields of some kind, ie:

<!-- //... other inputs and stuff -->
<div>
    <label for="date1">Date</label>
    <input id="date1" name="dates[]" />
</div>
<div>
    <label for="date2">Date</label>
    <input id="date2" name="dates[]" />
</div>
<button>click to add another date</button>

I think I want to be able to do something like this:

// My\Filter::init()

//.. init validation/sanitize other inputs...

// some kind of array_filter function?
// ie. unset blank values?
$this->sanitize('dates')->to('nonblank');

$this->validate('dates')->is(
    'array',  // subject? collection? countable?
    $minCount,
    $maxCount
);

// This is a little weird because I don't think this would be a value filter or
// a subjct filter?
$dateSpec = $this->newSubjectValueFilter();

// set some rules
$dateSpec->validate()->isNotBlank();
$dateSpec->validate()->is('dateTime');
$dateSpec->sanitize()->to('dateTime', 'Y-m-d');

// use spec for each
$this->filterEach('dates', $dateSpec);

One weird thing here is that $dateSpec isn't really a SubjectFilter as it's
not a collection of fields itself, but also not a ValueFilter as I don't think
you can configure a spec for a value filter like you do a subject filter, it's
more a one off thing, right?

... so anyway. Any thoughts here? Am I approaching this wrong? People solve
similar problems in different ways? Or maybe have similar issues and think we
should try to hash out a solution?

composer.json of master

1 ) composer.json of master is wrong one . Please update with that of the recent develop, so we can submit to packagist .

2 ) Now showing forked from pmjones .

Have you submitted to github guys a ticket or we can make it as we did for Aura.Uri ?

Multibyte strings, various problems with the lack thereof

I was looking at the code and found that currently the non-mb string functions are being used:
ex:

Aura\Filter\Rule\Sanitize\Strlen
if (strlen($value) < $len) {
     $subject->$field = str_pad($value, $len, $pad_string, $pad_type);
}
if (strlen($value) > $len) {
     $subject->$field = substr($value, 0, $len);
}

Here we have strlen, substr and str_pad which are non-mb safe. Which will result in various problems:

Ex. take a cyrillic script string's length - strlen("тесттест") = 16 instead of 8, so our validation will fail if we ask for strings of less than 15 characters.

An even bigger issue will ensue with the substr which may cut a unicode character in half(offtopic: slashing symbols sounds funny though) - we will get a random ascii character.

Shouldn't we instead switch to the mb functions?

"Slug" Validation and Sanitization?

This might be 'too particular a use case', but I often find myself "sluggifying"
strings or checking strings for "slugginess".

Is there space for something like this?

I didn't submit a PR, since I thought I'd see what people thought before wasting
too much time. (Also, not sure I know the best way to deal with various out of
bound characters)

Alternatively, it may be better for me to just write something to integrate
aura/filter with some existing solution.

Most implementations of stuff like this are much more robust that what I'm
including as basic illustration of concept. Most handle things like transcoding
certain characters, take some amount of configuration, etc.

Handful of examples:

Basic Validate

namespace Aura\Filter\Rule\Validate;

class Alnum
{
    public function __invoke($subject, $field)
    {
        $value = $subject->$field;
        if (! is_scalar($value)) {
            return false;
        }

        return preg_match('/^[a-z][-a-z0-9]*$/', $value);
    }
}

Basic Sanitize

namespace Aura\Filter\Rule\Sanitize;

class Slug
{
    public function __invoke($subject, $field)
    {
        $value = $subject->$field;
        if (! is_scalar($value)) {
            return false;
        }

        $value = preg_replace('/[^a-z0-9-]+/', '-', strtolower($value));
        $value = preg_replace("/-+/", '-', $value);
        $value = trim($value, '-');

        $subject->$field = $value;
        return true;
    }
}

Thoughts?

best way to validate each item in array

Say I have a $subject like this:

$subject = [
  'field' => 'value'
  'array_field' => [
    1,
    2
  ]
];

What is the best way to create a $filter that will ensure that field is a string and that array_field only contains integers?

Currently I'm using a custom callback function. Is there a better way?

getDefaultMessage() error when using a Closure and the validation fails

Try the following:

$filter = $filter_factory->newSubjectFilter();
$filter->validate('age')->is('callback', function($s, $f) {
    return false;
});
// PHP Catchable fatal error:  Object of class Closure could not be converted to string in ... 
// filter/src/Spec/Spec.php on line 324

Seems that there should be a check to see if args is a Closure.

NOTE: if you use asHardRule('whatever') it works

// From Spec.php line 324ish
protected function getDefaultMessage()
{
    $message = $this->rule;
    if ($this->args) {
        $message .= '(' . implode(', ', $this->args) . ')';
    }
    return $message;
}

Wishlist

One thing I like in v2 is usage of

$email = new Aura\Filter\Email('[email protected]');
$email->isValid();

like interface. I am not sure whether this is possible currently.

But just a wishlist . The idea is usage of filters in DDD as Mathias Verras mentioned in some slides. So we don't need to inject anything to factory or use it.

How to get the tokens

When working with Aura.Intl how could we get the tokens that need to be passed .

Eg :

"FILTER_RULE_FAILURE_IS_NOT_BETWEEN" => "Please do not use a value between {min} and {max}.",

The min and max , may be something like getTokens() on the RuleCollection::addMessageFromRule will help ?

array(
    'min' => $min,
    'max' => $max,
);

/ cc @cordoval

What is the future of this project?

What is the future of this project? In my opinion, it is feature complete and only needs to have the latest versions of PHP (7.3, 7.4 & 8.0 as of this writing) tested via travis or Github Actions to ensure it continues to work with the currently supported version of PHP. Will anyone be updating the CI tests for this project?

Need a release for packagist

I was looking why aura/filter is not getting installed in packagist or is not easily reachable to people when newer components get installed more.

The tag validation is not in master. The master have the tag, we need to push it or edit the composer.json of master to have the validation tag. People are not looking for filters.

custom rules not applying when field is blank

Hello @pmjones
I was trying to make 'required-if' rule, where the field would be required only in some conditions, but because of the fact that rules are not called to blank fields there is no workaround about this issue.

Thanks for help
George

Sanitize to Field If Blank?

Often I wish to set a field (ie. slug) to the value of another field (ie. title) if the former is blank, then sanitize it further. I think I can accomplish this now with some magic strings like this:

$filter->sanitize('slug')->useBlankValue('FIELD_IS_BLANK');
$filter->sanitize('slug')->to('callback', function ($subject, $field) {
    if ($subject->$field == 'FIELD_IS_BLANK') {
        $subject->$field = $subject->title;
    }
    return true;
});
$filter->sanitize('slug')->to('uppercase');


$data = [
    'slug' => '',
    'title' => 'some thing here'
];

var_dump($filter->apply($data));
var_dump($data);

But that's kind of awkward/magical/weird.

Any suggestions? Think we need a PR?

I was thinking about patching the SanatizeSpec to be able to pass a callable to useBlankValue that would take the subject as an arg, but i don't actually think that's the way.

ie.:

    //  SanitizeSpec::__invoke
    public function __invoke($subject)
    {
        if (! $this->subjectFieldIsBlank($subject)) {
            return parent::__invoke($subject);
        }

        if (! $this->allow_blank) {
            return false;
        }

        $blank = $this->blank_value;

        if (is_callable($blank)) {
            $blank = $blank($subject, $this->field);
        }

        $field = $this->field;
        $subject->$field = $blank;
        return true;
    }

// filter
$filter->sanitize('slug')->useBlankValue(
    function ($subject, $field) {
        return $subject->title;
    }
);

Maybe what I want isn't really a "blank" value, but a "defaultTo" or something? and should encompass a new set of logic?

//  SanitizeSpec::__invoke
    public function __invoke($subject)
    {
        if (! $this->subjectFieldIsBlank($subject)) {
            return parent::__invoke($subject);
        }
        if ($defaultField = $this->defaultTo) {
            $subject->$field = $subject->$default;
            return parent::__invoke($subject);
        }
        // ...
    }

Thoughts?

Bool filters and rules do not handle non-scalar values properly

There is no code to handle values that are non-scalar when sanitizing or validating booleans, instead it tries to pass the value directly through assuming it is scalar and throws php warnings

PHPUnit_Framework_Error_Warning: trim() expects parameter 1 to be string, array given in aura/filter/src/Rule/AbstractBool.php on line 45

Sanitize is causing validation error

Maybe I've missed something, and hopefully this can be closed pretty quickly.

        $f->sanitize('member-url')->toBlankOr('callback', function ($subject, $field) {
            if (strlen($subject->$field) > 0 && strpos($subject->$field, 'http://') !== false) {
                $subject->$field = 'http://'.$subject->$field;
            }
        });
        $f->validate('member-url')->isBlankOr('url')->asSoftRule('Your website should be a valid url.');

Basically, if the field has a value, I want to ensure it starts with http, but this combination always gives me:

member-url should have sanitized to callback(*Closure*)

Can anyone triage what's wrong here?

Alternative approach without factory

Hi all,

I would like to discuss if anyone like this idea.

Currently the way of creating the Filter is via a FilterFactory and call the newSubjectFilter .

What I feel is we could improve the usage with something like

$filter = new Aura\Filter\SubjectFilter();

and in the class it can automatically add the dependencies if not passed.

class SubjectFilter
{
    public function __construct(
        ValidateSpec $validate_spec = null,
        SanitizeSpec $sanitize_spec = null,
        FailureCollection $failures = null
    ) {
        $this->validate_spec = $validate_spec ?: new ValidateSpec(new ValidateLocator());
        $this->sanitize_spec = $sanitize_spec ?: new SanitizeSpec(new SanitizeLocator());
        $this->proto_failures = $failures ?: new FailureCollection();
        $this->init();
    }
}

This helps to use Di if they are using it and if not passing their own or alternatively without anything if there is no other custom rule dependency.

I can make a PR if the idea seems good.

Thank you.

I'm little lost. How to use aura filter with multidimensional arrays?

Hi,
Let's say i have following POST array from form:

POST = array (
      'firstname' => 'John',
      'lastname' => 'Connor',
      'custom_fields' => array(
              'custom_field' => 'some_value',
              'another_one' => 'some_value',
             );
   );

Now i'm creating new aura filter:

use Aura\FilterFactory;

$filter_factory = new FilterFactory();
$filter = $filter_factory->newFilter();

And i'm applying all filter rules...

    $filter->validate('firstname')->isNot('blank');
    $filter->validate('firstname')->is('alpha');
    $filter->validate('firstname')->is('strlenMin', 3);
    $filter->sanitize('firstname')->to('string');

    $filter->validate('lastname')->isNot('blank');
    $filter->validate('lastname')->is('alpha');
    $filter->validate('lastname')->is('strlenMin', 3);
    $filter->sanitize('lastname')->to('string');

Except... yeah. How i can validate all fields inside custom_fields array?

I've tried stuff like

  $filter->validate('custom_fields/custom_field')->isNot('blank');

and even

   $filter->validate('custom_fields')->('custom_field')->isNot('blank');

I know i could just make another filter and apply my subarray into it, but i don't want to

Validation arguments should be constants

We are currently allowing users to validate by using a string value to indicate the validator they wish to use:

$filter->validate('credit_card')->is('creditCard');

For built-in validators, we should instead use constants:

$filter->validate('credit_card')->is(Filter::CREDIT_CARD);

Configure RuleLocator readme section missing

In the readme you have the the following:

(Note that if we instantiate manually, we will need to configure the RuleLocator manually to add rule services. See the "Advanced Usage" section near the end of this page for more information.)

This section doesn't seem to be present?

PSR-7 upload validator?

$filter->validate('field')->is('upload');

Using this, with a PSR based request, how do I test the uploadedFiles part of the request?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.