Skip to content

Instantly share code, notes, and snippets.

@langemike
Created June 22, 2016 14:18
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save langemike/ba4f3dea8fe0a1546f81549d4448d10b to your computer and use it in GitHub Desktop.
Save langemike/ba4f3dea8fe0a1546f81549d4448d10b to your computer and use it in GitHub Desktop.
Validation class for validating dead links through a whitelist function
<?php
use BadMethodCallException;
trait LinkCheckerTrait {
/**
* The failed links.
*
* @var array
*/
protected $diffLinks = [];
/**
* Resolved links from classes.
*
* @var array
*/
protected static $resolvedLinks = [];
/**
* Validate links
* @param string $attribute
* @param string $value
* @param array $parameters
* @param \Validator $validator
* @return bool
**/
public function validateLinks($attribute, $value, $parameters, $validator)
{
$this->requireParameterCount(1, $parameters, 'link');
if (! isset($this->customMessages['links'])) {
$this->setCustomMessages(['links' => 'De volgende links bestaan niet :links']);
}
$whitelist = array();
foreach ($parameters as $class) {
$whitelist = array_unique(array_merge($whitelist, $this->fetchLinksFromClass($class)));
}
$links = $this->fetchLinks($value);
$this->diffLinks = array_diff($links, $whitelist);
if (count($this->diffLinks) > 0) {
//dd($links);
}
return count($this->diffLinks) === 0;
}
/**
* Nice validation messages with failed links
* @param string $message
* @param string $attribute
* @param string $rule
* @param array $parameters
* @return string
**/
public function replaceLinks($message, $attribute, $rule, $parameters)
{
return str_replace([':links'], implode(', ', $this->diffLinks), $message);
}
/**
* Get URLs from a mixed value
* @param mixed $value
* @return array
*/
protected function fetchLinks($value)
{
$links = array();
if (is_string($value)) {
$links = $this->fetchLinksFromString($value);
} else if (is_array($value)) {
$links = $this->fetchLinksFromArray($value);
}
return array_filter($links, array($this, 'disallowedUrl'));
}
/**
* Fetch links from array
* @param array $value
* @return array
**/
protected function fetchLinksFromArray($value)
{
$links = array_filter($value, function($value) {
return preg_match('/^(http|\/)/', $value) !== 0;
});
return array_map(array($this, 'normalizeUrl'), $links);
}
/**
* Fetch links from string
* @param string $value
* @return array
**/
protected function fetchLinksFromString($value)
{
$matches = preg_match_all('/<a.*?href\s*=\s*[\'\"](.*?)[\'\"]/', $value, $links);
return array_map(array($this, 'normalizeUrl'), $links[1]);
}
/**
* Get URLs from a class instance
* @param string $class
* @return array
*/
protected function fetchLinksFromClass($class)
{
if (array_key_exists($class, static::$resolvedLinks)) {
return static::$resolvedLinks[$class];
}
$instance = new $class;
if (method_exists($instance, 'getValidatorLinks') === false) {
throw new BadMethodCallException("Method [getValidatorLinks] does not exist on [$class].");
}
// Collect links from class
static::$resolvedLinks[$class] = array_map(array($this, 'normalizeUrl'), $instance->getValidatorLinks());
return static::$resolvedLinks[$class];
}
/**
* Disallowed URLs
* @param string $url
* @return bool
*/
protected function disallowedUrl($url)
{
return strpos($url, 'http') === false;
}
/**
* Transform URLs into consistent format
* - Base URL removed
* - Remove query string
* - Consitent trailing slash
* @param string $url
* @return string
*/
protected function normalizeUrl($url)
{
if (strpos($url, 'http') === 0) {
$url = str_replace($this->getBaseUrl(), '', $url);
}
return rtrim(preg_replace('/\?.*/', '', $url), '/');
}
/**
* Get Base URL of application
* @return string
**/
protected function getBaseUrl()
{
return $this->container['config']->get('app.url');
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment