PHPFUI Tests Latest Packagist release

PHP Wrapper for the Foundation CSS Framework

PHPFUI, PHP Foundation User Interface, is a modern PHP library that produces HTML formated for Foundation. It does everything you need for a fully functional Foundation page, with the power of an OO language. It currently uses Foundation 6.6.

"I was surprised that people were prepared to write HTML. In my initial requirements for this thing, I had assumed, as an absolute pre-condition, that nobody would have to do HTML or deal with URLs. If you use the original World Wide Web program, you never see a URL or have to deal with HTML. You're presented with the raw information. You then input more information. So you are linking information to information--like using a word processor. That was a surprise to me--that people were prepared to painstakingly write HTML."

Sir Tim Berners-Lee, inventor of the World Wide Web

Using PHPFUI for view output will produce 100% valid HTML and insulate you from future changes to Foundation, your custom HMTL layouts, CSS and JS library changes. You write to an abstract concept (I want a checkbox here), and the library will output a checkbox formatted for Foundation. You can inherit from CheckBox and add your own take on a checkbox, and when the graphic designer decides they have the most awesome checkbox ever, you simply change your CheckBox class, and it is changed on every page system wide.

Don't write HTML by hand!

Usage

namespace PHPFUI;
$page = new Page();
$form = new Form($page);
$fieldset = new FieldSet('A basic input form');
$time = new Input\Time($page, 'time', 'Enter A Time in 15 minute increments');
$time->setRequired();
$date = new Input\Date($page, 'date', 'Pick A Date');
$fieldset->add(new MultiColumn($time, $date));
$fieldset->add(new Input\TextArea('text', 'Enter some text'));
$fieldset->add(new Submit());
$form->add($fieldset);
$page->add($form);
$page->addStyleSheet('/css/styles.css');
echo $page;

Installation Instructions

composer require phpfui/phpfui

Then run update.php from the vendor/phpfui/phpfui directory and supply the path to your public directory / the directory for the various JS and CSS files PHPFUI uses. This will copy all required public files into your public directory. For example:

php vendor/phpfui/phpfui/update.php public/PHPFUI

The PHPFUI library defaults to your-public-directory/PHPFUI, it can be overridden, but it is suggested to use PHPFUI to keep everything in one place. update.php should be run when ever you update PHPFUI.

Versioning

Versioning will match the Foundation versions for Major semantic versions. PHPUI will always support the most recent version of Foundation possible for the Major version. PHPFUI Minor version will include breaking changes and may incorporate changes for the latest version of Foundation. The PHPFUI Patch version will include non breaking changes or additions. So PHPFUI Version 6.0.0 would be the first version of the library, 6.0.1 would be the first patch of PHPFUI. Both should work with any Foundation 6.x version. PHPFUI 6.1.0 would be a breaking change to PHPFUI, but still track Foundation 6.x. PHPFUI 7.0.0 would track Foundation 7.x series.

Depreciation and Foundation changes

Since major versions of Foundation have in the past depreciated and obsoleted things, PHPFUI will track the latest version of Foundation for class names and functionality. However, when Foundation makes a breaking change or removes something, PHPFUI will continue to support the old functionality as best as possible in the new Foundation framework. Depreciated classes will be put in the \PHPFUI\Vx namespace (where x would be the prior Major Foundation version containing that feature). So if something gets depreciated in a newer version of Foundation, you simply will need to change your code from \PHPFUI\Example to \PHPFUI\V6\Example. The depreciated namespace will only be supported for one Major version of PHPFUI, so it is recommended you migrate off of it in a timely manor.

Documentation

Via PHPFUI/InstaDoc

Live Examples

Via PHPFUI/Examples

Unit Testing

Full unit testing using phpfui/html-unit-tester

License

PHPFUI is distributed under the MIT License.

PHP Versions

This library only supports modern versions of PHP which still receive security updates. While we would love to support PHP from the late Ming Dynasty, the advantages of modern PHP versions far out weigh quaint notions of backward compatibility. Time to upgrade.


PHPFUI\InstaDoc Library Tests Latest Packagist release

A quick and easy way to add documentation to your PHP project

We all document our code with PHP DocBlocks but we never seem to actually generate the documentation and add it to our project. Why? It simply takes too much time (over a minute), so we put it off till later, and later never comes.

But with PHPFUI\InstaDoc, you can document your site in about a minute (OK, maybe 2). The steps involved:

  • Install PHPFUI\InstaDoc via Composer (30 seconds)
  • Run installation script (30 seconds)
  • Create document page (1 minute, 6 lines of code)

Two minutes to usable documentation with the following features:

PHPFUI\InstaDoc Features

  • Always up to date, even with code that is not yet checked in
  • Send constructor information including parameters and default values to clipboard
  • Child and Parent class hierarchy clearly displayed and accessable
  • Quick access to highlighted PHP source with user selectable highlighting
  • Quick access to the file's git history for the local repo
  • Full support for @inheritDoc tag so child method docs are displayed correctly
  • Documents all projects loaded via Composer automatically
  • Tabbed documentation so you are not looking at irrelevant methods
  • Alphabetized everything, no more searching unalphabetized pages!
  • Support for markdown and custom markdown pages
  • Ability to generate static html files for high volume sites
  • Add any local repo directories
  • Remove any Composer project you don't care about
  • 5+ line config compatible with all PHP frameworks, or standalone
  • Uses Foundation CSS framework for a great experience on mobile

Install PHPFUI\InstaDoc (requires PHP >= 7.3)

composer require phpfui/InstaDoc

Run Installation Script

Once installed, you need to run an installation script to copy static files to your public directory. From your project root, run the following:

php vendor/phpfui/instadoc/install.php yourPublicDirectory/subDirectory

Example: php vendor/phpfui/instadoc/install.php public/PHPFUI will add all needed files to public/PHPFUI, which will avoid any conflicts with your current files. You can specify any directory by using \PHPFUI\Page::setResourcePath, but PHPFUI is recomended to keep things simple.

Create Document Page

PHPFUI\InstaDoc does not reply on any framework and can run on a standalone page. It is recommended that you do not make your documentation public, as PHPFUI\InstaDoc will display PHP source files. How you restrict access to the page is up to you. The following does not restrict access and is simply an example:

<?php
include 'yourAutoLoader.php';

// pass the directory containing your composer.json file
$fileManager = new \PHPFUI\InstaDoc\FileManager('../');

// add your App class tree in, pass true as the last parameter if this namespace is in your local git repo.
$fileManager->addNamespace('App', '../App', true);

// load your cached files
$fileManager->load();

// load child classes if you want to display them, if you don't do this step, docs will not show classes that extend the displayed class
\PHPFUI\InstaDoc\ChildClasses::load();

// get the controller
$controller = new \PHPFUI\InstaDoc\Controller($fileManager);

// display will return a fully formed page
echo $controller->display();

That is it. You are done!

Adding New Classes

PHPFUI\InstaDoc saves the classes to display in PHP serialized files. Delete those files (.serial extension) when you want to display new classes. PHPFUI\InstaDoc will regenerate automatically if the files are missing.

Add Child Classes to the Docs

\PHPFUI\InstaDoc\ChildClasses::load('../ChildClasses.serial');

Add a Global Namespace Class

The git repo path defaults to the composer directory, but you can change the path by calling:

$fileManager->addGlobalNameSpaceClass(__DIR__ . '/global/FPDF.php');

Removing a Namespace

$fileManager->excludeNamespace('Carbon');

Add git Repository Page

The git repo path defaults to the composer directory, but you can change the path by calling:

$controller->setGitRoot(getcwd() . '/../');

Add Documents To Your Docs Home Page

$controller->addHomePageMarkdown('../PHPFUI/InstaDoc/README.md');

Set Your Home Page

You may want users to get back into your system easily. Clicking on the top left menu bar will take them here:

$controller->setHomeUrl('/');

Breakup Your Documentation Into Sections

If you have a lot of source code, you might want to break it into sections, so you will need a separate file to store the index in per section:

$fileManager->setBaseFile('SubProject');

Generate Static Files

Just the doc and file pages, no git!

$controller->generate('static/file/path', [\PHPFUI\InstaDoc\Controller::DOC_PAGE, \PHPFUI\InstaDoc\Controller::FILE_PAGE, ]));

Example and Full Documentation

PHPFUI/InstaDoc

Package Documentation

  • \cebe\markdown Readme

    A super fast, highly extensible markdown parser for PHP

    Latest Stable Version
    Total Downloads
    Build Status
    Code Coverage
    Scrutinizer Quality Score

    What is this?

    A set of PHP classes, each representing a Markdown flavor, and a command line tool
    for converting markdown files to HTML files.

    The implementation focus is to be fast (see benchmark) and extensible.
    Parsing Markdown to HTML is as simple as calling a single method (see Usage) providing a solid implementation
    that gives most expected results even in non-trivial edge cases.

    Extending the Markdown language with new elements is as simple as adding a new method to the class that converts the
    markdown text to the expected output in HTML. This is possible without dealing with complex and error prone regular expressions.
    It is also possible to hook into the markdown structure and add elements or read meta information using the internal representation
    of the Markdown text as an abstract syntax tree (see Extending the language).

    Currently the following markdown flavors are supported:

    Future plans are to support:

    Who is using it?

    Installation

    PHP 5.4 or higher is required to use it.
    It will also run on facebook's hhvm.

    The library uses PHPDoc annotations to determine the markdown elements that should be parsed.
    So in case you are using PHP opcache, make sure
    it does not strip comments.

    Installation is recommended to be done via composer by running:

    composer require cebe/markdown "~1.2.0"
    

    Alternatively you can add the following to the require section in your composer.json manually:

    "cebe/markdown": "~1.2.0"
    

    Run composer update afterwards.

    Note: If you have configured PHP with opcache you need to enable the
    opcache.save_comments option because inline element parsing relies on PHPdoc annotations to find declared elements.

    Usage

    In your PHP project

    To parse your markdown you need only two lines of code. The first one is to choose the markdown flavor as
    one of the following:

    • Traditional Markdown: $parser = new \cebe\markdown\Markdown();
    • Github Flavored Markdown: $parser = new \cebe\markdown\GithubMarkdown();
    • Markdown Extra: $parser = new \cebe\markdown\MarkdownExtra();

    The next step is to call the parse()-method for parsing the text using the full markdown language
    or calling the parseParagraph()-method to parse only inline elements.

    Here are some examples:

    // traditional markdown and parse full text
    $parser = new \cebe\markdown\Markdown();
    echo $parser->parse($markdown);
    
    // use github markdown
    $parser = new \cebe\markdown\GithubMarkdown();
    echo $parser->parse($markdown);
    
    // use markdown extra
    $parser = new \cebe\markdown\MarkdownExtra();
    echo $parser->parse($markdown);
    
    // parse only inline elements (useful for one-line descriptions)
    $parser = new \cebe\markdown\GithubMarkdown();
    echo $parser->parseParagraph($markdown);
    

    You may optionally set one of the following options on the parser object:

    For all Markdown Flavors:

    • $parser->html5 = true to enable HTML5 output instead of HTML4.
    • $parser->keepListStartNumber = true to enable keeping the numbers of ordered lists as specified in the markdown.
      The default behavior is to always start from 1 and increment by one regardless of the number in markdown.

    For GithubMarkdown:

    • $parser->enableNewlines = true to convert all newlines to <br/>-tags. By default only newlines with two preceding spaces are converted to <br/>-tags.

    It is recommended to use UTF-8 encoding for the input strings. Other encodings may work, but are currently untested.

    The command line script

    You can use it to render this readme:

    bin/markdown README.md > README.html
    

    Using github flavored markdown:

    bin/markdown --flavor=gfm README.md > README.html
    

    or convert the original markdown description to html using the unix pipe:

    curl http://daringfireball.net/projects/markdown/syntax.text | bin/markdown > md.html
    

    Here is the full Help output you will see when running bin/markdown --help:

    PHP Markdown to HTML converter
    ------------------------------
    
    by Carsten Brandt <mail@cebe.cc>
    
    Usage:
        bin/markdown [--flavor=<flavor>] [--full] [file.md]
    
        --flavor  specifies the markdown flavor to use. If omitted the original markdown by John Gruber [1] will be used.
                  Available flavors:
    
                  gfm   - Github flavored markdown [2]
                  extra - Markdown Extra [3]
    
        --full    ouput a full HTML page with head and body. If not given, only the parsed markdown will be output.
    
        --help    shows this usage information.
    
        If no file is specified input will be read from STDIN.
    
    Examples:
    
        Render a file with original markdown:
    
            bin/markdown README.md > README.html
    
        Render a file using gihtub flavored markdown:
    
            bin/markdown --flavor=gfm README.md > README.html
    
        Convert the original markdown description to html using STDIN:
    
            curl http://daringfireball.net/projects/markdown/syntax.text | bin/markdown > md.html
    
    
    [1] http://daringfireball.net/projects/markdown/syntax
    [2] https://help.github.com/articles/github-flavored-markdown
    [3] http://michelf.ca/projects/php-markdown/extra/
    

    Extensions

    Here are some extensions to this library:

    Extending the language

    Markdown consists of two types of language elements, I'll call them block and inline elements simlar to what you have in
    HTML with <div> and <span>. Block elements are normally spreads over several lines and are separated by blank lines.
    The most basic block element is a paragraph (<p>).
    Inline elements are elements that are added inside of block elements i.e. inside of text.

    This markdown parser allows you to extend the markdown language by changing existing elements behavior and also adding
    new block and inline elements. You do this by extending from the parser class and adding/overriding class methods and
    properties. For the different element types there are different ways to extend them as you will see in the following sections.

    Adding block elements

    The markdown is parsed line by line to identify each non-empty line as one of the block element types.
    To identify a line as the beginning of a block element it calls all protected class methods who's name begins with identify.
    An identify function returns true if it has identified the block element it is responsible for or false if not.
    In the following example we will implement support for fenced code blocks which are part of the github flavored markdown.

    <?php
    
    class MyMarkdown extends \cebe\markdown\Markdown
    {
    	protected function identifyFencedCode($line, $lines, $current)
    	{
    		// if a line starts with at least 3 backticks it is identified as a fenced code block
    		if (strncmp($line, '```', 3) === 0) {
    			return true;
    		}
    		return false;
    	}
    
    	// ...
    }
    

    In the above, $line is a string containing the content of the current line and is equal to $lines[$current].
    You may use $lines and $current to check other lines than the current line. In most cases you can ignore these parameters.

    Parsing of a block element is done in two steps:

    1. Consuming all the lines belonging to it. In most cases this is iterating over the lines starting from the identified
      line until a blank line occurs. This step is implemented by a method named consume{blockName}() where {blockName}
      is the same name as used for the identify function above. The consume method also takes the lines array
      and the number of the current line. It will return two arguments: an array representing the block element in the abstract syntax tree
      of the markdown document and the line number to parse next. In the abstract syntax array the first element refers to the name of
      the element, all other array elements can be freely defined by yourself.
      In our example we will implement it like this:

      protected function consumeFencedCode($lines, $current)
      {
      	// create block array
      	$block = [
      		'fencedCode',
      		'content' => [],
      	];
      	$line = rtrim($lines[$current]);
      
      	// detect language and fence length (can be more than 3 backticks)
      	$fence = substr($line, 0, $pos = strrpos($line, '`') + 1);
      	$language = substr($line, $pos);
      	if (!empty($language)) {
      		$block['language'] = $language;
      	}
      
      	// consume all lines until ```
      	for($i = $current + 1, $count = count($lines); $i < $count; $i++) {
      		if (rtrim($line = $lines[$i]) !== $fence) {
      			$block['content'][] = $line;
      		} else {
      			// stop consuming when code block is over
      			break;
      		}
      	}
      	return [$block, $i];
      }
      
    2. Rendering the element. After all blocks have been consumed, they are being rendered using the
      render{elementName}()-method where elementName refers to the name of the element in the abstract syntax tree:

      protected function renderFencedCode($block)
      {
      	$class = isset($block['language']) ? ' class="language-' . $block['language'] . '"' : '';
      	return "<pre><code$class>" . htmlspecialchars(implode("\n", $block['content']) . "\n", ENT_NOQUOTES, 'UTF-8') . '</code></pre>';
      }
      

      You may also add code highlighting here. In general it would also be possible to render ouput in a different language than
      HTML for example LaTeX.

    Adding inline elements

    Adding inline elements is different from block elements as they are parsed using markers in the text.
    An inline element is identified by a marker that marks the beginning of an inline element (e.g. [ will mark a possible
    beginning of a link or ` will mark inline code).

    Parsing methods for inline elements are also protected and identified by the prefix parse. Additionally a @marker annotation
    in PHPDoc is needed to register the parse function for one or multiple markers.
    The method will then be called when a marker is found in the text. As an argument it takes the text starting at the position of the marker.
    The parser method will return an array containing the element of the abstract sytnax tree and an offset of text it has
    parsed from the input markdown. All text up to this offset will be removed from the markdown before the next marker will be searched.

    As an example, we will add support for the strikethrough feature of github flavored markdown:

    <?php
    
    class MyMarkdown extends \cebe\markdown\Markdown
    {
    	/**
    	 * @marker ~~
    	 */
    	protected function parseStrike($markdown)
    	{
    		// check whether the marker really represents a strikethrough (i.e. there is a closing ~~)
    		if (preg_match('/^~~(.+?)~~/', $markdown, $matches)) {
    			return [
    			    // return the parsed tag as an element of the abstract syntax tree and call `parseInline()` to allow
    			    // other inline markdown elements inside this tag
    				['strike', $this->parseInline($matches[1])],
    				// return the offset of the parsed text
    				strlen($matches[0])
    			];
    		}
    		// in case we did not find a closing ~~ we just return the marker and skip 2 characters
    		return [['text', '~~'], 2];
    	}
    
    	// rendering is the same as for block elements, we turn the abstract syntax array into a string.
    	protected function renderStrike($element)
    	{
    		return '<del>' . $this->renderAbsy($element[1]) . '</del>';
    	}
    }
    

    Composing your own Markdown flavor

    This markdown library is composed of traits so it is very easy to create your own markdown flavor by adding and/or removing
    the single feature traits.

    Designing your Markdown flavor consists of four steps:

    1. Select a base class
    2. Select language feature traits
    3. Define escapeable characters
    4. Optionally add custom rendering behavior

    Select a base class

    If you want to extend from a flavor and only add features you can use one of the existing classes
    (Markdown, GithubMarkdown or MarkdownExtra) as your flavors base class.

    If you want to define a subset of the markdown language, i.e. remove some of the features, you have to
    extend your class from Parser.

    Select language feature traits

    The following shows the trait selection for traditional Markdown.

    class MyMarkdown extends Parser
    {
    	// include block element parsing using traits
    	use block\CodeTrait;
    	use block\HeadlineTrait;
    	use block\HtmlTrait {
    		parseInlineHtml as private;
    	}
    	use block\ListTrait {
    		// Check Ul List before headline
    		identifyUl as protected identifyBUl;
    		consumeUl as protected consumeBUl;
    	}
    	use block\QuoteTrait;
    	use block\RuleTrait {
    		// Check Hr before checking lists
    		identifyHr as protected identifyAHr;
    		consumeHr as protected consumeAHr;
    	}
    	// include inline element parsing using traits
    	use inline\CodeTrait;
    	use inline\EmphStrongTrait;
    	use inline\LinkTrait;
    
    	/**
    	 * @var boolean whether to format markup according to HTML5 spec.
    	 * Defaults to `false` which means that markup is formatted as HTML4.
    	 */
    	public $html5 = false;
    
    	protected function prepare()
    	{
    		// reset references
    		$this->references = [];
    	}
    
    	// ...
    }
    

    In general, just adding the trait with use is enough, however in some cases some fine tuning is desired
    to get most expected parsing results. Elements are detected in alphabetical order of their identification
    function. This means that if a line starting with - could be a list or a horizontal rule, the preference has to be set
    by renaming the identification function. This is what is done with renaming identifyHr to identifyAHr
    and identifyBUl to identifyBUl. The consume function always has to have the same name as the identification function
    so this has to be renamed too.

    There is also a conflict for parsing of the < character. This could either be a link/email enclosed in < and >
    or an inline HTML tag. In order to resolve this conflict when adding the LinkTrait, we need to hide the parseInlineHtml
    method of the HtmlTrait.

    If you use any trait that uses the $html5 property to adjust its output you also need to define this property.

    If you use the link trait it may be useful to implement prepare() as shown above to reset references before
    parsing to ensure you get a reusable object.

    Define escapeable characters

    Depending on the language features you have chosen there is a different set of characters that can be escaped
    using \. The following is the set of escapeable characters for traditional markdown, you can copy it to your class
    as is.

    	/**
    	 * @var array these are "escapeable" characters. When using one of these prefixed with a
    	 * backslash, the character will be outputted without the backslash and is not interpreted
    	 * as markdown.
    	 */
    	protected $escapeCharacters = [
    		'\\', // backslash
    		'`', // backtick
    		'*', // asterisk
    		'_', // underscore
    		'{', '}', // curly braces
    		'[', ']', // square brackets
    		'(', ')', // parentheses
    		'#', // hash mark
    		'+', // plus sign
    		'-', // minus sign (hyphen)
    		'.', // dot
    		'!', // exclamation mark
    		'<', '>',
    	];
    

    Add custom rendering behavior

    Optionally you may also want to adjust rendering behavior by overriding some methods.
    You may refer to the consumeParagraph() method of the Markdown and GithubMarkdown classes for some inspiration
    which define different rules for which elements are allowed to interrupt a paragraph.

    Acknowledgements

    I'd like to thank @erusev for creating Parsedown which heavily influenced this work and provided
    the idea of the line based parsing approach.

    FAQ

    Why another markdown parser?

    While reviewing PHP markdown parsers for choosing one to use bundled with the Yii framework 2.0
    I found that most of the implementations use regex to replace patterns instead
    of doing real parsing. This way extending them with new language elements is quite hard
    as you have to come up with a complex regex, that matches your addition but does not mess
    with other elements. Such additions are very common as you see on github which supports referencing
    issues, users and commits in the comments.
    A real parser should use context aware methods that walk trough the text and
    parse the tokens as they find them. The only implentation that I have found that uses
    this approach is Parsedown which also shows that this implementation is much faster
    than the regex way. Parsedown however is an implementation that focuses on speed and implements
    its own flavor (mainly github flavored markdown) in one class and at the time of this writing was
    not easily extensible.

    Given the situation above I decided to start my own implementation using the parsing approach
    from Parsedown and making it extensible creating a class for each markdown flavor that extend each
    other in the way that also the markdown languages extend each other.
    This allows you to choose between markdown language flavors and also provides a way to compose your
    own flavor picking the best things from all.
    I chose this approach as it is easier to implement and also more intuitive approach compared
    to using callbacks to inject functionallity into the parser.

    Where do I report bugs or rendering issues?

    Just open an issue on github, post your markdown code and describe the problem. You may also attach screenshots of the rendered HTML result to describe your problem.

    How can I contribute to this library?

    Check the CONTRIBUTING.md file for more info.

    Am I free to use this?

    This library is open source and licensed under the MIT License. This means that you can do whatever you want
    with it as long as you mention my name and include the license file. Check the license for details.

    Contact

    Feel free to contact me using email or twitter.

  • \Composer\Semver Readme

    composer/semver

    Semver library that offers utilities, version constraint parsing and validation.

    Originally written as part of composer/composer,
    now extracted and made available as a stand-alone library.

    Continuous Integration

    Installation

    Install the latest version with:

    $ composer require composer/semver
    

    Requirements

    • PHP 5.3.2 is required but using the latest version of PHP is highly recommended.

    Version Comparison

    For details on how versions are compared, refer to the Versions
    article in the documentation section of the getcomposer.org website.

    Basic usage

    Comparator

    The Composer\Semver\Comparator class provides the following methods for comparing versions:

    • greaterThan($v1, $v2)
    • greaterThanOrEqualTo($v1, $v2)
    • lessThan($v1, $v2)
    • lessThanOrEqualTo($v1, $v2)
    • equalTo($v1, $v2)
    • notEqualTo($v1, $v2)

    Each function takes two version strings as arguments and returns a boolean. For example:

    use Composer\Semver\Comparator;
    
    Comparator::greaterThan('1.25.0', '1.24.0'); // 1.25.0 > 1.24.0
    

    Semver

    The Composer\Semver\Semver class provides the following methods:

    • satisfies($version, $constraints)
    • satisfiedBy(array $versions, $constraint)
    • sort($versions)
    • rsort($versions)

    Intervals

    The Composer\Semver\Intervals static class provides
    a few utilities to work with complex constraints or read version intervals from a constraint:

    use Composer\Semver\Intervals;
    
    // Checks whether $candidate is a subset of $constraint
    Intervals::isSubsetOf(ConstraintInterface $candidate, ConstraintInterface $constraint);
    
    // Checks whether $a and $b have any intersection, equivalent to $a->matches($b)
    Intervals::haveIntersections(ConstraintInterface $a, ConstraintInterface $b);
    
    // Optimizes a complex multi constraint by merging all intervals down to the smallest
    // possible multi constraint. The drawbacks are this is not very fast, and the resulting
    // multi constraint will have no human readable prettyConstraint configured on it
    Intervals::compactConstraint(ConstraintInterface $constraint);
    
    // Creates an array of numeric intervals and branch constraints representing a given constraint
    Intervals::get(ConstraintInterface $constraint);
    
    // Clears the memoization cache when you are done processing constraints
    Intervals::clear()
    

    See the class docblocks for more details.

    License

    composer/semver is licensed under the MIT License, see the LICENSE file for details.

  • \DeepCopy Readme

    DeepCopy

    DeepCopy helps you create deep copies (clones) of your objects. It is designed to handle cycles in the association graph.

    Build Status
    Coverage Status
    Scrutinizer Quality Score
    Total Downloads

    Table of Contents

    1. How
    2. Why
      1. Using simply clone
      2. Overridding __clone()
      3. With DeepCopy
    3. How it works
    4. Going further
      1. Matchers
        1. Property name
        2. Specific property
        3. Type
      2. Filters
        1. SetNullFilter
        2. KeepFilter
        3. DoctrineCollectionFilter
        4. DoctrineEmptyCollectionFilter
        5. DoctrineProxyFilter
        6. ReplaceFilter
        7. ShallowCopyFilter
    5. Edge cases
    6. Contributing
      1. Tests

    How?

    Install with Composer:

    composer require myclabs/deep-copy
    

    Use simply:

    use DeepCopy\DeepCopy;
    
    $copier = new DeepCopy();
    $myCopy = $copier->copy($myObject);
    

    Why?

    • How do you create copies of your objects?
    $myCopy = clone $myObject;
    
    • How do you create deep copies of your objects (i.e. copying also all the objects referenced in the properties)?

    You use __clone() and implement the behavior
    yourself.

    • But how do you handle cycles in the association graph?

    Now you're in for a big mess :(

    association graph

    Using simply clone

    Using clone

    Overridding __clone()

    Overridding __clone

    With DeepCopy

    With DeepCopy

    How it works

    DeepCopy recursively traverses all the object's properties and clones them. To avoid cloning the same object twice it
    keeps a hash map of all instances and thus preserves the object graph.

    To use it:

    use function DeepCopy\deep_copy;
    
    $copy = deep_copy($var);
    

    Alternatively, you can create your own DeepCopy instance to configure it differently for example:

    use DeepCopy\DeepCopy;
    
    $copier = new DeepCopy(true);
    
    $copy = $copier->copy($var);
    

    You may want to roll your own deep copy function:

    namespace Acme;
    
    use DeepCopy\DeepCopy;
    
    function deep_copy($var)
    {
        static $copier = null;
        
        if (null === $copier) {
            $copier = new DeepCopy(true);
        }
        
        return $copier->copy($var);
    }
    

    Going further

    You can add filters to customize the copy process.

    The method to add a filter is DeepCopy\DeepCopy::addFilter($filter, $matcher),
    with $filter implementing DeepCopy\Filter\Filter
    and $matcher implementing DeepCopy\Matcher\Matcher.

    We provide some generic filters and matchers.

    Matchers

    • DeepCopy\Matcher applies on a object attribute.
    • DeepCopy\TypeMatcher applies on any element found in graph, including array elements.

    Property name

    The PropertyNameMatcher will match a property by its name:

    use DeepCopy\Matcher\PropertyNameMatcher;
    
    // Will apply a filter to any property of any objects named "id"
    $matcher = new PropertyNameMatcher('id');
    

    Specific property

    The PropertyMatcher will match a specific property of a specific class:

    use DeepCopy\Matcher\PropertyMatcher;
    
    // Will apply a filter to the property "id" of any objects of the class "MyClass"
    $matcher = new PropertyMatcher('MyClass', 'id');
    

    Type

    The TypeMatcher will match any element by its type (instance of a class or any value that could be parameter of
    gettype() function):

    use DeepCopy\TypeMatcher\TypeMatcher;
    
    // Will apply a filter to any object that is an instance of Doctrine\Common\Collections\Collection
    $matcher = new TypeMatcher('Doctrine\Common\Collections\Collection');
    

    Filters

    • DeepCopy\Filter applies a transformation to the object attribute matched by DeepCopy\Matcher
    • DeepCopy\TypeFilter applies a transformation to any element matched by DeepCopy\TypeMatcher

    SetNullFilter (filter)

    Let's say for example that you are copying a database record (or a Doctrine entity), so you want the copy not to have
    any ID:

    use DeepCopy\DeepCopy;
    use DeepCopy\Filter\SetNullFilter;
    use DeepCopy\Matcher\PropertyNameMatcher;
    
    $object = MyClass::load(123);
    echo $object->id; // 123
    
    $copier = new DeepCopy();
    $copier->addFilter(new SetNullFilter(), new PropertyNameMatcher('id'));
    
    $copy = $copier->copy($object);
    
    echo $copy->id; // null
    

    KeepFilter (filter)

    If you want a property to remain untouched (for example, an association to an object):

    use DeepCopy\DeepCopy;
    use DeepCopy\Filter\KeepFilter;
    use DeepCopy\Matcher\PropertyMatcher;
    
    $copier = new DeepCopy();
    $copier->addFilter(new KeepFilter(), new PropertyMatcher('MyClass', 'category'));
    
    $copy = $copier->copy($object);
    // $copy->category has not been touched
    

    DoctrineCollectionFilter (filter)

    If you use Doctrine and want to copy an entity, you will need to use the DoctrineCollectionFilter:

    use DeepCopy\DeepCopy;
    use DeepCopy\Filter\Doctrine\DoctrineCollectionFilter;
    use DeepCopy\Matcher\PropertyTypeMatcher;
    
    $copier = new DeepCopy();
    $copier->addFilter(new DoctrineCollectionFilter(), new PropertyTypeMatcher('Doctrine\Common\Collections\Collection'));
    
    $copy = $copier->copy($object);
    

    DoctrineEmptyCollectionFilter (filter)

    If you use Doctrine and want to copy an entity who contains a Collection that you want to be reset, you can use the
    DoctrineEmptyCollectionFilter

    use DeepCopy\DeepCopy;
    use DeepCopy\Filter\Doctrine\DoctrineEmptyCollectionFilter;
    use DeepCopy\Matcher\PropertyMatcher;
    
    $copier = new DeepCopy();
    $copier->addFilter(new DoctrineEmptyCollectionFilter(), new PropertyMatcher('MyClass', 'myProperty'));
    
    $copy = $copier->copy($object);
    
    // $copy->myProperty will return an empty collection
    

    DoctrineProxyFilter (filter)

    If you use Doctrine and use cloning on lazy loaded entities, you might encounter errors mentioning missing fields on a
    Doctrine proxy class (...\__CG__\Proxy).
    You can use the DoctrineProxyFilter to load the actual entity behind the Doctrine proxy class.
    Make sure, though, to put this as one of your very first filters in the filter chain so that the entity is loaded
    before other filters are applied!

    use DeepCopy\DeepCopy;
    use DeepCopy\Filter\Doctrine\DoctrineProxyFilter;
    use DeepCopy\Matcher\Doctrine\DoctrineProxyMatcher;
    
    $copier = new DeepCopy();
    $copier->addFilter(new DoctrineProxyFilter(), new DoctrineProxyMatcher());
    
    $copy = $copier->copy($object);
    
    // $copy should now contain a clone of all entities, including those that were not yet fully loaded.
    

    ReplaceFilter (type filter)

    1. If you want to replace the value of a property:
    use DeepCopy\DeepCopy;
    use DeepCopy\Filter\ReplaceFilter;
    use DeepCopy\Matcher\PropertyMatcher;
    
    $copier = new DeepCopy();
    $callback = function ($currentValue) {
      return $currentValue . ' (copy)'
    };
    $copier->addFilter(new ReplaceFilter($callback), new PropertyMatcher('MyClass', 'title'));
    
    $copy = $copier->copy($object);
    
    // $copy->title will contain the data returned by the callback, e.g. 'The title (copy)'
    
    1. If you want to replace whole element:
    use DeepCopy\DeepCopy;
    use DeepCopy\TypeFilter\ReplaceFilter;
    use DeepCopy\TypeMatcher\TypeMatcher;
    
    $copier = new DeepCopy();
    $callback = function (MyClass $myClass) {
      return get_class($myClass);
    };
    $copier->addTypeFilter(new ReplaceFilter($callback), new TypeMatcher('MyClass'));
    
    $copy = $copier->copy([new MyClass, 'some string', new MyClass]);
    
    // $copy will contain ['MyClass', 'some string', 'MyClass']
    

    The $callback parameter of the ReplaceFilter constructor accepts any PHP callable.

    ShallowCopyFilter (type filter)

    Stop DeepCopy from recursively copying element, using standard clone instead:

    use DeepCopy\DeepCopy;
    use DeepCopy\TypeFilter\ShallowCopyFilter;
    use DeepCopy\TypeMatcher\TypeMatcher;
    use Mockery as m;
    
    $this->deepCopy = new DeepCopy();
    $this->deepCopy->addTypeFilter(
    	new ShallowCopyFilter,
    	new TypeMatcher(m\MockInterface::class)
    );
    
    $myServiceWithMocks = new MyService(m::mock(MyDependency1::class), m::mock(MyDependency2::class));
    // All mocks will be just cloned, not deep copied
    

    Edge cases

    The following structures cannot be deep-copied with PHP Reflection. As a result they are shallow cloned and filters are
    not applied. There is two ways for you to handle them:

    • Implement your own __clone() method
    • Use a filter with a type matcher

    Contributing

    DeepCopy is distributed under the MIT license.

    Tests

    Running the tests is simple:

    vendor/bin/phpunit
    

    Support

    Get professional support via the Tidelift Subscription.

  • \Gitonomy\Git Readme

    Gitlib for Gitonomy

    Build Status
    StyleCI
    License
    Downloads

    This library provides methods to access Git repository from PHP 5.6+.

    It makes shell calls, which makes it less performant than any solution.

    Anyway, it's convenient and don't need to build anything to use it. That's how we love it.

    Quick Start

    You can install gitlib using Composer. Simply require the version you need:

    $ composer require gitonomy/gitlib
    

    or edit your composer.json file by hand:

    {
        "require": {
            "gitonomy/gitlib": "^1.3"
        }
    }
    

    Example Usage

    <?php
    
    use Gitonomy\Git\Repository;
    
    $repository = new Repository('/path/to/repository');
    
    foreach ($repository->getReferences()->getBranches() as $branch) {
        echo '- '.$branch->getName().PHP_EOL;
    }
    
    $repository->run('fetch', ['--all']);
    

    API Documentation

    For Enterprise

    Available as part of the Tidelift Subscription

    The maintainers of gitonomy/gitlib and thousands of other packages are working with Tidelift to deliver commercial support and maintenance for the open source dependencies you use to build your applications. Save time, reduce risk, and improve code health, while paying the maintainers of the exact dependencies you use. Learn more.

  • \GuzzleHttp Readme

    Guzzle

    Guzzle, PHP HTTP client

    Latest Version
    Build Status
    Total Downloads

    Guzzle is a PHP HTTP client that makes it easy to send HTTP requests and
    trivial to integrate with web services.

    • Simple interface for building query strings, POST requests, streaming large
      uploads, streaming large downloads, using HTTP cookies, uploading JSON data,
      etc...
    • Can send both synchronous and asynchronous requests using the same interface.
    • Uses PSR-7 interfaces for requests, responses, and streams. This allows you
      to utilize other PSR-7 compatible libraries with Guzzle.
    • Supports PSR-18 allowing interoperability between other PSR-18 HTTP Clients.
    • Abstracts away the underlying HTTP transport, allowing you to write
      environment and transport agnostic code; i.e., no hard dependency on cURL,
      PHP streams, sockets, or non-blocking event loops.
    • Middleware system allows you to augment and compose client behavior.
    $client = new \GuzzleHttp\Client();
    $response = $client->request('GET', 'https://api.github.com/repos/guzzle/guzzle');
    
    echo $response->getStatusCode(); // 200
    echo $response->getHeaderLine('content-type'); // 'application/json; charset=utf8'
    echo $response->getBody(); // '{"id": 1420053, "name": "guzzle", ...}'
    
    // Send an asynchronous request.
    $request = new \GuzzleHttp\Psr7\Request('GET', 'http://httpbin.org');
    $promise = $client->sendAsync($request)->then(function ($response) {
        echo 'I completed! ' . $response->getBody();
    });
    
    $promise->wait();
    

    Help and docs

    We use GitHub issues only to discuss bugs and new features. For support please refer to:

    Installing Guzzle

    The recommended way to install Guzzle is through
    Composer.

    composer require guzzlehttp/guzzle
    

    Version Guidance

    Version Status Packagist Namespace Repo Docs PSR-7 PHP Version
    3.x EOL guzzle/guzzle Guzzle v3 v3 No >= 5.3.3
    4.x EOL guzzlehttp/guzzle GuzzleHttp v4 N/A No >= 5.4
    5.x EOL guzzlehttp/guzzle GuzzleHttp v5 v5 No >= 5.4
    6.x Security fixes guzzlehttp/guzzle GuzzleHttp v6 v6 Yes >= 5.5
    7.x Latest guzzlehttp/guzzle GuzzleHttp v7 v7 Yes >= 7.2

    Security

    If you discover a security vulnerability within this package, please send an email to security@tidelift.com. All security vulnerabilities will be promptly addressed. Please do not disclose security-related issues publicly until a fix has been announced. Please see Security Policy for more information.

    License

    Guzzle is made available under the MIT License (MIT). Please see License File for more information.

    For Enterprise

    Available as part of the Tidelift Subscription

    The maintainers of Guzzle and thousands of other packages are working with Tidelift to deliver commercial support and maintenance for the open source dependencies you use to build your applications. Save time, reduce risk, and improve code health, while paying the maintainers of the exact dependencies you use. Learn more.

  • \GuzzleHttp\Promise Readme

    Guzzle Promises

    Promises/A+ implementation that handles promise
    chaining and resolution iteratively, allowing for "infinite" promise chaining
    while keeping the stack size constant. Read this blog post
    for a general introduction to promises.

    Features

    • Promises/A+ implementation.
    • Promise resolution and chaining is handled iteratively, allowing for
      "infinite" promise chaining.
    • Promises have a synchronous wait method.
    • Promises can be cancelled.
    • Works with any object that has a then function.
    • C# style async/await coroutine promises using
      GuzzleHttp\Promise\Coroutine::of().

    Quick start

    A promise represents the eventual result of an asynchronous operation. The
    primary way of interacting with a promise is through its then method, which
    registers callbacks to receive either a promise's eventual value or the reason
    why the promise cannot be fulfilled.

    Callbacks

    Callbacks are registered with the then method by providing an optional
    $onFulfilled followed by an optional $onRejected function.

    use GuzzleHttp\Promise\Promise;
    
    $promise = new Promise();
    $promise->then(
        // $onFulfilled
        function ($value) {
            echo 'The promise was fulfilled.';
        },
        // $onRejected
        function ($reason) {
            echo 'The promise was rejected.';
        }
    );
    

    Resolving a promise means that you either fulfill a promise with a value or
    reject a promise with a reason. Resolving a promises triggers callbacks
    registered with the promises's then method. These callbacks are triggered
    only once and in the order in which they were added.

    Resolving a promise

    Promises are fulfilled using the resolve($value) method. Resolving a promise
    with any value other than a GuzzleHttp\Promise\RejectedPromise will trigger
    all of the onFulfilled callbacks (resolving a promise with a rejected promise
    will reject the promise and trigger the $onRejected callbacks).

    use GuzzleHttp\Promise\Promise;
    
    $promise = new Promise();
    $promise
        ->then(function ($value) {
            // Return a value and don't break the chain
            return "Hello, " . $value;
        })
        // This then is executed after the first then and receives the value
        // returned from the first then.
        ->then(function ($value) {
            echo $value;
        });
    
    // Resolving the promise triggers the $onFulfilled callbacks and outputs
    // "Hello, reader."
    $promise->resolve('reader.');
    

    Promise forwarding

    Promises can be chained one after the other. Each then in the chain is a new
    promise. The return value of a promise is what's forwarded to the next
    promise in the chain. Returning a promise in a then callback will cause the
    subsequent promises in the chain to only be fulfilled when the returned promise
    has been fulfilled. The next promise in the chain will be invoked with the
    resolved value of the promise.

    use GuzzleHttp\Promise\Promise;
    
    $promise = new Promise();
    $nextPromise = new Promise();
    
    $promise
        ->then(function ($value) use ($nextPromise) {
            echo $value;
            return $nextPromise;
        })
        ->then(function ($value) {
            echo $value;
        });
    
    // Triggers the first callback and outputs "A"
    $promise->resolve('A');
    // Triggers the second callback and outputs "B"
    $nextPromise->resolve('B');
    

    Promise rejection

    When a promise is rejected, the $onRejected callbacks are invoked with the
    rejection reason.

    use GuzzleHttp\Promise\Promise;
    
    $promise = new Promise();
    $promise->then(null, function ($reason) {
        echo $reason;
    });
    
    $promise->reject('Error!');
    // Outputs "Error!"
    

    Rejection forwarding

    If an exception is thrown in an $onRejected callback, subsequent
    $onRejected callbacks are invoked with the thrown exception as the reason.

    use GuzzleHttp\Promise\Promise;
    
    $promise = new Promise();
    $promise->then(null, function ($reason) {
        throw new Exception($reason);
    })->then(null, function ($reason) {
        assert($reason->getMessage() === 'Error!');
    });
    
    $promise->reject('Error!');
    

    You can also forward a rejection down the promise chain by returning a
    GuzzleHttp\Promise\RejectedPromise in either an $onFulfilled or
    $onRejected callback.

    use GuzzleHttp\Promise\Promise;
    use GuzzleHttp\Promise\RejectedPromise;
    
    $promise = new Promise();
    $promise->then(null, function ($reason) {
        return new RejectedPromise($reason);
    })->then(null, function ($reason) {
        assert($reason === 'Error!');
    });
    
    $promise->reject('Error!');
    

    If an exception is not thrown in a $onRejected callback and the callback
    does not return a rejected promise, downstream $onFulfilled callbacks are
    invoked using the value returned from the $onRejected callback.

    use GuzzleHttp\Promise\Promise;
    
    $promise = new Promise();
    $promise
        ->then(null, function ($reason) {
            return "It's ok";
        })
        ->then(function ($value) {
            assert($value === "It's ok");
        });
    
    $promise->reject('Error!');
    

    Synchronous wait

    You can synchronously force promises to complete using a promise's wait
    method. When creating a promise, you can provide a wait function that is used
    to synchronously force a promise to complete. When a wait function is invoked
    it is expected to deliver a value to the promise or reject the promise. If the
    wait function does not deliver a value, then an exception is thrown. The wait
    function provided to a promise constructor is invoked when the wait function
    of the promise is called.

    $promise = new Promise(function () use (&$promise) {
        $promise->resolve('foo');
    });
    
    // Calling wait will return the value of the promise.
    echo $promise->wait(); // outputs "foo"
    

    If an exception is encountered while invoking the wait function of a promise,
    the promise is rejected with the exception and the exception is thrown.

    $promise = new Promise(function () use (&$promise) {
        throw new Exception('foo');
    });
    
    $promise->wait(); // throws the exception.
    

    Calling wait on a promise that has been fulfilled will not trigger the wait
    function. It will simply return the previously resolved value.

    $promise = new Promise(function () { die('this is not called!'); });
    $promise->resolve('foo');
    echo $promise->wait(); // outputs "foo"
    

    Calling wait on a promise that has been rejected will throw an exception. If
    the rejection reason is an instance of \Exception the reason is thrown.
    Otherwise, a GuzzleHttp\Promise\RejectionException is thrown and the reason
    can be obtained by calling the getReason method of the exception.

    $promise = new Promise();
    $promise->reject('foo');
    $promise->wait();
    

    PHP Fatal error: Uncaught exception 'GuzzleHttp\Promise\RejectionException' with message 'The promise was rejected with value: foo'

    Unwrapping a promise

    When synchronously waiting on a promise, you are joining the state of the
    promise into the current state of execution (i.e., return the value of the
    promise if it was fulfilled or throw an exception if it was rejected). This is
    called "unwrapping" the promise. Waiting on a promise will by default unwrap
    the promise state.

    You can force a promise to resolve and not unwrap the state of the promise
    by passing false to the first argument of the wait function:

    $promise = new Promise();
    $promise->reject('foo');
    // This will not throw an exception. It simply ensures the promise has
    // been resolved.
    $promise->wait(false);
    

    When unwrapping a promise, the resolved value of the promise will be waited
    upon until the unwrapped value is not a promise. This means that if you resolve
    promise A with a promise B and unwrap promise A, the value returned by the
    wait function will be the value delivered to promise B.

    Note: when you do not unwrap the promise, no value is returned.

    Cancellation

    You can cancel a promise that has not yet been fulfilled using the cancel()
    method of a promise. When creating a promise you can provide an optional
    cancel function that when invoked cancels the action of computing a resolution
    of the promise.

    API

    Promise

    When creating a promise object, you can provide an optional $waitFn and
    $cancelFn. $waitFn is a function that is invoked with no arguments and is
    expected to resolve the promise. $cancelFn is a function with no arguments
    that is expected to cancel the computation of a promise. It is invoked when the
    cancel() method of a promise is called.

    use GuzzleHttp\Promise\Promise;
    
    $promise = new Promise(
        function () use (&$promise) {
            $promise->resolve('waited');
        },
        function () {
            // do something that will cancel the promise computation (e.g., close
            // a socket, cancel a database query, etc...)
        }
    );
    
    assert('waited' === $promise->wait());
    

    A promise has the following methods:

    • then(callable $onFulfilled, callable $onRejected) : PromiseInterface

      Appends fulfillment and rejection handlers to the promise, and returns a new promise resolving to the return value of the called handler.

    • otherwise(callable $onRejected) : PromiseInterface

      Appends a rejection handler callback to the promise, and returns a new promise resolving to the return value of the callback if it is called, or to its original fulfillment value if the promise is instead fulfilled.

    • wait($unwrap = true) : mixed

      Synchronously waits on the promise to complete.

      $unwrap controls whether or not the value of the promise is returned for a
      fulfilled promise or if an exception is thrown if the promise is rejected.
      This is set to true by default.

    • cancel()

      Attempts to cancel the promise if possible. The promise being cancelled and
      the parent most ancestor that has not yet been resolved will also be
      cancelled. Any promises waiting on the cancelled promise to resolve will also
      be cancelled.

    • getState() : string

      Returns the state of the promise. One of pending, fulfilled, or
      rejected.

    • resolve($value)

      Fulfills the promise with the given $value.

    • reject($reason)

      Rejects the promise with the given $reason.

    FulfilledPromise

    A fulfilled promise can be created to represent a promise that has been
    fulfilled.

    use GuzzleHttp\Promise\FulfilledPromise;
    
    $promise = new FulfilledPromise('value');
    
    // Fulfilled callbacks are immediately invoked.
    $promise->then(function ($value) {
        echo $value;
    });
    

    RejectedPromise

    A rejected promise can be created to represent a promise that has been
    rejected.

    use GuzzleHttp\Promise\RejectedPromise;
    
    $promise = new RejectedPromise('Error');
    
    // Rejected callbacks are immediately invoked.
    $promise->then(null, function ($reason) {
        echo $reason;
    });
    

    Promise interop

    This library works with foreign promises that have a then method. This means
    you can use Guzzle promises with React promises
    for example. When a foreign promise is returned inside of a then method
    callback, promise resolution will occur recursively.

    // Create a React promise
    $deferred = new React\Promise\Deferred();
    $reactPromise = $deferred->promise();
    
    // Create a Guzzle promise that is fulfilled with a React promise.
    $guzzlePromise = new GuzzleHttp\Promise\Promise();
    $guzzlePromise->then(function ($value) use ($reactPromise) {
        // Do something something with the value...
        // Return the React promise
        return $reactPromise;
    });
    

    Please note that wait and cancel chaining is no longer possible when forwarding
    a foreign promise. You will need to wrap a third-party promise with a Guzzle
    promise in order to utilize wait and cancel functions with foreign promises.

    Event Loop Integration

    In order to keep the stack size constant, Guzzle promises are resolved
    asynchronously using a task queue. When waiting on promises synchronously, the
    task queue will be automatically run to ensure that the blocking promise and
    any forwarded promises are resolved. When using promises asynchronously in an
    event loop, you will need to run the task queue on each tick of the loop. If
    you do not run the task queue, then promises will not be resolved.

    You can run the task queue using the run() method of the global task queue
    instance.

    // Get the global task queue
    $queue = GuzzleHttp\Promise\Utils::queue();
    $queue->run();
    

    For example, you could use Guzzle promises with React using a periodic timer:

    $loop = React\EventLoop\Factory::create();
    $loop->addPeriodicTimer(0, [$queue, 'run']);
    

    TODO: Perhaps adding a futureTick() on each tick would be faster?

    Implementation notes

    Promise resolution and chaining is handled iteratively

    By shuffling pending handlers from one owner to another, promises are
    resolved iteratively, allowing for "infinite" then chaining.

    <?php
    require 'vendor/autoload.php';
    
    use GuzzleHttp\Promise\Promise;
    
    $parent = new Promise();
    $p = $parent;
    
    for ($i = 0; $i < 1000; $i++) {
        $p = $p->then(function ($v) {
            // The stack size remains constant (a good thing)
            echo xdebug_get_stack_depth() . ', ';
            return $v + 1;
        });
    }
    
    $parent->resolve(0);
    var_dump($p->wait()); // int(1000)
    
    

    When a promise is fulfilled or rejected with a non-promise value, the promise
    then takes ownership of the handlers of each child promise and delivers values
    down the chain without using recursion.

    When a promise is resolved with another promise, the original promise transfers
    all of its pending handlers to the new promise. When the new promise is
    eventually resolved, all of the pending handlers are delivered the forwarded
    value.

    A promise is the deferred.

    Some promise libraries implement promises using a deferred object to represent
    a computation and a promise object to represent the delivery of the result of
    the computation. This is a nice separation of computation and delivery because
    consumers of the promise cannot modify the value that will be eventually
    delivered.

    One side effect of being able to implement promise resolution and chaining
    iteratively is that you need to be able for one promise to reach into the state
    of another promise to shuffle around ownership of handlers. In order to achieve
    this without making the handlers of a promise publicly mutable, a promise is
    also the deferred value, allowing promises of the same parent class to reach
    into and modify the private properties of promises of the same type. While this
    does allow consumers of the value to modify the resolution or rejection of the
    deferred, it is a small price to pay for keeping the stack size constant.

    $promise = new Promise();
    $promise->then(function ($value) { echo $value; });
    // The promise is the deferred value, so you can deliver a value to it.
    $promise->resolve('foo');
    // prints "foo"
    

    Upgrading from Function API

    A static API was first introduced in 1.4.0, in order to mitigate problems with functions conflicting between global and local copies of the package. The function API will be removed in 2.0.0. A migration table has been provided here for your convenience:

    Original Function Replacement Method
    queue Utils::queue
    task Utils::task
    promise_for Create::promiseFor
    rejection_for Create::rejectionFor
    exception_for Create::exceptionFor
    iter_for Create::iterFor
    inspect Utils::inspect
    inspect_all Utils::inspectAll
    unwrap Utils::unwrap
    all Utils::all
    some Utils::some
    any Utils::any
    settle Utils::settle
    each Each::of
    each_limit Each::ofLimit
    each_limit_all Each::ofLimitAll
    !is_fulfilled Is::pending
    is_fulfilled Is::fulfilled
    is_rejected Is::rejected
    is_settled Is::settled
    coroutine Coroutine::of

    Security

    If you discover a security vulnerability within this package, please send an email to security@tidelift.com. All security vulnerabilities will be promptly addressed. Please do not disclose security-related issues publicly until a fix has been announced. Please see Security Policy for more information.

    License

    Guzzle is made available under the MIT License (MIT). Please see License File for more information.

    For Enterprise

    Available as part of the Tidelift Subscription

    The maintainers of Guzzle and thousands of other packages are working with Tidelift to deliver commercial support and maintenance for the open source dependencies you use to build your applications. Save time, reduce risk, and improve code health, while paying the maintainers of the exact dependencies you use. Learn more.

  • \GuzzleHttp\Psr7 Readme

    PSR-7 Message Implementation

    This repository contains a full PSR-7
    message implementation, several stream decorators, and some helpful
    functionality like query string parsing.

    CI
    Static analysis

    Stream implementation

    This package comes with a number of stream implementations and stream
    decorators.

    AppendStream

    GuzzleHttp\Psr7\AppendStream

    Reads from multiple streams, one after the other.

    use GuzzleHttp\Psr7;
    
    $a = Psr7\Utils::streamFor('abc, ');
    $b = Psr7\Utils::streamFor('123.');
    $composed = new Psr7\AppendStream([$a, $b]);
    
    $composed->addStream(Psr7\Utils::streamFor(' Above all listen to me'));
    
    echo $composed; // abc, 123. Above all listen to me.
    

    BufferStream

    GuzzleHttp\Psr7\BufferStream

    Provides a buffer stream that can be written to fill a buffer, and read
    from to remove bytes from the buffer.

    This stream returns a "hwm" metadata value that tells upstream consumers
    what the configured high water mark of the stream is, or the maximum
    preferred size of the buffer.

    use GuzzleHttp\Psr7;
    
    // When more than 1024 bytes are in the buffer, it will begin returning
    // false to writes. This is an indication that writers should slow down.
    $buffer = new Psr7\BufferStream(1024);
    

    CachingStream

    The CachingStream is used to allow seeking over previously read bytes on
    non-seekable streams. This can be useful when transferring a non-seekable
    entity body fails due to needing to rewind the stream (for example, resulting
    from a redirect). Data that is read from the remote stream will be buffered in
    a PHP temp stream so that previously read bytes are cached first in memory,
    then on disk.

    use GuzzleHttp\Psr7;
    
    $original = Psr7\Utils::streamFor(fopen('http://www.google.com', 'r'));
    $stream = new Psr7\CachingStream($original);
    
    $stream->read(1024);
    echo $stream->tell();
    // 1024
    
    $stream->seek(0);
    echo $stream->tell();
    // 0
    

    DroppingStream

    GuzzleHttp\Psr7\DroppingStream

    Stream decorator that begins dropping data once the size of the underlying
    stream becomes too full.

    use GuzzleHttp\Psr7;
    
    // Create an empty stream
    $stream = Psr7\Utils::streamFor();
    
    // Start dropping data when the stream has more than 10 bytes
    $dropping = new Psr7\DroppingStream($stream, 10);
    
    $dropping->write('01234567890123456789');
    echo $stream; // 0123456789
    

    FnStream

    GuzzleHttp\Psr7\FnStream

    Compose stream implementations based on a hash of functions.

    Allows for easy testing and extension of a provided stream without needing
    to create a concrete class for a simple extension point.

    
    use GuzzleHttp\Psr7;
    
    $stream = Psr7\Utils::streamFor('hi');
    $fnStream = Psr7\FnStream::decorate($stream, [
        'rewind' => function () use ($stream) {
            echo 'About to rewind - ';
            $stream->rewind();
            echo 'rewound!';
        }
    ]);
    
    $fnStream->rewind();
    // Outputs: About to rewind - rewound!
    

    InflateStream

    GuzzleHttp\Psr7\InflateStream

    Uses PHP's zlib.inflate filter to inflate zlib (HTTP deflate, RFC1950) or gzipped (RFC1952) content.

    This stream decorator converts the provided stream to a PHP stream resource,
    then appends the zlib.inflate filter. The stream is then converted back
    to a Guzzle stream resource to be used as a Guzzle stream.

    LazyOpenStream

    GuzzleHttp\Psr7\LazyOpenStream

    Lazily reads or writes to a file that is opened only after an IO operation
    take place on the stream.

    use GuzzleHttp\Psr7;
    
    $stream = new Psr7\LazyOpenStream('/path/to/file', 'r');
    // The file has not yet been opened...
    
    echo $stream->read(10);
    // The file is opened and read from only when needed.
    

    LimitStream

    GuzzleHttp\Psr7\LimitStream

    LimitStream can be used to read a subset or slice of an existing stream object.
    This can be useful for breaking a large file into smaller pieces to be sent in
    chunks (e.g. Amazon S3's multipart upload API).

    use GuzzleHttp\Psr7;
    
    $original = Psr7\Utils::streamFor(fopen('/tmp/test.txt', 'r+'));
    echo $original->getSize();
    // >>> 1048576
    
    // Limit the size of the body to 1024 bytes and start reading from byte 2048
    $stream = new Psr7\LimitStream($original, 1024, 2048);
    echo $stream->getSize();
    // >>> 1024
    echo $stream->tell();
    // >>> 0
    

    MultipartStream

    GuzzleHttp\Psr7\MultipartStream

    Stream that when read returns bytes for a streaming multipart or
    multipart/form-data stream.

    NoSeekStream

    GuzzleHttp\Psr7\NoSeekStream

    NoSeekStream wraps a stream and does not allow seeking.

    use GuzzleHttp\Psr7;
    
    $original = Psr7\Utils::streamFor('foo');
    $noSeek = new Psr7\NoSeekStream($original);
    
    echo $noSeek->read(3);
    // foo
    var_export($noSeek->isSeekable());
    // false
    $noSeek->seek(0);
    var_export($noSeek->read(3));
    // NULL
    

    PumpStream

    GuzzleHttp\Psr7\PumpStream

    Provides a read only stream that pumps data from a PHP callable.

    When invoking the provided callable, the PumpStream will pass the amount of
    data requested to read to the callable. The callable can choose to ignore
    this value and return fewer or more bytes than requested. Any extra data
    returned by the provided callable is buffered internally until drained using
    the read() function of the PumpStream. The provided callable MUST return
    false when there is no more data to read.

    Implementing stream decorators

    Creating a stream decorator is very easy thanks to the
    GuzzleHttp\Psr7\StreamDecoratorTrait. This trait provides methods that
    implement Psr\Http\Message\StreamInterface by proxying to an underlying
    stream. Just use the StreamDecoratorTrait and implement your custom
    methods.

    For example, let's say we wanted to call a specific function each time the last
    byte is read from a stream. This could be implemented by overriding the
    read() method.

    use Psr\Http\Message\StreamInterface;
    use GuzzleHttp\Psr7\StreamDecoratorTrait;
    
    class EofCallbackStream implements StreamInterface
    {
        use StreamDecoratorTrait;
    
        private $callback;
    
        public function __construct(StreamInterface $stream, callable $cb)
        {
            $this->stream = $stream;
            $this->callback = $cb;
        }
    
        public function read($length)
        {
            $result = $this->stream->read($length);
    
            // Invoke the callback when EOF is hit.
            if ($this->eof()) {
                call_user_func($this->callback);
            }
    
            return $result;
        }
    }
    

    This decorator could be added to any existing stream and used like so:

    use GuzzleHttp\Psr7;
    
    $original = Psr7\Utils::streamFor('foo');
    
    $eofStream = new EofCallbackStream($original, function () {
        echo 'EOF!';
    });
    
    $eofStream->read(2);
    $eofStream->read(1);
    // echoes "EOF!"
    $eofStream->seek(0);
    $eofStream->read(3);
    // echoes "EOF!"
    

    PHP StreamWrapper

    You can use the GuzzleHttp\Psr7\StreamWrapper class if you need to use a
    PSR-7 stream as a PHP stream resource.

    Use the GuzzleHttp\Psr7\StreamWrapper::getResource() method to create a PHP
    stream from a PSR-7 stream.

    use GuzzleHttp\Psr7\StreamWrapper;
    
    $stream = GuzzleHttp\Psr7\Utils::streamFor('hello!');
    $resource = StreamWrapper::getResource($stream);
    echo fread($resource, 6); // outputs hello!
    

    Static API

    There are various static methods available under the GuzzleHttp\Psr7 namespace.

    GuzzleHttp\Psr7\Message::toString

    public static function toString(MessageInterface $message): string

    Returns the string representation of an HTTP message.

    $request = new GuzzleHttp\Psr7\Request('GET', 'http://example.com');
    echo GuzzleHttp\Psr7\Message::toString($request);
    

    GuzzleHttp\Psr7\Message::bodySummary

    public static function bodySummary(MessageInterface $message, int $truncateAt = 120): string|null

    Get a short summary of the message body.

    Will return null if the response is not printable.

    GuzzleHttp\Psr7\Message::rewindBody

    public static function rewindBody(MessageInterface $message): void

    Attempts to rewind a message body and throws an exception on failure.

    The body of the message will only be rewound if a call to tell()
    returns a value other than 0.

    GuzzleHttp\Psr7\Message::parseMessage

    public static function parseMessage(string $message): array

    Parses an HTTP message into an associative array.

    The array contains the "start-line" key containing the start line of
    the message, "headers" key containing an associative array of header
    array values, and a "body" key containing the body of the message.

    GuzzleHttp\Psr7\Message::parseRequestUri

    public static function parseRequestUri(string $path, array $headers): string

    Constructs a URI for an HTTP request message.

    GuzzleHttp\Psr7\Message::parseRequest

    public static function parseRequest(string $message): Request

    Parses a request message string into a request object.

    GuzzleHttp\Psr7\Message::parseResponse

    public static function parseResponse(string $message): Response

    Parses a response message string into a response object.

    GuzzleHttp\Psr7\Header::parse

    public static function parse(string|array $header): array

    Parse an array of header values containing ";" separated data into an
    array of associative arrays representing the header key value pair data
    of the header. When a parameter does not contain a value, but just
    contains a key, this function will inject a key with a '' string value.

    GuzzleHttp\Psr7\Header::normalize

    public static function normalize(string|array $header): array

    Converts an array of header values that may contain comma separated
    headers into an array of headers with no comma separated values.

    GuzzleHttp\Psr7\Query::parse

    public static function parse(string $str, int|bool $urlEncoding = true): array

    Parse a query string into an associative array.

    If multiple values are found for the same key, the value of that key
    value pair will become an array. This function does not parse nested
    PHP style arrays into an associative array (e.g., foo[a]=1&foo[b]=2
    will be parsed into ['foo[a]' => '1', 'foo[b]' => '2']).

    GuzzleHttp\Psr7\Query::build

    public static function build(array $params, int|false $encoding = PHP_QUERY_RFC3986): string

    Build a query string from an array of key value pairs.

    This function can use the return value of parse() to build a query
    string. This function does not modify the provided keys when an array is
    encountered (like http_build_query() would).

    GuzzleHttp\Psr7\Utils::caselessRemove

    public static function caselessRemove(iterable<string> $keys, $keys, array $data): array

    Remove the items given by the keys, case insensitively from the data.

    GuzzleHttp\Psr7\Utils::copyToStream

    public static function copyToStream(StreamInterface $source, StreamInterface $dest, int $maxLen = -1): void

    Copy the contents of a stream into another stream until the given number
    of bytes have been read.

    GuzzleHttp\Psr7\Utils::copyToString

    public static function copyToString(StreamInterface $stream, int $maxLen = -1): string

    Copy the contents of a stream into a string until the given number of
    bytes have been read.

    GuzzleHttp\Psr7\Utils::hash

    public static function hash(StreamInterface $stream, string $algo, bool $rawOutput = false): string

    Calculate a hash of a stream.

    This method reads the entire stream to calculate a rolling hash, based on
    PHP's hash_init functions.

    GuzzleHttp\Psr7\Utils::modifyRequest

    public static function modifyRequest(RequestInterface $request, array $changes): RequestInterface

    Clone and modify a request with the given changes.

    This method is useful for reducing the number of clones needed to mutate
    a message.

    • method: (string) Changes the HTTP method.
    • set_headers: (array) Sets the given headers.
    • remove_headers: (array) Remove the given headers.
    • body: (mixed) Sets the given body.
    • uri: (UriInterface) Set the URI.
    • query: (string) Set the query string value of the URI.
    • version: (string) Set the protocol version.

    GuzzleHttp\Psr7\Utils::readLine

    public static function readLine(StreamInterface $stream, int $maxLength = null): string

    Read a line from the stream up to the maximum allowed buffer length.

    GuzzleHttp\Psr7\Utils::streamFor

    public static function streamFor(resource|string|null|int|float|bool|StreamInterface|callable|\Iterator $resource = '', array $options = []): StreamInterface

    Create a new stream based on the input type.

    Options is an associative array that can contain the following keys:

    • metadata: Array of custom metadata.
    • size: Size of the stream.

    This method accepts the following $resource types:

    • Psr\Http\Message\StreamInterface: Returns the value as-is.
    • string: Creates a stream object that uses the given string as the contents.
    • resource: Creates a stream object that wraps the given PHP stream resource.
    • Iterator: If the provided value implements Iterator, then a read-only
      stream object will be created that wraps the given iterable. Each time the
      stream is read from, data from the iterator will fill a buffer and will be
      continuously called until the buffer is equal to the requested read size.
      Subsequent read calls will first read from the buffer and then call next
      on the underlying iterator until it is exhausted.
    • object with __toString(): If the object has the __toString() method,
      the object will be cast to a string and then a stream will be returned that
      uses the string value.
    • NULL: When null is passed, an empty stream object is returned.
    • callable When a callable is passed, a read-only stream object will be
      created that invokes the given callable. The callable is invoked with the
      number of suggested bytes to read. The callable can return any number of
      bytes, but MUST return false when there is no more data to return. The
      stream object that wraps the callable will invoke the callable until the
      number of requested bytes are available. Any additional bytes will be
      buffered and used in subsequent reads.
    $stream = GuzzleHttp\Psr7\Utils::streamFor('foo');
    $stream = GuzzleHttp\Psr7\Utils::streamFor(fopen('/path/to/file', 'r'));
    
    $generator = function ($bytes) {
        for ($i = 0; $i < $bytes; $i++) {
            yield ' ';
        }
    }
    
    $stream = GuzzleHttp\Psr7\Utils::streamFor($generator(100));
    

    GuzzleHttp\Psr7\Utils::tryFopen

    public static function tryFopen(string $filename, string $mode): resource

    Safely opens a PHP stream resource using a filename.

    When fopen fails, PHP normally raises a warning. This function adds an
    error handler that checks for errors and throws an exception instead.

    GuzzleHttp\Psr7\Utils::uriFor

    public static function uriFor(string|UriInterface $uri): UriInterface

    Returns a UriInterface for the given value.

    This function accepts a string or UriInterface and returns a
    UriInterface for the given value. If the value is already a
    UriInterface, it is returned as-is.

    GuzzleHttp\Psr7\MimeType::fromFilename

    public static function fromFilename(string $filename): string|null

    Determines the mimetype of a file by looking at its extension.

    GuzzleHttp\Psr7\MimeType::fromExtension

    public static function fromExtension(string $extension): string|null

    Maps a file extensions to a mimetype.

    Upgrading from Function API

    The static API was first introduced in 1.7.0, in order to mitigate problems with functions conflicting between global and local copies of the package. The function API was removed in 2.0.0. A migration table has been provided here for your convenience:

    Original Function Replacement Method
    str Message::toString
    uri_for Utils::uriFor
    stream_for Utils::streamFor
    parse_header Header::parse
    normalize_header Header::normalize
    modify_request Utils::modifyRequest
    rewind_body Message::rewindBody
    try_fopen Utils::tryFopen
    copy_to_string Utils::copyToString
    copy_to_stream Utils::copyToStream
    hash Utils::hash
    readline Utils::readLine
    parse_request Message::parseRequest
    parse_response Message::parseResponse
    parse_query Query::parse
    build_query Query::build
    mimetype_from_filename MimeType::fromFilename
    mimetype_from_extension MimeType::fromExtension
    _parse_message Message::parseMessage
    _parse_request_uri Message::parseRequestUri
    get_message_body_summary Message::bodySummary
    _caseless_remove Utils::caselessRemove

    Additional URI Methods

    Aside from the standard Psr\Http\Message\UriInterface implementation in form of the GuzzleHttp\Psr7\Uri class,
    this library also provides additional functionality when working with URIs as static methods.

    URI Types

    An instance of Psr\Http\Message\UriInterface can either be an absolute URI or a relative reference.
    An absolute URI has a scheme. A relative reference is used to express a URI relative to another URI,
    the base URI. Relative references can be divided into several forms according to
    RFC 3986 Section 4.2:

    • network-path references, e.g. //example.com/path
    • absolute-path references, e.g. /path
    • relative-path references, e.g. subpath

    The following methods can be used to identify the type of the URI.

    GuzzleHttp\Psr7\Uri::isAbsolute

    public static function isAbsolute(UriInterface $uri): bool

    Whether the URI is absolute, i.e. it has a scheme.

    GuzzleHttp\Psr7\Uri::isNetworkPathReference

    public static function isNetworkPathReference(UriInterface $uri): bool

    Whether the URI is a network-path reference. A relative reference that begins with two slash characters is
    termed an network-path reference.

    GuzzleHttp\Psr7\Uri::isAbsolutePathReference

    public static function isAbsolutePathReference(UriInterface $uri): bool

    Whether the URI is a absolute-path reference. A relative reference that begins with a single slash character is
    termed an absolute-path reference.

    GuzzleHttp\Psr7\Uri::isRelativePathReference

    public static function isRelativePathReference(UriInterface $uri): bool

    Whether the URI is a relative-path reference. A relative reference that does not begin with a slash character is
    termed a relative-path reference.

    GuzzleHttp\Psr7\Uri::isSameDocumentReference

    public static function isSameDocumentReference(UriInterface $uri, UriInterface $base = null): bool

    Whether the URI is a same-document reference. A same-document reference refers to a URI that is, aside from its
    fragment component, identical to the base URI. When no base URI is given, only an empty URI reference
    (apart from its fragment) is considered a same-document reference.

    URI Components

    Additional methods to work with URI components.

    GuzzleHttp\Psr7\Uri::isDefaultPort

    public static function isDefaultPort(UriInterface $uri): bool

    Whether the URI has the default port of the current scheme. Psr\Http\Message\UriInterface::getPort may return null
    or the standard port. This method can be used independently of the implementation.

    GuzzleHttp\Psr7\Uri::composeComponents

    public static function composeComponents($scheme, $authority, $path, $query, $fragment): string

    Composes a URI reference string from its various components according to
    RFC 3986 Section 5.3. Usually this method does not need to be called
    manually but instead is used indirectly via Psr\Http\Message\UriInterface::__toString.

    GuzzleHttp\Psr7\Uri::fromParts

    public static function fromParts(array $parts): UriInterface

    Creates a URI from a hash of parse_url components.

    GuzzleHttp\Psr7\Uri::withQueryValue

    public static function withQueryValue(UriInterface $uri, $key, $value): UriInterface

    Creates a new URI with a specific query string value. Any existing query string values that exactly match the
    provided key are removed and replaced with the given key value pair. A value of null will set the query string
    key without a value, e.g. "key" instead of "key=value".

    GuzzleHttp\Psr7\Uri::withQueryValues

    public static function withQueryValues(UriInterface $uri, array $keyValueArray): UriInterface

    Creates a new URI with multiple query string values. It has the same behavior as withQueryValue() but for an
    associative array of key => value.

    GuzzleHttp\Psr7\Uri::withoutQueryValue

    public static function withoutQueryValue(UriInterface $uri, $key): UriInterface

    Creates a new URI with a specific query string value removed. Any existing query string values that exactly match the
    provided key are removed.

    Reference Resolution

    GuzzleHttp\Psr7\UriResolver provides methods to resolve a URI reference in the context of a base URI according
    to RFC 3986 Section 5. This is for example also what web browsers
    do when resolving a link in a website based on the current request URI.

    GuzzleHttp\Psr7\UriResolver::resolve

    public static function resolve(UriInterface $base, UriInterface $rel): UriInterface

    Converts the relative URI into a new URI that is resolved against the base URI.

    GuzzleHttp\Psr7\UriResolver::removeDotSegments

    public static function removeDotSegments(string $path): string

    Removes dot segments from a path and returns the new path according to
    RFC 3986 Section 5.2.4.

    GuzzleHttp\Psr7\UriResolver::relativize

    public static function relativize(UriInterface $base, UriInterface $target): UriInterface

    Returns the target URI as a relative reference from the base URI. This method is the counterpart to resolve():

    (string) $target === (string) UriResolver::resolve($base, UriResolver::relativize($base, $target))
    

    One use-case is to use the current request URI as base URI and then generate relative links in your documents
    to reduce the document size or offer self-contained downloadable document archives.

    $base = new Uri('http://example.com/a/b/');
    echo UriResolver::relativize($base, new Uri('http://example.com/a/b/c'));  // prints 'c'.
    echo UriResolver::relativize($base, new Uri('http://example.com/a/x/y'));  // prints '../x/y'.
    echo UriResolver::relativize($base, new Uri('http://example.com/a/b/?q')); // prints '?q'.
    echo UriResolver::relativize($base, new Uri('http://example.org/a/b/'));   // prints '//example.org/a/b/'.
    

    Normalization and Comparison

    GuzzleHttp\Psr7\UriNormalizer provides methods to normalize and compare URIs according to
    RFC 3986 Section 6.

    GuzzleHttp\Psr7\UriNormalizer::normalize

    public static function normalize(UriInterface $uri, $flags = self::PRESERVING_NORMALIZATIONS): UriInterface

    Returns a normalized URI. The scheme and host component are already normalized to lowercase per PSR-7 UriInterface.
    This methods adds additional normalizations that can be configured with the $flags parameter which is a bitmask
    of normalizations to apply. The following normalizations are available:

    • UriNormalizer::PRESERVING_NORMALIZATIONS

      Default normalizations which only include the ones that preserve semantics.

    • UriNormalizer::CAPITALIZE_PERCENT_ENCODING

      All letters within a percent-encoding triplet (e.g., "%3A") are case-insensitive, and should be capitalized.

      Example: http://example.org/a%c2%b1bhttp://example.org/a%C2%B1b

    • UriNormalizer::DECODE_UNRESERVED_CHARACTERS

      Decodes percent-encoded octets of unreserved characters. For consistency, percent-encoded octets in the ranges of
      ALPHA (%41–%5A and %61–%7A), DIGIT (%30–%39), hyphen (%2D), period (%2E), underscore (%5F), or tilde (%7E) should
      not be created by URI producers and, when found in a URI, should be decoded to their corresponding unreserved
      characters by URI normalizers.

      Example: http://example.org/%7Eusern%61me/http://example.org/~username/

    • UriNormalizer::CONVERT_EMPTY_PATH

      Converts the empty path to "/" for http and https URIs.

      Example: http://example.orghttp://example.org/

    • UriNormalizer::REMOVE_DEFAULT_HOST

      Removes the default host of the given URI scheme from the URI. Only the "file" scheme defines the default host
      "localhost". All of file:/myfile, file:///myfile, and file://localhost/myfile are equivalent according to
      RFC 3986.

      Example: file://localhost/myfilefile:///myfile

    • UriNormalizer::REMOVE_DEFAULT_PORT

      Removes the default port of the given URI scheme from the URI.

      Example: http://example.org:80/http://example.org/

    • UriNormalizer::REMOVE_DOT_SEGMENTS

      Removes unnecessary dot-segments. Dot-segments in relative-path references are not removed as it would
      change the semantics of the URI reference.

      Example: http://example.org/../a/b/../c/./d.htmlhttp://example.org/a/c/d.html

    • UriNormalizer::REMOVE_DUPLICATE_SLASHES

      Paths which include two or more adjacent slashes are converted to one. Webservers usually ignore duplicate slashes
      and treat those URIs equivalent. But in theory those URIs do not need to be equivalent. So this normalization
      may change the semantics. Encoded slashes (%2F) are not removed.

      Example: http://example.org//foo///bar.htmlhttp://example.org/foo/bar.html

    • UriNormalizer::SORT_QUERY_PARAMETERS

      Sort query parameters with their values in alphabetical order. However, the order of parameters in a URI may be
      significant (this is not defined by the standard). So this normalization is not safe and may change the semantics
      of the URI.

      Example: ?lang=en&article=fred?article=fred&lang=en

    GuzzleHttp\Psr7\UriNormalizer::isEquivalent

    public static function isEquivalent(UriInterface $uri1, UriInterface $uri2, $normalizations = self::PRESERVING_NORMALIZATIONS): bool

    Whether two URIs can be considered equivalent. Both URIs are normalized automatically before comparison with the given
    $normalizations bitmask. The method also accepts relative URI references and returns true when they are equivalent.
    This of course assumes they will be resolved against the same base URI. If this is not the case, determination of
    equivalence or difference of relative references does not mean anything.

    Security

    If you discover a security vulnerability within this package, please send an email to security@tidelift.com. All security vulnerabilities will be promptly addressed. Please do not disclose security-related issues publicly until a fix has been announced. Please see Security Policy for more information.

    License

    Guzzle is made available under the MIT License (MIT). Please see License File for more information.

    For Enterprise

    Available as part of the Tidelift Subscription

    The maintainers of Guzzle and thousands of other packages are working with Tidelift to deliver commercial support and maintenance for the open source dependencies you use to build your applications. Save time, reduce risk, and improve code health, while paying the maintainers of the exact dependencies you use. Learn more.

  • \Highlight Readme

    highlight.php

    Unit Tests
    Latest Packagist release
    Monthly downloads on Packagist

    highlight.php is a server-side syntax highlighter written in PHP that currently supports 185 languages. It's a port of highlight.js by Ivan Sagalaev that makes full use of the language and style definitions of the original JavaScript project.

    This is the README for highlight.php v10, which is currently under development. The latest stable release is the 9.18.x series.

    Table of Contents

    Installation + Setup

    The recommended approach is to install the project through Composer.

    composer require scrivo/highlight.php
    

    If you're not using Composer, ensure that the classes defined in the Highlight namespace can be found either by inclusion or by an autoloader. A trivial autoloader for this purpose is included in this project as Highlight\Autoloader.php

    Composer Version Constraints

    When requiring this project in your composer.json, it is recommended you use the caret version range and use only the major and minor values; i.e. ^9.14.

    It's come to our attention that a lot of tutorials and projects out there are locking themselves into highly specific versions of this project; e.g. "scrivo/highlight.php": "v9.12.0.1". Please do not do this or encourage it. We promise a reliable backward compatibility policy so there's no reason to lock yourself to such a specific version. By doing this, you are preventing yourself or your users from receiving updates to language definitions and bug fixes.

    Usage

    The \Highlight\Highlighter class contains the syntax highlighting functionality. You can choose between two highlighting modes:

    1. explicit mode
    2. automatic language detection mode

    Explicit Mode

    In explicit mode, you must define which language you will be highlighting as.

    // Instantiate the Highlighter.
    $hl = new \Highlight\Highlighter();
    $code = file_get_contents('some_ruby_script.rb');
    
    try {
        // Highlight some code.
        $highlighted = $hl->highlight('ruby', $code);
    
        echo "<pre><code class=\"hljs {$highlighted->language}\">";
        echo $highlighted->value;
        echo "</code></pre>";
    }
    catch (DomainException $e) {
        // This is thrown if the specified language does not exist
    
        echo "<pre><code>";
        echo htmlentities($code);
        echo "</code></pre>";
    }
    

    Automatic Language Detection Mode

    Alternatively you can use the automatic detection mode, which highlights your code with the language the library thinks is best. It is highly recommended you explicitly choose the language or limit the number of languages to automatically detect to reduce the number of inaccuracies.

    Warning: Auto-detection occurs in a brute force fashion and the language with the most accurate result will be selected. This is extremely inefficient as you supply more languages and may not always be 100% accurate if similar languages are configured.

    $hl = new \Highlight\Highlighter();
    $hl->setAutodetectLanguages(array('ruby', 'python', 'perl'));
    
    $highlighted = $hl->highlightAuto(file_get_contents('some_ruby_script.rb'));
    
    echo "<pre><code class=\"hljs {$highlighted->language}\">";
    echo $highlighted->value;
    echo "</code></pre>";
    

    Default Languages

    If no autodetect languages are set in the highlighter, then every language will be used and cause significant performance issues.

    Stylesheets

    The same stylesheets available in the highlight.js project are available in the styles directory of this project and may be included in your own CSS or made accessible to your web server.

    Highlighter Utilities

    The core of the project is loyal port of highlight.js and is available under the main Highlight namespace. A series of convenience functions are provided under the HighlightUtilities namespace to introduce additional functionality without the need for another dependency.

    Available functions:

    Versioning

    This project will follow the same version numbers as the highlight.js project with regards to languages, meaning that a language definition available in highlight.js 9.12.0 will be available in highlight.php 9.12.0. However, there are times where bugs may arise in this project or its translated definition files, so there'll be one more number appended to the version number. For example, version 9.12.0.1 will contain all of the same languages as highlight.js 9.12.0 but also contain fixes solely to this project. This is done so this project can have version bumps without conflicts should highlight.js release version 9.12.1.

    Backward Compatibility Promise

    Despite the fact that the semantic versioning used in this project mirrors that of highlight.js, this project will adhere to Symfony's Backward Compatibility Promise. You can rest assured that there will be no breaking changes during 9.x and any deprecations will be marked with @deprecated and won't be removed until the next major release.

    Some History

    Geert Bergman
    Sep 30, 2013

    JavaScript code highlighting is very convenient and in many cases just what you want to use. Especially for programming blogs I would not advice you to use otherwise. But there are occasions where you're better off with a more 'static' approach, for instance if you want to send highlighted code in an email or for API documents. For this I needed a code highlighting program preferably written in PHP.

    I couldn't found any satisfactory PHP solution so I decided to port one from JavaScript. After some comparison of different highlighting programs based on license, technology, language support highlight.js came out most favorable in my opinion.

    It was my decision not to make a PHP highlighter but to do a port of highlight.js, these are different things. The goal was to make it work exactly as highlight.js to make as much use as possible of the language definitions and CSS files of the original program.

    Happy coding!

    License

    BSD

  • \ICalendarOrg Readme

    Zap Calendar iCalendar Library Tests Latest Packagist release

    A modern 7.4 namespaced fork of Zap Calendar iCalendar Library

    The Zap Calendar iCalendar Library is a PHP library for supporting the iCalendar (RFC 5545) standard.

    This PHP library is for reading and writing iCalendar formatted feeds and files. Features of the library include:

    • Read AND write support for iCalendar files
    • Object based creation and manipulation of iCalendar files
    • Supports expansion of RRULE to a list of repeating dates
    • Supports adding timezone info to iCalendar file

    All iCalendar data is stored in a PHP object tree. This allows any property to be added to the iCalendar feed without requiring specialized library function calls. With power comes responsibility. Missing or invalid properties can cause the resulting iCalendar file to be invalid. Visit iCalendar.org to view valid properties and test your feed using the site's iCalendar validator tool.

    Library API documentation can be found at http://icalendar.org/zapcallibdocs and PHPFUI/ICalendarOrg

    See the examples folder for programs that read and write iCalendar files. Best to include the sample files into a file with an active autoloader or include all the classes to run the examples directly.

    Create an ical object using the ZCiCal object:

    $icalobj = new \ICalendarOrg\ZCiCal();
    

    Add an event object:

    $eventobj = new \ICalendarOrg\ZCiCalNode("VEVENT", $icalobj->curnode);
    

    Add a start and end date to the event:

    // add start date
    $eventobj->addNode(new \ICalendarOrg\ZCiCalDataNode("DTSTART:" . \ICalendarOrg\ZCiCal::fromSqlDateTime("2020-01-01 12:00:00")));
    
    // add end date
    $eventobj->addNode(new \ICalendarOrg\ZCiCalDataNode("DTEND:" . \ICalendarOrg\ZCiCal::fromSqlDateTime("2020-01-01 13:00:00")));
    

    Write the object in iCalendar format using the export() function call:

    echo $icalobj->export();
    

    This example will not validate since it is missing some required elements. Look at the simpleevent.php example for the minimum # of elements needed for a validated iCalendar file.

    To create a multi-event iCalendar file, simply create multiple event objects. For example:

    $icalobj = new \ICalendarOrg\ZCiCal();
    $eventobj1 = new \ICalendarOrg\ZCiCalNode("VEVENT", $icalobj->curnode);
    $eventobj1->addNode(new \ICalendarOrg\ZCiCalDataNode("SUMMARY:Event 1"));
    ...
    $eventobj2 = new \ICalendarOrg\ZCiCalNode("VEVENT", $icalobj->curnode);
    $eventobj2->addNode(new \ICalendarOrg\ZCiCalDataNode("SUMMARY:Event 2"));
    ...
    

    To read an existing iCalendar file/feed, create the ZCiCal object with a string representing the contents of the iCalendar file:

    $icalobj = new \ICalendarOrg\ZCiCal($icalstring);
    

    Large iCalendar files can be read in chunks to reduce the amount of memory needed to hold the iCalendar feed in memory. This example reads 500 events at a time:

    $icalobj = null;
    $eventcount = 0;
    $maxevents = 500;
    do
    {
    	$icalobj = new \ICalendarOrg\ZCiCal($icalstring, $maxevents, $eventcount);
    	...
    	$eventcount += $maxevents;
    }
    while($icalobj->countEvents() >= $eventcount);
    

    You can read the events from an imported (or created) iCalendar object in this manner:

    foreach($icalobj->tree->child as $node)
    {
    	if($node->getName() == "VEVENT")
    	{
    		foreach($node->data as $key => $value)
    		{
    			if($key == "SUMMARY")
    			{
    				echo "event title: " . $value->getValues() . "\n";
    			}
    		}
    	}
    }
    

    Known Limitations

    • Since the library utilizes objects to read and write iCalendar data, the size of the iCalendar data is limited to the amount of available memory on the machine. The ZCiCal() object supports reading a range of events to minimize memory space.
    • The library ignores timezone info when importing files, instead utilizing PHP's timezone library for calculations (timezones are supported when exporting files). Imported timezones need to be aliased to a PHP supported timezone.
    • At this time, the library does not support the "BYSETPOS" option in RRULE items.
  • \NXP Readme

    MathExecutor Tests

    A simple and extensible math expressions calculator

    Features:

    • Built in support for +, -, *, / and power (^) operators plus ()
    • Logical operators (==, !=, <, <, >=, <=, &&, ||)
    • Built in support for most PHP math functions
    • Conditional If logic
    • Support for user defined operators
    • Support for user defined functions
    • Dynamic variable resolution (delayed computation)
    • Unlimited variable name lengths
    • String support, as function parameters or as evaluated as a number by PHP
    • Exceptions on divide by zero, or treat as zero
    • Unary Plus and Minus (e.g. +3 or -sin(12))
    • Pi ($pi) and Euler's number ($e) support to 11 decimal places
    • Easily extensible

    Install via Composer:

    composer require nxp/math-executor
    

    Sample usage:

    use NXP\MathExecutor;
    
    $executor = new MathExecutor();
    
    echo $executor->execute('1 + 2 * (2 - (4+10))^2 + sin(10)');
    

    Functions:

    Default functions:

    • abs
    • acos (arccos)
    • acosh
    • arcctg (arccot, arccotan)
    • arcsec
    • arccsc (arccosec)
    • asin (arcsin)
    • atan (atn, arctan, arctg)
    • atan2
    • atanh
    • avg
    • bindec
    • ceil
    • cos
    • cosec (csc)
    • cosh
    • ctg (cot, cotan, cotg, ctn)
    • decbin
    • dechex
    • decoct
    • deg2rad
    • exp
    • expm1
    • floor
    • fmod
    • hexdec
    • hypot
    • if
    • intdiv
    • log (ln)
    • log10 (lg)
    • log1p
    • max
    • min
    • octdec
    • pi
    • pow
    • rad2deg
    • round
    • sec
    • sin
    • sinh
    • sqrt
    • tan (tn, tg)
    • tanh

    Add custom function to executor:

    $executor->addFunction('abs', function($arg) {return abs($arg);});
    

    Function default parameters are not supported at this time.

    Operators:

    Default operators: + - * / ^

    Add custom operator to executor:

    use NXP\Classes\Operator;
    
    $executor->addOperator(new Operator(
        '%', // Operator sign
        false, // Is right associated operator
        170, // Operator priority
        function (&$stack)
        {
           $op2 = array_pop($stack);
           $op1 = array_pop($stack);
           $result = $op1->getValue() % $op2->getValue();
    
           return $result;
        }
    ));
    

    Logical operators:

    Logical operators (==, !=, <, <, >=, <=, &&, ||) are supported, but logically they can only return true (1) or false (0). In order to leverage them, use the built in if function:

    if($a > $b, $a - $b, $b - $a)
    

    You can think of the if function as prototyped like:

    function if($condition, $returnIfTrue, $returnIfFalse)
    

    Variables:

    Variables can be prefixed with the dollar sign ($) for PHP compatibility, but is not required.

    Default variables:

    $pi = 3.14159265359
    $e  = 2.71828182846
    

    You can add your own variables to executor:

    $executor->setVar('var1', 0.15)->setVar('var2', 0.22);
    
    echo $executor->execute("$var1 + var2");
    

    You can dynamically define variables at run time. If a variable has a high computation cost, but might not be used, then you can define an undefined variable handler. It will only get called when the variable is used, rather than having to always set it initially.

    $calculator = new MathExecutor();
    $calculator->setVarNotFoundHandler(
        function ($varName) {
            if ($varName == 'trans') {
                return transmogrify();
            }
            return null;
        }
    );
    

    Division By Zero Support:

    Division by zero throws a \NXP\Exception\DivisionByZeroException by default

    try {
        echo $executor->execute('1/0');
    } catch (DivisionByZeroException $e) {
        echo $e->getMessage();
    }
    

    Or call setDivisionByZeroIsZero

    echo $executor->setDivisionByZeroIsZero()->execute('1/0');
    

    If you want another behavior, you can override division operator:

    $executor->addOperator("/", false, 180, function($a, $b) {
        if ($b == 0) {
            return null;
        }
        return $a / $b;
    });
    echo $executor->execute('1/0');
    

    String Support:

    Expressions can contain double or single quoted strings that are evaluated the same way as PHP evalutes strings as numbers. You can also pass strings to functions.

    echo $executor->execute("1 + '2.5' * '.5' + myFunction('category')");
    

    Extending MathExecutor

    You can add operators, functions and variables with the public methods in MathExecutor, but if you need to do more serious modifications to base behaviours, the easiest way to extend MathExecutor is to redefine the following methods in your derived class:

    • defaultOperators
    • defaultFunctions
    • defaultVars

    This will allow you to remove functions and operators if needed, or implement different types more simply.

    Also note that you can replace an existing default operator by adding a new operator with the same regular expression string. For example if you just need to redefine TokenPlus, you can just add a new operator with the same regex string, in this case '\+'.

    Documentation

    Full class documentation via PHPFUI/InstaDoc

    Future Enhancements

    This package will continue to track currently supported versions of PHP.

  • \phpDocumentor\Reflection Readme

    License: MIT

    Coveralls Coverage
    Scrutinizer Code Coverage
    Scrutinizer Code Quality
    Packagist Version
    Packagist Version

    TypeResolver and FqsenResolver

    The specification on types in DocBlocks (PSR-5) describes various keywords and special constructs
    but also how to statically resolve the partial name of a Class into a Fully Qualified Class Name (FQCN).

    PSR-5 also introduces an additional way to describe deeper elements than Classes, Interfaces and Traits
    called the Fully Qualified Structural Element Name (FQSEN). Using this it is possible to refer to methods,
    properties and class constants but also functions and global constants.

    This package provides two Resolvers that are capable of

    1. Returning a series of Value Object for given expression while resolving any partial class names, and
    2. Returning an FQSEN object after resolving any partial Structural Element Names into Fully Qualified Structural
      Element names.

    Installing

    The easiest way to install this library is with Composer using the following command:

    $ composer require phpdocumentor/type-resolver
    

    Examples

    Ready to dive in and don't want to read through all that text below? Just consult the examples folder and check which type of action that your want to accomplish.

    On Types and Element Names

    This component can be used in one of two ways

    1. To resolve a Type or
    2. To resolve a Fully Qualified Structural Element Name

    The big difference between these two is in the number of things it can resolve.

    The TypeResolver can resolve:

    • a php primitive or pseudo-primitive such as a string or void (@var string or @return void).
    • a composite such as an array of string (@var string[]).
    • a compound such as a string or integer (@var string|integer).
    • an array expression (@var (string|TypeResolver)[])
    • an object or interface such as the TypeResolver class (@var TypeResolver
      or @var \phpDocumentor\Reflection\TypeResolver)

      please note that if you want to pass partial class names that additional steps are necessary, see the
      chapter Resolving partial classes and FQSENs for more information.

    Where the FqsenResolver can resolve:

    • Constant expressions (i.e. @see \MyNamespace\MY_CONSTANT)
    • Function expressions (i.e. @see \MyNamespace\myFunction())
    • Class expressions (i.e. @see \MyNamespace\MyClass)
    • Interface expressions (i.e. @see \MyNamespace\MyInterface)
    • Trait expressions (i.e. @see \MyNamespace\MyTrait)
    • Class constant expressions (i.e. @see \MyNamespace\MyClass::MY_CONSTANT)
    • Property expressions (i.e. @see \MyNamespace\MyClass::$myProperty)
    • Method expressions (i.e. @see \MyNamespace\MyClass::myMethod())

    Resolving a type

    In order to resolve a type you will have to instantiate the class \phpDocumentor\Reflection\TypeResolver and call its resolve method like this:

    $typeResolver = new \phpDocumentor\Reflection\TypeResolver();
    $type = $typeResolver->resolve('string|integer');
    

    In this example you will receive a Value Object of class \phpDocumentor\Reflection\Types\Compound that has two
    elements, one of type \phpDocumentor\Reflection\Types\String_ and one of type
    \phpDocumentor\Reflection\Types\Integer.

    The real power of this resolver is in its capability to expand partial class names into fully qualified class names; but in order to do that we need an additional \phpDocumentor\Reflection\Types\Context class that will inform the resolver in which namespace the given expression occurs and which namespace aliases (or imports) apply.

    Resolving nullable types

    Php 7.1 introduced nullable types e.g. ?string. Type resolver will resolve the original type without the nullable notation ?
    just like it would do without the ?. After that the type is wrapped in a \phpDocumentor\Reflection\Types\Nullable object.
    The Nullable type has a method to fetch the actual type.

    Resolving an FQSEN

    A Fully Qualified Structural Element Name is a reference to another element in your code bases and can be resolved using the \phpDocumentor\Reflection\FqsenResolver class' resolve method, like this:

    $fqsenResolver = new \phpDocumentor\Reflection\FqsenResolver();
    $fqsen = $fqsenResolver->resolve('\phpDocumentor\Reflection\FqsenResolver::resolve()');
    

    In this example we resolve a Fully Qualified Structural Element Name (meaning that it includes the full namespace, class name and element name) and receive a Value Object of type \phpDocumentor\Reflection\Fqsen.

    The real power of this resolver is in its capability to expand partial element names into Fully Qualified Structural Element Names; but in order to do that we need an additional \phpDocumentor\Reflection\Types\Context class that will inform the resolver in which namespace the given expression occurs and which namespace aliases (or imports) apply.

    Resolving partial Classes and Structural Element Names

    Perhaps the best feature of this library is that it knows how to resolve partial class names into fully qualified class names.

    For example, you have this file:

    namespace My\Example;
    
    use phpDocumentor\Reflection\Types;
    
    class Classy
    {
        /**
         * @var Types\Context
         * @see Classy::otherFunction()
         */
        public function __construct($context) {}
        
        public function otherFunction(){}
    }
    

    Suppose that you would want to resolve (and expand) the type in the @var tag and the element name in the @see tag.

    For the resolvers to know how to expand partial names you have to provide a bit of Context for them by instantiating a new class named \phpDocumentor\Reflection\Types\Context with the name of the namespace and the aliases that are in play.

    Creating a Context

    You can do this by manually creating a Context like this:

    $context = new \phpDocumentor\Reflection\Types\Context(
        '\My\Example', 
        [ 'Types' => '\phpDocumentor\Reflection\Types']
    );
    

    Or by using the \phpDocumentor\Reflection\Types\ContextFactory to instantiate a new context based on a Reflector object or by providing the namespace that you'd like to extract and the source code of the file in which the given type expression occurs.

    $contextFactory = new \phpDocumentor\Reflection\Types\ContextFactory();
    $context = $contextFactory->createFromReflector(new ReflectionMethod('\My\Example\Classy', '__construct'));
    

    or

    $contextFactory = new \phpDocumentor\Reflection\Types\ContextFactory();
    $context = $contextFactory->createForNamespace('\My\Example', file_get_contents('My/Example/Classy.php'));
    

    Using the Context

    After you have obtained a Context it is just a matter of passing it along with the resolve method of either Resolver class as second argument and the Resolvers will take this into account when resolving partial names.

    To obtain the resolved class name for the @var tag in the example above you can do:

    $typeResolver = new \phpDocumentor\Reflection\TypeResolver();
    $type = $typeResolver->resolve('Types\Context', $context);
    

    When you do this you will receive an object of class \phpDocumentor\Reflection\Types\Object_ for which you can call the getFqsen method to receive a Value Object that represents the complete FQSEN. So that would be phpDocumentor\Reflection\Types\Context.

    Why is the FQSEN wrapped in another object Object_?

    The resolve method of the TypeResolver only returns object with the interface Type and the FQSEN is a common type that does not represent a Type. Also: in some cases a type can represent an "Untyped Object", meaning that it is an object (signified by the object keyword) but does not refer to a specific element using an FQSEN.

    Another example is on how to resolve the FQSEN of a method as can be seen with the @see tag in the example above. To resolve that you can do the following:

    $fqsenResolver = new \phpDocumentor\Reflection\FqsenResolver();
    $type = $fqsenResolver->resolve('Classy::otherFunction()', $context);
    

    Because Classy is a Class in the current namespace its FQSEN will have the My\Example namespace and by calling the resolve method of the FQSEN Resolver you will receive an Fqsen object that refers to \My\Example\Classy::otherFunction().

  • \PHPFUI Readme

    PHPFUI Tests Latest Packagist release

    PHP Wrapper for the Foundation CSS Framework

    PHPFUI, PHP Foundation User Interface, is a modern PHP library that produces HTML formated for Foundation. It does everything you need for a fully functional Foundation page, with the power of an OO language. It currently uses Foundation 6.6.

    "I was surprised that people were prepared to write HTML. In my initial requirements for this thing, I had assumed, as an absolute pre-condition, that nobody would have to do HTML or deal with URLs. If you use the original World Wide Web program, you never see a URL or have to deal with HTML. You're presented with the raw information. You then input more information. So you are linking information to information--like using a word processor. That was a surprise to me--that people were prepared to painstakingly write HTML."

    Sir Tim Berners-Lee, inventor of the World Wide Web

    Using PHPFUI for view output will produce 100% valid HTML and insulate you from future changes to Foundation, your custom HMTL layouts, CSS and JS library changes. You write to an abstract concept (I want a checkbox here), and the library will output a checkbox formatted for Foundation. You can inherit from CheckBox and add your own take on a checkbox, and when the graphic designer decides they have the most awesome checkbox ever, you simply change your CheckBox class, and it is changed on every page system wide.

    Don't write HTML by hand!

    Usage

    namespace PHPFUI;
    $page = new Page();
    $form = new Form($page);
    $fieldset = new FieldSet('A basic input form');
    $time = new Input\Time($page, 'time', 'Enter A Time in 15 minute increments');
    $time->setRequired();
    $date = new Input\Date($page, 'date', 'Pick A Date');
    $fieldset->add(new MultiColumn($time, $date));
    $fieldset->add(new Input\TextArea('text', 'Enter some text'));
    $fieldset->add(new Submit());
    $form->add($fieldset);
    $page->add($form);
    $page->addStyleSheet('/css/styles.css');
    echo $page;

    Installation Instructions

    composer require phpfui/phpfui
    

    Then run update.php from the vendor/phpfui/phpfui directory and supply the path to your public directory / the directory for the various JS and CSS files PHPFUI uses. This will copy all required public files into your public directory. For example:

    php vendor/phpfui/phpfui/update.php public/PHPFUI
    

    The PHPFUI library defaults to your-public-directory/PHPFUI, it can be overridden, but it is suggested to use PHPFUI to keep everything in one place. update.php should be run when ever you update PHPFUI.

    Versioning

    Versioning will match the Foundation versions for Major semantic versions. PHPUI will always support the most recent version of Foundation possible for the Major version. PHPFUI Minor version will include breaking changes and may incorporate changes for the latest version of Foundation. The PHPFUI Patch version will include non breaking changes or additions. So PHPFUI Version 6.0.0 would be the first version of the library, 6.0.1 would be the first patch of PHPFUI. Both should work with any Foundation 6.x version. PHPFUI 6.1.0 would be a breaking change to PHPFUI, but still track Foundation 6.x. PHPFUI 7.0.0 would track Foundation 7.x series.

    Depreciation and Foundation changes

    Since major versions of Foundation have in the past depreciated and obsoleted things, PHPFUI will track the latest version of Foundation for class names and functionality. However, when Foundation makes a breaking change or removes something, PHPFUI will continue to support the old functionality as best as possible in the new Foundation framework. Depreciated classes will be put in the \PHPFUI\Vx namespace (where x would be the prior Major Foundation version containing that feature). So if something gets depreciated in a newer version of Foundation, you simply will need to change your code from \PHPFUI\Example to \PHPFUI\V6\Example. The depreciated namespace will only be supported for one Major version of PHPFUI, so it is recommended you migrate off of it in a timely manor.

    Documentation

    Via PHPFUI/InstaDoc

    Live Examples

    Via PHPFUI/Examples

    Unit Testing

    Full unit testing using phpfui/html-unit-tester

    License

    PHPFUI is distributed under the MIT License.

    PHP Versions

    This library only supports modern versions of PHP which still receive security updates. While we would love to support PHP from the late Ming Dynasty, the advantages of modern PHP versions far out weigh quaint notions of backward compatibility. Time to upgrade.

  • \PHPFUI\HTMLUnitTester Readme

    PHPFUI\HTMLUnitTester Tests Latest Packagist release

    PHPUnit Testing extensions for HMTL and CSS. PHPFUI\HTMLUnitTester allows you to unit test HTML and CSS for errors and warnings. Often simple errors in HTML or CSS create hard to debug issues where a simple check will reveal bad code.

    This package will check detect errors and warnings in HTML and CSS in stand alone strings, files, entire directories or urls.

    For the best performanance, a local install of https://github.com/validator/validator is recommended.

    Installation

    composer require phpfui/html-unit-tester
    

    Configuration

    It is recommended you run https://github.com/validator/validator locally. Install Java and download the .jar file. Run with the following command:

    java -Xss1024k -cp vnu.jar nu.validator.servlet.Main 8888
    

    If you are not using a local server, you will need to add the following lines to your phpunit.xml config in the phpunit element:

    <php>
      <env name="PHPFUI\HTMLUnitTester\Extensions_url" value="http://validator.w3.org/nu"/>
      <env name="PHPFUI\HTMLUnitTester\Extensions_delay" value="500000"/>
    </php>
    

    Usage

    Extend your unit tests from \PHPFUI\HTMLUnitTester\Extensions

    class UnitTest extends \PHPFUI\HTMLUnitTester\Extensions
      {
      public function testValidHtml()
        {
        $this->assertValidHtml('<h1>Header</h1>');
        $this->assertValidHtmlPage('<!DOCTYPE html><html><head><meta charset="utf-8"/><title>Title</title></head><body><div>This is a test</div></body></html>');
        }
      }
    

    You can use any of the following asserts:

    • assertNotWarningCss
    • assertNotWarningCssFile
    • assertNotWarningCssUrl
    • assertNotWarningFile
    • assertNotWarningHtml
    • assertNotWarningHtmlPage
    • assertNotWarningUrl
    • assertValidCss
    • assertValidCssFile
    • assertValidCssUrl
    • assertValidFile
    • assertValidHtml
    • assertValidHtmlPage
    • assertValidUrl

    Directory Testing

    Instead of file by file testing, use assertDirectory to test an entire directory. Any files added to the directory will be automatically tested.

    	$this->assertDirectory('ValidCSS', 'cssDirectory', 'Invalid CSS');
    	$this->assertDirectory('NotWarningCSS', 'cssDirectory', 'CSS has warnings');
    

    The error message will include the offending file name.

    Examples

    See examples

    Documentation

    Full documentation at PHPFUI\HTMLUnitTester

    License

    PHPFUI\HTMLUnitTester is distributed under the MIT License.

    PHP Versions

    This library only supports modern versions of PHP which still receive security updates. While we would love to support PHP from the late Ming Dynasty, the advantages of modern PHP versions far out weigh quaint notions of backward compatibility. Time to upgrade.

  • \PHPFUI\InstaDoc Readme

    PHPFUI\InstaDoc Library Tests Latest Packagist release

    A quick and easy way to add documentation to your PHP project

    We all document our code with PHP DocBlocks but we never seem to actually generate the documentation and add it to our project. Why? It simply takes too much time (over a minute), so we put it off till later, and later never comes.

    But with PHPFUI\InstaDoc, you can document your site in about a minute (OK, maybe 2). The steps involved:

    • Install PHPFUI\InstaDoc via Composer (30 seconds)
    • Run installation script (30 seconds)
    • Create document page (1 minute, 6 lines of code)

    Two minutes to usable documentation with the following features:

    PHPFUI\InstaDoc Features

    • Always up to date, even with code that is not yet checked in
    • Send constructor information including parameters and default values to clipboard
    • Child and Parent class hierarchy clearly displayed and accessable
    • Quick access to highlighted PHP source with user selectable highlighting
    • Quick access to the file's git history for the local repo
    • Full support for @inheritDoc tag so child method docs are displayed correctly
    • Documents all projects loaded via Composer automatically
    • Tabbed documentation so you are not looking at irrelevant methods
    • Alphabetized everything, no more searching unalphabetized pages!
    • Support for markdown and custom markdown pages
    • Ability to generate static html files for high volume sites
    • Add any local repo directories
    • Remove any Composer project you don't care about
    • 5+ line config compatible with all PHP frameworks, or standalone
    • Uses Foundation CSS framework for a great experience on mobile

    Install PHPFUI\InstaDoc (requires PHP >= 7.3)

    composer require phpfui/InstaDoc
    

    Run Installation Script

    Once installed, you need to run an installation script to copy static files to your public directory. From your project root, run the following:

    php vendor/phpfui/instadoc/install.php yourPublicDirectory/subDirectory
    

    Example: php vendor/phpfui/instadoc/install.php public/PHPFUI will add all needed files to public/PHPFUI, which will avoid any conflicts with your current files. You can specify any directory by using \PHPFUI\Page::setResourcePath, but PHPFUI is recomended to keep things simple.

    Create Document Page

    PHPFUI\InstaDoc does not reply on any framework and can run on a standalone page. It is recommended that you do not make your documentation public, as PHPFUI\InstaDoc will display PHP source files. How you restrict access to the page is up to you. The following does not restrict access and is simply an example:

    <?php
    include 'yourAutoLoader.php';
    
    // pass the directory containing your composer.json file
    $fileManager = new \PHPFUI\InstaDoc\FileManager('../');
    
    // add your App class tree in, pass true as the last parameter if this namespace is in your local git repo.
    $fileManager->addNamespace('App', '../App', true);
    
    // load your cached files
    $fileManager->load();
    
    // load child classes if you want to display them, if you don't do this step, docs will not show classes that extend the displayed class
    \PHPFUI\InstaDoc\ChildClasses::load();
    
    // get the controller
    $controller = new \PHPFUI\InstaDoc\Controller($fileManager);
    
    // display will return a fully formed page
    echo $controller->display();
    

    That is it. You are done!

    Adding New Classes

    PHPFUI\InstaDoc saves the classes to display in PHP serialized files. Delete those files (.serial extension) when you want to display new classes. PHPFUI\InstaDoc will regenerate automatically if the files are missing.

    Add Child Classes to the Docs

    \PHPFUI\InstaDoc\ChildClasses::load('../ChildClasses.serial');
    

    Add a Global Namespace Class

    The git repo path defaults to the composer directory, but you can change the path by calling:

    $fileManager->addGlobalNameSpaceClass(__DIR__ . '/global/FPDF.php');
    

    Removing a Namespace

    $fileManager->excludeNamespace('Carbon');
    

    Add git Repository Page

    The git repo path defaults to the composer directory, but you can change the path by calling:

    $controller->setGitRoot(getcwd() . '/../');
    

    Add Documents To Your Docs Home Page

    $controller->addHomePageMarkdown('../PHPFUI/InstaDoc/README.md');
    

    Set Your Home Page

    You may want users to get back into your system easily. Clicking on the top left menu bar will take them here:

    $controller->setHomeUrl('/');
    

    Breakup Your Documentation Into Sections

    If you have a lot of source code, you might want to break it into sections, so you will need a separate file to store the index in per section:

    $fileManager->setBaseFile('SubProject');
    

    Generate Static Files

    Just the doc and file pages, no git!

    $controller->generate('static/file/path', [\PHPFUI\InstaDoc\Controller::DOC_PAGE, \PHPFUI\InstaDoc\Controller::FILE_PAGE, ]));
    

    Example and Full Documentation

    PHPFUI/InstaDoc

  • \PHPFUI\MySQLSlowQuery Readme

    PHPFUI\MySQLSlowLog\Parser Tests Latest Packagist release

    PHP Parser for MySQL Slow Query Logs featuring sortable results

    Requirements

    • PHP 7.1 or higher
    • MySQL 5.7 or higher

    Usage

    $parser = new \PHPFUI\MySQLSlowQuery\Parser($logFilePath);
    
    // Return the sessions in the file as array
    $sessions = $parser->getSessions();
    
    // Return all entries in file as array, or pass session number (0 based)
    $entries = $parser->getEntries();
    
    if (count($entries))
      {
      // Get the worst offender
      $entry = $parser->sortEntries()->getEntries()[0];
      echo 'Query ' . implode(' ', $entry->Query) . " took {$entry->Query_time} seconds at {$entry->Time}\n";
    
      // Get the most rows examined
      $entry = $parser->sortEntries('Rows_examined', 'desc')->getEntries()[0];
      echo 'Query ' . implode(' ', $entry->Query) . " looked at {$entry->Rows_examined} rows\n";
      }
    

    Entries

    \PHPFUI\MySQLSlowQuery\Entry provides details on each query.
    Supported fields:

    • Time
    • User
    • Host
    • Id
    • Query_time
    • Lock_time
    • Rows_sent
    • Rows_examined
    • Query (array)
    • Session (zero based)

    Sessions

    \PHPFUI\MySQLSlowQuery\Session contains MySQL server information and are created on server restarts and log flushes. Pass the zero based session number to getEntries for only that Session's entries.
    Supported fields:

    • Server
    • Port
    • Transport

    Sort Entries

    By default, entries are returned in log order, but call sortEntries on the Parser to sort by any valid field (parameter 1). Sort defaults to 'desc', anything else will sort ascending.

    Full Class Documentation

    Via PHPFUI/InstaDoc

    License

    Distributed under the MIT License.

  • \PHPFUI\subtrees\devbridge\jQuery-Autocomplete Readme

    Devbridge Group accelerates software to market for enterprise clients through dedicated product teams, user experience and software engineering expertise.

    www.devbridge.com

    Ajax Autocomplete for jQuery

    Ajax Autocomplete for jQuery allows you to easily create
    autocomplete/autosuggest boxes for text input fields.

    It has no dependencies other than jQuery.

    The standard jquery.autocomplete.js file is around 13KB when minified.

    API

    The following sets up autocomplete for input fields where options is an object literal that defines the settings to use for the autocomplete plugin. All available option settings are shown in the tables below.

    $(selector).autocomplete(options);
    

    General settings (local and Ajax)

    Setting Default Description
    noCache false Boolean value indicating whether to cache suggestion results
    delimiter optional String or RegExp, that splits input value and takes last part to as query for suggestions. Useful when for example you need to fill list of comma separated values.
    minChars 1 Minimum number of characters required to trigger autosuggest
    triggerSelectOnValidInput true Boolean value indicating if select should be triggered if it matches suggestion
    preventBadQueries true Boolean value indicating if it should prevent future Ajax requests for queries with the same root if no results were returned. E.g. if Jam returns no suggestions, it will not fire for any future query that starts with Jam
    autoSelectFirst false If set to true, first item will be selected when showing suggestions
    beforeRender optional function (container, suggestions) {} called before displaying the suggestions. You may manipulate suggestions DOM before it is displayed
    formatResult optional function (suggestion, currentValue) {} custom function to format suggestion entry inside suggestions container
    formatGroup optional function (suggestion, category) {} custom function to format group header
    groupBy optional property name of the suggestion data object, by which results should be grouped
    maxHeight 300 Maximum height of the suggestions container in pixels
    width auto Suggestions container width in pixels, e.g.: 300, flex for max suggestion size and auto takes input field width
    zIndex 9999 'z-index' for suggestions container
    appendTo optional Container where suggestions will be appended. Default value document.body. Can be jQuery object, selector or HTML element. Make sure to set position: absolute or position: relative for that element
    forceFixPosition false Suggestions are automatically positioned when their container is appended to body (look at appendTo option), in other cases suggestions are rendered but no positioning is applied. Set this option to force auto positioning in other cases
    orientation bottom Vertical orientation of the displayed suggestions, available values are auto, top, bottom. If set to auto, the suggestions will be orientated it the way that place them closer to middle of the view port
    preserveInput false If true, input value stays the same when navigating over suggestions
    showNoSuggestionNotice false When no matching results, display a notification label
    noSuggestionNotice No results Text or htmlString or Element or jQuery object for no matching results label
    onInvalidateSelection optional function () {} called when input is altered after selection has been made. this is bound to input element
    tabDisabled false Set to true to leave the cursor in the input field after the user tabs to select a suggestion

    Event function settings (local and Ajax)

    Event setting Function description
    onSearchStart function (params) {} called before Ajax request. this is bound to input element
    onHint function (hint) {} used to change input value to first suggestion automatically. this is bound to input element
    onSearchComplete function (query, suggestions) {} called after Ajax response is processed. this is bound to input element. suggestions is an array containing the results
    transformResult function(response, originalQuery) {} called after the result of the query is ready. Converts the result into response.suggestions format
    onSelect function (suggestion) {} Callback function invoked when user selects suggestion from the list. this inside callback refers to input HtmlElement.
    onSearchError function (query, jqXHR, textStatus, errorThrown) {} called if Ajax request fails. this is bound to input element
    onHide function (container) {} called before container will be hidden

    Local only settings

    Setting Default Description
    lookupLimit no limit Number of maximum results to display for local lookup
    lookup n/a Callback function or lookup array for the suggestions. It may be array of strings or suggestion object literals
    suggestion n/a Not a settings, but in the context of above row, a suggestion is an object literal with the following format: { value: 'string', data: any }
    lookupFilter n/a function (suggestion, query, queryLowerCase) {} filter function for local lookups. By default it does partial string match (case insensitive)

    Ajax only settings

    Setting Default Description
    serviceUrl n/a Server side URL or callback function that returns serviceUrl string
    type GET Ajax request type to get suggestions
    dataType text type of data returned from server. Either text, json or jsonp, which will cause the autocomplete to use jsonp. You may return a json object in your callback when using jsonp
    paramName query The name of the request parameter that contains the query
    params optional Additional parameters to pass with the request
    deferRequestBy 0 Number of miliseconds to defer Ajax request
    ajaxSettings optional Any additional Ajax Settings that configure the jQuery Ajax request

    Default Options

    Default options for all instances can be accessed via $.Autocomplete.defaults.

    Instance Methods

    Autocomplete instance has following methods:

    • setOptions(options): you may update any option at any time. Options are listed above.
    • clear: clears suggestion cache and current suggestions.
    • clearCache: clears suggestion cache.
    • disable: deactivate autocomplete.
    • enable: activates autocomplete if it was deactivated before.
    • hide: hides suggestions.
    • dispose: destroys autocomplete instance. All events are detached and suggestion containers removed.

    There are two ways that you can invoke Autocomplete method. One is calling autocomplete on jQuery object and passing method name as string literal.
    If method has arguments, arguments are passed as consecutive parameters:

    $('#autocomplete').autocomplete('disable');
    $('#autocomplete').autocomplete('setOptions', options);
    

    Or you can get Autocomplete instance by calling autcomplete on jQuery object without any parameters and then invoke desired method.

    $('#autocomplete').autocomplete().disable();
    $('#autocomplete').autocomplete().setOptions(options);
    

    Usage

    Html:

    <input type="text" name="country" id="autocomplete"/>
    

    Ajax lookup:

    $('#autocomplete').autocomplete({
        serviceUrl: '/autocomplete/countries',
        onSelect: function (suggestion) {
            alert('You selected: ' + suggestion.value + ', ' + suggestion.data);
        }
    });
    

    Local lookup (no Ajax):

    var countries = [
        { value: 'Andorra', data: 'AD' },
        // ...
        { value: 'Zimbabwe', data: 'ZZ' }
    ];
    
    $('#autocomplete').autocomplete({
        lookup: countries,
        onSelect: function (suggestion) {
            alert('You selected: ' + suggestion.value + ', ' + suggestion.data);
        }
    });
    

    Custom lookup function:

    
    $('#autocomplete').autocomplete({
        lookup: function (query, done) {
            // Do Ajax call or lookup locally, when done,
            // call the callback and pass your results:
            var result = {
                suggestions: [
                    { "value": "United Arab Emirates", "data": "AE" },
                    { "value": "United Kingdom",       "data": "UK" },
                    { "value": "United States",        "data": "US" }
                ]
            };
    
            done(result);
        },
        onSelect: function (suggestion) {
            alert('You selected: ' + suggestion.value + ', ' + suggestion.data);
        }
    });
    

    Styling

    Generated HTML markup for suggestions is displayed below. You may style it any way you'd like.

    <div class="autocomplete-suggestions">
        <div class="autocomplete-group"><strong>NHL</strong></div>
        <div class="autocomplete-suggestion autocomplete-selected">...</div>
        <div class="autocomplete-suggestion">...</div>
        <div class="autocomplete-suggestion">...</div>
    </div>
    

    Style sample:

    .autocomplete-suggestions { border: 1px solid #999; background: #FFF; overflow: auto; }
    .autocomplete-suggestion { padding: 2px 5px; white-space: nowrap; overflow: hidden; }
    .autocomplete-selected { background: #F0F0F0; }
    .autocomplete-suggestions strong { font-weight: normal; color: #3399FF; }
    .autocomplete-group { padding: 2px 5px; }
    .autocomplete-group strong { display: block; border-bottom: 1px solid #000; }
    

    Response Format

    Response from the server must be JSON formatted following JavaScript object:

    {
        // Query is not required as of version 1.2.5
        "query": "Unit",
        "suggestions": [
            { "value": "United Arab Emirates", "data": "AE" },
            { "value": "United Kingdom",       "data": "UK" },
            { "value": "United States",        "data": "US" }
        ]
    }
    

    Data can be any value or object. Data object is passed to formatResults function
    and onSelect callback. Alternatively, if there is no data you can
    supply just a string array for suggestions:

    {
        "query": "Unit",
        "suggestions": ["United Arab Emirates", "United Kingdom", "United States"]
    }
    

    Non standard query/results

    If your Ajax service expects the query in a different format, and returns data in a different format than the standard response,
    you can supply the "paramName" and "transformResult" options:

    $('#autocomplete').autocomplete({
        paramName: 'searchString',
        transformResult: function(response) {
            return {
                suggestions: $.map(response.myData, function(dataItem) {
                    return { value: dataItem.valueField, data: dataItem.dataField };
                })
            };
        }
    })
    

    Grouping Results

    Specify groupBy option of you data property if you wish results to be displayed in groups. For example, set groupBy: 'category' if your suggestion data format is:

    [
        { value: 'Chicago Blackhawks', data: { category: 'NHL' } },
        { value: 'Chicago Bulls', data: { category: 'NBA' } }
    ]
    

    Results will be formatted into two groups NHL and NBA.

    Known Issues

    If you use it with jQuery UI library it also has plugin named autocomplete. In this case you can use plugin alias devbridgeAutocomplete:

    $('.autocomplete').devbridgeAutocomplete({ ... });
    

    It seems that for mobile Safari click events are only triggered if the CSS of the object being tapped has the cursor set to pointer:

    .autocomplete-suggestion { 
        cursor: pointer;
    }
    

    See issue #542

    License

    Ajax Autocomplete for jQuery is freely distributable under the
    terms of an MIT-style license.

    Copyright notice and permission notice shall be included in all
    copies or substantial portions of the Software.

    Authors

    Tomas Kirda / @tkirda

  • \PHPFUI\subtrees\JeremyFagis\dropify Readme

    ⚠️ Repository archived ⚠️

    Dropify

    Dropify

    Override your input files with style.

    Demo here : http://jeremyfagis.github.io/dropify

    Dependency

    jQuery is required to do the magic.

    Installation

    Clone the project in your workspace

    $ git clone git@github.com:JeremyFagis/dropify.git
    $ cd dropify
    

    Download packages

    $ npm install
    

    Compile assets

    $ gulp build
    

    Compilation

    # All compilations and watch. You will have minified and not minified files.
    $ gulp
    
    # Dev compilation (watch & no-minification)
    $ gulp --dev
    
    # Prod compilation, you will have minified and not minified files
    $ gulp build
    
    # Prod compilation, you will have only minified files
    $ gulp build --dev
    

    NPM Package

    www.npmjs.com/package/dropify

    $ npm install dropify
    

    Bower Package

    $ bower install dropify
    

    Usage

    You have to include dist/js/dropify.js, dist/css/dropify.css and dist/fonts/* to your project, then you just have to init the jQuery plugin like that :

    $('.dropify').dropify();
    

    Options

    • defaultFile: If there is a default file on the input. You can use options when you use the plugin or directly __data-default-file="url_of_your_file"__ on you DOM element (it's recommended).
    <input type="file" class="dropify" data-default-file="url_of_your_file" />
    
    • height: Set the height of your dropify element. For exemple you want 300px height, you have to add the attribute data-height="300" on your DOM element.
    <input type="file" class="dropify" data-height="300" />
    
    • maxFileSize: Set the max filesize of the uploaded document. An error will be display if the file size is bigger than the option. You can use unit like K, M and G.
    <input type="file" class="dropify" data-max-file-size="3M" />
    
    • minWidth: Set the min width allowed. An error will be display if the width is smaller than the option.
    <input type="file" class="dropify" data-min-width="400" />
    
    • maxWidth: Set the max width allowed. An error will be display if the width is bigger than the option.
    <input type="file" class="dropify" data-max-width="1000" />
    
    • minHeight: Set the min height allowed. An error will be display if the height is smaller than the option.
    <input type="file" class="dropify" data-min-height="400" />
    
    • maxHeight: Set the max height allowed. An error will be display if the height is bigger than the option.
    <input type="file" class="dropify" data-max-height="1000" />
    
    • disabled: You can disable the input if you add the attr disabled="disabled".
    <input type="file" class="dropify" disabled="disabled" />
    
    • showRemove: You can hide the remove button if you add the attr data-show-remove="false". Default: true.
    <input type="file" class="dropify" data-show-remove="false" />
    
    • showLoader: You can hide the loader if you add the attr data-show-loader="false". Default: true.
    <input type="file" class="dropify" data-show-loader="false" />
    
    • showErrors: You can hide errors if you add the attr data-show-loader="false". Default: true.
    <input type="file" class="dropify" data-show-errors="true" />
    
    • errorsPosition: You can choose where you want to display the errors, overlay or outside. Default: overlay.
    <input type="file" class="dropify" data-errors-position="outside" />
    
    • allowedFormats: You can allow/deny pictures formats. If you add the attr data-allowed-formats="portrait square" only portrait and square picture will be allowed. Default: ['portrait', 'square', 'landscape'].
    <input type="file" class="dropify" data-allowed-formats="portrait square" />
    
    • allowedFileExtensions: You can allow only some file extensions. If you add the attr data-allowed-file-extensions="pdf png psd" only PDF, PNG and PSD files will be allowed. By default, everything is allowed. Default: ['*'].
    <input type="file" class="dropify" data-allowed-file-extensions="pdf png psd" />
    
    • maxFileSizePreview: Set the max filesize of the previewed document (if it's an image). If the file size is bigger than the option, it will be only the file icon and disabled the preview. You can use unit like K, M and G.
    <input type="file" class="dropify" data-max-file-size-preview="3M" />
    
    • messages: You can translate default messages. You just have to add an options array when you init the plugin. This messages will be replaced in the tpl option.
    $('.dropify').dropify({
        messages: {
            'default': 'Drag and drop a file here or click',
            'replace': 'Drag and drop or click to replace',
            'remove':  'Remove',
            'error':   'Ooops, something wrong happended.'
        }
    });
    
    • error: You can translate default errors messages. You just have to add an options array when you init the plugin. {{ value }} text will be replaced by the option.
    $('.dropify').dropify({
        error: {
            'fileSize': 'The file size is too big ({{ value }} max).',
            'minWidth': 'The image width is too small ({{ value }}}px min).',
            'maxWidth': 'The image width is too big ({{ value }}}px max).',
            'minHeight': 'The image height is too small ({{ value }}}px min).',
            'maxHeight': 'The image height is too big ({{ value }}px max).',
            'imageFormat': 'The image format is not allowed ({{ value }} only).'
        }
    });
    
    • tpl: You can update default template. You just have to add an options array when you init the plugin.
    $('.dropify').dropify({
        tpl: {
            wrap:            '<div class="dropify-wrapper"></div>',
            loader:          '<div class="dropify-loader"></div>',
            message:         '<div class="dropify-message"><span class="file-icon" /> <p>{{ default }}</p></div>',
            preview:         '<div class="dropify-preview"><span class="dropify-render"></span><div class="dropify-infos"><div class="dropify-infos-inner"><p class="dropify-infos-message">{{ replace }}</p></div></div></div>',
            filename:        '<p class="dropify-filename"><span class="file-icon"></span> <span class="dropify-filename-inner"></span></p>',
            clearButton:     '<button type="button" class="dropify-clear">{{ remove }}</button>',
            errorLine:       '<p class="dropify-error">{{ error }}</p>',
            errorsContainer: '<div class="dropify-errors-container"><ul></ul></div>'
        }
    });
    

    Events

    • dropify.beforeClear: This event is called when you click on the "remove" button, just before clearing the Dropify. You can access to all the Dropify object properties using element.xxxx. See how to use it.
    var drEvent = $('.dropify').dropify();
    
    drEvent.on('dropify.beforeClear', function(event, element){
        return confirm("Do you really want to delete \"" + element.filename + "\" ?");
    });
    
    • dropify.afterClear: This event is called after the Dropify is clear. You can access to all the Dropify object properties using element.xxxx. See how to use it.
    var drEvent = $('.dropify').dropify();
    
    drEvent.on('dropify.afterClear', function(event, element){
        alert('File deleted');
    });
    
    • dropify.errors: This event is called when there is one or more error during process. See how to use it.
    var drEvent = $('.dropify').dropify();
    
    drEvent.on('dropify.errors', function(event, element){
        alert('Has Errors!');
    });
    
    • dropify.error.xxxxx: In addition to the event dropify.errors:, you can bind errors events one by one. See how to use it.
    var drEvent = $('.dropify').dropify();
    
    drEvent.on('dropify.error.fileSize', function(event, element){
        alert('Filesize error message!');
    });
    drEvent.on('dropify.error.minWidth', function(event, element){
        alert('Min width error message!');
    });
    drEvent.on('dropify.error.maxWidth', function(event, element){
        alert('Max width error message!');
    });
    drEvent.on('dropify.error.minHeight', function(event, element){
        alert('Min height error message!');
    });
    drEvent.on('dropify.error.maxHeight', function(event, element){
        alert('Max height error message!');
    });
    drEvent.on('dropify.error.imageFormat', function(event, element){
        alert('Image format error message!');
    });
    
  • \PHPFUI\subtrees\najlepsiwebdesigner\foundation-datepicker Readme

    Foundation Datepicker

    Feel free to contribute! Fork, modify, and send me a pull request.

    EXAMPLES AND DOCS available at http://foundation-datepicker.peterbeno.com

    A note on forking:

    By forking this project you hereby grant permission for any commits to your fork to be merged back into this repository and, with attribution, be released under the terms of the Apache License.

    Issues

    Before you submit a new issue, please check closed (maybe also open) issues here, maybe your problem was solved already. Thanks!

  • \PHPFUI\subtrees\ten1seven\what-input Readme

    What Input?

    A global utility for tracking the current input method (mouse, keyboard or touch).

    What Input is now v5

    Now with more information and less opinion!

    What Input adds data attributes to the window based on the type of input being used. It also exposes a simple API that can be used for scripting interactions.

    How it works

    What Input uses event bubbling on the window to watch for mouse, keyboard and touch events (via mousedown, keydown and touchstart). It then sets or updates a data-whatinput attribute.

    Pointer Events are supported but note that pen inputs are remapped to touch.

    What Input also exposes a tiny API that allows the developer to ask for the current input, set custom ignore keys, and set and remove custom callback functions.

    What Input does not make assumptions about the input environment before the page is interacted with. However, the mousemove and pointermove events are used to set a data-whatintent="mouse" attribute to indicate that a mouse is being used indirectly.

    Demo

    Check out the demo to see What Input in action.

    https://ten1seven.github.io/what-input

    Interacting with Forms

    Since interacting with a form always requires use of the keyboard, What Input uses the data-whatintent attribute to display a "buffered" version of input events while form <input>s, <select>s, and <textarea>s are being interacted with (i.e. mouse user's data-whatintent will be preserved as mouse while typing).

    Installing

    Download the file directly.

    Install via Yarn:

    yarn add what-input
    

    Install via NPM:

    npm install what-input
    

    Usage

    Include the script directly in your project.

    <script src="path/to/what-input.js"></script>
    

    Or require with a script loader.

    import 'what-input'
    
    // or
    
    import whatInput from 'what-input'
    
    // or
    
    require('what-input')
    
    // or
    
    var whatInput = require('what-input')
    
    // or
    
    requirejs.config({
      paths: {
        whatInput: 'path/to/what-input',
      },
    })
    
    require(['whatInput'], function () {})
    

    What Input will start doing its thing while you do yours.

    Default Behavior

    Persisting Input/Intent Across Pages

    By default, What Input uses session storage to persist the input and intent values across pages. The benefit is that once a visitor has interacted with the page, subsequent pages won't have to wait for interactions to know the input method.

    This behavior can be disabled by adding a data-whatpersist="false" attribute on either the <html> or <body>.

    <html dir="ltr" lang="en" data-whatpersist="false">
      ...
    </html>
    

    or

    <body data-whatpersist="false">
      ...
    </body>
    

    Session storage can be cleared at any time with:

    whatInput.clearStorage()
    

    Basic Styling

    /*
     * only suppress the focus ring once what-input has successfully started
     */
    
    /* suppress focus ring on form controls for mouse users */
    [data-whatintent='mouse'] *:focus {
      outline: none;
    }
    

    Note: If you remove outlines with outline: none;, be sure to provide clear visual :focus styles so the user can see which element they are on at any time for greater accessibility. Visit W3C's WCAG 2.0 2.4.7 Guideline to learn more.

    Scripting

    Current Input

    Ask What Input what the current input method is. This works best if asked after the events What Input is bound to (mousedown, keydown and touchstart).

    whatInput.ask() // returns `mouse`, `keyboard` or `touch`
    
    myButton.addEventListener('click', () => {
      if (whatInput.ask() === 'mouse') {
        // do mousy things
      } else if (whatInput.ask() === 'keyboard') {
        // do keyboard things
      }
    })
    

    If it's necessary to know if mousemove is being used, use the 'intent' option. For example:

    /*
     * nothing has happened but the mouse has moved
     */
    
    whatInput.ask() // returns `initial` because the page has not been directly interacted with
    whatInput.ask('intent') // returns `mouse` because mouse movement was detected
    
    /*
     * the keyboard has been used, then the mouse was moved
     */
    
    whatInput.ask() // returns `keyboard` because the keyboard was the last direct page interaction
    whatInput.ask('intent') // returns `mouse` because mouse movement was the most recent action detected
    

    Current Element

    Ask What Input the currently focused DOM element.

    whatInput.element() // returns a string, like `input` or null
    

    Ignore Keys

    Set a custom array of keycodes that will be ignored (will not switch over to keyboard) when pressed. A custom list will overwrite the default values.

    /*
     * default ignored keys:
     * 16, // shift
     * 17, // control
     * 18, // alt
     * 91, // Windows key / left Apple cmd
     * 93  // Windows menu / right Apple cmd
     */
    
    whatInput.ignoreKeys([1, 2, 3])
    

    Specific Keys

    Set a custom array of keycodes that will trigger the keyboard pressed intent (will not switch to keyboard unless these keys are pressed). This overrides ignoreKeys.

    // only listen to tab keyboard press
    whatInput.specificKeys([9])
    

    Custom Callbacks

    Fire a function when the input or intent changes.

    // create a function to be fired
    var myFunction = function (type) {
      console.log(type)
    }
    
    // fire `myFunction` when the intent changes
    whatInput.registerOnChange(myFunction, 'intent')
    
    // fire `myFunction` when the input changes
    whatInput.registerOnChange(myFunction, 'input')
    
    // remove custom event
    whatInput.unRegisterOnChange(myFunction)
    

    Compatibility

    What Input works in all modern browsers.

    Changelog

    v5.2.8 - 5.2.10

    • Added: TypeScript definitions via @greypants

    v5.2.7

    • Fixed: Moves sourcemap to sit next to JavaScript package.

    v5.2.6

    • Fixed: adds DOMContentLoaded event before looking for data-whatpersist attribute on body.

    v5.2.5

    • Fixed: Hotfix for shaky support of dataset in IE10.

    v5.2.4

    • Added: Ability to add data-whatpersist="false" attribute to the <html> or <body> tag to disable usage of session storage to persist input/intent across pages.
    • Updated: Build tools and added linting.

    v5.2.3

    • Fixed: activeElement is null bug in IE is fixed (thanks @EasterPeanut).
    • Fixed: Mousewheel event detection works correctly again.

    v5.2.1

    • Fixed: iOS was occasionally reporting mouse because of event execution order.
    • Added: touchend to input map
    • Added: Allows buttons inside forms to be treated like other form inputs.
    • Added: iTouch intent indicator in demo page (it worked all along, you just couldn't see it).

    v5.1.4

    • Fixed: Increase buffering time by 20ms to fix iOS reporting mousedown
    • Fixed: Adds touchend to input map

    v5.1.3

    • Added: Sourcemap for the minified version.

    v5.1.2

    • Added: specificKeys functionality to allow overriding of keyboard keys list. Fix via bk3.

    v5.1.1

    • Fixed: Browsers with cookies turned off would throw an error with session storage. Fix via yuheiy.

    v5.1.0

    • Added: Session variable stores last used input and intent so subsequent page loads don't have to wait for interactions to set the correct input and intent state.
    • Removed: IE8 support.

    v5.0.7

    • Fixed: unRegisterOnChange failed to unregister items at index 0.

    v5.0.5

    • Fixed: Fail gracefully in non-DOM environments.

    v5.0.3

    • Fixed: Event buffer for touch was not working correctly.

    Changes from v4

    • Added: A the ability to add and remove custom callback function when the input or intent changes with whatInput.registerOnChange and whatInput.unRegisterOnChange.
    • Added: A data-whatelement attribute exposes any currently focused DOM element (i.e. data-whatelement="a" or data-whatelement="input").
    • Added: A data-whatclasses attribute exposes any currently focused element's classes as a comma-separated list (i.e. data-whatclasses="class1,class2").
    • Added: An API option to provide a custom array of keycodes that will be ignored.
    • Changed: Typing in form fields is no longer filtered out. The data-whatinput attribute immediately reflects the current input. The data-whatintent attribute now takes on the role of remembering mouse input prior to typing in or clicking on a form field.
    • Changed: If you use the Tab key to move from one input to another one - the data-whatinput attribute reflects the current input (switches to "keyboard").
    • Removed: whatInput.types() API option.
    • Removed: Bower support.
    • Fixed: Using mouse modifier keys (shift, control, alt, cmd) no longer toggles back to keyboard.

    Acknowledgments

    Special thanks to Viget for their encouragement and commitment to open source projects. Visit code.viget.com to see more projects from Viget.

    Thanks to mAAdhaTTah for the initial conversion to Webpack. Thanks to greypants for adding TypeScript definitions.

    What Input is written and maintained by @ten1seven.

    License

    What Input is freely available under the MIT License.

  • \PhpParser Readme

    PHP Parser

    Coverage Status

    This is a PHP 5.2 to PHP 8.0 parser written in PHP. Its purpose is to simplify static code analysis and
    manipulation.

    Documentation for version 4.x (stable; for running on PHP >= 7.0; for parsing PHP 5.2 to PHP 8.0).

    Documentation for version 3.x (unsupported; for running on PHP >= 5.5; for parsing PHP 5.2 to PHP 7.2).

    Features

    The main features provided by this library are:

    • Parsing PHP 5, PHP 7, and PHP 8 code into an abstract syntax tree (AST).
      • Invalid code can be parsed into a partial AST.
      • The AST contains accurate location information.
    • Dumping the AST in human-readable form.
    • Converting an AST back to PHP code.
      • Experimental: Formatting can be preserved for partially changed ASTs.
    • Infrastructure to traverse and modify ASTs.
    • Resolution of namespaced names.
    • Evaluation of constant expressions.
    • Builders to simplify AST construction for code generation.
    • Converting an AST into JSON and back.

    Quick Start

    Install the library using composer:

    php composer.phar require nikic/php-parser
    

    Parse some PHP code into an AST and dump the result in human-readable form:

    <?php
    use PhpParser\Error;
    use PhpParser\NodeDumper;
    use PhpParser\ParserFactory;
    
    $code = <<<'CODE'
    <?php
    
    function test($foo)
    {
        var_dump($foo);
    }
    CODE;
    
    $parser = (new ParserFactory)->create(ParserFactory::PREFER_PHP7);
    try {
        $ast = $parser->parse($code);
    } catch (Error $error) {
        echo "Parse error: {$error->getMessage()}\n";
        return;
    }
    
    $dumper = new NodeDumper;
    echo $dumper->dump($ast) . "\n";
    

    This dumps an AST looking something like this:

    array(
        0: Stmt_Function(
            byRef: false
            name: Identifier(
                name: test
            )
            params: array(
                0: Param(
                    type: null
                    byRef: false
                    variadic: false
                    var: Expr_Variable(
                        name: foo
                    )
                    default: null
                )
            )
            returnType: null
            stmts: array(
                0: Stmt_Expression(
                    expr: Expr_FuncCall(
                        name: Name(
                            parts: array(
                                0: var_dump
                            )
                        )
                        args: array(
                            0: Arg(
                                value: Expr_Variable(
                                    name: foo
                                )
                                byRef: false
                                unpack: false
                            )
                        )
                    )
                )
            )
        )
    )
    

    Let's traverse the AST and perform some kind of modification. For example, drop all function bodies:

    use PhpParser\Node;
    use PhpParser\Node\Stmt\Function_;
    use PhpParser\NodeTraverser;
    use PhpParser\NodeVisitorAbstract;
    
    $traverser = new NodeTraverser();
    $traverser->addVisitor(new class extends NodeVisitorAbstract {
        public function enterNode(Node $node) {
            if ($node instanceof Function_) {
                // Clean out the function body
                $node->stmts = [];
            }
        }
    });
    
    $ast = $traverser->traverse($ast);
    echo $dumper->dump($ast) . "\n";
    

    This gives us an AST where the Function_::$stmts are empty:

    array(
        0: Stmt_Function(
            byRef: false
            name: Identifier(
                name: test
            )
            params: array(
                0: Param(
                    type: null
                    byRef: false
                    variadic: false
                    var: Expr_Variable(
                        name: foo
                    )
                    default: null
                )
            )
            returnType: null
            stmts: array(
            )
        )
    )
    

    Finally, we can convert the new AST back to PHP code:

    use PhpParser\PrettyPrinter;
    
    $prettyPrinter = new PrettyPrinter\Standard;
    echo $prettyPrinter->prettyPrintFile($ast);
    

    This gives us our original code, minus the var_dump() call inside the function:

    <?php
    
    function test($foo)
    {
    }
    

    For a more comprehensive introduction, see the documentation.

    Documentation

    1. Introduction
    2. Usage of basic components

    Component documentation:

    • Walking the AST
      • Node visitors
      • Modifying the AST from a visitor
      • Short-circuiting traversals
      • Interleaved visitors
      • Simple node finding API
      • Parent and sibling references
    • Name resolution
      • Name resolver options
      • Name resolution context
    • Pretty printing
      • Converting AST back to PHP code
      • Customizing formatting
      • Formatting-preserving code transformations
    • AST builders
      • Fluent builders for AST nodes
    • Lexer
      • Lexer options
      • Token and file positions for nodes
      • Custom attributes
    • Error handling
      • Column information for errors
      • Error recovery (parsing of syntactically incorrect code)
    • Constant expression evaluation
      • Evaluating constant/property/etc initializers
      • Handling errors and unsupported expressions
    • JSON representation
      • JSON encoding and decoding of ASTs
    • Performance
      • Disabling Xdebug
      • Reusing objects
      • Garbage collection impact
    • Frequently asked questions
      • Parent and sibling references
  • \PhpParser\grammar Readme

    What do all those files mean?

    • php5.y: PHP 5 grammar written in a pseudo language
    • php7.y: PHP 7 grammar written in a pseudo language
    • tokens.y: Tokens definition shared between PHP 5 and PHP 7 grammars
    • parser.template: A kmyacc parser prototype file for PHP
    • tokens.template: A kmyacc prototype file for the Tokens class
    • rebuildParsers.php: Preprocesses the grammar and builds the parser using kmyacc

    .phpy pseudo language

    The .y file is a normal grammar in kmyacc (yacc) style, with some transformations
    applied to it:

    • Nodes are created using the syntax Name[..., ...]. This is transformed into
      new Name(..., ..., attributes())
    • Some function-like constructs are resolved (see rebuildParsers.php for a list)

    Building the parser

    Run php grammar/rebuildParsers.php to rebuild the parsers. Additional options:

    • The KMYACC environment variable can be used to specify an alternative kmyacc binary.
      By default the phpyacc dev dependency will be used. To use the original kmyacc, you
      need to compile moriyoshi's fork.
    • The --debug option enables emission of debug symbols and creates the y.output file.
    • The --keep-tmp-grammar option preserves the preprocessed grammar file.
  • \Psr\Cache Readme

    Caching Interface

    This repository holds all interfaces related to PSR-6 (Caching Interface).

    Note that this is not a Caching implementation of its own. It is merely interfaces that describe the components of a Caching mechanism.

    The installable package and implementations are listed on Packagist.

  • \Psr\Container Readme

    Container interface

    This repository holds all interfaces related to PSR-11 (Container Interface).

    Note that this is not a Container implementation of its own. It is merely abstractions that describe the components of a Dependency Injection Container.

    The installable package and implementations are listed on Packagist.

  • \Psr\EventDispatcher Readme

    PSR Event Dispatcher

    This repository holds the interfaces related to PSR-14.

    Note that this is not an Event Dispatcher implementation of its own. It is merely interfaces that describe the components of an Event Dispatcher. See the specification for more details.

  • \Psr\Http\Client Readme

    HTTP Client

    This repository holds all the common code related to PSR-18 (HTTP Client).

    Note that this is not a HTTP Client implementation of its own. It is merely abstractions that describe the components of a HTTP Client.

    The installable package and implementations are listed on Packagist.

  • \Psr\Http\Message Readme

    PSR Http Message

    This repository holds all interfaces/classes/traits related to
    PSR-7.

    Note that this is not a HTTP message implementation of its own. It is merely an
    interface that describes a HTTP message. See the specification for more details.

    Usage

    We'll certainly need some stuff in here.

  • \Psr\Log Readme

    PSR Log

    This repository holds all interfaces/classes/traits related to
    PSR-3.

    Note that this is not a logger of its own. It is merely an interface that
    describes a logger. See the specification for more details.

    Installation

    composer require psr/log
    

    Usage

    If you need a logger, you can use the interface like this:

    <?php
    
    use Psr\Log\LoggerInterface;
    
    class Foo
    {
        private $logger;
    
        public function __construct(LoggerInterface $logger = null)
        {
            $this->logger = $logger;
        }
    
        public function doSomething()
        {
            if ($this->logger) {
                $this->logger->info('Doing work');
            }
               
            try {
                $this->doSomethingElse();
            } catch (Exception $exception) {
                $this->logger->error('Oh no!', array('exception' => $exception));
            }
    
            // do something useful
        }
    }
    

    You can then pick one of the implementations of the interface to get a logger.

    If you want to implement the interface, you can require this package and
    implement Psr\Log\LoggerInterface in your code. Please read the
    specification text
    for details.

  • \Symfony\Component\CssSelector Readme

    CssSelector Component

    The CssSelector component converts CSS selectors to XPath expressions.

    Resources

    Credits

    This component is a port of the Python cssselect library
    v0.7.1,
    which is distributed under the BSD license.

  • \Symfony\Component\Process Readme

    Process Component

    The Process component executes commands in sub-processes.

    Sponsor

    The Process component for Symfony 5.4/6.0 is backed by SensioLabs.

    As the creator of Symfony, SensioLabs supports companies using Symfony, with an
    offering encompassing consultancy, expertise, services, training, and technical
    assistance to ensure the success of web application development projects.

    Help Symfony by sponsoring its development!

    Resources

  • \voku\helper Readme

    Build Status
    Coverage Status
    Codacy Badge
    Latest Stable Version
    Total Downloads
    License
    Donate to this project using Paypal
    Donate to this project using Patreon

    :scroll: Simple Html Dom Parser for PHP

    A HTML DOM parser written in PHP - let you manipulate HTML in a very easy way!
    This is a fork of PHP Simple HTML DOM Parser project but instead of string manipulation we use DOMDocument and modern php classes like "Symfony CssSelector".

    • PHP 7.0+ & 8.0 Support
    • PHP-FIG Standard
    • Composer & PSR-4 support
    • PHPUnit testing via Travis CI
    • PHP-Quality testing via SensioLabsInsight
    • UTF-8 Support (more support via "voku/portable-utf8")
    • Invalid HTML Support (partly ...)
    • Find tags on an HTML page with selectors just like jQuery
    • Extract contents from HTML in a single line

    Install via "composer require"

    composer require voku/simple_html_dom
    composer require voku/portable-utf8 # if you need e.g. UTF-8 fixed output
    

    Quick Start

    use voku\helper\HtmlDomParser;
    
    require_once 'composer/autoload.php';
    
    ...
    $dom = HtmlDomParser::str_get_html($str);
    // or 
    $dom = HtmlDomParser::file_get_html($file);
    
    $element = $dom->findOne('#css-selector'); // "$element" === instance of "SimpleHtmlDomInterface"
    
    $elements = $dom->findMulti('.css-selector'); // "$elements" === instance of SimpleHtmlDomNodeInterface<int, SimpleHtmlDomInterface>
    
    $elementOrFalse = $dom->findOneOrFalse('#css-selector'); // "$elementOrFalse" === instance of "SimpleHtmlDomInterface" or false
    
    $elementsOrFalse = $dom->findMultiOrFalse('.css-selector'); // "$elementsOrFalse" === instance of SimpleHtmlDomNodeInterface<int, SimpleHtmlDomInterface> or false
    ...
    
    

    Examples

    github.com/voku/simple_html_dom/tree/master/example

    API

    github.com/voku/simple_html_dom/tree/master/README_API.md

    Support

    For support and donations please visit Github | Issues | PayPal | Patreon.

    For status updates and release announcements please visit Releases | Twitter | Patreon.

    For professional support please contact me.

    Thanks

    • Thanks to GitHub (Microsoft) for hosting the code and a good infrastructure including Issues-Managment, etc.
    • Thanks to IntelliJ as they make the best IDEs for PHP and they gave me an open source license for PhpStorm!
    • Thanks to Travis CI for being the most awesome, easiest continous integration tool out there!
    • Thanks to StyleCI for the simple but powerfull code style check.
    • Thanks to PHPStan && Psalm for relly great Static analysis tools and for discover bugs in the code!

    License

    FOSSA Status

  • \Webmozart\Assert Readme

    Webmozart Assert

    Latest Stable Version
    Total Downloads

    This library contains efficient assertions to test the input and output of
    your methods. With these assertions, you can greatly reduce the amount of coding
    needed to write a safe implementation.

    All assertions in the Assert class throw an Webmozart\Assert\InvalidArgumentException if
    they fail.

    FAQ

    What's the difference to beberlei/assert?

    This library is heavily inspired by Benjamin Eberlei's wonderful assert package,
    but fixes a usability issue with error messages that can't be fixed there without
    breaking backwards compatibility.

    This package features usable error messages by default. However, you can also
    easily write custom error messages:

    Assert::string($path, 'The path is expected to be a string. Got: %s');
    

    In beberlei/assert, the ordering of the %s placeholders is different for
    every assertion. This package, on the contrary, provides consistent placeholder
    ordering for all assertions:

    • %s: The tested value as string, e.g. "/foo/bar".
    • %2$s, %3$s, ...: Additional assertion-specific values, e.g. the
      minimum/maximum length, allowed values, etc.

    Check the source code of the assertions to find out details about the additional
    available placeholders.

    Installation

    Use Composer to install the package:

    $ composer require webmozart/assert
    

    Example

    use Webmozart\Assert\Assert;
    
    class Employee
    {
        public function __construct($id)
        {
            Assert::integer($id, 'The employee ID must be an integer. Got: %s');
            Assert::greaterThan($id, 0, 'The employee ID must be a positive integer. Got: %s');
        }
    }
    

    If you create an employee with an invalid ID, an exception is thrown:

    new Employee('foobar');
    // => Webmozart\Assert\InvalidArgumentException:
    //    The employee ID must be an integer. Got: string
    
    new Employee(-10);
    // => Webmozart\Assert\InvalidArgumentException:
    //    The employee ID must be a positive integer. Got: -10
    

    Assertions

    The Assert class provides the following assertions:

    Type Assertions

    Method Description
    string($value, $message = '') Check that a value is a string
    stringNotEmpty($value, $message = '') Check that a value is a non-empty string
    integer($value, $message = '') Check that a value is an integer
    integerish($value, $message = '') Check that a value casts to an integer
    positiveInteger($value, $message = '') Check that a value is a positive (non-zero) integer
    float($value, $message = '') Check that a value is a float
    numeric($value, $message = '') Check that a value is numeric
    natural($value, $message= ''') Check that a value is a non-negative integer
    boolean($value, $message = '') Check that a value is a boolean
    scalar($value, $message = '') Check that a value is a scalar
    object($value, $message = '') Check that a value is an object
    resource($value, $type = null, $message = '') Check that a value is a resource
    isCallable($value, $message = '') Check that a value is a callable
    isArray($value, $message = '') Check that a value is an array
    isTraversable($value, $message = '') (deprecated) Check that a value is an array or a \Traversable
    isIterable($value, $message = '') Check that a value is an array or a \Traversable
    isCountable($value, $message = '') Check that a value is an array or a \Countable
    isInstanceOf($value, $class, $message = '') Check that a value is an instanceof a class
    isInstanceOfAny($value, array $classes, $message = '') Check that a value is an instanceof at least one class on the array of classes
    notInstanceOf($value, $class, $message = '') Check that a value is not an instanceof a class
    isAOf($value, $class, $message = '') Check that a value is of the class or has one of its parents
    isAnyOf($value, array $classes, $message = '') Check that a value is of at least one of the classes or has one of its parents
    isNotA($value, $class, $message = '') Check that a value is not of the class or has not one of its parents
    isArrayAccessible($value, $message = '') Check that a value can be accessed as an array
    uniqueValues($values, $message = '') Check that the given array contains unique values

    Comparison Assertions

    Method Description
    true($value, $message = '') Check that a value is true
    false($value, $message = '') Check that a value is false
    notFalse($value, $message = '') Check that a value is not false
    null($value, $message = '') Check that a value is null
    notNull($value, $message = '') Check that a value is not null
    isEmpty($value, $message = '') Check that a value is empty()
    notEmpty($value, $message = '') Check that a value is not empty()
    eq($value, $value2, $message = '') Check that a value equals another (==)
    notEq($value, $value2, $message = '') Check that a value does not equal another (!=)
    same($value, $value2, $message = '') Check that a value is identical to another (===)
    notSame($value, $value2, $message = '') Check that a value is not identical to another (!==)
    greaterThan($value, $value2, $message = '') Check that a value is greater than another
    greaterThanEq($value, $value2, $message = '') Check that a value is greater than or equal to another
    lessThan($value, $value2, $message = '') Check that a value is less than another
    lessThanEq($value, $value2, $message = '') Check that a value is less than or equal to another
    range($value, $min, $max, $message = '') Check that a value is within a range
    inArray($value, array $values, $message = '') Check that a value is one of a list of values
    oneOf($value, array $values, $message = '') Check that a value is one of a list of values (alias of inArray)

    String Assertions

    You should check that a value is a string with Assert::string() before making
    any of the following assertions.

    Method Description
    contains($value, $subString, $message = '') Check that a string contains a substring
    notContains($value, $subString, $message = '') Check that a string does not contain a substring
    startsWith($value, $prefix, $message = '') Check that a string has a prefix
    notStartsWith($value, $prefix, $message = '') Check that a string does not have a prefix
    startsWithLetter($value, $message = '') Check that a string starts with a letter
    endsWith($value, $suffix, $message = '') Check that a string has a suffix
    notEndsWith($value, $suffix, $message = '') Check that a string does not have a suffix
    regex($value, $pattern, $message = '') Check that a string matches a regular expression
    notRegex($value, $pattern, $message = '') Check that a string does not match a regular expression
    unicodeLetters($value, $message = '') Check that a string contains Unicode letters only
    alpha($value, $message = '') Check that a string contains letters only
    digits($value, $message = '') Check that a string contains digits only
    alnum($value, $message = '') Check that a string contains letters and digits only
    lower($value, $message = '') Check that a string contains lowercase characters only
    upper($value, $message = '') Check that a string contains uppercase characters only
    length($value, $length, $message = '') Check that a string has a certain number of characters
    minLength($value, $min, $message = '') Check that a string has at least a certain number of characters
    maxLength($value, $max, $message = '') Check that a string has at most a certain number of characters
    lengthBetween($value, $min, $max, $message = '') Check that a string has a length in the given range
    uuid($value, $message = '') Check that a string is a valid UUID
    ip($value, $message = '') Check that a string is a valid IP (either IPv4 or IPv6)
    ipv4($value, $message = '') Check that a string is a valid IPv4
    ipv6($value, $message = '') Check that a string is a valid IPv6
    email($value, $message = '') Check that a string is a valid e-mail address
    notWhitespaceOnly($value, $message = '') Check that a string contains at least one non-whitespace character

    File Assertions

    Method Description
    fileExists($value, $message = '') Check that a value is an existing path
    file($value, $message = '') Check that a value is an existing file
    directory($value, $message = '') Check that a value is an existing directory
    readable($value, $message = '') Check that a value is a readable path
    writable($value, $message = '') Check that a value is a writable path

    Object Assertions

    Method Description
    classExists($value, $message = '') Check that a value is an existing class name
    subclassOf($value, $class, $message = '') Check that a class is a subclass of another
    interfaceExists($value, $message = '') Check that a value is an existing interface name
    implementsInterface($value, $class, $message = '') Check that a class implements an interface
    propertyExists($value, $property, $message = '') Check that a property exists in a class/object
    propertyNotExists($value, $property, $message = '') Check that a property does not exist in a class/object
    methodExists($value, $method, $message = '') Check that a method exists in a class/object
    methodNotExists($value, $method, $message = '') Check that a method does not exist in a class/object

    Array Assertions

    Method Description
    keyExists($array, $key, $message = '') Check that a key exists in an array
    keyNotExists($array, $key, $message = '') Check that a key does not exist in an array
    validArrayKey($key, $message = '') Check that a value is a valid array key (int or string)
    count($array, $number, $message = '') Check that an array contains a specific number of elements
    minCount($array, $min, $message = '') Check that an array contains at least a certain number of elements
    maxCount($array, $max, $message = '') Check that an array contains at most a certain number of elements
    countBetween($array, $min, $max, $message = '') Check that an array has a count in the given range
    isList($array, $message = '') Check that an array is a non-associative list
    isNonEmptyList($array, $message = '') Check that an array is a non-associative list, and not empty
    isMap($array, $message = '') Check that an array is associative and has strings as keys
    isNonEmptyMap($array, $message = '') Check that an array is associative and has strings as keys, and is not empty

    Function Assertions

    Method Description
    throws($closure, $class, $message = '') Check that a function throws a certain exception. Subclasses of the exception class will be accepted.

    Collection Assertions

    All of the above assertions can be prefixed with all*() to test the contents
    of an array or a \Traversable:

    Assert::allIsInstanceOf($employees, 'Acme\Employee');
    

    Nullable Assertions

    All of the above assertions can be prefixed with nullOr*() to run the
    assertion only if it the value is not null:

    Assert::nullOrString($middleName, 'The middle name must be a string or null. Got: %s');
    

    Extending Assert

    The Assert class comes with a few methods, which can be overridden to change the class behaviour. You can also extend it to
    add your own assertions.

    Overriding methods

    Overriding the following methods in your assertion class allows you to change the behaviour of the assertions:

    • public static function __callStatic($name, $arguments)
      • This method is used to 'create' the nullOr and all versions of the assertions.
    • protected static function valueToString($value)
      • This method is used for error messages, to convert the value to a string value for displaying. You could use this for representing a value object with a __toString method for example.
    • protected static function typeToString($value)
      • This method is used for error messages, to convert the a value to a string representing its type.
    • protected static function strlen($value)
      • This method is used to calculate string length for relevant methods, using the mb_strlen if available and useful.
    • protected static function reportInvalidArgument($message)
      • This method is called when an assertion fails, with the specified error message. Here you can throw your own exception, or log something.

    Static analysis support

    Where applicable, assertion functions are annotated to support Psalm's
    Assertion syntax.
    A dedicated PHPStan Plugin is
    required for proper type support.

    Authors

    Contribute

    Contributions to the package are always welcome!

    License

    All contents of this package are licensed under the MIT license.

© 2021 Bruce Wells
Search Namespaces \ Classes
Configuration