Skip to content

Instantly share code, notes, and snippets.

@jasonhofer
Last active July 13, 2018 21:26
Show Gist options
  • Save jasonhofer/167f2bde6bd2ecc485fb51dd438f9a21 to your computer and use it in GitHub Desktop.
Save jasonhofer/167f2bde6bd2ecc485fb51dd438f9a21 to your computer and use it in GitHub Desktop.
PHP port of classnames.js
<?php
/**
* PHP port of https://github.com/JedWatson/classnames
*
* Examples:
* <code>
* classnames('foo', 'bar'); // "foo bar"
* classnames('foo', ['bar' => true]); // "foo bar"
* classnames(['foo-bar' => true]); // "foo-bar"
* classnames(['foo-bar' => false]); // ""
* classnames(['foo' => true], ['bar' => true]); // "foo bar"
* classnames(['foo' => true, 'bar' => true]); // "foo bar"
* classnames(' ', [' foo ', ''], ['' => true]); // "foo" (empty strings and whitespace ignored)
* classnames('foo bar', ['foo' => true], ['bar', 'foo']); // "foo bar" (duplicates removed)
* classnames('foo', ['foo' => false], ['foo' => true]); // "" (false trumps all others)
* </code>
*
* @param array|string $names
*
* @return string
*/
function classnames($names) {
static $recursion = false, $falsified;
if (!$recursion) {
$falsified = array();
}
$classes = array();
foreach (func_get_args() as $arg) {
if (!$arg) { continue; }
if (is_scalar($arg)) {
$classes[] = trim((string) $arg);
} elseif (is_assoc($arg)) {
/** @var array $arg */
foreach ($arg as $key => $result) {
if ($result) {
$classes[] = trim($key);
} else {
foreach (array_filter(explode(' ', $key)) as $k) {
$falsified[] = $k;
}
}
}
} elseif (is_array($arg)) {
$recursion = true;
$classes[] = classnames($arg);
$recursion = false;
} elseif (is_object($arg) && method_exists($arg, '__toString')) {
$classes[] = $arg->__toString();
}
}
if (empty($classes)) { return ''; }
$classes = array_unique(explode(' ', implode(' ', $classes)));
$classes = array_diff($classes, $falsified);
return implode(' ', array_filter($classes));
}
<?php
/**
* Like "classnames()" above, but for HTML attributes.
*
* @param array|array[] $arguments
*
* @return string
*/
function html_attributes($arguments) {
$html = [];
foreach (func_get_args() as $attributes) {
if (empty($attributes)) {
continue;
}
if (!is_array($attributes)) {
if ($value = trim((string) $attributes)) {
$html[] = ' '.$value;
}
continue;
}
if (isset($attributes['class'])) {
$attributes['class'] = classnames($attributes['class']) ?: false; // false prevents class=""
}
if (isset($attributes['data']) && is_array($attributes['data'])) {
foreach ($attributes['data'] as $name => $value) {
$attributes['data-'.to_dashed($name)] = $value;
}
unset($attributes['data']);
}
foreach ($attributes as $name => $value) {
if (is_array($value)) {
if ($result = html_attributes($value)) {
$html[] = $result;
}
} elseif (null !== $value && false !== $value) {
$html[] = ' '.strtolower($name).(true === $value ? '' : sprintf('="%s"', htmlentities($value)));
}
}
}
return implode($html);
}
<?php
function is_assoc($var, $allowEmpty = true) {
if (!is_array($var)) {
return false;
}
if (empty($var)) {
return $allowEmpty;
}
// Fastest method I've seen so far.
foreach (array_keys($var) as $idx => $key) {
if ($key !== $idx) {
return true;
}
}
return false;
}
<?php
function to_dashed($str, $upper = false) {
$str = uncamel($str, '-', $upper ? CASE_UPPER : CASE_LOWER);
return preg_replace('/[^[:alnum:]]+/', '-', $str);
}
<?php
function uncamel($strIn, $delim = ' ', $case = null) {
static $rxSplit = '/
(?<=[0-9]) (?=[a-zA-Z]) | # split at number-letter
(?<=[a-zA-Z]) (?=[0-9]) | # split at letter-number
(?<=[a-z]) (?=[A-Z]) | # split at lower-UPPER
(?<=[A-Z]) (?=[A-Z][a-z]) # split at UPPER-Capitalized
/x';
$strOut = preg_replace($rxSplit, $delim, trim($strIn));
switch ($case) {
case CASE_LOWER: return strtolower($strOut);
case CASE_UPPER: return strtoupper($strOut);
default: return $strOut;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment