외부 코드를 Composer 기반으로 변경

This commit is contained in:
Hide_D committed 2018-01-28 19:25:31 +09:00
1 parent 8a181055a0
commit d422c03003
101 files changed
+12743 -19

No files matched your search

+1
View File
@@ -0,0 +1 @@
service_name: travis-ci
@@ -0,0 +1,4 @@
test.php
build/*
report/*
tests/test*
+22
View File
@@ -0,0 +1,22 @@
language: php
php:
- 5.3
- 5.4
- 5.5
- 5.6
- hhvm
matrix:
allow_failures:
- php: hhvm
before_script:
- pyrus install pear/PHP_CodeSniffer
- wget -nc http://getcomposer.org/composer.phar
- php composer.phar install --dev --no-interaction
- mkdir -p build/logs
- phpenv rehash
after_script:
- php vendor/bin/coveralls
+86
View File
@@ -0,0 +1,86 @@
Change Log
==========
1.1.0
-----
This release introduces a deprecation notice for `slugify()`, please update your code.
* Added a cryptographically secure random string function `secure_random_string`. Thanks to @abhimanyusharma003 via [Pull Request #53](https://github.com/brandonwamboldt/utilphp/pull/53)
* Added `limit_characters` and `limit_words` functions. Thanks to @abhimanyusharma003 via [Pull Request #55](https://github.com/brandonwamboldt/utilphp/pull/55)
* Added `rmdir` method to recursively delete a directory. Thanks to @ARACOOOL via [Pull Request #56](https://github.com/brandonwamboldt/utilphp/pull/56)
* Added `set_executable`, `set_readable`, `set_writable`, `directory_size`, `directory_contents` and `get_user_dir` functions. Thanks to @sergserg via [Pull Request #70](https://github.com/brandonwamboldt/utilphp/pull/70)
* Changed parameter ordering for `slugify`, `$css_mode` is now the third argument. For backwards compatibility, the old order will still work but it will generate an `E_USER_DEPRECATED` warning. Thanks to @abhimanyusharma003 via [Pull Request #71](https://github.com/brandonwamboldt/utilphp/pull/71)
* Added `match_string` method. Thanks to @abhimanyusharma003 via [Pull Request #72](https://github.com/brandonwamboldt/utilphp/pull/72)
* Renamed internal methods (protected ones) for PSR-2 compliance
* General performance improvements, code quality improvements, and increased unit test coverage (special thanks to @hopeseekr for getting us near 100% coverage)
1.0.7
-----
* Added `fix_broken_serialization` to fix broken serialized strings (Thanks to @hopeseekr via [Pull Request #48](https://github.com/brandonwamboldt/utilphp/pull/48))
* Fixed `get_current_url` appending port 80 or 443 when not needed (Thanks to @scottchiefbaker via [Pull Request #49](https://github.com/brandonwamboldt/utilphp/pull/49))
* `var_dump` can now handle recursive data structures without crashing
* `var_dump` code was minified and cleaned up
* `array_flatten` was optimized (thanks to @hopeseekr via [Pull Request #47](https://github.com/brandonwamboldt/utilphp/pull/47))
* `remove_accents` was completely rewritten and is now ~4x faster
1.0.6
-----
* Added `start_with` function
* Added `ends_with` function
* Added `str_contains` function
* Added `str_icontains` function
* Added `get_file_ext` function
* Fixing permissions on the files & directories
* Fixing a bug with the include path of util.php
1.0.5
-----
* [Issue #29](https://github.com/brandonwamboldt/utilphp/issues/29) Fixed error in `var_dump` if mbstring extension wasn't present
* Adding Composer support
* Updating license from GPL to MIT
* Adding Changelog to project
* Bumping minimum version to PHP 5.3.3
1.0.4
-----
* [Issue #22](https://github.com/brandonwamboldt/utilphp/issues/22) Removed all superglobal *_get functions, you can use the modified array_get now
* [Issue #22](https://github.com/brandonwamboldt/utilphp/issues/22) Modifed the behaviour of `array_get`, see documentation
* [Pull Request #21](https://github.com/brandonwamboldt/utilphp/pull/21) Added multibyte support to html* functions
* [Issue #9](https://github.com/brandonwamboldt/utilphp/issues/9) Removed the `str_to_utf8` function
* [Issue #3](https://github.com/brandonwamboldt/utilphp/issues/3) Removed the `absint` function
* Removed declare() from util.php to avoid errors
* Updated PHPUnit tests to use PHPUnit 3.6
1.0.3
-----
* [Issue #16](https://github.com/brandonwamboldt/utilphp/issues/16) Improved performance of `slugify`
* [Issue #14](https://github.com/brandonwamboldt/utilphp/issues/14) Modified the regex for `seems_utf8` to be more accurate
* [Issue #13](https://github.com/brandonwamboldt/utilphp/issues/13) Changed `validate_email` to be wrapper for `filter_var`
* Added 'ok' to the list of yes words for `str_to_bool`
* `str_to_bool` matches no followed by any number of 'o's
1.0.2
-----
* [Issue #12](https://github.com/brandonwamboldt/utilphp/issues/12) `get_current_url` now includes the port and user/password if required
* [Issue #11](https://github.com/brandonwamboldt/utilphp/issues/11) `human_time_diff` now uses the DateTime functions
* [Issue #10](https://github.com/brandonwamboldt/utilphp/issues/10) `is_https` no longer checks the port as well
1.0.1
-----
* [Issue #7](https://github.com/brandonwamboldt/utilphp/issues/7) Added the `$trust_proxy_headers` parameter to `get_client_ip`
* [Issue #6](https://github.com/brandonwamboldt/utilphp/issues/6) Removed `is_isset` as the function did not work as intended
* [Issue #6](https://github.com/brandonwamboldt/utilphp/issues/6) Removed `is_empty` as it is redundant, use ! with function calls instead
* Fixed a bug with `get_gravatar`
1.0.0
-----
* Initial release of util.php.
+48
View File
@@ -0,0 +1,48 @@
# CONTRIBUTORS
Util.php is the combined effort of many people who contributed new functions and features, bug fixes, tests, and documentation.
# Maintainer / Lead
* Brandon Wamboldt (http://brandonwamboldt.ca)
## Third-Party Projects
The following projects were fully or partially incorporated into util.php (and properly attributed).
* IntToWords (https://github.com/hemant347/IntToWords)
* LinkifyURL (https://github.com/jmrware/LinkifyURL)
* URLify.php (https://github.com/jbroadway/urlify/)
* Pure PHP http_build_url (https://github.com/jakeasmith/http_build_url)
## Methods
The following developers and/or companies helped contribute to building util.php.
* PHP Experts, Inc. (http://www.phpexperts.pro/)
- `array_flatten()`
- `fix_broken_serialization()`
- Lots of unit tests.
* Tony Ferrara (ircmaxwell, http://blog.ircmaxell.com/)
- `seemsUtf8Regex()`: http://stackoverflow.com/a/11709412/430062
* Askar ([@ARACOOOL](https://github.com/ARACOOOL))
- `rmdir()`
- `limit_characters()`
- `limit_words()`
* Anonymous (tmp1000@fastmail.fm)
- `htmlspecialentities()`: http://php.timesoft.cc/manual/en/function.htmlentities.php
- `htmlspecialchars()`
* Laravel Project (https://github.com/laravel/laravel)
- `secure_random_string()`: http://trac.allenjb.me.uk/php/browser/tagi/vendor/laravel/framework/src/Illuminate/Support/Str.php?rev=87#L127
* Abhimanyu Sharma ([@abhimanyusharma003](https://github.com/abhimanyusharma003))
- `limit_characters()`
- `limit_words()`
- `match_string()`
* Scott Baker ([@scottchiefbaker](https://github.com/scottchiefbaker))
* [@sergserg](https://github.com/sergserg)
- `set_writable()`
- `set_executable()`
- `set_readable()`
- `directory_size()`
- `directory_contents()`
- `get_user_dir()`
+24
View File
@@ -0,0 +1,24 @@
The MIT License (MIT)
=====================
The MIT License (MIT)
Copyright (c) 2013 Brandon Wamboldt
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
+123
View File
@@ -0,0 +1,123 @@
# Util.php [![Build Status](https://img.shields.io/travis/brandonwamboldt/utilphp.svg)](https://travis-ci.org/brandonwamboldt/utilphp) [![Coverage Status](https://img.shields.io/coveralls/brandonwamboldt/utilphp/master.svg)](https://coveralls.io/r/brandonwamboldt/utilphp)
[UtilPHP](http://brandonwamboldt.github.com/utilphp/) (Aka util.php) is a
collection of useful functions and snippets that you need or could use every
day. It's implemented as a class with static methods, to avoid conflicts with
your existing code-base. Just drop it in and start using it immediately.
Included are 55+ functions that provide you with the ability to do common
tasks much easier and more efficiently, without having to find that one comment
on php.net where you know it's been done already. Access superglobals without
checking to see if certain indexes are set first and pass default values, use a
nicely formatted var dump, validate emails, generate random strings, flatten an
array, pull a single column out of a multidimensional array and much more.
Although it's implemented as one giant class, util.php has extensive
documentation and a full suite of unit tests to avoid breaking
backwards-compatibility unintentionally.
## Release Information
This repo contains in development code for future releases as well as the
current stable branch. Development code is contained in the develop branch.
## Changelog and New Features
You can find a list of all changes for each release in the
[official documentation](http://brandonwamboldt.github.com/utilphp/#changelog)
## Installation
### Server Requirements
* PHP version 5.3.3 or higher.
### Standalone File
Simply drop `util.php` in any project and call `include 'util.php';` in your
project. You can then access the `Util` class.
### Composer
Add the following dependency to your composer.json:
```
"brandonwamboldt/utilphp": "1.0.*"
```
When used with composer, the class is namespaced (`\utilphp\util`) instead of
just `util`.
## Contributing
UtilPHP is a community driven project and accepts contributions of code and
documentation from the community. These contributions are made in the form of
Issues or [Pull Requests](http://help.github.com/send-pull-requests/) on the
[UtilityPHP repository](https://github.com/brandonwamboldt/utilphp) on GitHub.
Issues are a quick way to point out a bug. If you find a bug or documentation
error in UtilityPHP then please check a few things first:
* There is not already an open Issue
* The issue has already been fixed (check the develop branch, or look for closed Issues)
* Is it something really obvious that you fix it yourself?
Reporting issues is helpful but an even better approach is to send a Pull
Request, which is done by "Forking" the main repository and committing to your
own copy. This will require you to use the version control system called Git.
## Guidelines
Before we look into how, here are the guidelines. If your Pull Requests fail to
pass these guidelines it will be declined and you will need to re-submit when
you’ve made the changes. This might sound a bit tough, but it is required for
me to maintain quality of the code-base.
### PHP Style
Please ensure all new contributions match the [PSR-2](http://www.php-fig.org/psr/psr-2/)
coding style guide.
### Documentation
If you change anything that requires a change to documentation then you will
need to add it. New methods, parameters, changing default values, adding
constants, etc are all things that will require a change to documentation. The
change-log must also be updated for every change. Also PHPDoc blocks must be
maintained.
### PHP Version Compatibility
UtilityPHP is compatible with PHP 5.3.3 so all code supplied must stick to this
requirement.
Of particular note is avoiding short array notation like this:
```
$var = [];
```
Please use the old notation instead:
```
$var = array();
```
I know it's uglier, but PHP 5.3 while EOL'd, still isn't that old.
### Branching
One thing at a time: A pull request should only contain one change. That does
not mean only one commit, but one change - however many commits it took. The
reason for this is that if you change X and Y but send a pull request for both
at the same time, we might really want X but disagree with Y, meaning we cannot
merge the request. Using the Git-Flow branching model you can create new
branches for both of these features and send two requests.
## License
UtilPHP is licensed under the MIT license.
## Resources
* [Documentation](http://brandonwamboldt.github.com/utilphp/)
+24
View File
@@ -0,0 +1,24 @@
{
"name": "brandonwamboldt/utilphp",
"type": "library",
"version": "1.1.0",
"description": "util.php is a collection of useful functions and snippets that you need or could use every day, designed to avoid conflicts with existing projects",
"keywords": ["php", "utility", "collection", "helpers"],
"homepage": "https://github.com/brandonwamboldt/utilphp",
"license": "MIT",
"authors": [
{
"name": "Brandon Wamboldt",
"email": "brandon.wamboldt@gmail.com"
}
],
"autoload": {
"psr-0": { "utilphp\\": "src/" }
},
"require-dev": {
"satooshi/php-coveralls": "dev-master"
},
"require": {
"php": ">=5.3.3"
}
}
+168
View File
@@ -0,0 +1,168 @@
body {
background: #f4f4f4 url('../images/background.png');
color: #333;
font: 18px/30px "Droid Serif", "Helvetica Neue", Helvetica, Arial;
}
a {
text-decoration: none;
color: #f00;
padding: 2px;
}
a:hover {
background: #277585;
color: #fff;
border-radius: 3px;
}
h1, h2, h3, h4, h5, h6 {
padding-top: 20px;
}
h2 {
font-size: 40px;
font-weight: normal;
margin: 0 0 15px;
}
p {
margin: 20px 0;
min-width: 550px;
max-width: 900px;
}
table, tr, td {
margin: 0; padding: 0;
}
td {
padding: 2px 12px 2px 0;
}
ul {
list-style-type: circle;
padding: 0 0 0 20px;
}
li {
width: 500px;
margin-bottom: 10px;
}
code, pre, tt {
font-family: Monaco, Consolas, "Lucida Console", monospace;
font-size: 12px;
line-height: 18px;
font-style: normal;
}
tt {
padding: 0px 3px;
background: #fff;
border: 1px solid #ddd;
zoom: 1;
}
code {
margin-left: 20px;
}
pre {
font-size: 12px;
padding: 12px;
background: #fff;
margin: 0px 0 30px;
border-radius: 0 0 2px 2px;
box-shadow: inset 0 0 0 1px rgba(0,0,0,.15);
}
span.header {
font-size: 24px;
line-height: 30px;
border-left: 10px solid #ddd;
padding-left: 10px;
}
.desc-text code {
margin-left: 0;
font-size: 18px;
color: #0E04C8;
}
#sidebar {
background: #fff;
position: fixed;
top: 0; left: 0; bottom: 0;
width: 220px;
overflow-y: auto;
overflow-x: hidden;
padding: 5px 0 30px 10px;
border-right: 1px solid #bbb;
box-shadow: 0 0 20px #ccc;
-webkit-box-shadow: 0 0 20px #ccc;
-moz-box-shadow: 0 0 20px #ccc;
-webkit-overflow-scrolling: touch;
}
.toc_title, .toc_title:visited {
display: block;
color: #000;
margin-top: 15px;
}
.toc_title:hover {
background: none;
color: #f00;
}
.toc_title .version {
font-size: 12px;
font-weight: normal;
}
.toc_section {
font-size: 14px;
line-height: 24px;
margin: 5px 0 0 0;
padding-left: 10px;
list-style-type: none;
}
.toc_section li {
cursor: pointer;
margin: 0 0 3px 0;
}
.toc_section li a {
text-decoration: none;
color: black;
}
.toc_section li a:hover {
background: none;
color: #f00;
}
.container {
min-width: 550px;
max-width: 1000px;
margin: 40px 0 50px 260px;
}
#documentation section > article > p > code {
color: #999;
}
#documentation section > article > p > code > .util_class {
color: #bbb;
}
#documentation section > article > p > code > .func_name {
color: #0E04C8;
}
#documentation section > article > p > code > .param {
color: #DA72F3;
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 803 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 83 KiB

+1234
View File
@@ -0,0 +1,1234 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="chrome=1" />
<meta name="viewport" content="width=device-width" />
<link rel="canonical" href="http://includephp.brandonwamboldt.ca/" />
<link rel="shortcut icon" href="favicon.png" type="image/png" />
<link rel="stylesheet" href="http://fonts.googleapis.com/css?family=Droid+Serif:400,700,400italic" />
<link rel="stylesheet" href="css/docs.css" />
<title>util.php - The PHP programmers best friend - UtilityPHP</title>
</head>
<body>
<div id="sidebar" class="interface">
<a class="toc_title" href="#">util.php <span class="version">(1.1.0)</span></a>
<a class="toc_title" href="#debug_functions">Debugging</a>
<ul class="toc_section">
<li>- <a href="#var_dump">var_dump</a></li>
</ul>
<a class="toc_title" href="#arrays">Arrays &amp; Objects</a>
<ul class="toc_section">
<li>- <a href="#array_first">array_first</a></li>
<li>- <a href="#array_first_key">array_first_key</a></li>
<li>- <a href="#array_flatten">array_flatten</a></li>
<li>- <a href="#array_get">array_get</a></li>
<li>- <a href="#array_last">array_last</a></li>
<li>- <a href="#array_last_key">array_last_key</a></li>
<li>- <a href="#array_map_deep">array_map_deep</a></li>
<li>- <a href="#array_pluck">array_pluck</a></li>
<li>- <a href="#array_search_deep">array_search_deep</a></li>
<li>- <a href="#array_clean">array_clean</a></li>
</ul>
<a class="toc_title" href="#urls">URLs</a>
<ul class="toc_section">
<li>- <a href="#add_query_arg">add_query_arg</a></li>
<li>- <a href="#get_current_url">get_current_url</a></li>
<li>- <a href="#http_build_url">http_build_url</a></li>
<li>- <a href="#is_https">is_https</a></li>
<li>- <a href="#remove_query_arg">remove_query_arg</a></li>
<li>- <a href="#slugify">slugify</a></li>
</ul>
<a class="toc_title" href="#strings">Strings</a>
<ul class="toc_section">
<li>- <a href="#htmlentities">htmlentities</a></li>
<li>- <a href="#htmlspecialchars">htmlspecialchars</a></li>
<li>- <a href="#linkify">linkify</a></li>
<li>- <a href="#match_string">match_string</a></li>
<li>- <a href="#random_string">random_string</a></li>
<li>- <a href="#number_to_word">number_to_word</a></li>
<li>- <a href="#ordinal">ordinal</a></li>
<li>- <a href="#remove_accents">remove_accents</a></li>
<li>- <a href="#secure_random_string">secure_random_string</a></li>
<li>- <a href="#seems_utf8">seems_utf8</a></li>
<li>- <a href="#safe_truncate">safe_truncate</a></li>
<li>- <a href="#size_format">size_format</a></li>
<li>- <a href="#str_to_bool">str_to_bool</a></li>
<li>- <a href="#zero_pad">zero_pad</a></li>
<li>- <a href="#strip_space">strip_space</a></li>
<li>- <a href="#sanitize_string">sanitize_string</a></li>
</ul>
<a class="toc_title" href="#files">Files</a>
<ul class="toc_section">
<li>- <a href="#full_permissions">full_permissions</a></li>
<li>- <a href="#rmdir">rmdir</a></li>
</ul>
<a class="toc_title" href="#serialization">Serialization</a>
<ul class="toc_section">
<li>- <a href="#is_serialized">is_serialized</a></li>
<li>- <a href="#maybe_serialize">maybe_serialize</a></li>
<li>- <a href="#maybe_unserialize">maybe_unserialize</a></li>
<li>- <a href="#fix_broken_serialization">fix_broken_serialization</a></li>
</ul>
<a class="toc_title" href="#other">Other</a>
<ul class="toc_section">
<li>- <a href="#force_download">force_download</a></li>
<li>- <a href="#get_client_ip">get_client_ip</a></li>
<li>- <a href="#get_gravatar">get_gravatar</a></li>
<li>- <a href="#human_time_diff">human_time_diff</a></li>
<li>- <a href="#nocache_headers">nocache_headers</a></li>
<li>- <a href="#utf8_headers">utf8_headers</a></li>
<li>- <a href="#validate_email">validate_email</a></li>
</ul>
<a class="toc_title" href="#constants">Constants</a>
<ul class="toc_section">
<li>- <a href="#SECONDS_IN_A_MINUTE">SECONDS_IN_A_MINUTE</a></li>
<li>- <a href="#SECONDS_IN_AN_HOUR">SECONDS_IN_AN_HOUR</a></li>
<li>- <a href="#SECONDS_IN_A_DAY">SECONDS_IN_A_DAY</a></li>
<li>- <a href="#SECONDS_IN_A_WEEK">SECONDS_IN_A_WEEK</a></li>
<li>- <a href="#SECONDS_IN_A_MONTH">SECONDS_IN_A_MONTH</a></li>
<li>- <a href="#SECONDS_IN_A_YEAR">SECONDS_IN_A_YEAR</a></li>
</ul>
<a class="toc_title" href="#changelog">Change Log</a>
</div>
<div class="container">
<p id="introduction">
<img id="logo" src="images/utility_logo.png" alt="Util.php" />
</p>
<p>
<a href="http://github.com/brandonwamboldt/utilphp/">util.php</a> is a collection of useful functions and snippets
that you need or could use every day. It's implemented as a class with static methods, to avoid conflicts with your
existing code-base. Just drop it in and start using it immediately.
</p>
<p>
Included are 60+ functions that provide you with the ability to do common tasks much easier and more efficiently,
without having to find that one comment on php.net where you know its been done already. Access superglobals
without checking to see if certain indexes are set first and pass default values, use a nicely formatted var dump,
validate emails, generate random strings, flatten an array, pull a single column out of a multidimensional array
and much more.
</p>
<p>
Although it's implemented as one giant class, util.php has extensive documentation and a full suite of unit tests
to avoid breaking backwards-compatibility unintentionally.
</p>
<p>
The project is <a href="http://github.com/brandonwamboldt/utilphp/">hosted on GitHub</a>.
You can report bugs and discuss features on the
<a href="https://github.com/brandonwamboldt/utilphp/issues">issues page</a>,
or send tweets to <a href="http://twitter.com/brandonwamboldt">@brandonwamboldt</a>.
</p>
<h2>Downloads <i style="padding-left: 12px; font-size:12px;">(Right-click, and use "Save As")</i></h2>
<p>
<a href="https://github.com/brandonwamboldt/utilphp/archive/1.1.0.zip">Stable Version (1.1.0)</a><br>
<a href="https://github.com/brandonwamboldt/utilphp/zipball/master">Unstable Version (master)</a>
</p>
<h2>Installation</h2>
<span class="header">Server Requirements</span><br>
<ul>
<li>PHP 5.3.3+</li>
</ul>
<span class="header">Standalone File</span><br>
<p class="desc-text">
Simply drop <code>util.php</code> in any project and call <code>include 'util.php';</code> in your project.
You can then access the <code>Util</code> class.
</p>
<span class="header">Composer</span><br>
<p class="desc-text">
Add the following dependency to your composer.json:
<pre>"brandonwamboldt/utilphp": "1.1.*"</pre>
When used with composer, the class is namespaced (<code>\utilphp\util</code>) instead of
just <code>util</code>.
</p>
<div id="documentation">
<h2 id="debug_functions">Debugging Functions</h2>
<section>
<article id="var_dump">
<p>
<span class="header">var_dump</span>
<code>
<span class="util_class">util::</span><span class="func_name">var_dump</span>(mixed <span class="param">$var</span>[, bool <span class="param">$return</span> = FALSE])
</code>
</p>
<p>
Nicely prints out the contents of a passed variable. Booleans are properly displayed as 'true' or 'false',
null values are shown as 'NULL', variable types are displayed, and arrays and objects are displayed as a
collapsible tree powered by JavaScript.
</p>
<p><strong>Usage:</strong></p>
<pre class="usage-example">util::var_dump($var);</pre>
<img src="images/awesome_var_dump.jpg" style="border: 1px solid #ccc;" />
</article>
</section>
<h2 id="arrays">Array/Object Functions</h2>
<section>
<article id="array_first">
<p>
<span class="header">array_first</span>
<code>
<span class="util_class">util::</span><span class="func_name">array_first</span>(array <span class="param">$array</span>)
</code>
</p>
<p>
Retrieve the first value from an array. Can be run on function callbacks, and it will not modify the pointer
of the source array unlike most other methods of doing this.
</p>
<p><strong>Usage:</strong></p>
<pre>util::array_first( ['a', 'b', 'c'] );<br />=&gt; Returns 'a'</pre>
</article>
<article id="array_first_key">
<p>
<span class="header">array_first_key</span>
<code>
<span class="util_class">util::</span><span class="func_name">array_first_key</span>(array <span class="param">$array</span>)
</code>
</p>
<p>
Retrieve the first key from an array. Can be run on function callbacks, and it will not modify the pointer of
the source array unlike most other methods of doing this.
</p>
<p><strong>Usage:</strong></p>
<pre>util::array_first_key( $users );<br />=&gt; Returns 'brandon'</pre>
</article>
<article id="array_flatten">
<p>
<span class="header">array_flatten</span>
<code>
<span class="util_class">util::</span><span class="func_name">array_flatten</span>(array <span class="param">$array</span>[, bool <span class="param">$preserve_keys</span> = TRUE])
</code>
</p>
<p>Flattens a multi-dimensional array into a one dimensional array</p>
<p><strong>Usage:</strong></p>
<pre>util::array_flatten( [ 'a', 'b', [ 'c', 'd', 'e', [ 'f', 'g', [ [ [ [ 'h', 'i', 'j' ] ] ] ] ] ] ] );
=&gt; Returns [ 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j' ]</pre>
</article>
<article id="array_get">
<p>
<span class="header">array_get</span>
<code>
<span class="util_class">util::</span><span class="func_name">array_get</span>(<span class="param">$var</span>[, mixed <span class="param">$default</span> = NULL])
</code>
</p>
<p>Retrieve a value from an array, or return a given default if the index isn't set</p>
<p><strong>Usage:</strong></p>
<pre>util::array_get($_POST['action'], 'index');
=&gt; If $_POST['action'] is set, returns its value, otherwise returns 'index'
util::array_get($_POST['action']['do'], 'index');
=&gt; Returns the value of $_POST['action']['do'] or 'index'</pre>
</article>
<article id="array_last">
<p>
<span class="header">array_last</span>
<code>
<span class="util_class">util::</span><span class="func_name">array_last</span>(array <span class="param">$array</span>)
</code>
</p>
<p>
Retrieve the last value from an array. Can be run on function callbacks, and it will not modify the pointer
of the source array unlike most other methods of doing this.
</p>
<p><strong>Usage:</strong></p>
<pre>util::array_last( [ 'a', 'b', 'c'] );
=&gt; Returns 'c'</pre>
</article>
<article id="array_last_key">
<p>
<span class="header">array_last_key</span>
<code>
<span class="util_class">util::</span><span class="func_name">array_last_key</span>(array <span class="param">$array</span>)
</code>
</p>
<p>
Retrieve the last key from an array. Can be run on function callbacks, and it will not modify the pointer of
the source array unlike most other methods of doing this.
</p>
<p><strong>Usage:</strong></p>
<pre>util::array_last_key( $users );
=&gt; Returns 'zane'</pre>
</article>
<article id="array_map_deep">
<p>
<span class="header">array_map_deep</span>
<code>
<span class="util_class">util::</span><span class="func_name">array_map_deep</span>(array <span class="param">$array</span>, callable <span class="param">$callback</span>[, bool <span class="param">$on_nonscalar</span> = FALSE])
</code>
</p>
<p>
Returns an array containing all the elements of $array after applying the callback function to each one recursively.
Particularly useful for avoiding errors when calling functions that only accept scalar values on an array that could
contain nested arrays, such as $_GET or $_POST.
</p>
<p><strong>Usage:</strong></p>
<pre>util::array_map_deep($_POST, 'htmlentities');
=&gt; Recursively escapes each scalar value in $_POST
util::array_map_deep($_POST, 'htmlentities', TRUE);
=&gt; Recursively escapes each value in $_POST regardless of its type</pre>
</article>
<article id="array_pluck">
<p>
<span class="header">array_pluck</span>
<code>
<span class="util_class">util::</span><span class="func_name">array_pluck</span>(array <span class="param">$array</span>, string <span class="param">$field</span>[, bool <span class="param">$preserve_keys</span>, bool <span class="param">$remove_nomatches</span>])
</code>
</p>
<p>
Replaces each value in an array with the specified field of the array or object that used to be the value. Very
useful when you have an array of objects or arrays from a database, and you only want one specific field. For
example, you want an array of emails from an array of users.
</p>
<p><strong>Usage:</strong></p>
<pre>util::array_pluck([['val' => 1], ['val' => 2], ['val' => 3]], 'val');
=&gt; Returns [1, 2, 3]
util::array_pluck($users, 'email');
=&gt; Returns an array of email addresses for each user</pre>
</article>
<article id="array_search_deep">
<p>
<span class="header">array_search_deep</span>
<code>
<span class="util_class">util::</span><span class="func_name">array_search_deep</span>(array <span class="param">$array</span>, mixed <span class="param">$search</span>[, string <span class="param">$field</span> = FALSE])
</code>
</p>
<p>
Allows you to search for a value in an array of arrays or an array of objects, and return the key of the value
that matches the search criteria. If $field is unspecified, the entire array/object is searched.
</p>
<p><strong>Usage:</strong></p>
<pre>util::array_search_deep($_POST, 'delete_post');
=&gt; Might return 'do' if $_POST['do']['action'] = 'delete_post'
util::array_search_deep($users, 'rogue_coder', 'username');
=&gt; Might return 5 if $users[5]->username = 'rogue_coder'</pre>
</article>
<article id="array_clean">
<p>
<span class="header">array_clean</span>
<code>
<span class="util_class">util::</span><span class="func_name">array_clean</span>(array <span class="param">$array</span>)
</code>
</p>
<p>
Remove all null/empty/false values from the given array.
</p>
<p><strong>Usage:</strong></p>
<pre>util::array_clean( array( 'a', 'b', '', null, false, 0) );<br />=&gt; Returns array('a', 'b');</pre>
</article>
</section>
<h2 id="urls">URL Functions</h2>
<section>
<article id="add_query_arg">
<p>
<span class="header">add_query_arg</span>
<code>
<span class="util_class">util::</span><span class="func_name">add_query_arg</span>()
</code>
</p>
<p>Adds one ore more query args to the query string of the current URL or a given URL</p>
<p><strong>Usage:</strong></p>
<pre>util::add_query_arg( 'user', '5', '/admin/users?action=edit' );
=&gt; Returns '/admin/users?action=edit&amp;user=5'
util::add_query_arg( [ 'user' => 5, 'action' => 'edit' ], '/admin/users' );
=&gt; Returns '/admin/users?user=5&amp;action=edit'</pre>
</article>
<article id="get_current_url">
<p>
<span class="header">get_current_url</span>
<code>
<span class="util_class">util::</span><span class="func_name">get_current_url</span>()
</code>
</p>
<p>Returns the current URL with hostname</p>
<p><strong>Usage:</strong></p>
<pre>util::get_current_url();
=&gt; Returns 'http://brandonwamboldt.ca/utilphp/'</pre>
</article>
<article id="is_https">
<p>
<span class="header">is_https</span>
<code>
<span class="util_class">util::</span><span class="func_name">is_https</span>()
</code>
</p>
<p>Returns true if the current page is being loaded over https, false if it isn't</p>
<p><strong>Usage:</strong></p>
<pre>util::is_https();
=&gt; Returns false</pre>
</article>
<article id="http_build_url">
<p>
<span class="header">http_build_url</span>
<code>
<span class="util_class">util::</span><span class="func_name">http_build_url</span>([mixed $url[, mixed $parts[, int $flags = HTTP_URL_REPLACE[, array &amo;$new_url]]]])
</code>
</p>
<p>
Pure PHP implementation/polyfill for <a href="http://php.net/http_build_url">http_build_url</a>
which requires pecl_http to be installed.
</p>
<p><strong>Usage:</strong></p>
<pre>echo util::http_build_url("http://user@www.example.com/pub/index.php?a=b#files",
array(
"scheme" => "ftp",
"host" => "ftp.example.com",
"path" => "files/current/",
"query" => "a=c"
),
HTTP_URL_STRIP_AUTH | HTTP_URL_JOIN_PATH | HTTP_URL_JOIN_QUERY | HTTP_URL_STRIP_FRAGMENT
);</pre>
<p>The above example will output:</p>
<pre>ftp://ftp.example.com/pub/files/current/?a=c</pre>
</article>
<article id="is_https">
<p>
<span class="header">is_https</span>
<code>
<span class="util_class">util::</span><span class="func_name">is_https</span>()
</code>
</p>
<p>Returns true if the current page is being loaded over https, false if it isn't</p>
<p><strong>Usage:</strong></p>
<pre>util::is_https();
=&gt; Returns false</pre>
</article>
<article id="remove_query_arg">
<p>
<span class="header">remove_query_arg</span>
<code>
<span class="util_class">util::</span><span class="func_name">remove_query_arg</span>( array|string <span class="param">$query_args</span>[, string <span class="param">$url</span>])
</code>
</p>
<p>Removes one ore more query args from the query string of the current URL or a given URL</p>
<p><strong>Usage:</strong></p>
<pre>util::remove_query_arg( 'action', '/admin/users?action=edit&amp;user=5' );
=&gt; Returns '/admin/users?user=5'
util::remove_query_arg( [ 'user', 'action'], '/admin/users?action=edit&amp;user=5' );
=&gt; Returns '/admin/users'</pre>
</article>
<article id="slugify">
<p>
<span class="header">slugify</span>
<code>
<span class="util_class">util::</span><span class="func_name">slugify</span>(string <span class="param">$string</span>[, string <span class="param">$separator</span> = "-", bool <span class="param">$css_mode</span> = FALSE])
</code>
</p>
<p>
Generate a string safe for use in URLs from any given string. Converts any accent characters
to their equivalent normal characters and converts any other non-alphanumeric characters to
dashes, then converts any sequence of two or more dashes to a single dash. This function
generates slugs safe for use as URLs, and if you pass TRUE as the second parameter, it will
create strings safe for use as CSS classes or IDs.
</p>
<p><strong>Usage:</strong></p>
<pre>util::slugify('This is a random --string with an Ãccent');
=&gt; Returns 'this-is-a-random-string-with-an-accent'
util::slugify('Another String', '.');
=&gt; Returns 'another.string'</pre>
</article>
</section>
<h2 id="strings">String Functions</h2>
<section>
<article id="htmlentities">
<p>
<span class="header">htmlentities</span>
<code>
<span class="util_class">util::</span><span class="func_name">htmlentities</span>(string <span class="param">$string</span>[, bool <span class="param">$preserve_encoded_entities</span> = FALSE])
</code>
</p>
<p>
Executes htmlentities with ENT_QUOTES set by default. However, if you pass TRUE as
the second parameter, it will not re-encode entities that are already encoded.
</p>
<p><strong>Usage:</strong></p>
<pre>util::htmlentities('this string &lt; this string', TRUE);
=&gt; Returns 'this string &lt; this string'</pre>
</article>
<article id="htmlspecialchars">
<p>
<span class="header">htmlspecialchars</span>
<code>
<span class="util_class">util::</span><span class="func_name">htmlspecialchars</span>(string <span class="param">$string</span>[, bool <span class="param">$preserve_encoded_entities</span> = FALSE])
</code>
</p>
<p>
Executes htmlspecialchars with ENT_QUOTES set by default. However, if you pass TRUE as
the second parameter, it will not re-encode entities that are already encoded.
</p>
<p><strong>Usage:</strong></p>
<pre>util::htmlspecialchars('this string &lt; this string', TRUE);
=&gt; Returns 'this string &lt; this string'</pre>
</article>
<article id="linkify">
<p>
<span class="header">linkify</span>
<code>
<span class="util_class">util::</span><span class="func_name">linkify</span>(string <span class="param">$text</span>)
</code>
</p>
<p>Find's any URLs in the specified text and wraps them with HTML anchor tags</p>
<p><strong>Usage:</strong></p>
<pre>util::linkify('this string has a link to www.google.com');
=&gt; Returns 'this string has a link to &lt;a href="http://wwww.google.com/"&gt;www.google.com&lt;/a&gt;'</pre>
</article>
<article id="match_string">
<p>
<span class="header">match_string</span>
<code>
<span class="util_class">util::</span><span class="func_name">match_string</span>(string <span class="param">$pattern</span>, string <span class="param">$string</span>[, bool <span class="param">$caseSensitive</span> = true])
</code>
</p>
<p>
Check if a string matches a given pattern. You can use '*' as a wildcard character.
</p>
<p><strong>Usage:</strong></p>
<pre>util::match_string("test/*", "test/my/test");
=&gt; Returns true
util::match_string("test/", "test/my/test");
=&gt; Returns false</pre>
</article>
<article id="random_string">
<p>
<span class="header">random_string</span>
<code>
<span class="util_class">util::</span><span class="func_name">random_string</span>(int <span class="param">$length</span>[, bool <span class="param">$human_friendly</span> = TRUE, bool <span class="param">$include_symbols</span> = FALSE, bool <span class="param">$no_duplicate_chars</span> = FALSE])
</code>
</p>
<p>
Generates a random string of the specified length. Human friendly mode
will exclude characters that can be confused with other characters, such
as 0 (zero) and O (capital o), 1 (one) and l (lowercase L).
</p>
<p><strong>Usage:</strong></p>
<pre>util::random_string(8);
=&gt; Returns 'a6BiF4UW'</pre>
</article>
<article id="number_to_word">
<p>
<span class="header">number_to_word</span>
<code>
<span class="util_class">util::</span><span class="func_name">number_to_word</span>(int|float <span class="param">$number</span>)
</code>
</p>
<p>Converts a number into its text equivalent. For example, 56 becomes fifty-six.</p>
<pre>util::number_to_word(512.5);
=&gt; Returns 'five hundred and twelve point five'</pre>
</article>
<article id="ordinal">
<p>
<span class="header">ordinal</span>
<code>
<span class="util_class">util::</span><span class="func_name">ordinal</span>(int <span class="param">$number</span>)
</code>
</p>
<p>Returns the ordinal version of a number (appends th, st, nd, rd)</p>
<p><strong>Usage:</strong></p>
<pre>util::ordinal(22);
=&gt; Returns '22nd'</pre>
</article>
<article id="remove_accents">
<p>
<span class="header">remove_accents</span>
<code>
<span class="util_class">util::</span><span class="func_name">remove_accents</span>(string <span class="param">$string</span>)
</code>
</p>
<p>Converts all accent characters to their ASCII equivalents</p>
<p><strong>Usage:</strong></p>
<pre>util::remove_accents('&#192;ccent');
=&gt; Returns 'Accent'</pre>
</article>
<article id="secure_random_string">
<p>
<span class="header">secure_random_string</span>
<code>
<span class="util_class">util::</span><span class="func_name">secure_random_string</span>(int <span class="param">$length</span>)
</code>
</p>
<p>Generate a random string of characters. Will attempt to use a secure source (openssl).</p>
<p><strong>Usage:</strong></p>
<pre>util::secure_random_string(16);
=&gt; Returns '5bB1RJH0cQhNjviT'</pre>
</article>
<article id="seems_utf8">
<p>
<span class="header">seems_utf8</span>
<code>
<span class="util_class">util::</span><span class="func_name">seems_utf8</span>(string <span class="param">$string</span>)
</code>
</p>
<p>Checks to see if a given string is UTF-8 encoded/safe</p>
<p><strong>Usage:</strong></p>
<pre>util::seems_utf8('This is some random string user input');
=&gt; Returns true</pre>
</article>
<article id="safe_truncate">
<p>
<span class="header">safe_truncate</span>
<code>
<span class="util_class">util::</span><span class="func_name">safe_truncate</span>(string <span class="param">$string</span>, int <span class="param">$length</span>[, string <span class="param">$append</span> = '...'])
</code>
</p>
<p>Truncate a string to a specified length without cutting a word off</p>
<p><strong>Usage:</strong></p>
<pre>util::safe_truncate('The quick brown fox jumps over the lazy dog', 24);
=&gt; Returns 'The quick brown fox...'</pre>
</article>
<article id="size_format">
<p>
<span class="header">size_format</span>
<code>
<span class="util_class">util::</span><span class="func_name">size_format</span>(int <span class="param">$bytes</span>[, int <span class="param">$decimals</span> = 0])
</code>
</p>
<p>Formats an integer as a human friendly size string, such as 4 KiB.</p>
<p><strong>Usage:</strong></p>
<pre>util::size_format( 25151251, 2 );
=&gt; Returns '23.99 MiB'</pre>
</article>
<article id="str_to_bool">
<p>
<span class="header">str_to_bool</span>
<code>
<span class="util_class">util::</span><span class="func_name">str_to_bool</span>(string <span class="param">$string</span>)
</code>
</p>
<p>Converts a string to boolean, looking for yes/no words like 'yes', 'no', 'true', 'false', 'y', 'n', etc</p>
<p><strong>Usage:</strong></p>
<pre>util::str_to_bool('yes');
=&gt; Returns true</pre>
</article>
<article id="zero_pad">
<p>
<span class="header">zero_pad</span>
<code>
<span class="util_class">util::</span><span class="func_name">zero_pad</span>(int <span class="param">$number</span>, int <span class="param">$length</span>)
</code>
</p>
<p>Pads a given number with zeroes on the left</p>
<p><strong>Usage:</strong></p>
<pre>util::zero_pad(341, 8);
=&gt; Returns '00000341'</pre>
</article>
<article id="strip_space">
<p>
<span class="header">strip_space</span>
<code>
<span class="util_class">util::</span><span class="func_name">strip_space</span>(string <span class="param">$string</span>)
</code>
</p>
<p>Strip all withspace from the given string</p>
<p><strong>Usage:</strong></p>
<pre>util::strip_space(' The quick brown fox jumps over the lazy dog ');
=&gt; Returns 'Thequickbrownfoxjumpsoverthelazydog'</pre>
</article>
<article id="sanitize_string">
<p>
<span class="header">sanitize_string</span>
<code>
<span class="util_class">util::</span><span class="func_name">sanitize_string</span>(string <span class="param">$string</span>)
</code>
</p>
<p>
Sanitize a string by performing the following operation :
<ul>
<li>Remove accents</li>
<li>Lower the string</li>
<li>Remove punctuation characters</li>
<li>Strip whitespaces</li>
</ul>
</p>
<p><strong>Usage:</strong></p>
<pre>util::sanitize_string(' Benoit! à New-York? j’ai perçu 1 % : Qu’as-tu "gagné" chez M. V. Noël? Dix francs.');
=&gt; Returns 'benoitanewyorkjaipercu1quastugagnechezmvnoeldixfrancs'</pre>
</article>
</section>
<h2 id="files">Files</h2>
<section>
<article id="full_permissions">
<p>
<span class="header">full_permissions</span>
<code>
<span class="util_class">util::</span><span class="func_name">full_permissions</span>(string <span class="param">$file</span>)
</code>
</p>
<p>Returns the file permissions as a nice string, like -rw-r--r--</p>
<p><strong>Usage:</strong></p>
<pre>util::full_permissions('/etc/passwd');
=&gt; Returns '-rw-r--r--'</pre>
</article>
<article id="rmdir">
<p>
<span class="header">rmdir</span>
<code>
<span class="util_class">util::</span><span class="func_name">rmdir</span>(string <span class="param">$dir</span>[, bool <span class="param">$traverseSymlinks</span> = false])
</code>
</p>
<p>Recursively deletes a directories (including all contents).</p>
<p><strong>Usage:</strong></p>
<pre>util::rmdir('/tmp/working/dir');
=&gt; Returns true</pre>
</article>
</section>
<h2 id="serialization">Serialization</h2>
<section>
<article id="is_serialized">
<p>
<span class="header">is_serialized</span>
<code>
<span class="util_class">util::</span><span class="func_name">is_serialized</span>(mixed <span class="param">$data</span>)
</code>
</p>
<p>Checks to see if a given variable is a seralized data structure</p>
<p><strong>Usage:</strong></p>
<pre>util::is_serialized( 'a:0:{}' );
=&gt; Returns true</pre>
</article>
<article id="maybe_serialize">
<p>
<span class="header">maybe_serialize</span>
<code>
<span class="util_class">util::</span><span class="func_name">maybe_serialize</span>(mixed <span class="param">$data</span>)
</code>
</p>
<p>Serialize data, if needed to store in plaintext (Arrays or objects)</p>
<p><strong>Usage:</strong></p>
<pre>util::maybe_serialize( 5 );
=&gt; Returns 5
util::maybe_serialize( array() );
=&gt; Returns 'a:0:{}'</pre>
</article>
<article id="maybe_unserialize">
<p>
<span class="header">maybe_unserialize</span>
<code>
<span class="util_class">util::</span><span class="func_name">maybe_unserialize</span>(mixed <span class="param">$data</span>)
</code>
</p>
<p>Unserialize data, if it's a serialized string</p>
<p><strong>Usage:</strong></p>
<pre>util::maybe_unserialize(5);
=&gt; Returns 5
util::maybe_unserialize("a:0:{}");
=&gt; Returns array()</pre>
</article>
<article id="fix_broken_serialization">
<p>
<span class="header">fix_broken_serialization</span>
<code>
<span class="util_class">util::</span><span class="func_name">fix_broken_serialization</span>(mixed <span class="param">$data</span>)
</code>
</p>
<p>
Attempt to fix a broken serialization string (e.g. where string offsets are incorrect). Can fix
errors that frequently occur with mismatched character sets or higher-than-ASCII characters.
</p>
<p><strong>Usage:</strong></p>
<pre>util::fix_broken_serialization('a:1:{s:4:"test";s:4:"abc";}');
=&gt; Returns 'a:1:{s:4:"test";s:3:"abc";}'</pre>
</article>
</section>
<h2 id="other">Other</h2>
<section>
<article id="force_download">
<p>
<span class="header">force_download</span>
<code>
<span class="util_class">util::</span><span class="func_name">force_download</span>(string <span class="param">$filename</span>, string <span class="param">$content</span> = FALSE)
</code>
</p>
<p>
Transmit headers that force a browser to display the download file dialog. Cross
browser compatible. Only fires if headers have not already been sent.
</p>
<p><strong>Usage:</strong></p>
<pre>util::force_download( 'export.csv', file_get_contents( 'securefile.csv' ) );
=&gt; The user will be prompted to download the file</pre>
</article>
<article id="get_client_ip">
<p>
<span class="header">get_client_ip</span>
<code>
<span class="util_class">util::</span><span class="func_name">get_client_ip</span>(bool <span class="param">$trust_proxy_headers</span> = FALSE)
</code>
</p>
<p>
Returns the IP address of the client. Only enable $trust_proxy_headers if your server is behind a proxy
that sets the HTTP_CLIENT_IP and HTTP_X_FORWARDED_FOR headers.
</p>
<p><strong>Usage:</strong></p>
<pre>util::get_client_ip();
=&gt; Returns '12.123.12.100'</pre>
</article>
<article id="get_gravatar">
<p>
<span class="header">get_gravatar</span>
<code>
<span class="util_class">util::</span><span class="func_name">get_gravatar</span>(string <span class="param">$email</span>, int <span class="param">$size</span> = 32)
</code>
</p>
<p>Return the URL to a user's gravatar</p>
<p><strong>Usage:</strong></p>
<pre>util::get_gravatar('brandon.wamboldt@gmail.com');
=&gt; Returns 'http://www.gravatar.com/avatar/46679faeb6780ecb1ea57527fdc66eb3?s=32'</pre>
</article>
<article id="human_time_diff">
<p>
<span class="header">human_time_diff</span>
<code>
<span class="util_class">util::</span><span class="func_name">human_time_diff</span>(int <span class="param">$from</span>, int <span class="param">$to</span> = '', int <span class="param">$as_text</span> = FALSE, string <span class="param">$suffix</span> = ' ago')
</code>
</p>
<p>Converts a unix timestamp to a relative time string, such as "3 days ago" or "2 weeks ago"</p>
<p><strong>Usage:</strong></p>
<pre>util::human_time_diff(time() - 7400);
=&gt; Returns '2 hours ago'
util::human_time_diff(time() - 7400, '', TRUE);
=&gt; Returns 'two hours ago'</pre>
</article>
<article id="nocache_headers">
<p>
<span class="header">nocache_headers</span>
<code>
<span class="util_class">util::</span><span class="func_name">nocache_headers</span>(mixed <span class="param">$data</span>)
</code>
</p>
<p>Sets the headers to prevent caching for the different browsers</p>
<p>
Different browsers support different nocache headers, so several headers must be sent
so that all of them get the point that no caching should occur
</p>
<p><strong>Usage:</strong></p>
<pre>util::nocache_headers();</pre>
</article>
<article id="utf8_headers">
<p>
<span class="header">utf8_headers</span>
<code>
<span class="util_class">util::</span><span class="func_name">utf8_headers</span>(mixed <span class="param">$content_type</span> = 'text/html')
</code>
</p>
<p>Transmit UTF-8 content headers if the headers haven't already been sent</p>
<p><strong>Usage:</strong></p>
<pre>util::utf8_headers();</pre>
</article>
<article id="validate_email">
<p>
<span class="header">validate_email</span>
<code>
<span class="util_class">util::</span><span class="func_name">validate_email</span>(string <span class="param">$possible_email</span>)
</code>
</p>
<p>Validate an email address</p>
<p><strong>Usage:</strong></p>
<pre>util::validate_email( 'brandon.wamboldt@gmail.com' );
=&gt; Returns true
util::validate_email( 'not an email' );
=&gt; Returns false</pre>
</article>
</section>
<h2 id="constants">Constants</h2>
<section>
<article id="SECONDS_IN_A_MINUTE">
<p>
<span class="header">SECONDS_IN_A_MINUTE</span>
<code>
<span class="util_class">util::</span><span class="func_name">SECONDS_IN_A_MINUTE</span>
</code>
</p>
<p>The number of seconds in a minute, useful for making code more verbose</p>
</article>
<article id="SECONDS_IN_AN_HOUR">
<p>
<span class="header">SECONDS_IN_AN_HOUR</span>
<code>
<span class="util_class">util::</span><span class="func_name">SECONDS_IN_AN_HOUR</span>
</code>
</p>
<p>The number of seconds in an hour, useful for making code more verbose</p>
</article>
<article id="SECONDS_IN_A_DAY">
<p>
<span class="header">SECONDS_IN_A_DAY</span>
<code>
<span class="util_class">util::</span><span class="func_name">SECONDS_IN_A_DAY</span>
</code>
</p>
<p>The number of seconds in a day, useful for making code more verbose</p>
</article>
<article id="SECONDS_IN_A_WEEK">
<p>
<span class="header">SECONDS_IN_A_WEEK</span>
<code>
<span class="util_class">util::</span><span class="func_name">SECONDS_IN_A_WEEK</span>
</code>
</p>
<p>The number of seconds in a week (7 days), useful for making code more verbose</p>
</article>
<article id="SECONDS_IN_A_MONTH">
<p>
<span class="header">SECONDS_IN_A_MONTH</span>
<code>
<span class="util_class">util::</span><span class="func_name">SECONDS_IN_A_MONTH</span>
</code>
</p>
<p>The number of seconds in a month (30 days), useful for making code more verbose</p>
</article>
<article id="SECONDS_IN_A_YEAR">
<p>
<span class="header">SECONDS_IN_A_YEAR</span>
<code>
<span class="util_class">util::</span><span class="func_name">SECONDS_IN_A_YEAR</span>
</code>
</p>
<p>The number of seconds in a year (365 days), useful for making code more verbose</p>
</article>
</section>
<h2 id="changelog">Change Log</h2>
<!--
Find: `(.*?)`
Replace: <code>\1<\/code>
Find: \[(.*?)\]\((.*?)\)
Replace: <a href="\2">\1</a>
-->
<p class="desc-text">
<span class="header">1.1.0</span><br>
This release introduces a deprecation notice for <code>slugify()</code>, please update your code.<br><br>
- Added a cryptographically secure random string function <code>secure_random_string</code>. Thanks to @abhimanyusharma003 via <a href="https://github.com/brandonwamboldt/utilphp/pull/53">Pull Request #53</a><br>
- Added <code>limit_characters</code> and <code>limit_words</code> functions. Thanks to @abhimanyusharma003 via <a href="https://github.com/brandonwamboldt/utilphp/pull/55">Pull Request #55</a><br>
- Added <code>rmdir</code> method to recursively delete a directory. Thanks to @ARACOOOL via <a href="https://github.com/brandonwamboldt/utilphp/pull/56">Pull Request #56</a><br>
- Added <code>set_executable</code>, <code>set_readable</code>, <code>set_writable</code>, <code>directory_size</code>, <code>directory_contents</code> and <code>get_user_dir</code> functions. Thanks to @sergserg via <a href="https://github.com/brandonwamboldt/utilphp/pull/70">Pull Request #70</a><br>
- Changed parameter ordering for <code>slugify</code>, <code>$css_mode</code> is now the third argument. For backwards compatibility, the old order will still work but it will generate an <code>E_USER_DEPRECATED</code> warning. Thanks to @abhimanyusharma003 via <a href="https://github.com/brandonwamboldt/utilphp/pull/71">Pull Request #71</a><br>
- Added <code>match_string</code> method. Thanks to @abhimanyusharma003 via <a href="https://github.com/brandonwamboldt/utilphp/pull/72">Pull Request #72</a><br>
- Renamed internal methods (protected ones) for PSR-2 compliance<br>
- General performance improvements, code quality improvements, and increased unit test coverage (special thanks to @hopeseekr for getting us near 100% coverage)<br>
</p>
<p class="desc-text">
<span class="header">1.0.7</span><br>
- Added <code>fix_broken_serialization</code> to fix broken serialized strings (Thanks to @hopeseekr via <a href="https://github.com/brandonwamboldt/utilphp/pull/48">Pull Request #48</a>)<br>
- Fixed <code>get_current_url</code> appending port 80 or 443 when not needed (Thanks to @scottchiefbaker via <a href="https://github.com/brandonwamboldt/utilphp/pull/49">Pull Request #49</a>)<br>
- <code>var_dump</code> can now handle recursive data structures without crashing<br>
- <code>var_dump</code> code was minified and cleaned up<br>
- <code>array_flatten</code> was optimized (thanks to @hopeseekr via <a href="https://github.com/brandonwamboldt/utilphp/pull/47">Pull Request #47</a>)<br>
- <code>remove_accents</code> was completely rewritten and is now ~4x faster<br>
</p>
<p class="desc-text">
<span class="header">1.0.6</span><br>
- Added <code>start_with</code> function<br>
- Added <code>ends_with</code> function<br>
- Added <code>str_contains</code> function<br>
- Added <code>str_icontains</code> function<br>
- Added <code>get_file_ext</code> function<br>
- Fixing permissions on the files &amp; directories<br>
- Fixing a bug with the include path of util.php<br>
</p>
<p class="desc-text">
<span class="header">1.0.5</span><br>
- <a href="https://github.com/brandonwamboldt/utilphp/issues/29">Issue #29</a> Fixed error in <code>var_dump</code> if mbstring extension wasn't present<br>
- Adding Composer support<br>
- Updating license from GPL to MIT<br>
- Adding Changelog to project<br>
- Bumping minimum version to PHP 5.3.3<br>
</p>
<p class="desc-text">
<span class="header">1.0.4</span><br />
- <a href="https://github.com/brandonwamboldt/utilphp/issues/22">Issue #22</a> Removed all superglobal *_get functions, you can use the modified <code>array_get</code> now<br />
- <a href="https://github.com/brandonwamboldt/utilphp/issues/22">Issue #22</a> Modifed the behaviour of <code>array_get</code>, see documentation<br />
- <a href="https://github.com/brandonwamboldt/utilphp/pull/21">Pull Request #21</a> Added multibyte support to html* functions<br />
- <a href="https://github.com/brandonwamboldt/utilphp/issues/9">Issue #9</a> Removed the <code>str_to_utf8</code> function<br />
- <a href="https://github.com/brandonwamboldt/utilphp/issues/3">Issue #3</a> Removed the absint function<br />
- Removed declare() from util.php to avoid errors<br />
- Updated PHPUnit tests to use PHPUnit 3.6
</p>
<p class="desc-text">
<span class="header">1.0.3</span><br />
- <a href="https://github.com/brandonwamboldt/utilphp/issues/16">Issue #16</a> Improved performance of <code>slugify</code><br />
- <a href="https://github.com/brandonwamboldt/utilphp/issues/14">Issue #14</a> Modified the regex for <code>seems_utf8</code> to be more accurate<br />
- <a href="https://github.com/brandonwamboldt/utilphp/issues/13">Issue #13</a> Changed <code>validate_email</code> to be wrapper for <code>filter_var</code><br />
- Added 'ok' to the list of yes words for <code>str_to_bool</code><br />
- <code>str_to_bool</code> matches no followed by any number of 'o's
</p>
<p class="desc-text">
<span class="header">1.0.2</span><br />
- <a href="https://github.com/brandonwamboldt/utilphp/issues/12">Issue #12</a> <code>get_current_url</code> now includes the port and user/password if required<br />
- <a href="https://github.com/brandonwamboldt/utilphp/issues/11">Issue #11</a> <code>human_time_diff</code> now uses the DateTime functions<br />
- <a href="https://github.com/brandonwamboldt/utilphp/issues/10">Issue #10</a> <code>is_https</code> no longer checks the port as well
</p>
<p class="desc-text">
<span class="header">1.0.1</span><br />
- <a href="https://github.com/brandonwamboldt/utilphp/issues/7">Issue #7</a> Added the <code style="color:#DA72F3">$trust_proxy_headers</code> parameter to <code>get_client_ip</code><br />
- <a href="https://github.com/brandonwamboldt/utilphp/issues/6">Issue #6</a> Removed <code>is_isset</code> as the function did not work as intended<br />
- <a href="https://github.com/brandonwamboldt/utilphp/issues/6">Issue #6</a> Removed <code>is_empty</code> as it is redundant, use ! with function calls instead<br />
- Fixed a bug with <code>get_gravatar</code>
</p>
<p class="desc-text">
<span class="header">1.0.0</span><br />
Initial release of util.php.
</p>
</div>
</div>
</body>
</html>
+25
View File
@@ -0,0 +1,25 @@
<?xml version="1.0" encoding="UTF-8"?>
<phpunit backupGlobals="false"
backupStaticAttributes="false"
colors="true"
convertErrorsToExceptions="true"
convertNoticesToExceptions="true"
convertWarningsToExceptions="true"
processIsolation="false"
stopOnFailure="false"
syntaxCheck="false"
>
<testsuites>
<testsuite name="Tests suite">
<directory>./tests</directory>
</testsuite>
</testsuites>
<filter>
<whitelist>
<directory>./src</directory>
</whitelist>
</filter>
<logging>
<log type="coverage-clover" target="build/logs/clover.xml"/>
</logging>
</phpunit>
+2535
View File
@@ -0,0 +1,2535 @@
<?php
namespace utilphp;
/**
* util.php
*
* util.php is a library of helper functions for common tasks such as
* formatting bytes as a string or displaying a date in terms of how long ago
* it was in human readable terms (E.g. 4 minutes ago). The library is entirely
* contained within a single file and hosts no dependencies. The library is
* designed to avoid any possible conflicts.
*
* @author Brandon Wamboldt <brandon.wamboldt@gmail.com>
* @link http://github.com/brandonwamboldt/utilphp/ Official Documentation
*/
class util
{
/**
* A constant representing the number of seconds in a minute, for
* making code more verbose
*
* @var integer
*/
const SECONDS_IN_A_MINUTE = 60;
/**
* A constant representing the number of seconds in an hour, for making
* code more verbose
*
* @var integer
*/
const SECONDS_IN_A_HOUR = 3600;
const SECONDS_IN_AN_HOUR = 3600;
/**
* A constant representing the number of seconds in a day, for making
* code more verbose
*
* @var integer
*/
const SECONDS_IN_A_DAY = 86400;
/**
* A constant representing the number of seconds in a week, for making
* code more verbose
*
* @var integer
*/
const SECONDS_IN_A_WEEK = 604800;
/**
* A constant representing the number of seconds in a month (30 days),
* for making code more verbose
*
* @var integer
*/
const SECONDS_IN_A_MONTH = 2592000;
/**
* A constant representing the number of seconds in a year (365 days),
* for making code more verbose
*
* @var integer
*/
const SECONDS_IN_A_YEAR = 31536000;
/**
* URL constants as defined in the PHP Manual under "Constants usable with
* http_build_url()".
*
* @see http://us2.php.net/manual/en/http.constants.php#http.constants.url
*/
const HTTP_URL_REPLACE = 1;
const HTTP_URL_JOIN_PATH = 2;
const HTTP_URL_JOIN_QUERY = 4;
const HTTP_URL_STRIP_USER = 8;
const HTTP_URL_STRIP_PASS = 16;
const HTTP_URL_STRIP_AUTH = 32;
const HTTP_URL_STRIP_PORT = 64;
const HTTP_URL_STRIP_PATH = 128;
const HTTP_URL_STRIP_QUERY = 256;
const HTTP_URL_STRIP_FRAGMENT = 512;
const HTTP_URL_STRIP_ALL = 1024;
/**
* A collapse icon, using in the dump_var function to allow collapsing
* an array or object
*
* @var string
*/
public static $icon_collapse = 'iVBORw0KGgoAAAANSUhEUgAAAAkAAAAJCAMAAADXT/YiAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA2RpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMC1jMDYwIDYxLjEzNDc3NywgMjAxMC8wMi8xMi0xNzozMjowMCAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0ieG1wLmRpZDo3MjlFRjQ2NkM5QzJFMTExOTA0MzkwRkI0M0ZCODY4RCIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDpFNzFDNDQyNEMyQzkxMUUxOTU4MEM4M0UxRDA0MUVGNSIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDpFNzFDNDQyM0MyQzkxMUUxOTU4MEM4M0UxRDA0MUVGNSIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ1M1IFdpbmRvd3MiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDo3NDlFRjQ2NkM5QzJFMTExOTA0MzkwRkI0M0ZCODY4RCIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDo3MjlFRjQ2NkM5QzJFMTExOTA0MzkwRkI0M0ZCODY4RCIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PuF4AWkAAAA2UExURU9t2DBStczM/1h16DNmzHiW7iNFrypMvrnD52yJ4ezs7Onp6ejo6P///+Tk5GSG7D9h5SRGq0Q2K74AAAA/SURBVHjaLMhZDsAgDANRY3ZISnP/y1ZWeV+jAeuRSky6cKL4ryDdSggP8UC7r6GvR1YHxjazPQDmVzI/AQYAnFQDdVSJ80EAAAAASUV Line truncated
/**
* A collapse icon, using in the dump_var function to allow collapsing
* an array or object
*
* @var string
*/
public static $icon_expand = 'iVBORw0KGgoAAAANSUhEUgAAAAkAAAAJCAMAAADXT/YiAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA2RpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMC1jMDYwIDYxLjEzNDc3NywgMjAxMC8wMi8xMi0xNzozMjowMCAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0ieG1wLmRpZDo3MTlFRjQ2NkM5QzJFMTExOTA0MzkwRkI0M0ZCODY4RCIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDpFQzZERTJDNEMyQzkxMUUxODRCQzgyRUNDMzZEQkZFQiIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDpFQzZERTJDM0MyQzkxMUUxODRCQzgyRUNDMzZEQkZFQiIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ1M1IFdpbmRvd3MiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDo3MzlFRjQ2NkM5QzJFMTExOTA0MzkwRkI0M0ZCODY4RCIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDo3MTlFRjQ2NkM5QzJFMTExOTA0MzkwRkI0M0ZCODY4RCIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PkmDvWIAAABIUExURU9t2MzM/3iW7ubm59/f5urq85mZzOvr6////9ra38zMzObm5rfB8FZz5myJ4SNFrypMvjBStTNmzOvr+mSG7OXl8T9h5SRGq/OfqCEAAABKSURBVHjaFMlbEoAwCEPRULXF2jdW9r9T4czcyUdA4XWB0IgdNSybxU9amMzHzDlPKKu7Fd1e6+wY195jW Line truncated
private static $hasArray = false;
/**
* Map of special non-ASCII characters and suitable ASCII replacement
* characters.
*
* Part of the URLify.php Project <https://github.com/jbroadway/urlify/>
*
* @see https://github.com/jbroadway/urlify/blob/master/URLify.php
*/
public static $maps = array(
'de' => array(/* German */
'Ä' => 'Ae', 'Ö' => 'Oe', 'Ü' => 'Ue', 'ä' => 'ae', 'ö' => 'oe', 'ü' => 'ue', 'ß' => 'ss',
'ẞ' => 'SS'
),
'latin' => array(
'À' => 'A', 'Á' => 'A', 'Â' => 'A', 'Ã' => 'A', 'Ä' => 'A', 'Å' => 'A','Ă' => 'A', 'Æ' => 'AE', 'Ç' =>
'C', 'È' => 'E', 'É' => 'E', 'Ê' => 'E', 'Ë' => 'E', 'Ì' => 'I', 'Í' => 'I', 'Î' => 'I',
'Ï' => 'I', 'Ð' => 'D', 'Ñ' => 'N', 'Ò' => 'O', 'Ó' => 'O', 'Ô' => 'O', 'Õ' => 'O', 'Ö' =>
'O', 'Ő' => 'O', 'Ø' => 'O','Ș' => 'S','Ț' => 'T', 'Ù' => 'U', 'Ú' => 'U', 'Û' => 'U', 'Ü' => 'U', 'Ű' => 'U',
'Ý' => 'Y', 'Þ' => 'TH', 'ß' => 'ss', 'à' => 'a', 'á' => 'a', 'â' => 'a', 'ã' => 'a', 'ä' =>
'a', 'å' => 'a', 'ă' => 'a', 'æ' => 'ae', 'ç' => 'c', 'è' => 'e', 'é' => 'e', 'ê' => 'e', 'ë' => 'e',
'ì' => 'i', 'í' => 'i', 'î' => 'i', 'ï' => 'i', 'ð' => 'd', 'ñ' => 'n', 'ò' => 'o', 'ó' =>
'o', 'ô' => 'o', 'õ' => 'o', 'ö' => 'o', 'ő' => 'o', 'ø' => 'o', 'ș' => 's', 'ț' => 't', 'ù' => 'u', 'ú' => 'u',
'û' => 'u', 'ü' => 'u', 'ű' => 'u', 'ý' => 'y', 'þ' => 'th', 'ÿ' => 'y'
),
'latin_symbols' => array(
'©' => '(c)'
),
'el' => array(/* Greek */
'α' => 'a', 'β' => 'b', 'γ' => 'g', 'δ' => 'd', 'ε' => 'e', 'ζ' => 'z', 'η' => 'h', 'θ' => '8',
'ι' => 'i', 'κ' => 'k', 'λ' => 'l', 'μ' => 'm', 'ν' => 'n', 'ξ' => '3', 'ο' => 'o', 'π' => 'p',
'ρ' => 'r', 'σ' => 's', 'τ' => 't', 'υ' => 'y', 'φ' => 'f', 'χ' => 'x', 'ψ' => 'ps', 'ω' => 'w',
'ά' => 'a', 'έ' => 'e', 'ί' => 'i', 'ό' => 'o', 'ύ' => 'y', 'ή' => 'h', 'ώ' => 'w', 'ς' => 's',
'ϊ' => 'i', 'ΰ' => 'y', 'ϋ' => 'y', 'ΐ' => 'i',
'Α' => 'A', 'Β' => 'B', 'Γ' => 'G', 'Δ' => 'D', 'Ε' => 'E', 'Ζ' => 'Z', 'Η' => 'H', 'Θ' => '8',
'Ι' => 'I', 'Κ' => 'K', 'Λ' => 'L', 'Μ' => 'M', 'Ν' => 'N', 'Ξ' => '3', 'Ο' => 'O', 'Π' => 'P',
'Ρ' => 'R', 'Σ' => 'S', 'Τ' => 'T', 'Υ' => 'Y', 'Φ' => 'F', 'Χ' => 'X', 'Ψ' => 'PS', 'Ω' => 'W',
'Ά' => 'A', 'Έ' => 'E', 'Ί' => 'I', 'Ό' => 'O', 'Ύ' => 'Y', 'Ή' => 'H', 'Ώ' => 'W', 'Ϊ' => 'I',
'Ϋ' => 'Y'
),
'tr' => array(/* Turkish */
'ş' => 's', 'Ş' => 'S', 'ı' => 'i', 'İ' => 'I', 'ç' => 'c', 'Ç' => 'C', 'ü' => 'u', 'Ü' => 'U',
'ö' => 'o', 'Ö' => 'O', 'ğ' => 'g', 'Ğ' => 'G'
),
'ru' => array(/* Russian */
'а' => 'a', 'б' => 'b', 'в' => 'v', 'г' => 'g', 'д' => 'd', 'е' => 'e', 'ё' => 'yo', 'ж' => 'zh',
'з' => 'z', 'и' => 'i', 'й' => 'j', 'к' => 'k', 'л' => 'l', 'м' => 'm', 'н' => 'n', 'о' => 'o',
'п' => 'p', 'р' => 'r', 'с' => 's', 'т' => 't', 'у' => 'u', 'ф' => 'f', 'х' => 'h', 'ц' => 'c',
'ч' => 'ch', 'ш' => 'sh', 'щ' => 'sh', 'ъ' => '', 'ы' => 'y', 'ь' => '', 'э' => 'e', 'ю' => 'yu',
'я' => 'ya',
'А' => 'A', 'Б' => 'B', 'В' => 'V', 'Г' => 'G', 'Д' => 'D', 'Е' => 'E', 'Ё' => 'Yo', 'Ж' => 'Zh',
'З' => 'Z', 'И' => 'I', 'Й' => 'J', 'К' => 'K', 'Л' => 'L', 'М' => 'M', 'Н' => 'N', 'О' => 'O',
'П' => 'P', 'Р' => 'R', 'С' => 'S', 'Т' => 'T', 'У' => 'U', 'Ф' => 'F', 'Х' => 'H', 'Ц' => 'C',
'Ч' => 'Ch', 'Ш' => 'Sh', 'Щ' => 'Sh', 'Ъ' => '', 'Ы' => 'Y', 'Ь' => '', 'Э' => 'E', 'Ю' => 'Yu',
'Я' => 'Ya',
'№' => ''
),
'uk' => array(/* Ukrainian */
'Є' => 'Ye', 'І' => 'I', 'Ї' => 'Yi', 'Ґ' => 'G', 'є' => 'ye', 'і' => 'i', 'ї' => 'yi', 'ґ' => 'g'
),
'cs' => array(/* Czech */
'č' => 'c', 'ď' => 'd', 'ě' => 'e', 'ň' => 'n', 'ř' => 'r', 'š' => 's', 'ť' => 't', 'ů' => 'u',
'ž' => 'z', 'Č' => 'C', 'Ď' => 'D', 'Ě' => 'E', 'Ň' => 'N', 'Ř' => 'R', 'Š' => 'S', 'Ť' => 'T',
'Ů' => 'U', 'Ž' => 'Z'
),
'pl' => array(/* Polish */
'ą' => 'a', 'ć' => 'c', 'ę' => 'e', 'ł' => 'l', 'ń' => 'n', 'ó' => 'o', 'ś' => 's', 'ź' => 'z',
'ż' => 'z', 'Ą' => 'A', 'Ć' => 'C', 'Ę' => 'e', 'Ł' => 'L', 'Ń' => 'N', 'Ó' => 'O', 'Ś' => 'S',
'Ź' => 'Z', 'Ż' => 'Z'
),
'ro' => array(/* Romanian */
'ă' => 'a', 'â' => 'a', 'î' => 'i', 'ș' => 's', 'ț' => 't', 'Ţ' => 'T', 'ţ' => 't'
),
'lv' => array(/* Latvian */
'ā' => 'a', 'č' => 'c', 'ē' => 'e', 'ģ' => 'g', 'ī' => 'i', 'ķ' => 'k', 'ļ' => 'l', 'ņ' => 'n',
'š' => 's', 'ū' => 'u', 'ž' => 'z', 'Ā' => 'A', 'Č' => 'C', 'Ē' => 'E', 'Ģ' => 'G', 'Ī' => 'i',
'Ķ' => 'k', 'Ļ' => 'L', 'Ņ' => 'N', 'Š' => 'S', 'Ū' => 'u', 'Ž' => 'Z'
),
'lt' => array(/* Lithuanian */
'ą' => 'a', 'č' => 'c', 'ę' => 'e', 'ė' => 'e', 'į' => 'i', 'š' => 's', 'ų' => 'u', 'ū' => 'u', 'ž' => 'z',
'Ą' => 'A', 'Č' => 'C', 'Ę' => 'E', 'Ė' => 'E', 'Į' => 'I', 'Š' => 'S', 'Ų' => 'U', 'Ū' => 'U', 'Ž' => 'Z'
),
'vn' => array(/* Vietnamese */
'Á' => 'A', 'À' => 'A', 'Ả' => 'A', 'Ã' => 'A', 'Ạ' => 'A', 'Ă' => 'A', 'Ắ' => 'A', 'Ằ' => 'A', 'Ẳ' => 'A', 'Ẵ' => 'A', 'Ặ' => 'A', 'Â' => 'A', 'Ấ' => 'A', 'Ầ' => 'A', 'Ẩ' => 'A', 'Ẫ' => 'A', 'Ậ' => 'A',
'á' => 'a', 'à' => 'a', 'ả' => 'a', 'ã' => 'a', 'ạ' => 'a', 'ă' => 'a', 'ắ' => 'a', 'ằ' => 'a', 'ẳ' => 'a', 'ẵ' => 'a', 'ặ' => 'a', 'â' => 'a', 'ấ' => 'a', 'ầ' => 'a', 'ẩ' => 'a', 'ẫ' => 'a', 'ậ' => 'a',
'É' => 'E', 'È' => 'E', 'Ẻ' => 'E', 'Ẽ' => 'E', 'Ẹ' => 'E', 'Ê' => 'E', 'Ế' => 'E', 'Ề' => 'E', 'Ể' => 'E', 'Ễ' => 'E', 'Ệ' => 'E',
'é' => 'e', 'è' => 'e', 'ẻ' => 'e', 'ẽ' => 'e', 'ẹ' => 'e', 'ê' => 'e', 'ế' => 'e', 'ề' => 'e', 'ể' => 'e', 'ễ' => 'e', 'ệ' => 'e',
'Í' => 'I', 'Ì' => 'I', 'Ỉ' => 'I', 'Ĩ' => 'I', 'Ị' => 'I', 'í' => 'i', 'ì' => 'i', 'ỉ' => 'i', 'ĩ' => 'i', 'ị' => 'i',
'Ó' => 'O', 'Ò' => 'O', 'Ỏ' => 'O', 'Õ' => 'O', 'Ọ' => 'O', 'Ô' => 'O', 'Ố' => 'O', 'Ồ' => 'O', 'Ổ' => 'O', 'Ỗ' => 'O', 'Ộ' => 'O', 'Ơ' => 'O', 'Ớ' => 'O', 'Ờ' => 'O', 'Ở' => 'O', 'Ỡ' => 'O', 'Ợ' => 'O',
'ó' => 'o', 'ò' => 'o', 'ỏ' => 'o', 'õ' => 'o', 'ọ' => 'o', 'ô' => 'o', 'ố' => 'o', 'ồ' => 'o', 'ổ' => 'o', 'ỗ' => 'o', 'ộ' => 'o', 'ơ' => 'o', 'ớ' => 'o', 'ờ' => 'o', 'ở' => 'o', 'ỡ' => 'o', 'ợ' => 'o',
'Ú' => 'U', 'Ù' => 'U', 'Ủ' => 'U', 'Ũ' => 'U', 'Ụ' => 'U', 'Ư' => 'U', 'Ứ' => 'U', 'Ừ' => 'U', 'Ử' => 'U', 'Ữ' => 'U', 'Ự' => 'U',
'ú' => 'u', 'ù' => 'u', 'ủ' => 'u', 'ũ' => 'u', 'ụ' => 'u', 'ư' => 'u', 'ứ' => 'u', 'ừ' => 'u', 'ử' => 'u', 'ữ' => 'u', 'ự' => 'u',
'Ý' => 'Y', 'Ỳ' => 'Y', 'Ỷ' => 'Y', 'Ỹ' => 'Y', 'Ỵ' => 'Y', 'ý' => 'y', 'ỳ' => 'y', 'ỷ' => 'y', 'ỹ' => 'y', 'ỵ' => 'y',
'Đ' => 'D', 'đ' => 'd'
),
'ar' => array(/* Arabic */
'أ' => 'a', 'ب' => 'b', 'ت' => 't', 'ث' => 'th', 'ج' => 'g', 'ح' => 'h', 'خ' => 'kh', 'د' => 'd',
'ذ' => 'th', 'ر' => 'r', 'ز' => 'z', 'س' => 's', 'ش' => 'sh', 'ص' => 's', 'ض' => 'd', 'ط' => 't',
'ظ' => 'th', 'ع' => 'aa', 'غ' => 'gh', 'ف' => 'f', 'ق' => 'k', 'ك' => 'k', 'ل' => 'l', 'م' => 'm',
'ن' => 'n', 'ه' => 'h', 'و' => 'o', 'ي' => 'y'
),
'sr' => array(/* Serbian */
'ђ' => 'dj', 'ј' => 'j', 'љ' => 'lj', 'њ' => 'nj', 'ћ' => 'c', 'џ' => 'dz', 'đ' => 'dj',
'Ђ' => 'Dj', 'Ј' => 'j', 'Љ' => 'Lj', 'Њ' => 'Nj', 'Ћ' => 'C', 'Џ' => 'Dz', 'Đ' => 'Dj'
),
'az' => array(/* Azerbaijani */
'ç' => 'c', 'ə' => 'e', 'ğ' => 'g', 'ı' => 'i', 'ö' => 'o', 'ş' => 's', 'ü' => 'u',
'Ç' => 'C', 'Ə' => 'E', 'Ğ' => 'G', 'İ' => 'I', 'Ö' => 'O', 'Ş' => 'S', 'Ü' => 'U'
),
);
/**
* The character map for the designated language
*
* @see https://github.com/jbroadway/urlify/blob/master/URLify.php
*/
private static $map = array();
/**
* The character list as a string.
*
* @see https://github.com/jbroadway/urlify/blob/master/URLify.php
*/
private static $chars = '';
/**
* The character list as a regular expression.
*
* @see https://github.com/jbroadway/urlify/blob/master/URLify.php
*/
private static $regex = '';
/**
* The current language
*
* @see https://github.com/jbroadway/urlify/blob/master/URLify.php
*/
private static $language = '';
/**
* Initializes the character map.
*
* Part of the URLify.php Project <https://github.com/jbroadway/urlify/>
*
* @see https://github.com/jbroadway/urlify/blob/master/URLify.php
*/
private static function initLanguageMap($language = '')
{
if (count(self::$map) > 0 && (($language == '') || ($language == self::$language))) {
return;
}
// Is a specific map associated with $language?
if (isset(self::$maps[$language]) && is_array(self::$maps[$language])) {
// Move this map to end. This means it will have priority over others
$m = self::$maps[$language];
unset(self::$maps[$language]);
self::$maps[$language] = $m;
}
// Reset static vars
self::$language = $language;
self::$map = array();
self::$chars = '';
foreach (self::$maps as $map) {
foreach ($map as $orig => $conv) {
self::$map[$orig] = $conv;
self::$chars .= $orig;
}
}
self::$regex = '/[' . self::$chars . ']/u';
}
/**
* Access an array index, retrieving the value stored there if it
* exists or a default if it does not. This function allows you to
* concisely access an index which may or may not exist without
* raising a warning.
*
* @param array $var Array value to access
* @param mixed $default Default value to return if the key is not
* present in the array
* @return mixed
*/
public static function array_get(&$var, $default = null)
{
if (isset($var)) {
return $var;
}
return $default;
}
/**
* Display a variable's contents using nice HTML formatting and will
* properly display the value of booleans as true or false
*
* @see var_dump_plain()
*
* @param mixed $var The variable to dump
* @return string
*/
public static function var_dump($var, $return = false, $expandLevel = 1)
{
self::$hasArray = false;
$toggScript = 'var colToggle = function(toggID) {var img = document.getElementById(toggID);if (document.getElementById(toggID + "-collapsable").style.display == "none") {document.getElementById(toggID + "-collapsable").style.display = "inline";setImg(toggID, 0);var previousSibling = document.getElementById(toggID + "-collapsable").previousSibling;while (previousSibling != null && (previousSibling.nodeType != 1 || previousSibling.tagName.toLowerCase() != "br")) {previousSibling = previousSibling.previousSibling;}} else {document.getElementById(toggID + "-collapsable").style.display = "none";setImg(toggID, 1);var previousSibling = document.getElementById(toggID + "-collapsable").previousSibling; while (previousSibling != null && (previousSibling.nodeType != 1 || previousSibling.tagName.toLowerCase() != "br")) {previousSibling = previousSibling.previousSibling;}}};';
$imgScript = 'var setImg = function(objID,imgID,addStyle) {var imgStore = ["data:image/png;base64,' . self::$icon_collapse . '", "data:image/png;base64,' . self::$icon_expand . '"];if (objID) {document.getElementById(objID).setAttribute("src", imgStore[imgID]);if (addStyle){document.getElementById(objID).setAttribute("style", "position:relative;left:-5px;top:-1px;cursor:pointer;");}}};';
$jsCode = preg_replace('/ +/', ' ', '<script>' . $toggScript . $imgScript . '</script>');
$html = '<pre style="margin-bottom: 18px;' .
'background: #f7f7f9;' .
'border: 1px solid #e1e1e8;' .
'padding: 8px;' .
'border-radius: 4px;' .
'-moz-border-radius: 4px;' .
'-webkit-border radius: 4px;' .
'display: block;' .
'font-size: 12.05px;' .
'white-space: pre-wrap;' .
'word-wrap: break-word;' .
'color: #333;' .
'font-family: Menlo,Monaco,Consolas,\'Courier New\',monospace;">';
$done = array();
$html .= self::var_dump_plain($var, intval($expandLevel), 0, $done);
$html .= '</pre>';
if (self::$hasArray) {
$html = $jsCode . $html;
}
if (!$return) {
echo $html;
}
return $html;
}
/**
* Display a variable's contents using nice HTML formatting (Without
* the <pre> tag) and will properly display the values of variables
* like booleans and resources. Supports collapsable arrays and objects
* as well.
*
* @param mixed $var The variable to dump
* @return string
*/
public static function var_dump_plain($var, $expLevel, $depth = 0, $done = array())
{
$html = '';
if ($expLevel > 0) {
$expLevel--;
$setImg = 0;
$setStyle = 'display:inline;';
} elseif ($expLevel == 0) {
$setImg = 1;
$setStyle='display:none;';
} elseif ($expLevel < 0) {
$setImg = 0;
$setStyle = 'display:inline;';
}
if (is_bool($var)) {
$html .= '<span style="color:#588bff;">bool</span><span style="color:#999;">(</span><strong>' . (($var) ? 'true' : 'false') . '</strong><span style="color:#999;">)</span>';
} elseif (is_int($var)) {
$html .= '<span style="color:#588bff;">int</span><span style="color:#999;">(</span><strong>' . $var . '</strong><span style="color:#999;">)</span>';
} elseif (is_float($var)) {
$html .= '<span style="color:#588bff;">float</span><span style="color:#999;">(</span><strong>' . $var . '</strong><span style="color:#999;">)</span>';
} elseif (is_string($var)) {
$html .= '<span style="color:#588bff;">string</span><span style="color:#999;">(</span>' . strlen($var) . '<span style="color:#999;">)</span> <strong>"' . self::htmlentities($var) . '"</strong>';
} elseif (is_null($var)) {
$html .= '<strong>NULL</strong>';
} elseif (is_resource($var)) {
$html .= '<span style="color:#588bff;">resource</span>("' . get_resource_type($var) . '") <strong>"' . $var . '"</strong>';
} elseif (is_array($var)) {
// Check for recursion
if ($depth > 0) {
foreach ($done as $prev) {
if ($prev === $var) {
$html .= '<span style="color:#588bff;">array</span>(' . count($var) . ') *RECURSION DETECTED*';
return $html;
}
}
// Keep track of variables we have already processed to detect recursion
$done[] = &$var;
}
self::$hasArray = true;
$uuid = 'include-php-' . uniqid() . mt_rand(1, 1000000);
$html .= (!empty($var) ? ' <img id="' . $uuid . '" src="data:image/gif;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs%3D" onclick="javascript:colToggle(this.id);" /><script>setImg("' . $uuid . '",'.$setImg.',1);</script>' : '') . '<span style="color:#588bff;">array</span>(' . count($var) . ')';
if (!empty($var)) {
$html .= ' <span id="' . $uuid . '-collapsable" style="'.$setStyle.'"><br />[<br />';
$indent = 4;
$longest_key = 0;
foreach ($var as $key => $value) {
if (is_string($key)) {
$longest_key = max($longest_key, strlen($key) + 2);
} else {
$longest_key = max($longest_key, strlen($key));
}
}
foreach ($var as $key => $value) {
if (is_numeric($key)) {
$html .= str_repeat(' ', $indent) . str_pad($key, $longest_key, ' ');
} else {
$html .= str_repeat(' ', $indent) . str_pad('"' . self::htmlentities($key) . '"', $longest_key, ' ');
}
$html .= ' => ';
$value = explode('<br />', self::var_dump_plain($value, $expLevel, $depth + 1, $done));
foreach ($value as $line => $val) {
if ($line != 0) {
$value[$line] = str_repeat(' ', $indent * 2) . $val;
}
}
$html .= implode('<br />', $value) . '<br />';
}
$html .= ']</span>';
}
} elseif (is_object($var)) {
// Check for recursion
foreach ($done as $prev) {
if ($prev === $var) {
$html .= '<span style="color:#588bff;">object</span>(' . get_class($var) . ') *RECURSION DETECTED*';
return $html;
}
}
// Keep track of variables we have already processed to detect recursion
$done[] = &$var;
self::$hasArray=true;
$uuid = 'include-php-' . uniqid() . mt_rand(1, 1000000);
$html .= ' <img id="' . $uuid . '" src="data:image/gif;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs%3D" onclick="javascript:colToggle(this.id);" /><script>setImg("' . $uuid . '",'.$setImg.',1);</script><span style="color:#588bff;">object</span>(' . get_class($var) . ') <span id="' . $uuid . '-collapsable" style="'.$setStyle.'"><br />[<br />';
$varArray = (array) $var;
$indent = 4;
$longest_key = 0;
foreach ($varArray as $key => $value) {
if (substr($key, 0, 2) == "\0*") {
unset($varArray[$key]);
$key = 'protected:' . substr($key, 3);
$varArray[$key] = $value;
} elseif (substr($key, 0, 1) == "\0") {
unset($varArray[$key]);
$key = 'private:' . substr($key, 1, strpos(substr($key, 1), "\0")) . ':' . substr($key, strpos(substr($key, 1), "\0") + 2);
$varArray[$key] = $value;
}
if (is_string($key)) {
$longest_key = max($longest_key, strlen($key) + 2);
} else {
$longest_key = max($longest_key, strlen($key));
}
}
foreach ($varArray as $key => $value) {
if (is_numeric($key)) {
$html .= str_repeat(' ', $indent) . str_pad($key, $longest_key, ' ');
} else {
$html .= str_repeat(' ', $indent) . str_pad('"' . self::htmlentities($key) . '"', $longest_key, ' ');
}
$html .= ' => ';
$value = explode('<br />', self::var_dump_plain($value, $expLevel, $depth + 1, $done));
foreach ($value as $line => $val) {
if ($line != 0) {
$value[$line] = str_repeat(' ', $indent * 2) . $val;
}
}
$html .= implode('<br />', $value) . '<br />';
}
$html .= ']</span>';
}
return $html;
}
/**
* Converts any accent characters to their equivalent normal characters
* and converts any other non-alphanumeric characters to dashes, then
* converts any sequence of two or more dashes to a single dash. This
* function generates slugs safe for use as URLs, and if you pass true
* as the second parameter, it will create strings safe for use as CSS
* classes or IDs.
*
* @param string $string A string to convert to a slug
* @param string $separator The string to separate words with
* @param boolean $css_mode Whether or not to generate strings safe for
* CSS classes/IDs (Default to false)
* @return string
*/
public static function slugify($string, $separator = '-', $css_mode = false)
{
// Compatibility with 1.0.* parameter ordering for semvar
if ($separator === true || $separator === false) {
$css_mode = $separator;
$separator = '-';
// Raise deprecation error
trigger_error(
'util::slugify() now takes $css_mode as the third parameter, please update your code',
E_USER_DEPRECATED
);
}
$slug = preg_replace('/([^a-z0-9]+)/', $separator, strtolower(self::remove_accents($string)));
if ($css_mode) {
$digits = array('zero', 'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine');
if (is_numeric(substr($slug, 0, 1))) {
$slug = $digits[substr($slug, 0, 1)] . substr($slug, 1);
}
}
return $slug;
}
/**
* Checks to see if a string is utf8 encoded.
*
* NOTE: This function checks for 5-Byte sequences, UTF8
* has Bytes Sequences with a maximum length of 4.
*
* Written by Tony Ferrara <http://blog.ircmaxwell.com>
*
* @param string $string The string to be checked
* @return boolean
*/
public static function seems_utf8($string)
{
if (function_exists('mb_check_encoding')) {
// If mbstring is available, this is significantly faster than
// using PHP regexps.
return mb_check_encoding($string, 'UTF-8');
}
// @codeCoverageIgnoreStart
return self::seemsUtf8Regex($string);
// @codeCoverageIgnoreEnd
}
/**
* A non-Mbstring UTF-8 checker.
*
* @param $string
* @return bool
*/
protected static function seemsUtf8Regex($string)
{
// Obtained from http://stackoverflow.com/a/11709412/430062 with permission.
$regex = '/(
[\xC0-\xC1] # Invalid UTF-8 Bytes
| [\xF5-\xFF] # Invalid UTF-8 Bytes
| \xE0[\x80-\x9F] # Overlong encoding of prior code point
| \xF0[\x80-\x8F] # Overlong encoding of prior code point
| [\xC2-\xDF](?![\x80-\xBF]) # Invalid UTF-8 Sequence Start
| [\xE0-\xEF](?![\x80-\xBF]{2}) # Invalid UTF-8 Sequence Start
| [\xF0-\xF4](?![\x80-\xBF]{3}) # Invalid UTF-8 Sequence Start
| (?<=[\x0-\x7F\xF5-\xFF])[\x80-\xBF] # Invalid UTF-8 Sequence Middle
| (?<![\xC2-\xDF]|[\xE0-\xEF]|[\xE0-\xEF][\x80-\xBF]|[\xF0-\xF4]|[\xF0-\xF4][\x80-\xBF]|[\xF0-\xF4][\x80-\xBF]{2})[\x80-\xBF] # Overlong Sequence
| (?<=[\xE0-\xEF])[\x80-\xBF](?![\x80-\xBF]) # Short 3 byte sequence
| (?<=[\xF0-\xF4])[\x80-\xBF](?![\x80-\xBF]{2}) # Short 4 byte sequence
| (?<=[\xF0-\xF4][\x80-\xBF])[\x80-\xBF](?![\x80-\xBF]) # Short 4 byte sequence (2)
)/x';
return ! preg_match($regex, $string);
}
/**
* Nice formatting for computer sizes (Bytes).
*
* @param integer $bytes The number in bytes to format
* @param integer $decimals The number of decimal points to include
* @return string
*/
public static function size_format($bytes, $decimals = 0)
{
$bytes = floatval($bytes);
if ($bytes < 1024) {
return $bytes . ' B';
} elseif ($bytes < pow(1024, 2)) {
return number_format($bytes / 1024, $decimals, '.', '') . ' KiB';
} elseif ($bytes < pow(1024, 3)) {
return number_format($bytes / pow(1024, 2), $decimals, '.', '') . ' MiB';
} elseif ($bytes < pow(1024, 4)) {
return number_format($bytes / pow(1024, 3), $decimals, '.', '') . ' GiB';
} elseif ($bytes < pow(1024, 5)) {
return number_format($bytes / pow(1024, 4), $decimals, '.', '') . ' TiB';
} elseif ($bytes < pow(1024, 6)) {
return number_format($bytes / pow(1024, 5), $decimals, '.', '') . ' PiB';
} else {
return number_format($bytes / pow(1024, 5), $decimals, '.', '') . ' PiB';
}
}
/**
* Serialize data, if needed.
*
* @param mixed $data Data that might need to be serialized
* @return mixed
*/
public static function maybe_serialize($data)
{
if (is_array($data) || is_object($data)) {
return serialize($data);
}
return $data;
}
/**
* Unserialize value only if it is serialized.
*
* @param string $data A variable that may or may not be serialized
* @return mixed
*/
public static function maybe_unserialize($data)
{
// If it isn't a string, it isn't serialized
if (!is_string($data)) {
return $data;
}
$data = trim($data);
// Is it the serialized NULL value?
if ($data === 'N;') {
return null;
}
$length = strlen($data);
// Check some basic requirements of all serialized strings
if ($length < 4 || $data[1] !== ':' || ($data[$length - 1] !== ';' && $data[$length - 1] !== '}')) {
return $data;
}
// $data is the serialized false value
if ($data === 'b:0;') {
return false;
}
// Don't attempt to unserialize data that isn't serialized
$uns = @unserialize($data);
// Data failed to unserialize?
if ($uns === false) {
$uns = @unserialize(self::fix_broken_serialization($data));
if ($uns === false) {
return $data;
} else {
return $uns;
}
} else {
return $uns;
}
}
/**
* Check value to find if it was serialized.
*
* If $data is not an string, then returned value will always be false.
* Serialized data is always a string.
*
* @param mixed $data Value to check to see if was serialized
* @return boolean
*/
public static function is_serialized($data)
{
// If it isn't a string, it isn't serialized
if (!is_string($data)) {
return false;
}
$data = trim($data);
// Is it the serialized NULL value?
if ($data === 'N;') {
return true;
}
// Is it a serialized boolean?
elseif ($data === 'b:0;' || $data === 'b:1;') {
return true;
}
$length = strlen($data);
// Check some basic requirements of all serialized strings
if ($length < 4 || $data[1] !== ':' || ($data[$length - 1] !== ';' && $data[$length - 1] !== '}')) {
return false;
}
return @unserialize($data) !== false;
}
/**
* Unserializes partially-corrupted arrays that occur sometimes. Addresses
* specifically the `unserialize(): Error at offset xxx of yyy bytes` error.
*
* NOTE: This error can *frequently* occur with mismatched character sets
* and higher-than-ASCII characters.
*
* Contributed by Theodore R. Smith of PHP Experts, Inc. <http://www.phpexperts.pro/>
*
* @param string $brokenSerializedData
* @return string
*/
public static function fix_broken_serialization($brokenSerializedData)
{
$fixdSerializedData = preg_replace_callback('!s:(\d+):"(.*?)";!', function($matches) {
$snip = $matches[2];
return 's:' . strlen($snip) . ':"' . $snip . '";';
}, $brokenSerializedData);
return $fixdSerializedData;
}
/**
* Checks to see if the page is being server over SSL or not
*
* @return boolean
*/
public static function is_https()
{
return isset($_SERVER['HTTPS']) && !empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] != 'off';
}
/**
* Add or remove query arguments to the URL.
*
* @param mixed $newKey Either newkey or an associative array
* @param mixed $newValue Either newvalue or oldquery or uri
* @param mixed $uri URI or URL to append the queru/queries to.
* @return string
*/
public static function add_query_arg($newKey, $newValue = null, $uri = null)
{
// Was an associative array of key => value pairs passed?
if (is_array($newKey)) {
$newParams = $newKey;
// Was the URL passed as an argument?
if (!is_null($newValue)) {
$uri = $newValue;
} elseif (!is_null($uri)) {
$uri = $uri;
} else {
$uri = self::array_get($_SERVER['REQUEST_URI'], '');
}
} else {
$newParams = array($newKey => $newValue);
// Was the URL passed as an argument?
$uri = is_null($uri) ? self::array_get($_SERVER['REQUEST_URI'], '') : $uri;
}
// Parse the URI into it's components
$puri = parse_url($uri);
if (isset($puri['query'])) {
parse_str($puri['query'], $queryParams);
$queryParams = array_merge($queryParams, $newParams);
} elseif (isset($puri['path']) && strstr($puri['path'], '=') !== false) {
$puri['query'] = $puri['path'];
unset($puri['path']);
parse_str($puri['query'], $queryParams);
$queryParams = array_merge($queryParams, $newParams);
} else {
$queryParams = $newParams;
}
// Strip out any query params that are set to false
foreach ($queryParams as $param => $value) {
if ($value === false) {
unset($queryParams[$param]);
}
}
// Re-construct the query string
$puri['query'] = http_build_query($queryParams);
// Re-construct the entire URL
$nuri = self::http_build_url($puri);
// Make the URI consistent with our input
if ($nuri[0] === '/' && strstr($uri, '/') === false) {
$nuri = substr($nuri, 1);
}
if ($nuri[0] === '?' && strstr($uri, '?') === false) {
$nuri = substr($nuri, 1);
}
return rtrim($nuri, '?');
}
/**
* Removes an item or list from the query string.
*
* @param string|array $keys Query key or keys to remove.
* @param bool $uri When false uses the $_SERVER value
* @return string
*/
public static function remove_query_arg($keys, $uri = null)
{
if (is_array($keys)) {
return self::add_query_arg(array_combine($keys, array_fill(0, count($keys), null)), $uri);
}
return self::add_query_arg(array($keys => null), $uri);
}
/**
* Build a URL.
*
* The parts of the second URL will be merged into the first according to
* the flags argument.
*
* @author Jake Smith <theman@jakeasmith.com>
* @see https://github.com/jakeasmith/http_build_url/
*
* @param mixed $url (part(s) of) an URL in form of a string or
* associative array like parse_url() returns
* @param mixed $parts same as the first argument
* @param int $flags a bitmask of binary or'ed HTTP_URL constants;
* HTTP_URL_REPLACE is the default
* @param array $new_url if set, it will be filled with the parts of the
* composed url like parse_url() would return
* @return string
*/
public static function http_build_url($url, $parts = array(), $flags = self::HTTP_URL_REPLACE, &$new_url = array())
{
is_array($url) || $url = parse_url($url);
is_array($parts) || $parts = parse_url($parts);
isset($url['query']) && is_string($url['query']) || $url['query'] = null;
isset($parts['query']) && is_string($parts['query']) || $parts['query'] = null;
$keys = array('user', 'pass', 'port', 'path', 'query', 'fragment');
// HTTP_URL_STRIP_ALL and HTTP_URL_STRIP_AUTH cover several other flags.
if ($flags & self::HTTP_URL_STRIP_ALL) {
$flags |= self::HTTP_URL_STRIP_USER | self::HTTP_URL_STRIP_PASS
| self::HTTP_URL_STRIP_PORT | self::HTTP_URL_STRIP_PATH
| self::HTTP_URL_STRIP_QUERY | self::HTTP_URL_STRIP_FRAGMENT;
} elseif ($flags & self::HTTP_URL_STRIP_AUTH) {
$flags |= self::HTTP_URL_STRIP_USER | self::HTTP_URL_STRIP_PASS;
}
// Schema and host are alwasy replaced
foreach (array('scheme', 'host') as $part) {
if (isset($parts[$part])) {
$url[$part] = $parts[$part];
}
}
if ($flags & self::HTTP_URL_REPLACE) {
foreach ($keys as $key) {
if (isset($parts[$key])) {
$url[$key] = $parts[$key];
}
}
} else {
if (isset($parts['path']) && ($flags & self::HTTP_URL_JOIN_PATH)) {
if (isset($url['path']) && substr($parts['path'], 0, 1) !== '/') {
$url['path'] = rtrim(
str_replace(basename($url['path']), '', $url['path']),
'/'
) . '/' . ltrim($parts['path'], '/');
} else {
$url['path'] = $parts['path'];
}
}
if (isset($parts['query']) && ($flags & self::HTTP_URL_JOIN_QUERY)) {
if (isset($url['query'])) {
parse_str($url['query'], $url_query);
parse_str($parts['query'], $parts_query);
$url['query'] = http_build_query(
array_replace_recursive(
$url_query,
$parts_query
)
);
} else {
$url['query'] = $parts['query'];
}
}
}
if (isset($url['path']) && substr($url['path'], 0, 1) !== '/') {
$url['path'] = '/' . $url['path'];
}
foreach ($keys as $key) {
$strip = 'HTTP_URL_STRIP_' . strtoupper($key);
if ($flags & constant('utilphp\\util::' . $strip)) {
unset($url[$key]);
}
}
$parsed_string = '';
if (isset($url['scheme'])) {
$parsed_string .= $url['scheme'] . '://';
}
if (isset($url['user'])) {
$parsed_string .= $url['user'];
if (isset($url['pass'])) {
$parsed_string .= ':' . $url['pass'];
}
$parsed_string .= '@';
}
if (isset($url['host'])) {
$parsed_string .= $url['host'];
}
if (isset($url['port'])) {
$parsed_string .= ':' . $url['port'];
}
if (!empty($url['path'])) {
$parsed_string .= $url['path'];
} else {
$parsed_string .= '/';
}
if (isset($url['query'])) {
$parsed_string .= '?' . $url['query'];
}
if (isset($url['fragment'])) {
$parsed_string .= '#' . $url['fragment'];
}
$new_url = $url;
return $parsed_string;
}
/**
* Converts many english words that equate to true or false to boolean.
*
* Supports 'y', 'n', 'yes', 'no' and a few other variations.
*
* @param string $string The string to convert to boolean
* @param bool $default The value to return if we can't match any
* yes/no words
* @return boolean
*/
public static function str_to_bool($string, $default = false)
{
$yes_words = 'affirmative|all right|aye|indubitably|most assuredly|ok|of course|okay|sure thing|y|yes+|yea|yep|sure|yeah|true|t|on|1|oui|vrai';
$no_words = 'no*|no way|nope|nah|na|never|absolutely not|by no means|negative|never ever|false|f|off|0|non|faux';
if (preg_match('/^(' . $yes_words . ')$/i', $string)) {
return true;
} elseif (preg_match('/^(' . $no_words . ')$/i', $string)) {
return false;
}
return $default;
}
/**
* Check if a string starts with the given string.
*
* @param string $string
* @param string $starts_with
* @return boolean
*/
public static function starts_with($string, $starts_with)
{
return strpos($string, $starts_with) === 0;
}
/**
* Check if a string ends with the given string.
*
* @param string $string
* @param string $starts_with
* @return boolean
*/
public static function ends_with($string, $ends_with)
{
return substr($string, -strlen($ends_with)) === $ends_with;
}
/**
* Check if a string contains another string.
*
* @param string $haystack
* @param string $needle
* @return boolean
*/
public static function str_contains($haystack, $needle)
{
return strpos($haystack, $needle) !== false;
}
/**
* Check if a string contains another string. This version is case
* insensitive.
*
* @param string $haystack
* @param string $needle
* @return boolean
*/
public static function str_icontains($haystack, $needle)
{
return stripos($haystack, $needle) !== false;
}
/**
* Return the file extension of the given filename.
*
* @param string $filename
* @return string
*/
public static function get_file_ext($filename)
{
return pathinfo($filename, PATHINFO_EXTENSION);
}
/**
* Removes a directory (and its contents) recursively.
*
* Contributed by Askar (ARACOOL) <https://github.com/ARACOOOL>
*
* @param string $dir The directory to be deleted recursively
* @param bool $traverseSymlinks Delete contents of symlinks recursively
* @return bool
* @throws \RuntimeException
*/
public static function rmdir($dir, $traverseSymlinks = false)
{
if (!file_exists($dir)) {
return true;
} elseif (!is_dir($dir)) {
throw new \RuntimeException('Given path is not a directory');
}
if (!is_link($dir) || $traverseSymlinks) {
foreach (scandir($dir) as $file) {
if ($file === '.' || $file === '..') {
continue;
}
$currentPath = $dir . '/' . $file;
if (is_dir($currentPath)) {
self::rmdir($currentPath, $traverseSymlinks);
} elseif (!unlink($currentPath)) {
// @codeCoverageIgnoreStart
throw new \RuntimeException('Unable to delete ' . $currentPath);
// @codeCoverageIgnoreEnd
}
}
}
// Windows treats removing directory symlinks identically to removing directories.
if (is_link($dir) && !defined('PHP_WINDOWS_VERSION_MAJOR')) {
if (!unlink($dir)) {
// @codeCoverageIgnoreStart
throw new \RuntimeException('Unable to delete ' . $dir);
// @codeCoverageIgnoreEnd
}
} else {
if (!rmdir($dir)) {
// @codeCoverageIgnoreStart
throw new \RuntimeException('Unable to delete ' . $dir);
// @codeCoverageIgnoreEnd
}
}
return true;
}
/**
* Convert entities, while preserving already-encoded entities.
*
* @param string $string The text to be converted
* @return string
*/
public static function htmlentities($string, $preserve_encoded_entities = false)
{
if ($preserve_encoded_entities) {
// @codeCoverageIgnoreStart
if (defined('HHVM_VERSION')) {
$translation_table = get_html_translation_table(HTML_ENTITIES, ENT_QUOTES);
} else {
$translation_table = get_html_translation_table(HTML_ENTITIES, ENT_QUOTES, self::mbInternalEncoding());
}
// @codeCoverageIgnoreEnd
$translation_table[chr(38)] = '&';
return preg_replace('/&(?![A-Za-z]{0,4}\w{2,3};|#[0-9]{2,3};)/', '&amp;', strtr($string, $translation_table));
}
return htmlentities($string, ENT_QUOTES, self::mbInternalEncoding());
}
/**
* Convert >, <, ', " and & to html entities, but preserves entities that
* are already encoded.
*
* @param string $string The text to be converted
* @return string
*/
public static function htmlspecialchars($string, $preserve_encoded_entities = false)
{
if ($preserve_encoded_entities) {
// @codeCoverageIgnoreStart
if (defined('HHVM_VERSION')) {
$translation_table = get_html_translation_table(HTML_SPECIALCHARS, ENT_QUOTES);
} else {
$translation_table = get_html_translation_table(HTML_SPECIALCHARS, ENT_QUOTES, self::mbInternalEncoding());
}
// @codeCoverageIgnoreEnd
$translation_table[chr(38)] = '&';
return preg_replace('/&(?![A-Za-z]{0,4}\w{2,3};|#[0-9]{2,3};)/', '&amp;', strtr($string, $translation_table));
}
return htmlentities($string, ENT_QUOTES, self::mbInternalEncoding());
}
/**
* Transliterates characters to their ASCII equivalents.
*
* Part of the URLify.php Project <https://github.com/jbroadway/urlify/>
*
* @see https://github.com/jbroadway/urlify/blob/master/URLify.php
*
* @param string $text Text that might have not-ASCII characters
* @param string $language Specifies a priority for a specific language.
* @return string Filtered string with replaced "nice" characters
*/
public static function downcode($text, $language = '')
{
self::initLanguageMap($language);
if (self::seems_utf8($text)) {
if (preg_match_all(self::$regex, $text, $matches)) {
for ($i = 0; $i < count($matches[0]); $i++) {
$char = $matches[0][$i];
if (isset(self::$map[$char])) {
$text = str_replace($char, self::$map[$char], $text);
}
}
}
} else {
// Not a UTF-8 string so we assume its ISO-8859-1
$search = "\x80\x83\x8a\x8e\x9a\x9e\x9f\xa2\xa5\xb5\xc0\xc1\xc2\xc3\xc4\xc5\xc7\xc8\xc9\xca\xcb\xcc\xcd";
$search .= "\xce\xcf\xd1\xd2\xd3\xd4\xd5\xd6\xd8\xd9\xda\xdb\xdc\xdd\xe0\xe1\xe2\xe3\xe4\xe5\xe7\xe8\xe9";
$search .= "\xea\xeb\xec\xed\xee\xef\xf1\xf2\xf3\xf4\xf5\xf6\xf8\xf9\xfa\xfb\xfc\xfd\xff";
$text = strtr($text, $search, 'EfSZszYcYuAAAAAACEEEEIIIINOOOOOOUUUUYaaaaaaceeeeiiiinoooooouuuuyy');
// These latin characters should be represented by two characters so
// we can't use strtr
$complexSearch = array("\x8c", "\x9c", "\xc6", "\xd0", "\xde", "\xdf", "\xe6", "\xf0", "\xfe");
$complexReplace = array('OE', 'oe', 'AE', 'DH', 'TH', 'ss', 'ae', 'dh', 'th');
$text = str_replace($complexSearch, $complexReplace, $text);
}
return $text;
}
/**
* Converts all accent characters to ASCII characters.
*
* If there are no accent characters, then the string given is just
* returned.
*
* @param string $string Text that might have accent characters
* @param string $language Specifies a priority for a specific language.
* @return string Filtered string with replaced "nice" characters
*/
public static function remove_accents($string, $language = '')
{
if (!preg_match('/[\x80-\xff]/', $string)) {
return $string;
}
return self::downcode($string, $language);
}
/**
* Strip all witespaces from the given string.
*
* @param string $string The string to strip
* @return string
*/
public static function strip_space($string)
{
return preg_replace('/\s+/', '', $string);
}
/**
* Sanitize a string by performing the following operation :
* - Remove accents
* - Lower the string
* - Remove punctuation characters
* - Strip whitespaces
*
* @param string $string the string to sanitize
* @return string
*/
public static function sanitize_string($string)
{
$string = self::remove_accents($string);
$string = strtolower($string);
$string = preg_replace('/[^a-zA-Z 0-9]+/', '', $string);
$string = self::strip_space($string);
return $string;
}
/**
* Pads a given string with zeroes on the left.
*
* @param int $number The number to pad
* @param int $length The total length of the desired string
* @return string
*/
public static function zero_pad($number, $length)
{
return str_pad($number, $length, '0', STR_PAD_LEFT);
}
/**
* Converts a unix timestamp to a relative time string, such as "3 days ago"
* or "2 weeks ago".
*
* @param int $from The date to use as a starting point
* @param int $to The date to compare to, defaults to now
* @param string $suffix The string to add to the end, defaults to " ago"
* @return string
*/
public static function human_time_diff($from, $to = '', $as_text = false, $suffix = ' ago')
{
if ($to == '') {
$to = time();
}
$from = new \DateTime(date('Y-m-d H:i:s', $from));
$to = new \DateTime(date('Y-m-d H:i:s', $to));
$diff = $from->diff($to);
if ($diff->y > 1) {
$text = $diff->y . ' years';
} elseif ($diff->y == 1) {
$text = '1 year';
} elseif ($diff->m > 1) {
$text = $diff->m . ' months';
} elseif ($diff->m == 1) {
$text = '1 month';
} elseif ($diff->d > 7) {
$text = ceil($diff->d / 7) . ' weeks';
} elseif ($diff->d == 7) {
$text = '1 week';
} elseif ($diff->d > 1) {
$text = $diff->d . ' days';
} elseif ($diff->d == 1) {
$text = '1 day';
} elseif ($diff->h > 1) {
$text = $diff->h . ' hours';
} elseif ($diff->h == 1) {
$text = ' 1 hour';
} elseif ($diff->i > 1) {
$text = $diff->i . ' minutes';
} elseif ($diff->i == 1) {
$text = '1 minute';
} elseif ($diff->s > 1) {
$text = $diff->s . ' seconds';
} else {
$text = '1 second';
}
if ($as_text) {
$text = explode(' ', $text, 2);
$text = self::number_to_word($text[0]) . ' ' . $text[1];
}
return trim($text) . $suffix;
}
/**
* Converts a number into the text equivalent. For example, 456 becomes four
* hundred and fifty-six.
*
* Part of the IntToWords Project.
*
* @param int|float $number The number to convert into text
* @return string
*/
public static function number_to_word($number)
{
$number = (string) $number;
if (strpos($number, '.') !== false) {
list($number, $decimal) = explode('.', $number);
} else {
$decimal = false;
}
$output = '';
if ($number[0] == '-') {
$output = 'negative ';
$number = ltrim($number, '-');
} elseif ($number[0] == '+') {
$output = 'positive ';
$number = ltrim($number, '+');
}
if ($number[0] == '0') {
$output .= 'zero';
} else {
$length = 19;
$number = str_pad($number, 60, '0', STR_PAD_LEFT);
$group = rtrim(chunk_split($number, 3, ' '), ' ');
$groups = explode(' ', $group);
$groups2 = array();
foreach ($groups as $group) {
$group[1] = isset($group[1]) ? $group[1] : null;
$group[2] = isset($group[2]) ? $group[2] : null;
$groups2[] = self::numberToWordThreeDigits($group[0], $group[1], $group[2]);
}
for ($z = 0; $z < count($groups2); $z++) {
if ($groups2[$z] != '') {
$output .= $groups2[$z] . self::numberToWordConvertGroup($length - $z);
$output .= ($z < $length && ! array_search('', array_slice($groups2, $z + 1, -1)) && $groups2[$length] != '' && $groups[$length][0] == '0' ? ' and ' : ', ');
}
}
$output = rtrim($output, ', ');
}
if ($decimal > 0) {
$output .= ' point';
for ($i = 0; $i < strlen($decimal); $i++) {
$output .= ' ' . self::numberToWordConvertDigit($decimal[$i]);
}
}
return $output;
}
protected static function numberToWordConvertGroup($index)
{
switch($index) {
case 11:
return ' decillion';
case 10:
return ' nonillion';
case 9:
return ' octillion';
case 8:
return ' septillion';
case 7:
return ' sextillion';
case 6:
return ' quintrillion';
case 5:
return ' quadrillion';
case 4:
return ' trillion';
case 3:
return ' billion';
case 2:
return ' million';
case 1:
return ' thousand';
case 0:
return '';
}
return '';
}
protected static function numberToWordThreeDigits($digit1, $digit2, $digit3)
{
$output = '';
if ($digit1 == '0' && $digit2 == '0' && $digit3 == '0') {
return '';
}
if ($digit1 != '0') {
$output .= self::numberToWordConvertDigit($digit1) . ' hundred';
if ($digit2 != '0' || $digit3 != '0') {
$output .= ' and ';
}
}
if ($digit2 != '0') {
$output .= self::numberToWordTwoDigits($digit2, $digit3);
} elseif ($digit3 != '0') {
$output .= self::numberToWordConvertDigit($digit3);
}
return $output;
}
protected static function numberToWordTwoDigits($digit1, $digit2)
{
if ($digit2 == '0') {
switch ($digit1) {
case '1':
return 'ten';
case '2':
return 'twenty';
case '3':
return 'thirty';
case '4':
return 'forty';
case '5':
return 'fifty';
case '6':
return 'sixty';
case '7':
return 'seventy';
case '8':
return 'eighty';
case '9':
return 'ninety';
}
} elseif ($digit1 == '1') {
switch ($digit2) {
case '1':
return 'eleven';
case '2':
return 'twelve';
case '3':
return 'thirteen';
case '4':
return 'fourteen';
case '5':
return 'fifteen';
case '6':
return 'sixteen';
case '7':
return 'seventeen';
case '8':
return 'eighteen';
case '9':
return 'nineteen';
}
} else {
$second_digit = self::numberToWordConvertDigit($digit2);
switch ($digit1) {
case '2':
return "twenty-{$second_digit}";
case '3':
return "thirty-{$second_digit}";
case '4':
return "forty-{$second_digit}";
case '5':
return "fifty-{$second_digit}";
case '6':
return "sixty-{$second_digit}";
case '7':
return "seventy-{$second_digit}";
case '8':
return "eighty-{$second_digit}";
case '9':
return "ninety-{$second_digit}";
}
}
}
/**
* @param $digit
* @return string
* @throws \LogicException
*/
protected static function numberToWordConvertDigit($digit)
{
switch ($digit) {
case '0':
return 'zero';
case '1':
return 'one';
case '2':
return 'two';
case '3':
return 'three';
case '4':
return 'four';
case '5':
return 'five';
case '6':
return 'six';
case '7':
return 'seven';
case '8':
return 'eight';
case '9':
return 'nine';
default:
throw new \LogicException('Not a number');
}
}
/**
* Transmit UTF-8 content headers if the headers haven't already been sent.
*
* @param string $content_type The content type to send out
* @return boolean
*/
public static function utf8_headers($content_type = 'text/html')
{
// @codeCoverageIgnoreStart
if (!headers_sent()) {
header('Content-type: ' . $content_type . '; charset=utf-8');
return true;
}
return false;
// @codeCoverageIgnoreEnd
}
/**
* Transmit headers that force a browser to display the download file
* dialog. Cross browser compatible. Only fires if headers have not
* already been sent.
*
* @param string $filename The name of the filename to display to
* browsers
* @param string $content The content to output for the download.
* If you don't specify this, just the
* headers will be sent
* @return boolean
*/
public static function force_download($filename, $content = false)
{
// @codeCoverageIgnoreStart
if (!headers_sent()) {
// Required for some browsers
if (ini_get('zlib.output_compression')) {
@ini_set('zlib.output_compression', 'Off');
}
header('Pragma: public');
header('Expires: 0');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
// Required for certain browsers
header('Cache-Control: private', false);
header('Content-Disposition: attachment; filename="' . basename(str_replace('"', '', $filename)) . '";');
header('Content-Type: application/force-download');
header('Content-Transfer-Encoding: binary');
if ($content) {
header('Content-Length: ' . strlen($content));
}
ob_clean();
flush();
if ($content) {
echo $content;
}
return true;
}
return false;
// @codeCoverageIgnoreEnd
}
/**
* Sets the headers to prevent caching for the different browsers.
*
* Different browsers support different nocache headers, so several
* headers must be sent so that all of them get the point that no
* caching should occur
*
* @return boolean
*/
public static function nocache_headers()
{
// @codeCoverageIgnoreStart
if (!headers_sent()) {
header('Expires: Wed, 11 Jan 1984 05:00:00 GMT');
header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT');
header('Cache-Control: no-cache, must-revalidate, max-age=0');
header('Pragma: no-cache');
return true;
}
return false;
// @codeCoverageIgnoreEnd
}
/**
* Generates a string of random characters.
*
* @throws LengthException If $length is bigger than the available
* character pool and $no_duplicate_chars is
* enabled
*
* @param integer $length The length of the string to
* generate
* @param boolean $human_friendly Whether or not to make the
* string human friendly by
* removing characters that can be
* confused with other characters (
* O and 0, l and 1, etc)
* @param boolean $include_symbols Whether or not to include
* symbols in the string. Can not
* be enabled if $human_friendly is
* true
* @param boolean $no_duplicate_chars Whether or not to only use
* characters once in the string.
* @return string
*/
public static function random_string($length = 16, $human_friendly = true, $include_symbols = false, $no_duplicate_chars = false)
{
$nice_chars = 'ABCDEFGHJKLMNPQRSTUVWXYZabcdefhjkmnprstuvwxyz23456789';
$all_an = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890';
$symbols = '!@#$%^&*()~_-=+{}[]|:;<>,.?/"\'\\`';
$string = '';
// Determine the pool of available characters based on the given parameters
if ($human_friendly) {
$pool = $nice_chars;
} else {
$pool = $all_an;
if ($include_symbols) {
$pool .= $symbols;
}
}
if (!$no_duplicate_chars) {
return substr(str_shuffle(str_repeat($pool, $length)), 0, $length);
}
// Don't allow duplicate letters to be disabled if the length is
// longer than the available characters
if ($no_duplicate_chars && strlen($pool) < $length) {
throw new \LengthException('$length exceeds the size of the pool and $no_duplicate_chars is enabled');
}
// Convert the pool of characters into an array of characters and
// shuffle the array
$pool = str_split($pool);
$poolLength = count($pool);
$rand = mt_rand(0, $poolLength - 1);
// Generate our string
for ($i = 0; $i < $length; $i++) {
$string .= $pool[$rand];
// Remove the character from the array to avoid duplicates
array_splice($pool, $rand, 1);
// Generate a new number
if (($poolLength - 2 - $i) > 0) {
$rand = mt_rand(0, $poolLength - 2 - $i);
} else {
$rand = 0;
}
}
return $string;
}
/**
* Generate secure random string of given length
* If 'openssl_random_pseudo_bytes' is not available
* then generate random string using default function
*
* Part of the Laravel Project <https://github.com/laravel/laravel>
*
* @param int $length length of string
* @return bool
*/
public static function secure_random_string($length = 16)
{
if (function_exists('openssl_random_pseudo_bytes')) {
$bytes = openssl_random_pseudo_bytes($length * 2);
if ($bytes === false) {
throw new \LengthException('$length is not accurate, unable to generate random string');
}
return substr(str_replace(array('/', '+', '='), '', base64_encode($bytes)), 0, $length);
}
// @codeCoverageIgnoreStart
return static::random_string($length);
// @codeCoverageIgnoreEnd
}
/**
* Check if a given string matches a given pattern.
*
* Contributed by Abhimanyu Sharma <https://github.com/abhimanyusharma003>
*
* @param string $pattern Parttern of string exptected
* @param string $string String that need to be matched
* @return bool
*/
public static function match_string($pattern, $string, $caseSensitive = true)
{
if ($pattern == $string) {
return true;
}
// Preg flags
$flags = $caseSensitive ? '' : 'i';
// Escape any regex special characters
$pattern = preg_quote($pattern, '#');
// Unescape * which is our wildcard character and change it to .*
$pattern = str_replace('\*', '.*', $pattern);
return (bool) preg_match('#^' . $pattern . '$#' . $flags, $string);
}
/**
* Validate an email address.
*
* @param string $possible_email An email address to validate
* @return bool
*/
public static function validate_email($possible_email)
{
return (bool) filter_var($possible_email, FILTER_VALIDATE_EMAIL);
}
/**
* Return the URL to a user's gravatar.
*
* @param string $email The email of the user
* @param integer $size The size of the gravatar
* @return string
*/
public static function get_gravatar($email, $size = 32)
{
if (self::is_https()) {
$url = 'https://secure.gravatar.com/';
} else {
$url = 'http://www.gravatar.com/';
}
$url .= 'avatar/' . md5($email) . '?s=' . (int) abs($size);
return $url;
}
/**
* Turns all of the links in a string into HTML links.
*
* Part of the LinkifyURL Project <https://github.com/jmrware/LinkifyURL>
*
* @param string $text The string to parse
* @return string
*/
public static function linkify($text)
{
$text = preg_replace('/&apos;/', '&#39;', $text); // IE does not handle &apos; entity!
$section_html_pattern = '%# Rev:20100913_0900 github.com/jmrware/LinkifyURL
# Section text into HTML <A> tags and everything else.
( # $1: Everything not HTML <A> tag.
[^<]+(?:(?!<a\b)<[^<]*)* # non A tag stuff starting with non-"<".
| (?:(?!<a\b)<[^<]*)+ # non A tag stuff starting with "<".
) # End $1.
| ( # $2: HTML <A...>...</A> tag.
<a\b[^>]*> # <A...> opening tag.
[^<]*(?:(?!</a\b)<[^<]*)* # A tag contents.
</a\s*> # </A> closing tag.
) # End $2:
%ix';
return preg_replace_callback($section_html_pattern, array(__CLASS__, 'linkifyCallback'), $text);
}
/**
* Callback for the preg_replace in the linkify() method.
*
* Part of the LinkifyURL Project <https://github.com/jmrware/LinkifyURL>
*
* @param array $matches Matches from the preg_ function
* @return string
*/
protected static function linkifyRegex($text)
{
$url_pattern = '/# Rev:20100913_0900 github.com\/jmrware\/LinkifyURL
# Match http & ftp URL that is not already linkified.
# Alternative 1: URL delimited by (parentheses).
(\() # $1 "(" start delimiter.
((?:ht|f)tps?:\/\/[a-z0-9\-._~!$&\'()*+,;=:\/?#[\]@%]+) # $2: URL.
(\)) # $3: ")" end delimiter.
| # Alternative 2: URL delimited by [square brackets].
(\[) # $4: "[" start delimiter.
((?:ht|f)tps?:\/\/[a-z0-9\-._~!$&\'()*+,;=:\/?#[\]@%]+) # $5: URL.
(\]) # $6: "]" end delimiter.
| # Alternative 3: URL delimited by {curly braces}.
(\{) # $7: "{" start delimiter.
((?:ht|f)tps?:\/\/[a-z0-9\-._~!$&\'()*+,;=:\/?#[\]@%]+) # $8: URL.
(\}) # $9: "}" end delimiter.
| # Alternative 4: URL delimited by <angle brackets>.
(<|&(?:lt|\#60|\#x3c);) # $10: "<" start delimiter (or HTML entity).
((?:ht|f)tps?:\/\/[a-z0-9\-._~!$&\'()*+,;=:\/?#[\]@%]+) # $11: URL.
(>|&(?:gt|\#62|\#x3e);) # $12: ">" end delimiter (or HTML entity).
| # Alternative 5: URL not delimited by (), [], {} or <>.
(# $13: Prefix proving URL not already linked.
(?: ^ # Can be a beginning of line or string, or
| [^=\s\'"\]] # a non-"=", non-quote, non-"]", followed by
) \s*[\'"]? # optional whitespace and optional quote;
| [^=\s]\s+ # or... a non-equals sign followed by whitespace.
) # End $13. Non-prelinkified-proof prefix.
(\b # $14: Other non-delimited URL.
(?:ht|f)tps?:\/\/ # Required literal http, https, ftp or ftps prefix.
[a-z0-9\-._~!$\'()*+,;=:\/?#[\]@%]+ # All URI chars except "&" (normal*).
(?: # Either on a "&" or at the end of URI.
(?! # Allow a "&" char only if not start of an...
&(?:gt|\#0*62|\#x0*3e); # HTML ">" entity, or
| &(?:amp|apos|quot|\#0*3[49]|\#x0*2[27]); # a [&\'"] entity if
[.!&\',:?;]? # followed by optional punctuation then
(?:[^a-z0-9\-._~!$&\'()*+,;=:\/?#[\]@%]|$) # a non-URI char or EOS.
) & # If neg-assertion true, match "&" (special).
[a-z0-9\-._~!$\'()*+,;=:\/?#[\]@%]* # More non-& URI chars (normal*).
)* # Unroll-the-loop (special normal*)*.
[a-z0-9\-_~$()*+=\/#[\]@%] # Last char can\'t be [.!&\',;:?]
) # End $14. Other non-delimited URL.
/imx';
$url_replace = '$1$4$7$10$13<a href="$2$5$8$11$14">$2$5$8$11$14</a>$3$6$9$12';
return preg_replace($url_pattern, $url_replace, $text);
}
/**
* Callback for the preg_replace in the linkify() method.
*
* Part of the LinkifyURL Project <https://github.com/jmrware/LinkifyURL>
*
* @param array $matches Matches from the preg_ function
* @return string
*/
protected static function linkifyCallback($matches)
{
if (isset($matches[2])) {
return $matches[2];
}
return self::linkifyRegex($matches[1]);
}
/**
* Return the current URL.
*
* @return string
*/
public static function get_current_url()
{
$url = '';
// Check to see if it's over https
$is_https = self::is_https();
if ($is_https) {
$url .= 'https://';
} else {
$url .= 'http://';
}
// Was a username or password passed?
if (isset($_SERVER['PHP_AUTH_USER'])) {
$url .= $_SERVER['PHP_AUTH_USER'];
if (isset($_SERVER['PHP_AUTH_PW'])) {
$url .= ':' . $_SERVER['PHP_AUTH_PW'];
}
$url .= '@';
}
// We want the user to stay on the same host they are currently on,
// but beware of security issues
// see http://shiflett.org/blog/2006/mar/server-name-versus-http-host
$url .= $_SERVER['HTTP_HOST'];
$port = $_SERVER['SERVER_PORT'];
// Is it on a non standard port?
if ($is_https && ($port != 443)) {
$url .= ':' . $_SERVER['SERVER_PORT'];
} elseif (!$is_https && ($port != 80)) {
$url .= ':' . $_SERVER['SERVER_PORT'];
}
// Get the rest of the URL
if (!isset($_SERVER['REQUEST_URI'])) {
// Microsoft IIS doesn't set REQUEST_URI by default
$url .= $_SERVER['PHP_SELF'];
if (isset($_SERVER['QUERY_STRING'])) {
$url .= '?' . $_SERVER['QUERY_STRING'];
}
} else {
$url .= $_SERVER['REQUEST_URI'];
}
return $url;
}
/**
* Returns the IP address of the client.
*
* @param boolean $trust_proxy_headers Whether or not to trust the
* proxy headers HTTP_CLIENT_IP
* and HTTP_X_FORWARDED_FOR. ONLY
* use if your server is behind a
* proxy that sets these values
* @return string
*/
public static function get_client_ip($trust_proxy_headers = false)
{
if (!$trust_proxy_headers) {
return $_SERVER['REMOTE_ADDR'];
}
if (!empty($_SERVER['HTTP_CLIENT_IP'])) {
$ip = $_SERVER['HTTP_CLIENT_IP'];
} elseif (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
$ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
} else {
$ip = $_SERVER['REMOTE_ADDR'];
}
return $ip;
}
/**
* Truncate a string to a specified length without cutting a word off.
*
* @param string $string The string to truncate
* @param integer $length The length to truncate the string to
* @param string $append Text to append to the string IF it gets
* truncated, defaults to '...'
* @return string
*/
public static function safe_truncate($string, $length, $append = '...')
{
$ret = substr($string, 0, $length);
$last_space = strrpos($ret, ' ');
if ($last_space !== false && $string != $ret) {
$ret = substr($ret, 0, $last_space);
}
if ($ret != $string) {
$ret .= $append;
}
return $ret;
}
/**
* Truncate the string to given length of charactes.
*
* @param $string
* @param $limit
* @param string $append
* @return string
*/
public static function limit_characters($string, $limit = 100, $append = '...')
{
if (mb_strlen($string) <= $limit) {
return $string;
}
return rtrim(mb_substr($string, 0, $limit, 'UTF-8')) . $append;
}
/**
* Truncate the string to given length of words.
*
* @param $string
* @param $limit
* @param string $append
* @return string
*/
public static function limit_words($string, $limit = 100, $append = '...')
{
preg_match('/^\s*+(?:\S++\s*+){1,' . $limit . '}/u', $string, $matches);
if (!isset($matches[0]) || strlen($string) === strlen($matches[0])) {
return $string;
}
return rtrim($matches[0]).$append;
}
/**
* Returns the ordinal version of a number (appends th, st, nd, rd).
*
* @param string $number The number to append an ordinal suffix to
* @return string
*/
public static function ordinal($number)
{
$test_c = abs($number) % 10;
$ext = ((abs($number) % 100 < 21 && abs($number) % 100 > 4) ? 'th' : (($test_c < 4) ? ($test_c < 3) ? ($test_c < 2) ? ($test_c < 1) ? 'th' : 'st' : 'nd' : 'rd' : 'th'));
return $number . $ext;
}
/**
* Returns the file permissions as a nice string, like -rw-r--r-- or false
* if the file is not found.
*
* @param string $file The name of the file to get permissions form
* @param int $perms Numerical value of permissions to display as text.
* @return string
*/
public static function full_permissions($file, $perms = null)
{
if (is_null($perms)) {
if (!file_exists($file)) {
return false;
}
$perms = fileperms($file);
}
if (($perms & 0xC000) == 0xC000) {
// Socket
$info = 's';
} elseif (($perms & 0xA000) == 0xA000) {
// Symbolic Link
$info = 'l';
} elseif (($perms & 0x8000) == 0x8000) {
// Regular
$info = '-';
} elseif (($perms & 0x6000) == 0x6000) {
// Block special
$info = 'b';
} elseif (($perms & 0x4000) == 0x4000) {
// Directory
$info = 'd';
} elseif (($perms & 0x2000) == 0x2000) {
// Character special
$info = 'c';
} elseif (($perms & 0x1000) == 0x1000) {
// FIFO pipe
$info = 'p';
} else {
// Unknown
$info = 'u';
}
// Owner
$info .= (($perms & 0x0100) ? 'r' : '-');
$info .= (($perms & 0x0080) ? 'w' : '-');
$info .= (($perms & 0x0040) ?
(($perms & 0x0800) ? 's' : 'x') :
(($perms & 0x0800) ? 'S' : '-'));
// Group
$info .= (($perms & 0x0020) ? 'r' : '-');
$info .= (($perms & 0x0010) ? 'w' : '-');
$info .= (($perms & 0x0008) ?
(($perms & 0x0400) ? 's' : 'x') :
(($perms & 0x0400) ? 'S' : '-'));
// World
$info .= (($perms & 0x0004) ? 'r' : '-');
$info .= (($perms & 0x0002) ? 'w' : '-');
$info .= (($perms & 0x0001) ?
(($perms & 0x0200) ? 't' : 'x') :
(($perms & 0x0200) ? 'T' : '-'));
return $info;
}
/**
* Returns the first element in an array.
*
* @param array $array
* @return mixed
*/
public static function array_first(array $array)
{
return reset($array);
}
/**
* Returns the last element in an array.
*
* @param array $array
* @return mixed
*/
public static function array_last(array $array)
{
return end($array);
}
/**
* Returns the first key in an array.
*
* @param array $array
* @return int|string
*/
public static function array_first_key(array $array)
{
reset($array);
return key($array);
}
/**
* Returns the last key in an array.
*
* @param array $array
* @return int|string
*/
public static function array_last_key(array $array)
{
end($array);
return key($array);
}
/**
* Flatten a multi-dimensional array into a one dimensional array.
*
* Contributed by Theodore R. Smith of PHP Experts, Inc. <http://www.phpexperts.pro/>
*
* @param array $array The array to flatten
* @param boolean $preserve_keys Whether or not to preserve array keys.
* Keys from deeply nested arrays will
* overwrite keys from shallowy nested arrays
* @return array
*/
public static function array_flatten(array $array, $preserve_keys = true)
{
$flattened = array();
array_walk_recursive($array, function($value, $key) use (&$flattened, $preserve_keys) {
if ($preserve_keys && !is_int($key)) {
$flattened[$key] = $value;
} else {
$flattened[] = $value;
}
});
return $flattened;
}
/**
* Accepts an array, and returns an array of values from that array as
* specified by $field. For example, if the array is full of objects
* and you call util::array_pluck($array, 'name'), the function will
* return an array of values from $array[]->name.
*
* @param array $array An array
* @param string $field The field to get values from
* @param boolean $preserve_keys Whether or not to preserve the
* array keys
* @param boolean $remove_nomatches If the field doesn't appear to be set,
* remove it from the array
* @return array
*/
public static function array_pluck(array $array, $field, $preserve_keys = true, $remove_nomatches = true)
{
$new_list = array();
foreach ($array as $key => $value) {
if (is_object($value)) {
if (isset($value->{$field})) {
if ($preserve_keys) {
$new_list[$key] = $value->{$field};
} else {
$new_list[] = $value->{$field};
}
} elseif (!$remove_nomatches) {
$new_list[$key] = $value;
}
} else {
if (isset($value[$field])) {
if ($preserve_keys) {
$new_list[$key] = $value[$field];
} else {
$new_list[] = $value[$field];
}
} elseif (!$remove_nomatches) {
$new_list[$key] = $value;
}
}
}
return $new_list;
}
/**
* Searches for a given value in an array of arrays, objects and scalar
* values. You can optionally specify a field of the nested arrays and
* objects to search in.
*
* @param array $array The array to search
* @param scalar $search The value to search for
* @param string $field The field to search in, if not specified
* all fields will be searched
* @return boolean|scalar False on failure or the array key on success
*/
public static function array_search_deep(array $array, $search, $field = false)
{
// *grumbles* stupid PHP type system
$search = (string) $search;
foreach ($array as $key => $elem) {
// *grumbles* stupid PHP type system
$key = (string) $key;
if ($field) {
if (is_object($elem) && $elem->{$field} === $search) {
return $key;
} elseif (is_array($elem) && $elem[$field] === $search) {
return $key;
} elseif (is_scalar($elem) && $elem === $search) {
return $key;
}
} else {
if (is_object($elem)) {
$elem = (array) $elem;
if (in_array($search, $elem)) {
return $key;
}
} elseif (is_array($elem) && in_array($search, $elem)) {
return $key;
} elseif (is_scalar($elem) && $elem === $search) {
return $key;
}
}
}
return false;
}
/**
* Returns an array containing all the elements of arr1 after applying
* the callback function to each one.
*
* @param string $callback Callback function to run for each
* element in each array
* @param array $array An array to run through the callback
* function
* @param boolean $on_nonscalar Whether or not to call the callback
* function on nonscalar values
* (Objects, resources, etc)
* @return array
*/
public static function array_map_deep(array $array, $callback, $on_nonscalar = false)
{
foreach ($array as $key => $value) {
if (is_array($value)) {
$args = array($value, $callback, $on_nonscalar);
$array[$key] = call_user_func_array(array(__CLASS__, __FUNCTION__), $args);
} elseif (is_scalar($value) || $on_nonscalar) {
$array[$key] = call_user_func($callback, $value);
}
}
return $array;
}
public static function array_clean(array $array)
{
return array_filter($array);
}
/**
* Wrapper to prevent errors if the user doesn't have the mbstring
* extension installed.
*
* @param string $encoding
* @return string
*/
protected static function mbInternalEncoding($encoding = null)
{
if (function_exists('mb_internal_encoding')) {
return $encoding ? mb_internal_encoding($encoding) : mb_internal_encoding();
}
// @codeCoverageIgnoreStart
return 'UTF-8';
// @codeCoverageIgnoreEnd
}
/**
* Set the writable bit on a file to the minimum value that allows the user
* running PHP to write to it.
*
* @param string $filename The filename to set the writable bit on
* @param boolean $writable Whether to make the file writable or not
* @return boolean
*/
public static function set_writable($filename, $writable = true)
{
$stat = @stat($filename);
if ($stat === false) {
return false;
}
// We're on Windows
if (strncasecmp(PHP_OS, 'WIN', 3) === 0) {
return true;
}
list($myuid, $mygid) = array(posix_geteuid(), posix_getgid());
if ($writable) {
// Set only the user writable bit (file is owned by us)
if ($stat['uid'] == $myuid) {
return chmod($filename, fileperms($filename) | 0200);
}
// Set only the group writable bit (file group is the same as us)
if ($stat['gid'] == $mygid) {
return chmod($filename, fileperms($filename) | 0220);
}
// Set the world writable bit (file isn't owned or grouped by us)
return chmod($filename, fileperms($filename) | 0222);
} else {
// Set only the user writable bit (file is owned by us)
if ($stat['uid'] == $myuid) {
return chmod($filename, (fileperms($filename) | 0222) ^ 0222);
}
// Set only the group writable bit (file group is the same as us)
if ($stat['gid'] == $mygid) {
return chmod($filename, (fileperms($filename) | 0222) ^ 0022);
}
// Set the world writable bit (file isn't owned or grouped by us)
return chmod($filename, (fileperms($filename) | 0222) ^ 0002);
}
}
/**
* Set the readable bit on a file to the minimum value that allows the user
* running PHP to read to it.
*
* @param string $filename The filename to set the readable bit on
* @param boolean $readable Whether to make the file readable or not
* @return boolean
*/
public static function set_readable($filename, $readable = true)
{
$stat = @stat($filename);
if ($stat === false) {
return false;
}
// We're on Windows
if (strncasecmp(PHP_OS, 'WIN', 3) === 0) {
return true;
}
list($myuid, $mygid) = array(posix_geteuid(), posix_getgid());
if ($readable) {
// Set only the user readable bit (file is owned by us)
if ($stat['uid'] == $myuid) {
return chmod($filename, fileperms($filename) | 0400);
}
// Set only the group readable bit (file group is the same as us)
if ($stat['gid'] == $mygid) {
return chmod($filename, fileperms($filename) | 0440);
}
// Set the world readable bit (file isn't owned or grouped by us)
return chmod($filename, fileperms($filename) | 0444);
} else {
// Set only the user readable bit (file is owned by us)
if ($stat['uid'] == $myuid) {
return chmod($filename, (fileperms($filename) | 0444) ^ 0444);
}
// Set only the group readable bit (file group is the same as us)
if ($stat['gid'] == $mygid) {
return chmod($filename, (fileperms($filename) | 0444) ^ 0044);
}
// Set the world readable bit (file isn't owned or grouped by us)
return chmod($filename, (fileperms($filename) | 0444) ^ 0004);
}
}
/**
* Set the executable bit on a file to the minimum value that allows the
* user running PHP to read to it.
*
* @param string $filename The filename to set the executable bit on
* @param boolean $executable Whether to make the file executable or not
* @return boolean
*/
public static function set_executable($filename, $executable = true)
{
$stat = @stat($filename);
if ($stat === false) {
return false;
}
// We're on Windows
if (strncasecmp(PHP_OS, 'WIN', 3) === 0) {
return true;
}
list($myuid, $mygid) = array(posix_geteuid(), posix_getgid());
if ($executable) {
// Set only the user readable bit (file is owned by us)
if ($stat['uid'] == $myuid) {
return chmod($filename, fileperms($filename) | 0100);
}
// Set only the group readable bit (file group is the same as us)
if ($stat['gid'] == $mygid) {
return chmod($filename, fileperms($filename) | 0110);
}
// Set the world readable bit (file isn't owned or grouped by us)
return chmod($filename, fileperms($filename) | 0111);
} else {
// Set only the user readable bit (file is owned by us)
if ($stat['uid'] == $myuid) {
return chmod($filename, (fileperms($filename) | 0111) ^ 0111);
}
// Set only the group readable bit (file group is the same as us)
if ($stat['gid'] == $mygid) {
return chmod($filename, (fileperms($filename) | 0111) ^ 0011);
}
// Set the world readable bit (file isn't owned or grouped by us)
return chmod($filename, (fileperms($filename) | 0111) ^ 0001);
}
}
/**
* Returns size of a given directory in bytes.
*
* @param string $dir
* @return integer
*/
public static function directory_size($dir)
{
$size = 0;
foreach(new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($dir, \FilesystemIterator::CURRENT_AS_FILEINFO | \FilesystemIterator::SKIP_DOTS)) as $file => $key) {
if ($key->isFile()) {
$size += $key->getSize();
}
}
return $size;
}
/**
* Returns a home directory of current user.
*
* @return string
*/
public static function get_user_directory()
{
if (isset($_SERVER['HOMEDRIVE'])) return $_SERVER['HOMEDRIVE'] . $_SERVER['HOMEPATH'];
else return $_SERVER['HOME'];
}
/**
* Returns all paths inside a directory.
*
* @param string $dir
* @return array
*/
public static function directory_contents($dir)
{
$contents = array();
foreach(new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($dir, \FilesystemIterator::KEY_AS_PATHNAME | \FilesystemIterator::CURRENT_AS_FILEINFO | \FilesystemIterator::SKIP_DOTS)) as $pathname => $fi) {
$contents[] = $pathname;
}
natsort($contents);
return $contents;
}
}
+39
View File
@@ -0,0 +1,39 @@
# UtilityPHP Unit Tests #
### Introduction
This is the testing documentation for util.php. The unit tests require PHPUnit,
and can be run in your web browser.
### Requirements
PHP Unit >= 3.5.6
#### Installation of PHPUnit
# Download the PHPUnit phar.
wget https://phar.phpunit.de/phpunit.phar
# You can just run it locally. (Preferred for Windows)
php phpunit.phar --version
# Or install it system-wide.
mv phpunit.phar phpunit
chmod +x phpunit
sudo mv phpunit /usr/local/bin
phpunit --version
## Test Suites:
util.php includes a phpunit config file, so just run `phpunit` from the working
directory to run the test suite.
```
phpunit
```
If you want code coverage reports, use the following:
```
phpunit --coverage-html ./report
```
+1183
View File
@@ -0,0 +1,1183 @@
<?php
date_default_timezone_set('UTC');
require_once dirname(__FILE__) . '/../util.php';
class VarDumpExperiment
{
public $public = 1;
protected $protected = 2;
private $private = 3;
public $data;
public function __construct()
{
$this->data = (object)array('a', 'b', 'c');
}
}
/**
* PHPUnit test case for the util.php library
*
* @author Brandon Wamboldt <brandon.wamboldt@gmail.com>
* @since 1.0.000
*/
class UtilityPHPTest extends PHPUnit_Framework_TestCase
{
/**
* Allows for the testing of private and protected methods.
*
* @param $name
* @return \ReflectionMethod
*/
protected static function getMethod($name)
{
$class = new \ReflectionClass('util');
$method = $class->getMethod($name);
$method->setAccessible(true);
return $method;
}
public function test_array_get()
{
$_GET = array();
$_GET['abc'] = 'def';
$_GET['nested'] = array( 'key1' => 'val1', 'key2' => 'val2', 'key3' => 'val3' );
// Looks for $array['abc']
$this->assertEquals( 'def', util::array_get( $_GET['abc'] ) );
// Looks for $array['nested']['key2']
$this->assertEquals( 'val2', util::array_get( $_GET['nested']['key2'] ) );
// Looks for $array['doesnotexist']
$this->assertEquals( 'defaultval', util::array_get( $_GET['doesnotexist'], 'defaultval' ) );
}
public function test_slugify()
{
$this->assertEquals( 'a-simple-title', util::slugify( 'A simple title' ) );
$this->assertEquals( 'this-post-it-has-a-dash', util::slugify( 'This post -- it has a dash' ) );
$this->assertEquals( '123-1251251', util::slugify( '123----1251251' ) );
$this->assertEquals( 'one23-1251251', util::slugify( '123----1251251', '-', true ) );
$this->assertEquals( 'a-simple-title', util::slugify( 'A simple title', '-' ) );
$this->assertEquals( 'this-post-it-has-a-dash', util::slugify( 'This post -- it has a dash', '-' ) );
$this->assertEquals( '123-1251251', util::slugify( '123----1251251', '-' ) );
$this->assertEquals( 'one23-1251251', util::slugify( '123----1251251', '-', true ) );
$this->assertEquals( 'a_simple_title', util::slugify( 'A simple title', '_' ) );
$this->assertEquals( 'this_post_it_has_a_dash', util::slugify( 'This post -- it has a dash', '_' ) );
$this->assertEquals( '123_1251251', util::slugify( '123----1251251', '_' ) );
$this->assertEquals( 'one23_1251251', util::slugify( '123----1251251', '_', true ) );
// Blank seperator test
$this->assertEquals( 'asimpletitle', util::slugify( 'A simple title', '' ) );
$this->assertEquals( 'thispostithasadash', util::slugify( 'This post -- it has a dash', '' ) );
$this->assertEquals( '1231251251', util::slugify( '123----1251251', '' ) );
$this->assertEquals( 'one231251251', util::slugify( '123----1251251', '', true ) );
// Test old parameter ordering for backwards compatability
error_reporting(E_ALL ^ E_USER_DEPRECATED);
$this->assertEquals( 'one23-1251251', util::slugify( '123----1251251', true ) );
$this->assertEquals( '123-1251251', util::slugify( '123----1251251', false ) );
}
public function test_seems_utf8()
{
// Test a valid UTF-8 sequence: "ÜTF-8 Fµñ".
$validUTF8 = "\xC3\x9CTF-8 F\xC2\xB5\xC3\xB1";
$this->assertTrue( util::seems_utf8( $validUTF8 ) );
$this->assertTrue( util::seems_utf8( "\xEF\xBF\xBD this has \xEF\xBF\xBD\xEF\xBF\xBD some invalid utf8 \xEF\xBF\xBD" ) );
// Test invalid UTF-8 sequences
$invalidUTF8 = "\xc3 this has \xe6\x9d some invalid utf8 \xe6";
$this->assertFalse( util::seems_utf8( $invalidUTF8 ) );
// And test some plain ASCII
$this->assertTrue( util::seems_utf8( 'The quick brown fox jumps over the lazy dog' ) );
// Test an invalid non-UTF-8 string.
if (function_exists('mb_convert_encoding')) {
mb_internal_encoding('UTF-8');
// Converts the 'ç' UTF-8 character to UCS-2LE
$utf8Char = pack('n', 50087);
$ucsChar = mb_convert_encoding($utf8Char, 'UCS-2LE', 'UTF-8');
// Ensure that PHP's internal encoding system isn't malconfigured.
$this->assertEquals( $utf8Char, 'ç', 'This PHP system\'s internal character set is not properly set as UTF-8.' );
$this->assertEquals( $utf8Char, pack('n', 50087), 'Something is wrong with your ICU unicode library.' );
// Test for not UTF-8.
$this->assertFalse( util::seems_utf8( $ucsChar) );
// Test the worker method.
$method = self::getMethod('seemsUtf8Regex');
$this->assertFalse($method->invoke(null, $invalidUTF8), 'util::seemsUtf8Regex did not properly detect invalid UTF-8.');
$this->assertTrue($method->invoke(null, $validUTF8), 'util::seemsUtf8Regex did not properly detect valid UTF-8.');
}
}
public function test_size_format()
{
$size = util::size_format( 512, 0 );
$this->assertEquals( '512 B', $size );
$size = util::size_format( 2048, 1 );
$this->assertEquals( '2.0 KiB', $size );
$size = util::size_format( 25151251, 2 );
$this->assertEquals( '23.99 MiB', $size );
$size = util::size_format( 19971597926, 2 );
$this->assertEquals( '18.60 GiB', $size );
$size = util::size_format( 2748779069440, 1 );
$this->assertEquals( '2.5 TiB', $size );
$size = util::size_format( 2.81475e15, 1 );
$this->assertEquals( '2.5 PiB', $size );
$size = util::size_format( 2.81475e19, 1 );
$this->assertEquals( '25000.0 PiB', $size );
}
public function test_maybe_serialize()
{
$obj = new stdClass();
$obj->prop1 = 'Hello';
$obj->prop2 = 'World';
$this->assertEquals( 'This is a string', util::maybe_serialize( 'This is a string' ) );
$this->assertEquals( 5.81, util::maybe_serialize( 5.81 ) );
$this->assertEquals( 'a:0:{}', util::maybe_serialize( array() ) );
$this->assertEquals( 'O:8:"stdClass":2:{s:5:"prop1";s:5:"Hello";s:5:"prop2";s:5:"World";}', util::maybe_serialize( $obj ) );
$this->assertEquals( 'a:4:{i:0;s:4:"test";i:1;s:4:"blah";s:5:"hello";s:5:"world";s:5:"array";O:8:"stdClass":2:{s:5:"prop1";s:5:"Hello";s:5:"prop2";s:5:"World";}}', util::maybe_serialize( array( 'test', 'blah', 'hello' => 'world', 'array' => $obj ) ) );
}
public function test_maybe_unserialize()
{
$obj = new stdClass();
$obj->prop1 = 'Hello';
$obj->prop2 = 'World';
$this->assertNull(util::maybe_unserialize(serialize(null)));
$this->assertFalse(util::maybe_unserialize(serialize(false)));
$this->assertEquals( 'This is a string', util::maybe_unserialize( 'This is a string' ) );
$this->assertEquals( 5.81, util::maybe_unserialize( 5.81 ) );
$this->assertEquals( array(), util::maybe_unserialize( 'a:0:{}' ) );
$this->assertEquals( $obj, util::maybe_unserialize( 'O:8:"stdClass":2:{s:5:"prop1";s:5:"Hello";s:5:"prop2";s:5:"World";}' ) );
$this->assertEquals( array( 'test', 'blah', 'hello' => 'world', 'array' => $obj ), util::maybe_unserialize( 'a:4:{i:0;s:4:"test";i:1;s:4:"blah";s:5:"hello";s:5:"world";s:5:"array";O:8:"stdClass":2:{s:5:"prop1";s:5:"Hello";s:5:"prop2";s:5:"World";}}' ) );
// Test a broken serialization.
$expectedData = array(
'Normal',
'High-value Char: '.chr(231).'a-va?', // High-value Char: ça-va? [in ISO-8859-1]
);
$brokenSerialization = 'a:2:{i:0;s:6:"Normal";i:1;s:23:"High-value Char: ▒a-va?";}';
$unserializedData = util::maybe_unserialize($brokenSerialization);
$this->assertEquals($expectedData[0], $unserializedData[0], 'Did not properly fix the broken serialized data.');
$this->assertEquals(substr($expectedData[1], 0, 10), substr($unserializedData[1], 0, 10), 'Did not properly fix the broken serialized data.');
// Test unfixable serialization.
$unfixableSerialization = 'a:2:{i:0;s:6:"Normal";}';
$this->assertEquals($unfixableSerialization, util::maybe_unserialize($unfixableSerialization), 'Somehow the [previously?] impossible happened and utilphp thinks it has unserialized an unfixable serialization.');
}
public function test_is_serialized()
{
$this->assertFalse( util::is_serialized(1) );
$this->assertFalse( util::is_serialized(null) );
$this->assertFalse( util::is_serialized( 's:4:"test;' ) );
$this->assertFalse( util::is_serialized( 'a:0:{}!' ) );
$this->assertFalse( util::is_serialized( 'a:0' ) );
$this->assertFalse( util::is_serialized( 'This is a string' ) );
$this->assertFalse( util::is_serialized( 'a string' ) );
$this->assertFalse( util::is_serialized( 'z:0;' ) );
$this->assertTrue( util::is_serialized( 'N;' ) );
$this->assertTrue( util::is_serialized( 'b:1;' ) );
$this->assertTrue( util::is_serialized( 'a:0:{}' ) );
$this->assertTrue( util::is_serialized( 'O:8:"stdClass":2:{s:5:"prop1";s:5:"Hello";s:5:"prop2";s:5:"World";}' ) );
}
public function test_fix_broken_serialization()
{
$expectedData = array(
'Normal',
'High-value Char: '.chr(231).'a-va?', // High-value Char: ça-va? [in ISO-8859-1]
);
$brokenSerialization = 'a:2:{i:0;s:6:"Normal";i:1;s:23:"High-value Char: ▒a-va?";}';
// Temporarily override error handling to ensure that this is, in fact, [still] a broken serialization.
{
$expectedError = array(
'errno' => 8,
'errstr' => 'unserialize(): Error at offset 55 of 60 bytes'
);
$reportedError = array();
set_error_handler(function ($errno, $errstr, $errfile, $errline, $errcontext) use (&$reportedError) {
$reportedError = compact('errno', 'errstr');
});
unserialize($brokenSerialization);
$this->assertEquals($expectedError['errno'], $reportedError['errno']);
// Because HHVM's unserialize() error message does not contain enough info to properly test.
if (!defined('HHVM_VERSION')) {
$this->assertEquals($expectedError['errstr'], $reportedError['errstr']);
}
restore_error_handler();
}
$fixedSerialization = util::fix_broken_serialization($brokenSerialization);
$unserializedData = unserialize($fixedSerialization);
$this->assertEquals($expectedData[0], $unserializedData[0], 'Did not properly fix the broken serialized data.');
$this->assertEquals(substr($expectedData[1], 0, 10), substr($unserializedData[1], 0, 10), 'Did not properly fix the broken serialized data.');
}
public function test_is_https()
{
$_SERVER['HTTPS'] = null;
$this->assertFalse( util::is_https() );
$_SERVER['HTTPS'] = 'on';
$this->assertTrue( util::is_https() );
}
public function test_add_query_arg()
{
// Regular tests
$this->assertEquals( '/app/admin/users?user=5', util::add_query_arg( 'user', 5, '/app/admin/users' ) );
$this->assertEquals( '/app/admin/users?user=5', util::add_query_arg( array( 'user' => 5 ), '/app/admin/users' ) );
$this->assertEquals( '/app/admin/users?user=5', util::add_query_arg( array( 'user' => 5 ), null, '/app/admin/users' ) );
$this->assertEquals( '/app/admin/users?action=edit&user=5', util::add_query_arg( 'user', 5, '/app/admin/users?action=edit' ) );
$this->assertEquals( '/app/admin/users?action=edit&user=5', util::add_query_arg( array( 'user' => 5 ), '/app/admin/users?action=edit' ) );
$this->assertEquals( '/app/admin/users?action=edit&tab=personal&user=5', util::add_query_arg( 'user', 5, '/app/admin/users?action=edit&tab=personal' ) );
$this->assertEquals( '/app/admin/users?action=edit&tab=personal&user=5', util::add_query_arg( array( 'user' => 5 ), '/app/admin/users?action=edit&tab=personal' ) );
// Ensure strips false.
$this->assertEquals('/index.php', util::add_query_arg('debug', false, '/index.php'));
// With a URL fragment
$this->assertEquals( '/app/admin/users?user=5#test', util::add_query_arg( 'user', 5, '/app/admin/users#test' ) );
// Full URL
$this->assertEquals( 'http://example.com/?a=b', util::add_query_arg( 'a', 'b', 'http://example.com' ) );
// Only the query string
$this->assertEquals( '?a=b&c=d', util::add_query_arg( 'c', 'd', '?a=b' ) );
$this->assertEquals( 'a=b&c=d', util::add_query_arg( 'c', 'd', 'a=b' ) );
// Url encoding test
$this->assertEquals( '/app/admin/users?param=containsa%26sym', util::add_query_arg( 'param', 'containsa&sym', '/app/admin/users' ) );
// If not provided, grab the URI from the server.
$_SERVER['REQUEST_URI'] = '/app/admin/users';
$this->assertEquals( '/app/admin/users?user=6', util::add_query_arg( array( 'user' => 6 ) ) );
$this->assertEquals( '/app/admin/users?user=7', util::add_query_arg( 'user', 7 ) );
}
public function test_remove_query_arg()
{
$this->assertEquals( '/app/admin/users', util::remove_query_arg( 'user', '/app/admin/users?user=5' ) );
$this->assertEquals( '/app/admin/users?action=edit', util::remove_query_arg( 'user', '/app/admin/users?action=edit&user=5' ) );
$this->assertEquals( '/app/admin/users?user=5', util::remove_query_arg( array( 'tab', 'action' ), '/app/admin/users?action=edit&tab=personal&user=5' ) );
}
public function test_http_build_url()
{
$url = 'http://user:pass@example.com:8080/path/?query#fragment';
$expected = 'http://example.com/';
$actual = util::http_build_url($url, array(), util::HTTP_URL_STRIP_ALL);
$this->assertEquals($expected, $actual);
$expected = 'http://example.com:8080/path/?query#fragment';
$actual = util::http_build_url($url, array(), util::HTTP_URL_STRIP_AUTH);
$this->assertEquals($expected, $actual);
$this->assertEquals('https://dev.example.com/', util::http_build_url('http://example.com/', array('scheme' => 'https', 'host' => 'dev.example.com')));
$this->assertEquals('http://example.com/#hi', util::http_build_url('http://example.com/', array('fragment' => 'hi'), util::HTTP_URL_REPLACE));
$this->assertEquals('http://example.com/page', util::http_build_url('http://example.com/', array('path' => 'page'), util::HTTP_URL_JOIN_PATH));
$this->assertEquals('http://example.com/page', util::http_build_url('http://example.com', array('path' => 'page'), util::HTTP_URL_JOIN_PATH));
$this->assertEquals('http://example.com/?hi=Bro', util::http_build_url('http://example.com/', array('query' => 'hi=Bro'), util::HTTP_URL_JOIN_QUERY));
$this->assertEquals('http://example.com/?show=1&hi=Bro', util::http_build_url('http://example.com/?show=1', array('query' => 'hi=Bro'), util::HTTP_URL_JOIN_QUERY));
$this->assertEquals('http://admin@example.com/', util::http_build_url('http://example.com/', array('user' => 'admin')));
$this->assertEquals('http://admin:1@example.com/', util::http_build_url('http://example.com/', array('user' => 'admin', 'pass' => '1')));
}
public function test_str_to_bool()
{
$this->assertTrue( util::str_to_bool( 'true' ) );
$this->assertTrue( util::str_to_bool( 'yes' ) );
$this->assertTrue( util::str_to_bool( 'y' ) );
$this->assertTrue( util::str_to_bool( 'oui' ) );
$this->assertTrue( util::str_to_bool( 'vrai' ) );
$this->assertFalse( util::str_to_bool( 'false' ) );
$this->assertFalse( util::str_to_bool( 'no' ) );
$this->assertFalse( util::str_to_bool( 'n' ) );
$this->assertFalse( util::str_to_bool( 'non' ) );
$this->assertFalse( util::str_to_bool( 'faux' ) );
$this->assertFalse( util::str_to_bool( 'test' , false) );
}
public function test_array_pluck()
{
$array = array(
array(
'name' => 'Bob',
'age' => 37
),
array(
'name' => 'Fred',
'age' => 37
),
array(
'name' => 'Jane',
'age' => 29
),
array(
'name' => 'Brandon',
'age' => 20
),
array(
'age' => 41
)
);
$obj_array = array(
'bob' => (object) array(
'name' => 'Bob',
'age' => 37
),
'fred' => (object) array(
'name' => 'Fred',
'age' => 37
),
'jane' => (object) array(
'name' => 'Jane',
'age' => 29
),
'brandon' => (object) array(
'name' => 'Brandon',
'age' => 20
),
'invalid' => (object) array(
'age' => 41
)
);
$obj_array_expect = array(
'bob' => 'Bob',
'fred' => 'Fred',
'jane' => 'Jane',
'brandon' => 'Brandon'
);
$this->assertEquals( array( 'Bob', 'Fred', 'Jane', 'Brandon' ), util::array_pluck( $array, 'name' ) );
$this->assertEquals( array( 'Bob', 'Fred', 'Jane', 'Brandon', array( 'age' => 41 ) ), util::array_pluck( $array, 'name', TRUE, FALSE ) );
$this->assertEquals( $obj_array_expect, util::array_pluck( $obj_array, 'name' ) );
$this->assertEquals( array( 'Bob', 'Fred', 'Jane', 'Brandon' ), util::array_pluck( $obj_array, 'name', FALSE ) );
$expected = array('Bob', 'Fred', 'Jane', 'Brandon', 'invalid' => (object)array('age' => 41));
$this->assertEquals($expected, util::array_pluck($obj_array, 'name', FALSE, FALSE));
$expected = array('Bob', 'Fred', 'Jane', 'Brandon', array('age' => 41));
$this->assertEquals($expected, util::array_pluck($array, 'name', false, false));
}
public function test_htmlentities()
{
$this->assertEquals( 'One &amp; Two', util::htmlentities( 'One & Two' ) );
$this->assertEquals( 'One &amp; Two', util::htmlentities( 'One &amp; Two', TRUE ) );
}
public function test_htmlspecialchars()
{
$this->assertEquals( 'One &amp; Two', util::htmlspecialchars( 'One & Two' ) );
$this->assertEquals( 'One &amp; Two', util::htmlspecialchars( 'One &amp; Two', TRUE ) );
}
public function test_remove_accents()
{
$this->assertEquals( 'A', util::remove_accents( "\xC3\x81" ) );
$this->assertEquals( 'e', util::remove_accents( "\xC4\x97" ) );
$this->assertEquals( 'U', util::remove_accents( "\xC3\x9C" ) );
$this->assertEquals( 'Ae', util::remove_accents( "Ä", 'de' ) );
$this->assertEquals( 'OEoeAEDHTHssaedhth', util::remove_accents(chr(140) . chr(156) . chr(198) . chr(208) . chr(222) . chr(223) . chr(230) . chr(240) . chr(254)));
}
public function test_zero_pad()
{
$this->assertEquals( '00000341', util::zero_pad( 341, 8 ) );
$this->assertEquals( '341', util::zero_pad( 341, 1 ) );
}
public function test_human_time_diff()
{
$this->assertEquals( '1 second ago', util::human_time_diff( time() - 1 ) );
$this->assertEquals( '30 seconds ago', util::human_time_diff( time() - 30 ) );
$this->assertEquals( '1 minute ago', util::human_time_diff( time() - ( util::SECONDS_IN_A_MINUTE * 1.4 ) ) );
$this->assertEquals( '5 minutes ago', util::human_time_diff( time() - ( util::SECONDS_IN_A_MINUTE * 5 ) ) );
$this->assertEquals( '1 hour ago', util::human_time_diff( time() - ( util::SECONDS_IN_AN_HOUR ) ) );
$this->assertEquals( '2 hours ago', util::human_time_diff( time() - ( util::SECONDS_IN_AN_HOUR * 2 ) ) );
$this->assertEquals( '1 day ago', util::human_time_diff( time() - ( util::SECONDS_IN_AN_HOUR * 24 ) ) );
$this->assertEquals( '5 days ago', util::human_time_diff( time() - ( util::SECONDS_IN_AN_HOUR * 24 * 5 ) ) );
$this->assertEquals( '1 week ago', util::human_time_diff( time() - ( util::SECONDS_IN_AN_HOUR * 24 * 7 ) ) );
$this->assertEquals( '2 weeks ago', util::human_time_diff( time() - ( util::SECONDS_IN_AN_HOUR * 24 * 14 ) ) );
$this->assertEquals( '1 month ago', util::human_time_diff( time() - ( util::SECONDS_IN_A_WEEK * 5 ) ) );
$this->assertEquals( '2 months ago', util::human_time_diff( time() - ( util::SECONDS_IN_A_WEEK * 10 ) ) );
$this->assertEquals( '1 year ago', util::human_time_diff( time() - ( util::SECONDS_IN_A_MONTH * 15 ) ) );
$this->assertEquals( '2 years ago', util::human_time_diff( time() - ( util::SECONDS_IN_A_MONTH * 36 ) ) );
$this->assertEquals( '11 years ago', util::human_time_diff( time() - ( util::SECONDS_IN_A_MONTH * 140 ) ) );
$this->assertEquals( 'fifteen minutes ago', util::human_time_diff( time() - ( util::SECONDS_IN_A_MINUTE * 15 ), '', TRUE ) );
}
public function test_number_to_word()
{
try {
util::number_to_word('junk data');
$this->fail('Accepted junk data');
} catch(\LogicException $e) {
$this->assertEquals('Not a number', $e->getMessage());
}
// Partially numeric.
$this->assertEquals('', util::number_to_word('1a'));
// Decimals
$this->assertEquals( 'five point zero five', util::number_to_word('5.05') );
$this->assertEquals( 'zero point eight', util::number_to_word( 0.8 ) );
// Integers
$this->assertEquals( 'positive one', util::number_to_word( '+1' ) );
$this->assertEquals( 'negative twelve', util::number_to_word( -12 ) );
$this->assertEquals( 'one', util::number_to_word( 1 ) );
$this->assertEquals( 'five', util::number_to_word( 5 ) );
$this->assertEquals( 'fifteen', util::number_to_word( 15 ) );
$this->assertEquals( 'twenty-one', util::number_to_word( 21 ) );
$this->assertEquals( 'thirty-two', util::number_to_word( 32 ) );
$this->assertEquals( 'forty-three', util::number_to_word( 43 ) );
$this->assertEquals( 'fifty-four', util::number_to_word( 54 ) );
$this->assertEquals( 'sixty-six', util::number_to_word( 66 ) );
$this->assertEquals( 'seventy-seven', util::number_to_word( 77 ) );
$this->assertEquals( 'eighty-eight', util::number_to_word( 88 ) );
$this->assertEquals( 'ninety-nine', util::number_to_word( 99 ) );
$this->assertEquals( 'one hundred and thirty-six', util::number_to_word( 136 ) );
$this->assertEquals( 'ten', util::number_to_word( 10 ) );
$this->assertEquals( 'twenty', util::number_to_word( 20 ) );
$this->assertEquals( 'thirty', util::number_to_word( 30 ) );
$this->assertEquals( 'forty', util::number_to_word( 40 ) );
$this->assertEquals( 'fifty', util::number_to_word( 50 ) );
$this->assertEquals( 'sixty', util::number_to_word( 60 ) );
$this->assertEquals( 'seventy', util::number_to_word( 70 ) );
$this->assertEquals( 'eighty', util::number_to_word( 80 ) );
$this->assertEquals( 'ninety', util::number_to_word( 90 ) );
$this->assertEquals( 'eleven', util::number_to_word( 11 ) );
$this->assertEquals( 'thirteen', util::number_to_word( 13 ) );
$this->assertEquals( 'fourteen', util::number_to_word( 14 ) );
$this->assertEquals( 'fifteen', util::number_to_word( 15 ) );
$this->assertEquals( 'sixteen', util::number_to_word( 16 ) );
$this->assertEquals( 'seventeen', util::number_to_word( 17 ) );
$this->assertEquals( 'eighteen', util::number_to_word( 18 ) );
$this->assertEquals( 'nineteen', util::number_to_word( 19 ) );
$this->assertEquals( 'one thousand', util::number_to_word( 1000 ) );
$this->assertEquals( 'one million', util::number_to_word( 1000000 ) );
$this->assertEquals( 'one billion', util::number_to_word( 1000000000 ) );
$this->assertEquals( 'one trillion', util::number_to_word( 1000000000000 ) );
$this->assertEquals( 'one quadrillion', util::number_to_word( '1000000000000000' ) );
$this->assertEquals( 'one quintrillion', util::number_to_word( '1000000000000000000' ) );
$this->assertEquals( 'one sextillion', util::number_to_word( '1000000000000000000000' ) );
$this->assertEquals( 'one septillion', util::number_to_word( '1000000000000000000000000' ) );
$this->assertEquals( 'one octillion', util::number_to_word( '1000000000000000000000000000' ) );
$this->assertEquals( 'one nonillion', util::number_to_word( '1000000000000000000000000000000' ) );
$this->assertEquals( 'one decillion', util::number_to_word( '1000000000000000000000000000000000' ) );
$this->assertEquals( 'one', util::number_to_word( '1000000000000000000000000000000000000000000' ) );
}
public function test_array_search_deep()
{
$users = array(
1 => (object) array( 'username' => 'brandon', 'age' => 20 ),
2 => (object) array( 'username' => 'matt', 'age' => 27 ),
3 => (object) array( 'username' => 'jane', 'age' => 53 ),
4 => (object) array( 'username' => 'john', 'age' => 41 ),
5 => (object) array( 'username' => 'steve', 'age' => 11 ),
6 => (object) array( 'username' => 'fred', 'age' => 42 ),
7 => (object) array( 'username' => 'rasmus', 'age' => 21 ),
8 => (object) array( 'username' => 'don', 'age' => 15 ),
9 => array( 'username' => 'darcy', 'age' => 33 ),
);
$test = array(
1 => 'brandon',
2 => 'devon',
3 => array( 'troy' ),
4 => 'annie'
);
$this->assertFalse( util::array_search_deep( $test, 'bob' ) );
$this->assertEquals( 3, util::array_search_deep( $test, 'troy' ) );
$this->assertEquals( 4, util::array_search_deep( $test, 'annie' ) );
$this->assertEquals( 2, util::array_search_deep( $test, 'devon', 'devon' ) );
$this->assertEquals( 7, util::array_search_deep( $users, 'rasmus', 'username' ) );
$this->assertEquals( 9, util::array_search_deep( $users, 'darcy', 'username' ) );
$this->assertEquals( 1, util::array_search_deep( $users, 'brandon' ) );
}
public function test_array_map_deep()
{
$input = array(
'<',
'abc',
'>',
'def',
array( '&', 'test', '123' ),
(object) array( 'hey', '<>' )
);
$expect = array(
'&lt;',
'abc',
'&gt;',
'def',
array( '&amp;', 'test', '123' ),
(object) array( 'hey', '<>' )
);
$this->assertEquals( $expect, util::array_map_deep( $input, 'htmlentities' ) );
}
public function test_random_string()
{
// Make sure the generated string contains only human friendly characters and is 30 characters long
$str = util::random_string( 30 );
$this->assertTrue( (bool) preg_match( '/^([ABCDEFGHJKLMNPQRSTUVWXYZabcdefhjkmnprstuvwxyz23456789]{30})$/', $str ) );
// Make sure the generated string is 30 characters long
$str = util::random_string( 30, false, true );
$this->assertTrue( strlen( $str ) === 30, 'random_string produced an invalid length string' );
// Make sure the generated string is 120 characters long
$str = util::random_string( 120 );
$this->assertTrue(strlen( $str ) === 120, 'random_string produced an invalid length string');
// Make sure the string doesn't contain duplicate letters
$str = util::random_string( 53, true, false, true );
$this->assertTrue(strlen($str) === 53, 'random_string produced an invalid length string');
$this->assertTrue(count(array_unique(str_split($str))) === strlen($str), 'random_string produced a string with duplicate characters');
// Longer length than characters available
try {
$str = util::random_string( 55, true, false, true );
$this->assertTrue( false );
} catch (Exception $e) {
$this->assertTrue( true );
}
// Test secure variant
$str = util::secure_random_string(16);
$this->assertTrue(strlen($str) === 16);
// Longer length than characters available
try {
$str = util::secure_random_string(0);
$this->assertTrue(false);
} catch (Exception $e) {
$this->assertTrue(true);
}
}
public function test_match_string()
{
$this->assertTrue( util::match_string('a', 'a') );
$this->assertFalse( util::match_string('a', ' a') );
$this->assertFalse( util::match_string('/', '/something') );
$this->assertTrue( util::match_string('test/*', 'test/first/second') );
$this->assertTrue( util::match_string('*/test', 'first/second/test') );
$this->assertFalse( util::match_string('first/', 'first/second/test') );
$this->assertFalse( util::match_string('test', 'TEST') );
$this->assertTrue( util::match_string('test', 'TEST', false) );
}
public function test_validate_email()
{
$this->assertTrue( util::validate_email( 'john.smith@gmail.com' ) );
$this->assertTrue( util::validate_email( 'john.smith+label@gmail.com' ) );
$this->assertTrue( util::validate_email( 'john.smith@gmail.co.uk' ) );
}
public function test_safe_truncate()
{
$this->assertEquals( 'The quick brown fox...', util::safe_truncate( 'The quick brown fox jumps over the lazy dog', 24 ) );
$this->assertEquals( 'The quick brown fox jumps over the lazy dog', util::safe_truncate( 'The quick brown fox jumps over the lazy dog', 55 ) );
$this->assertEquals( 'Th...', util::safe_truncate( 'The quick brown fox jumps over the lazy dog', 2 ) );
$this->assertEquals( 'The...', util::safe_truncate( 'The quick brown fox jumps over the lazy dog', 3 ) );
$this->assertEquals( 'The...', util::safe_truncate( 'The quick brown fox jumps over the lazy dog', 7 ) );
}
public function test_limit_characters()
{
$this->assertEquals( 'The quick brown fox jump...', util::limit_characters( 'The quick brown fox jumps over the lazy dog', 24 ) );
$this->assertEquals( 'The quick brown fox jumps over the lazy dog', util::limit_characters( 'The quick brown fox jumps over the lazy dog', 55 ) );
$this->assertEquals( 'Th...', util::limit_characters( 'The quick brown fox jumps over the lazy dog', 2 ) );
$this->assertEquals( 'The...', util::limit_characters( 'The quick brown fox jumps over the lazy dog', 3 ) );
$this->assertEquals( 'The qui...', util::limit_characters( 'The quick brown fox jumps over the lazy dog', 7 ) );
$this->assertEquals( 'The quick brown fox jumps over the lazy dog', util::limit_characters( 'The quick brown fox jumps over the lazy dog', 150 ) );
}
public function test_limit_words()
{
$this->assertEquals( 'The quick brown...', util::limit_words( 'The quick brown fox jumps over the lazy dog', 3 ) );
$this->assertEquals( 'The quick brown fox jumps...', util::limit_words( 'The quick brown fox jumps over the lazy dog', 5 ) );
$this->assertEquals( 'The...', util::limit_words( 'The quick brown fox jumps over the lazy dog', 1 ) );
$this->assertEquals( 'The quick brown fox jumps over the lazy dog', util::limit_words( 'The quick brown fox jumps over the lazy dog', 90 ) );
$this->assertEquals( 'The quick brown fox jumps over the...', util::limit_words( 'The quick brown fox jumps over the lazy dog', 7 ) );
}
public function test_ordinal()
{
$this->assertEquals( '1st', util::ordinal( 1 ) );
$this->assertEquals( '2nd', util::ordinal( 2 ) );
$this->assertEquals( '3rd', util::ordinal( 3 ) );
$this->assertEquals( '4th', util::ordinal( 4 ) );
$this->assertEquals( '5th', util::ordinal( 5 ) );
$this->assertEquals( '6th', util::ordinal( 6 ) );
$this->assertEquals( '7th', util::ordinal( 7 ) );
$this->assertEquals( '8th', util::ordinal( 8 ) );
$this->assertEquals( '9th', util::ordinal( 9 ) );
$this->assertEquals( '22nd', util::ordinal( 22 ) );
$this->assertEquals( '23rd', util::ordinal( 23 ) );
$this->assertEquals( '143rd', util::ordinal( 143 ) );
}
public function test_array_first()
{
$test = array( 'a' => array( 'a', 'b', 'c' ) );
$this->assertEquals( 'a', util::array_first( util::array_get( $test['a'] ) ) );
}
public function test_array_first_key()
{
$test = array( 'a' => array( 'a' => 'b', 'c' => 'd' ) );
$this->assertEquals( 'a', util::array_first_key( util::array_get( $test['a'] ) ) );
}
public function test_array_last()
{
$test = array( 'a' => array( 'a', 'b', 'c' ) );
$this->assertEquals( 'c', util::array_last( util::array_get( $test['a'] ) ) );
}
public function test_array_last_key()
{
$test = array( 'a' => array( 'a' => 'b', 'c' => 'd' ) );
$this->assertEquals( 'c', util::array_last_key( util::array_get( $test['a'] ) ) );
}
public function test_array_flatten()
{
$input = array( 'a', 'b', 'c', 'd', array( 'first' => 'e', 'f', 'second' => 'g', array( 'h', 'third' => 'i', array( array( array( array( 'j', 'k', 'l' ) ) ) ) ) ) );
$expectNoKeys = range( 'a', 'l' );
$expectWithKeys = array(
'a', 'b', 'c', 'd',
'first' => 'e',
'f',
'second' => 'g',
'h',
'third' => 'i',
'j', 'k', 'l'
);
$this->assertEquals( $expectWithKeys, util::array_flatten( $input ) );
$this->assertEquals( $expectNoKeys, util::array_flatten( $input, false ) );
$this->assertEquals( $expectWithKeys, util::array_flatten( $input, true ) );
}
public function test_strip_space()
{
$input = ' The quick brown fox jumps over the lazy dog ';
$expect = 'Thequickbrownfoxjumpsoverthelazydog';
$this->assertEquals($expect, Util::strip_space($input));
}
public function test_sanitize_string()
{
$input = ' Benoit! à New-York? j’ai perçu 1 % : Qu’as-tu "gagné" chez M. V. Noël? Dix francs.';
$expect = 'benoitanewyorkjaipercu1quastugagnechezmvnoeldixfrancs';
$this->assertEquals($expect, Util::sanitize_string($input));
}
public function test_get_gravatar()
{
$_SERVER['HTTPS'] = 'on';
$this->assertEquals('https://secure.gravatar.com/avatar/a4bf5bbb9feaa2713d99a3b52ab80024?s=32', util::get_gravatar('john.doe@example.org'));
$this->assertEquals('https://secure.gravatar.com/avatar/a4bf5bbb9feaa2713d99a3b52ab80024?s=128', util::get_gravatar('john.doe@example.org', 128));
$_SERVER['HTTPS'] = 'off';
$this->assertEquals('http://www.gravatar.com/avatar/a4bf5bbb9feaa2713d99a3b52ab80024?s=32', util::get_gravatar('john.doe@example.org'));
$this->assertEquals('http://www.gravatar.com/avatar/a4bf5bbb9feaa2713d99a3b52ab80024?s=128', util::get_gravatar('john.doe@example.org', 128));
}
public function test_get_client_ip()
{
$_SERVER['REMOTE_ADDR'] = '192.168.30.152';
$_SERVER['HTTP_CLIENT_IP'] = '192.168.30.153';
$_SERVER['HTTP_X_FORWARDED_FOR'] = '192.168.30.154';
$this->assertEquals('192.168.30.152', util::get_client_ip());
$this->assertEquals('192.168.30.153', util::get_client_ip(true));
unset($_SERVER['HTTP_CLIENT_IP']);
$this->assertEquals('192.168.30.154', util::get_client_ip(true));
unset($_SERVER['HTTP_X_FORWARDED_FOR']);
$this->assertEquals('192.168.30.152', util::get_client_ip(true));
}
public function test_full_permissions()
{
// Text a non-existant file.
$this->assertFalse(util::full_permissions('faker-123.blah'), 'Gave a permission value for a non-existant file.');
// Test an existing file.
$expected = '-rw-rw-rw-';
$tempFile = tempnam(sys_get_temp_dir(), 'foo');
$this->assertTrue(chmod($tempFile, 0666), 'Oops. Could not change temp file\'s permissions to 0666.');
$this->assertEquals($expected, util::full_permissions($tempFile), 'Could not properly obtain permissions of an existing file.');
unlink($tempFile);
$this->assertEquals('lr--r--r--', util::full_permissions('fake-file-222', octdec('120444')));
$this->assertEquals('ur--r--r--', util::full_permissions('fake-file-222', octdec('000444')));
$this->assertEquals('srwxr-xr-x', util::full_permissions('fake-file-222', octdec('140755')));
$this->assertEquals('drwxr-xr-x', util::full_permissions('fake-file-222', octdec('40755')));
$this->assertEquals('brw-rw----', util::full_permissions('fake-file-222', octdec('60660')));
$this->assertEquals('crw-rw----', util::full_permissions('fake-file-222', octdec('20660')));
$this->assertEquals('prw-rw----', util::full_permissions('fake-file-222', octdec('10660')));
$this->assertEquals('---x------', util::full_permissions('fake-file-222', octdec('100100')));
$this->assertEquals('--w-------', util::full_permissions('fake-file-222', octdec('100200')));
$this->assertEquals('--wx------', util::full_permissions('fake-file-222', octdec('100300')));
$this->assertEquals('-r--------', util::full_permissions('fake-file-222', octdec('100400')));
$this->assertEquals('-r-x------', util::full_permissions('fake-file-222', octdec('100500')));
$this->assertEquals('-rw-------', util::full_permissions('fake-file-222', octdec('100600')));
$this->assertEquals('-rwx------', util::full_permissions('fake-file-222', octdec('100700')));
// Windows does not have the concept of /.
if (!defined('PHP_WINDOWS_VERSION_MAJOR')) {
$this->assertEquals('drwxr-xr-x', util::full_permissions('/'));
}
}
public function test_array_clean()
{
$input = array( 'a', 'b', '', null, false, 0);
$expect = array('a', 'b');
$this->assertEquals($expect, Util::array_clean($input));
}
public function test_var_dump_plain()
{
$input = 'var';
$expect = '<span style="color:#588bff;">string</span><span style="color:#999;">(</span>3<span style="color:#999;">)</span> <strong>"var"</strong>';
$this->assertEquals($expect, Util::var_dump_plain($input, true));
$input = true;
$expect = '<span style="color:#588bff;">bool</span><span style="color:#999;">(</span><strong>true</strong><span style="color:#999;">)</span>';
$this->assertEquals($expect, Util::var_dump_plain($input, true));
$input = 1;
$expect = '<span style="color:#588bff;">int</span><span style="color:#999;">(</span><strong>1</strong><span style="color:#999;">)</span>';
$this->assertEquals($expect, Util::var_dump_plain($input, true));
$input = 1.5;
$expect = '<span style="color:#588bff;">float</span><span style="color:#999;">(</span><strong>1.5</strong><span style="color:#999;">)</span>';
$this->assertEquals($expect, Util::var_dump_plain($input, true));
$input = null;
$expect = '<strong>NULL</strong>';
$this->assertEquals($expect, Util::var_dump_plain($input, true));
$input = fopen('php://memory', 'r');
$expect = '<span style="color:#588bff;">resource</span>("stream") <strong>"' . $input . '"</strong>';
$this->assertEquals($expect, Util::var_dump_plain($input, -1));
fclose($input);
// Test complex arrays.
$input = array(1, 2, 4, 6, 10 => 20, 100 => 200);
$actual = util::var_dump_plain($input, true);
$this->assertContains('<img id="include-php-', $actual);
$this->assertContains('<br /> 100 => <span', $actual);
$this->assertContains('(</span><strong>200</strong><span style="color:#999;">)', $actual);
// Test complex objects.
$experiment = new VarDumpExperiment();
$actual = util::var_dump_plain($experiment, true);
$this->assertContains('1 => <span style="color:#588bff;">string</span><span style="color:#999;">(</span>1<span style="color:#999;">', $actual);
}
public function test_var_dump()
{
$input = 'var';
$expect = '<pre style="margin-bottom: 18px;background: #f7f7f9;border: 1px solid #e1e1e8;padding: 8px;border-radius: 4px;-moz-border-radius: 4px;-webkit-border radius: 4px;display: block;font-size: 12.05px;white-space: pre-wrap;word-wrap: break-word;color: #333;font-family: Menlo,Monaco,Consolas,\'Courier New\',monospace;"><span style="color:#588bff;">string</span><span style="color:#999;">(</span>3<span style="color:#999;">)</span> <strong>"var"</strong></pre>';
// Ensure the proper output is returned
$this->assertEquals($expect, Util::var_dump($input, true));
// Ensure the proper output is actually outputted
$this->expectOutputString($expect);
util::var_dump($input);
// Ensure we avoid infinite recursion on recursive arrays
$a = array('a' => 'value a', 'b' => 'value b');
$b = array('test' => &$a);
$c = array('a' => &$a, 'b' => &$b);
$a['c'] = &$c;
$b['c'] = &$c;
$this->assertContains('*RECURSION DETECTED*', Util::var_dump($c, true));
// Ensure we avoid infinite recursion on recursive objects
$a = (object) array('a' => 'value a', 'b' => 'value b');
$b = (object) array('test' => &$a);
$c = (object) array('a' => &$a, 'b' => &$b);
$a->c = &$c;
$b->c = &$c;
$this->assertContains('*RECURSION DETECTED*', Util::var_dump($c, true));
// Test class scoping.
$experiment = new VarDumpExperiment();
$actual = util::var_dump($experiment, true);
$snippet = substr($actual, strrpos($actual, 'display:inline'));
$this->assertContains('"public"', $snippet);
$this->assertContains('"protected:protected"', $snippet);
$this->assertContains('"private:VarDumpExperiment:private"', $actual);
}
public function test_linkify()
{
$input = 'great websites: http://www.google.com?param=test and http://yahoo.com/a/nested/folder';
$expect = 'great websites: <a href="http://www.google.com?param=test">http://www.google.com?param=test</a> and <a href="http://yahoo.com/a/nested/folder">http://yahoo.com/a/nested/folder</a>';
$this->assertEquals($expect, Util::linkify($input));
$this->assertEquals($expect, util::linkify($expect), 'linkify() tried to double linkify an href.');
}
public function test_start_with()
{
$this->assertTrue(Util::starts_with('start a string', 'start a'));
$this->assertFalse(Util::starts_with('start a string', 'string'));
}
public function test_end_with()
{
$this->assertTrue(Util::ends_with('start a string', 'a string'));
$this->assertFalse(Util::ends_with('start a string', 'start'));
}
public function test_contains()
{
$this->assertTrue(Util::str_contains('start a string', 'a string'));
$this->assertFalse(Util::str_contains('start a string', 'Start'));
}
public function test_iContains()
{
$this->assertTrue(Util::str_icontains('start a string', 'a string'));
$this->assertTrue(Util::str_icontains('start a string', 'Start'));
}
public function test_get_file_ext()
{
$input = 'a_pdf_fil.pdf';
$expect = 'pdf';
$this->assertEquals($expect, Util::get_file_ext($input));
}
public function test_rmdir()
{
$dirname = dirname(__FILE__);
// Test deleting a non-existant directory
$this->assertFalse(file_exists($dirname . '/test1'));
$this->assertTrue(util::rmdir($dirname . '/test1'));
// Test deleting an empty directory
$dir = $dirname . '/test2';
mkdir($dir);
$this->assertTrue(is_dir($dir));
if (is_dir($dir)) {
util::rmdir($dir);
$this->assertFalse(is_dir($dir));
}
// Test deleting a non-empty directory
$dir = $dirname . '/test3';
$file = $dirname . '/test3/test.txt';
mkdir($dir);
touch($file);
$this->assertTrue(is_dir($dir));
$this->assertTrue(is_file($file));
if (is_dir($dir)) {
util::rmdir($dir);
$this->assertFalse(is_dir($dir));
$this->assertFalse(is_file($file));
}
// Test deleting a non-directory path
$file = $dirname . '/test4.txt';
touch($file);
try {
$str = util::rmdir($file);
$this->assertTrue(false);
} catch (\Exception $e) {
$this->assertTrue(true);
}
unlink($file);
// Test deleting a nested directory
$dir1 = $dirname . '/test5';
$dir2 = $dirname . '/test5/nested_dir';
$file1 = $dir1 . '/file1.txt';
$file2 = $dir2 . '/file2.txt';
mkdir($dir1);
mkdir($dir2);
touch($file1);
touch($file2);
$this->assertTrue(is_dir($dir1));
$this->assertTrue(is_dir($dir2));
$this->assertTrue(is_file($file1));
$this->assertTrue(is_file($file2));
if (is_dir($dir1)) {
util::rmdir($dir1);
$this->assertFalse(is_dir($dir1));
$this->assertFalse(is_dir($dir2));
$this->assertFalse(is_file($file1));
$this->assertFalse(is_file($file2));
}
// Test symlink traversal.
$dir = $dirname . '/test6';
$nestedDir = "$dir/nested";
$symlink = "$dir/nested-symlink";
mkdir($dir);
mkdir($nestedDir);
$symlinkStatus = symlink($nestedDir, $symlink);
$this->assertTrue($symlinkStatus, 'The test system does not support making symlinks.');
if (!$symlink) {
return;
}
$this->assertTrue(util::rmdir($symlink, true), 'Could not delete a symlinked directory.');
$this->assertFalse(file_exists($symlink), 'Could not delete a symlinked directory.');
util::rmdir($dir, true);
$this->assertFalse(is_dir($dir), 'Could not delete a directory with a symlinked directory inside of it.');
}
public function test_get_current_url()
{
$expected = 'http://test.dev/test.php?foo=bar';
$expectedAuth = 'http://admin:123@test.dev/test.php?foo=bar';
$expectedPort = 'http://test.dev:443/test.php?foo=bar';
$expectedPort2 = 'https://test.dev:80/test.php?foo=bar';
$expectedSSL = 'https://test.dev/test.php?foo=bar';
$_SERVER['HTTP_HOST'] = 'test.dev';
$_SERVER['SERVER_PORT'] = 80;
$_SERVER['REQUEST_URI'] = '/test.php?foo=bar';
$_SERVER['QUERY_STRING'] = 'foo=bar';
$_SERVER['PHP_SELF'] = '/test.php';
// Test regular.
$this->assertEquals($expected, util::get_current_url());
// Test server auth.
$_SERVER['PHP_AUTH_USER'] = 'admin';
$_SERVER['PHP_AUTH_PW'] = '123';
$this->assertEquals($expectedAuth, util::get_current_url());
unset($_SERVER['PHP_AUTH_USER']);
unset($_SERVER['PHP_AUTH_PW']);
// Test port.
$_SERVER['SERVER_PORT'] = 443;
$this->assertEquals($expectedPort, util::get_current_url());
// Test SSL.
$_SERVER['HTTPS'] = 'on';
$this->assertEquals($expectedSSL, util::get_current_url());
$_SERVER['SERVER_PORT'] = 80;
$this->assertEquals($expectedPort2, util::get_current_url());
unset($_SERVER['HTTPS']);
// Test no $_SERVER['REQUEST_URI'] (e.g., MS IIS).
unset($_SERVER['REQUEST_URI']);
$this->assertEquals($expected, util::get_current_url());
}
public function test_set_writable()
{
if (strncasecmp(PHP_OS, 'WIN', 3) === 0) {
$this->markTestSkipped('This functionality is not working on Windows.');
}
if (posix_geteuid() === 0) {
$this->markTestSkipped('These tests don\'t work when run as root');
}
$this->assertFalse(util::set_writable('/no/such/file'));
// Create a file to test with
$dirname = dirname(__FILE__);
$file = $dirname . '/test7';
touch($file);
chmod($file, 0644);
// The file is owned by us so it should be writable
$this->assertTrue(is_writable($file));
$this->assertEquals('-rw-r--r--', util::full_permissions($file));
// Toggle writable bit off for us
util::set_writable($file, false);
clearstatcache();
$this->assertFalse(is_writable($file));
$this->assertEquals('-r--r--r--', util::full_permissions($file));
// Toggle writable bit back on for us
util::set_writable($file, true);
clearstatcache();
$this->assertTrue(is_writable($file));
$this->assertEquals('-rw-r--r--', util::full_permissions($file));
unlink($file);
}
public function test_set_readable()
{
if (strncasecmp(PHP_OS, 'WIN', 3) === 0) {
$this->markTestSkipped('This functionality is not working on Windows.');
}
if (posix_geteuid() === 0) {
$this->markTestSkipped('These tests don\'t work when run as root');
}
$this->assertFalse(util::set_readable('/no/such/file'));
$dirname = dirname(__FILE__);
$file = $dirname . '/test8';
touch($file);
$this->assertTrue(is_readable($file));
util::set_readable($file, false);
clearstatcache();
$this->assertFalse(is_readable($file));
util::set_readable($file, true);
clearstatcache();
$this->assertTrue(is_readable($file));
unlink($file);
}
public function test_set_executable()
{
if (strncasecmp(PHP_OS, 'WIN', 3) === 0) {
$this->markTestSkipped('This functionality is not working on Windows.');
}
if (posix_geteuid() === 0) {
$this->markTestSkipped('These tests don\'t work when run as root');
}
$this->assertFalse(util::set_executable('/no/such/file'));
$dirname = dirname(__FILE__);
$file = $dirname . '/test9';
touch($file);
$this->assertFalse(is_executable($file));
util::set_executable($file, true);
clearstatcache();
$this->assertTrue(is_executable($file));
util::set_executable($file, false);
clearstatcache();
$this->assertFalse(is_executable($file));
unlink($file);
}
public function test_directory_size() {
$dirname = dirname(__FILE__);
$dir = $dirname .'/dir1';
mkdir($dir);
$file1 = $dir .'/file1';
file_put_contents($file1, '1234567890');
$file2 = $dir .'/file2';
file_put_contents($file2, range('a', 'z'));
$this->assertEquals(10 + 26, util::directory_size($dir));
util::rmdir($dir);
}
public function test_get_user_directory() {
// Test for OS Default.
$this->assertTrue(is_writable(util::get_user_directory()));
$oldServer = $_SERVER;
unset($_SERVER);
// Test for UNIX.
$_SERVER['HOME'] = '/home/unknown';
$this->assertEquals($_SERVER['HOME'], util::get_user_directory(), 'Could not get the user\'s home directory in UNIX.');
unset($_SERVER);
// Test for Windows.
$expected = 'X:\Users\ThisUser';
$_SERVER['HOMEDRIVE'] = 'X:';
$_SERVER['HOMEPATH'] = '\Users\ThisUser';
$this->assertEquals($expected, util::get_user_directory(), 'Could not get the user\'s home directory in Windows.');
// In case the tests are not being run in isolation.
$_SERVER = $oldServer;
}
public function test_directory_contents() {
$dirname = dirname(__FILE__);
$dir = $dirname . DIRECTORY_SEPARATOR .'dir1';
mkdir($dir);
$file1 = $dir . DIRECTORY_SEPARATOR .'file1';
touch($file1);
$this->assertEquals(array($file1), util::directory_contents($dir));
util::rmdir($dir);
}
}
+10
View File
@@ -0,0 +1,10 @@
<?php
require __DIR__ . '/src/utilphp/util.php';
/**
* Globally namespaced version of the class.
*
* @author Brandon Wamboldt <brandon.wamboldt@gmail.com>
*/
class util extends \utilphp\util { }