mirror of
https://github.com/friendica/friendica
synced 2025-05-06 15:44:11 +02:00
Merge remote-tracking branch 'upstream/develop' into json-ld
This commit is contained in:
commit
8db0e090d7
328 changed files with 13255 additions and 10224 deletions
|
@ -119,7 +119,7 @@ abstract class MailBuilder
|
|||
{
|
||||
$this->recipientUid = $user['uid'] ?? 0;
|
||||
try {
|
||||
$this->l10n = $user['language'] ? $this->l10n->withLang($user['language']) : $this->l10n;
|
||||
$this->l10n = isset($user['language']) ? $this->l10n->withLang($user['language']) : $this->l10n;
|
||||
} catch (Exception $e) {
|
||||
$this->logger->warning('cannot use language.', ['user' => $user, 'exception' => $e]);
|
||||
}
|
||||
|
@ -164,7 +164,7 @@ abstract class MailBuilder
|
|||
*
|
||||
* @return string[][]
|
||||
*/
|
||||
public function getHeaders()
|
||||
public function getHeaders(): array
|
||||
{
|
||||
return $this->headers;
|
||||
}
|
||||
|
@ -182,7 +182,7 @@ abstract class MailBuilder
|
|||
* @param string[][] $headers
|
||||
* @return $this
|
||||
*/
|
||||
public function withHeaders(array $headers)
|
||||
public function withHeaders(array $headers): MailBuilder
|
||||
{
|
||||
$this->headers = $headers;
|
||||
|
||||
|
|
|
@ -141,7 +141,7 @@ class Emailer
|
|||
$countMessageId += count($value);
|
||||
}
|
||||
}
|
||||
if ($countMessageId > 0) {
|
||||
if ($countMessageId > 1) {
|
||||
$this->logger->warning('More than one Message-ID found - RFC violation', ['email' => $email]);
|
||||
}
|
||||
|
||||
|
|
|
@ -55,7 +55,7 @@ class HTTPSignature
|
|||
* @return array with verification data
|
||||
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
|
||||
*/
|
||||
public static function verifyMagic($key)
|
||||
public static function verifyMagic(string $key): array
|
||||
{
|
||||
$headers = null;
|
||||
$spoofable = false;
|
||||
|
@ -139,7 +139,7 @@ class HTTPSignature
|
|||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function createSig($head, $prvkey, $keyid = 'Key')
|
||||
public static function createSig(array $head, string $prvkey, string $keyid = 'Key'): array
|
||||
{
|
||||
$return_headers = [];
|
||||
if (!empty($head)) {
|
||||
|
@ -166,7 +166,7 @@ class HTTPSignature
|
|||
*
|
||||
* @return array
|
||||
*/
|
||||
private static function sign($head, $prvkey, $alg = 'sha256')
|
||||
private static function sign(array $head, string $prvkey, string $alg = 'sha256'): array
|
||||
{
|
||||
$ret = [];
|
||||
$headers = '';
|
||||
|
@ -204,7 +204,7 @@ class HTTPSignature
|
|||
* - \e string \b signature
|
||||
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
|
||||
*/
|
||||
public static function parseSigheader($header)
|
||||
public static function parseSigheader(string $header): array
|
||||
{
|
||||
// Remove obsolete folds
|
||||
$header = preg_replace('/\n\s+/', ' ', $header);
|
||||
|
@ -251,7 +251,7 @@ class HTTPSignature
|
|||
* @return string Decrypted signature string
|
||||
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
|
||||
*/
|
||||
private static function decryptSigheader(array $headers, string $prvkey)
|
||||
private static function decryptSigheader(array $headers, string $prvkey): string
|
||||
{
|
||||
if (!empty($headers['iv']) && !empty($headers['key']) && !empty($headers['data'])) {
|
||||
return Crypto::unencapsulate($headers, $prvkey);
|
||||
|
@ -341,7 +341,7 @@ class HTTPSignature
|
|||
* @param boolean $success Transmission status
|
||||
* @param boolean $shared The inbox is a shared inbox
|
||||
*/
|
||||
static public function setInboxStatus($url, $success, $shared = false)
|
||||
static public function setInboxStatus(string $url, bool $success, bool $shared = false)
|
||||
{
|
||||
$now = DateTimeFormat::utcNow();
|
||||
|
||||
|
@ -403,21 +403,21 @@ class HTTPSignature
|
|||
* @return array JSON array
|
||||
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
|
||||
*/
|
||||
public static function fetch($request, $uid)
|
||||
public static function fetch(string $request, int $uid): array
|
||||
{
|
||||
$curlResult = self::fetchRaw($request, $uid);
|
||||
|
||||
if (empty($curlResult)) {
|
||||
return false;
|
||||
return [];
|
||||
}
|
||||
|
||||
if (!$curlResult->isSuccess() || empty($curlResult->getBody())) {
|
||||
return false;
|
||||
return [];
|
||||
}
|
||||
|
||||
$content = json_decode($curlResult->getBody(), true);
|
||||
if (empty($content) || !is_array($content)) {
|
||||
return false;
|
||||
return [];
|
||||
}
|
||||
|
||||
return $content;
|
||||
|
@ -438,7 +438,7 @@ class HTTPSignature
|
|||
* @return \Friendica\Network\HTTPClient\Capability\ICanHandleHttpResponses CurlResult
|
||||
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
|
||||
*/
|
||||
public static function fetchRaw($request, $uid = 0, $opts = [HttpClientOptions::ACCEPT_CONTENT => [HttpClientAccept::JSON_AS]])
|
||||
public static function fetchRaw(string $request, int $uid = 0, array $opts = [HttpClientOptions::ACCEPT_CONTENT => [HttpClientAccept::JSON_AS]])
|
||||
{
|
||||
$header = [];
|
||||
|
||||
|
@ -488,13 +488,13 @@ class HTTPSignature
|
|||
/**
|
||||
* Gets a signer from a given HTTP request
|
||||
*
|
||||
* @param $content
|
||||
* @param $http_headers
|
||||
* @param string $content
|
||||
* @param array $http_headers
|
||||
*
|
||||
* @return string Signer
|
||||
* @return string|null|false Signer
|
||||
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
|
||||
*/
|
||||
public static function getSigner($content, $http_headers)
|
||||
public static function getSigner(string $content, array $http_headers)
|
||||
{
|
||||
if (empty($http_headers['HTTP_SIGNATURE'])) {
|
||||
Logger::debug('No HTTP_SIGNATURE header');
|
||||
|
@ -686,13 +686,13 @@ class HTTPSignature
|
|||
/**
|
||||
* fetches a key for a given id and actor
|
||||
*
|
||||
* @param $id
|
||||
* @param $actor
|
||||
* @param string $id
|
||||
* @param string $actor
|
||||
*
|
||||
* @return array with actor url and public key
|
||||
* @throws \Exception
|
||||
*/
|
||||
private static function fetchKey($id, $actor)
|
||||
private static function fetchKey(string $id, string $actor): array
|
||||
{
|
||||
$url = (strpos($id, '#') ? substr($id, 0, strpos($id, '#')) : $id);
|
||||
|
||||
|
@ -709,6 +709,6 @@ class HTTPSignature
|
|||
}
|
||||
|
||||
Logger::notice('Key could not be fetched', ['url' => $url, 'actor' => $actor]);
|
||||
return false;
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
|
|
@ -34,23 +34,23 @@ class Images
|
|||
/**
|
||||
* Maps Mime types to Imagick formats
|
||||
*
|
||||
* @return array
|
||||
* @return array Format map
|
||||
*/
|
||||
public static function getFormatsMap()
|
||||
{
|
||||
$m = [
|
||||
return [
|
||||
'image/jpeg' => 'JPG',
|
||||
'image/jpg' => 'JPG',
|
||||
'image/png' => 'PNG',
|
||||
'image/gif' => 'GIF'
|
||||
'image/gif' => 'GIF',
|
||||
];
|
||||
|
||||
return $m;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return file extension for mime type
|
||||
* @param string $mimetype
|
||||
* @return string
|
||||
* Return file extension for MIME type
|
||||
*
|
||||
* @param string $mimetype MIME type
|
||||
* @return string File extension for MIME type
|
||||
*/
|
||||
public static function getExtensionByMimeType(string $mimetype): string
|
||||
{
|
||||
|
@ -63,9 +63,14 @@ class Images
|
|||
$imagetype = IMAGETYPE_GIF;
|
||||
break;
|
||||
|
||||
default:
|
||||
case 'image/jpeg':
|
||||
case 'image/jpg':
|
||||
$imagetype = IMAGETYPE_JPEG;
|
||||
break;
|
||||
|
||||
default: // Unknown type must be a blob then
|
||||
return 'blob';
|
||||
break;
|
||||
}
|
||||
|
||||
return image_type_to_extension($imagetype);
|
||||
|
@ -76,11 +81,13 @@ class Images
|
|||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function supportedTypes()
|
||||
public static function supportedTypes(): array
|
||||
{
|
||||
$types = [
|
||||
'image/jpeg' => 'jpg'
|
||||
'image/jpeg' => 'jpg',
|
||||
'image/jpg' => 'jpg',
|
||||
];
|
||||
|
||||
if (class_exists('Imagick')) {
|
||||
// Imagick::queryFormats won't help us a lot there...
|
||||
// At least, not yet, other parts of friendica uses this array
|
||||
|
@ -102,21 +109,20 @@ class Images
|
|||
*
|
||||
* @param string $image_data Image data
|
||||
* @param string $filename File name (for guessing the type via the extension)
|
||||
* @param string $mime default mime type
|
||||
*
|
||||
* @return string
|
||||
* @param string $default Default MIME type
|
||||
* @return string MIME type
|
||||
* @throws \Exception
|
||||
*/
|
||||
public static function getMimeTypeByData(string $image_data, string $filename = '', string $mime = '')
|
||||
public static function getMimeTypeByData(string $image_data, string $filename = '', string $default = ''): string
|
||||
{
|
||||
if (substr($mime, 0, 6) == 'image/') {
|
||||
Logger::info('Using default mime type', ['filename' => $filename, 'mime' => $mime]);
|
||||
return $mime;
|
||||
if (substr($default, 0, 6) == 'image/') {
|
||||
Logger::info('Using default mime type', ['filename' => $filename, 'mime' => $default]);
|
||||
return $default;
|
||||
}
|
||||
|
||||
$image = @getimagesizefromstring($image_data);
|
||||
if (!empty($image['mime'])) {
|
||||
Logger::info('Mime type detected via data', ['filename' => $filename, 'default' => $mime, 'mime' => $image['mime']]);
|
||||
Logger::info('Mime type detected via data', ['filename' => $filename, 'default' => $default, 'mime' => $image['mime']]);
|
||||
return $image['mime'];
|
||||
}
|
||||
|
||||
|
@ -128,21 +134,20 @@ class Images
|
|||
*
|
||||
* @param string $sourcefile Source file of the image
|
||||
* @param string $filename File name (for guessing the type via the extension)
|
||||
* @param string $mime default mime type
|
||||
*
|
||||
* @return string
|
||||
* @param string $default default MIME type
|
||||
* @return string MIME type
|
||||
* @throws \Exception
|
||||
*/
|
||||
public static function getMimeTypeBySource(string $sourcefile, string $filename = '', string $mime = '')
|
||||
public static function getMimeTypeBySource(string $sourcefile, string $filename = '', string $default = ''): string
|
||||
{
|
||||
if (substr($mime, 0, 6) == 'image/') {
|
||||
Logger::info('Using default mime type', ['filename' => $filename, 'mime' => $mime]);
|
||||
return $mime;
|
||||
if (substr($default, 0, 6) == 'image/') {
|
||||
Logger::info('Using default mime type', ['filename' => $filename, 'mime' => $default]);
|
||||
return $default;
|
||||
}
|
||||
|
||||
$image = @getimagesize($sourcefile);
|
||||
if (!empty($image['mime'])) {
|
||||
Logger::info('Mime type detected via file', ['filename' => $filename, 'default' => $mime, 'image' => $image]);
|
||||
Logger::info('Mime type detected via file', ['filename' => $filename, 'default' => $default, 'image' => $image]);
|
||||
return $image['mime'];
|
||||
}
|
||||
|
||||
|
@ -150,14 +155,13 @@ class Images
|
|||
}
|
||||
|
||||
/**
|
||||
* Guess image mimetype from the filename
|
||||
* Guess image MIME type from the filename's extension
|
||||
*
|
||||
* @param string $filename Image filename
|
||||
*
|
||||
* @return string
|
||||
* @param string $filename Image filename
|
||||
* @return string Guessed MIME type by extension
|
||||
* @throws \Exception
|
||||
*/
|
||||
public static function guessTypeByExtension(string $filename)
|
||||
public static function guessTypeByExtension(string $filename): string
|
||||
{
|
||||
$ext = pathinfo(parse_url($filename, PHP_URL_PATH), PATHINFO_EXTENSION);
|
||||
$types = self::supportedTypes();
|
||||
|
@ -173,11 +177,13 @@ class Images
|
|||
}
|
||||
|
||||
/**
|
||||
* Gets info array from given URL, cached data has priority
|
||||
*
|
||||
* @param string $url
|
||||
* @return array
|
||||
* @return array Info
|
||||
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
|
||||
*/
|
||||
public static function getInfoFromURLCached($url)
|
||||
public static function getInfoFromURLCached(string $url): array
|
||||
{
|
||||
$data = [];
|
||||
|
||||
|
@ -195,15 +201,17 @@ class Images
|
|||
DI::cache()->set($cacheKey, $data);
|
||||
}
|
||||
|
||||
return $data;
|
||||
return $data ?? [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets info from URL uncached
|
||||
*
|
||||
* @param string $url
|
||||
* @return array
|
||||
* @return array Info array
|
||||
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
|
||||
*/
|
||||
public static function getInfoFromURL($url)
|
||||
public static function getInfoFromURL(string $url): array
|
||||
{
|
||||
$data = [];
|
||||
|
||||
|
@ -239,16 +247,18 @@ class Images
|
|||
$data['size'] = $filesize;
|
||||
}
|
||||
|
||||
return $data;
|
||||
return is_array($data) ? $data : [];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param integer $width
|
||||
* @param integer $height
|
||||
* @param integer $max
|
||||
* @return array
|
||||
* Returns scaling information
|
||||
*
|
||||
* @param integer $width Width
|
||||
* @param integer $height Height
|
||||
* @param integer $max Max width/height
|
||||
* @return array Scaling dimensions
|
||||
*/
|
||||
public static function getScalingDimensions($width, $height, $max)
|
||||
public static function getScalingDimensions(int $width, int $height, int $max): array
|
||||
{
|
||||
if ((!$width) || (!$height)) {
|
||||
return ['width' => 0, 'height' => 0];
|
||||
|
|
|
@ -31,12 +31,24 @@ use Friendica\Model\APContact;
|
|||
*/
|
||||
class LDSignature
|
||||
{
|
||||
public static function isSigned($data)
|
||||
/**
|
||||
* Checks if element 'signature' is found and not empty
|
||||
*
|
||||
* @param array $data
|
||||
* @return bool
|
||||
*/
|
||||
public static function isSigned(array $data): bool
|
||||
{
|
||||
return !empty($data['signature']);
|
||||
}
|
||||
|
||||
public static function getSigner($data)
|
||||
/**
|
||||
* Returns actor (signer) from given data
|
||||
*
|
||||
* @param array $data
|
||||
* @return mixed Returns actor or false on error
|
||||
*/
|
||||
public static function getSigner(array $data)
|
||||
{
|
||||
if (!self::isSigned($data)) {
|
||||
return false;
|
||||
|
@ -66,13 +78,20 @@ class LDSignature
|
|||
}
|
||||
}
|
||||
|
||||
public static function sign($data, $owner)
|
||||
/**
|
||||
* Signs given data by owner's signature
|
||||
*
|
||||
* @param array $data Data to sign
|
||||
* @param array $owner Owner information, like URL
|
||||
* @return array Merged array of $data and signature
|
||||
*/
|
||||
public static function sign(array $data, array $owner): array
|
||||
{
|
||||
$options = [
|
||||
'type' => 'RsaSignature2017',
|
||||
'nonce' => Strings::getRandomHex(64),
|
||||
'creator' => $owner['url'] . '#main-key',
|
||||
'created' => DateTimeFormat::utcNow(DateTimeFormat::ATOM)
|
||||
'created' => DateTimeFormat::utcNow(DateTimeFormat::ATOM),
|
||||
];
|
||||
|
||||
$ohash = self::hash(self::signableOptions($options));
|
||||
|
@ -82,13 +101,25 @@ class LDSignature
|
|||
return array_merge($data, ['signature' => $options]);
|
||||
}
|
||||
|
||||
private static function signableData($data)
|
||||
/**
|
||||
* Removes element 'signature' from array
|
||||
*
|
||||
* @param array $data
|
||||
* @return array With no element 'signature'
|
||||
*/
|
||||
private static function signableData(array $data): array
|
||||
{
|
||||
unset($data['signature']);
|
||||
return $data;
|
||||
}
|
||||
|
||||
private static function signableOptions($options)
|
||||
/**
|
||||
* Removes some elements and adds '@context' to it
|
||||
*
|
||||
* @param array $options
|
||||
* @return array With some removed elements and added '@context' element
|
||||
*/
|
||||
private static function signableOptions(array $options): array
|
||||
{
|
||||
$newopts = ['@context' => 'https://w3id.org/identity/v1'];
|
||||
|
||||
|
@ -99,7 +130,13 @@ class LDSignature
|
|||
return array_merge($newopts, $options);
|
||||
}
|
||||
|
||||
private static function hash($obj)
|
||||
/**
|
||||
* Hashes normalized object
|
||||
*
|
||||
* @param ??? $obj
|
||||
* @return string SHA256 hash
|
||||
*/
|
||||
private static function hash($obj): string
|
||||
{
|
||||
return hash('sha256', JsonLD::normalize($obj));
|
||||
}
|
||||
|
|
|
@ -29,7 +29,7 @@ class Mimetype
|
|||
* @param string $filename filename
|
||||
* @return mixed array or string
|
||||
*/
|
||||
public static function getContentType($filename)
|
||||
public static function getContentType(string $filename)
|
||||
{
|
||||
$mime_types = [
|
||||
|
||||
|
|
|
@ -82,7 +82,7 @@ class Network
|
|||
* @param string $addr The email address
|
||||
* @return boolean True if it's a valid email address, false if it's not
|
||||
*/
|
||||
public static function isEmailDomainValid(string $addr)
|
||||
public static function isEmailDomainValid(string $addr): bool
|
||||
{
|
||||
if (DI::config()->get('system', 'disable_email_validation')) {
|
||||
return true;
|
||||
|
@ -113,7 +113,7 @@ class Network
|
|||
* @param string $url URL which get tested
|
||||
* @return boolean True if url is allowed otherwise return false
|
||||
*/
|
||||
public static function isUrlAllowed(string $url)
|
||||
public static function isUrlAllowed(string $url): bool
|
||||
{
|
||||
$h = @parse_url($url);
|
||||
|
||||
|
@ -158,7 +158,7 @@ class Network
|
|||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public static function isUrlBlocked(string $url)
|
||||
public static function isUrlBlocked(string $url): bool
|
||||
{
|
||||
$host = @parse_url($url, PHP_URL_HOST);
|
||||
if (!$host) {
|
||||
|
@ -187,7 +187,7 @@ class Network
|
|||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public static function isRedirectBlocked(string $url)
|
||||
public static function isRedirectBlocked(string $url): bool
|
||||
{
|
||||
$host = @parse_url($url, PHP_URL_HOST);
|
||||
if (!$host) {
|
||||
|
@ -218,7 +218,7 @@ class Network
|
|||
* or if allowed list is not configured
|
||||
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
|
||||
*/
|
||||
public static function isEmailDomainAllowed(string $email)
|
||||
public static function isEmailDomainAllowed(string $email): bool
|
||||
{
|
||||
$domain = strtolower(substr($email, strpos($email, '@') + 1));
|
||||
if (!$domain) {
|
||||
|
@ -242,7 +242,7 @@ class Network
|
|||
* @param array $domain_list
|
||||
* @return boolean
|
||||
*/
|
||||
public static function isDomainAllowed(string $domain, array $domain_list)
|
||||
public static function isDomainAllowed(string $domain, array $domain_list): bool
|
||||
{
|
||||
$found = false;
|
||||
|
||||
|
@ -257,7 +257,7 @@ class Network
|
|||
return $found;
|
||||
}
|
||||
|
||||
public static function lookupAvatarByEmail(string $email)
|
||||
public static function lookupAvatarByEmail(string $email): string
|
||||
{
|
||||
$avatar['size'] = 300;
|
||||
$avatar['email'] = $email;
|
||||
|
@ -280,11 +280,12 @@ class Network
|
|||
* @param string $url Any user-submitted URL that may contain tracking params
|
||||
* @return string The same URL stripped of tracking parameters
|
||||
*/
|
||||
public static function stripTrackingQueryParams(string $url)
|
||||
public static function stripTrackingQueryParams(string $url): string
|
||||
{
|
||||
$urldata = parse_url($url);
|
||||
if (!empty($urldata["query"])) {
|
||||
$query = $urldata["query"];
|
||||
|
||||
if (!empty($urldata['query'])) {
|
||||
$query = $urldata['query'];
|
||||
parse_str($query, $querydata);
|
||||
|
||||
if (is_array($querydata)) {
|
||||
|
@ -292,30 +293,32 @@ class Network
|
|||
if (in_array(
|
||||
$param,
|
||||
[
|
||||
"utm_source", "utm_medium", "utm_term", "utm_content", "utm_campaign",
|
||||
"wt_mc", "pk_campaign", "pk_kwd", "mc_cid", "mc_eid",
|
||||
"fb_action_ids", "fb_action_types", "fb_ref",
|
||||
"awesm", "wtrid",
|
||||
"woo_campaign", "woo_source", "woo_medium", "woo_content", "woo_term"]
|
||||
'utm_source', 'utm_medium', 'utm_term', 'utm_content', 'utm_campaign',
|
||||
// As seen from Purism
|
||||
'mtm_source', 'mtm_medium', 'mtm_term', 'mtm_content', 'mtm_campaign',
|
||||
'wt_mc', 'pk_campaign', 'pk_kwd', 'mc_cid', 'mc_eid',
|
||||
'fb_action_ids', 'fb_action_types', 'fb_ref',
|
||||
'awesm', 'wtrid',
|
||||
'woo_campaign', 'woo_source', 'woo_medium', 'woo_content', 'woo_term']
|
||||
)
|
||||
) {
|
||||
$pair = $param . "=" . urlencode($value);
|
||||
$url = str_replace($pair, "", $url);
|
||||
$pair = $param . '=' . urlencode($value);
|
||||
$url = str_replace($pair, '', $url);
|
||||
|
||||
// Second try: if the url isn't encoded completely
|
||||
$pair = $param . "=" . str_replace(" ", "+", $value);
|
||||
$url = str_replace($pair, "", $url);
|
||||
$pair = $param . '=' . str_replace(' ', '+', $value);
|
||||
$url = str_replace($pair, '', $url);
|
||||
|
||||
// Third try: Maybey the url isn't encoded at all
|
||||
$pair = $param . "=" . $value;
|
||||
$url = str_replace($pair, "", $url);
|
||||
$pair = $param . '=' . $value;
|
||||
$url = str_replace($pair, '', $url);
|
||||
|
||||
$url = str_replace(["?&", "&&"], ["?", ""], $url);
|
||||
$url = str_replace(['?&', '&&'], ['?', ''], $url);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (substr($url, -1, 1) == "?") {
|
||||
if (substr($url, -1, 1) == '?') {
|
||||
$url = substr($url, 0, -1);
|
||||
}
|
||||
}
|
||||
|
@ -336,8 +339,10 @@ class Network
|
|||
return $url;
|
||||
}
|
||||
|
||||
$base = ['scheme' => parse_url($basepath, PHP_URL_SCHEME),
|
||||
'host' => parse_url($basepath, PHP_URL_HOST)];
|
||||
$base = [
|
||||
'scheme' => parse_url($basepath, PHP_URL_SCHEME),
|
||||
'host' => parse_url($basepath, PHP_URL_HOST),
|
||||
];
|
||||
|
||||
$parts = array_merge($base, parse_url('/' . ltrim($url, '/')));
|
||||
return self::unparseURL($parts);
|
||||
|
@ -348,12 +353,12 @@ class Network
|
|||
*
|
||||
* @param string $url1
|
||||
* @param string $url2
|
||||
* @return string The matching part
|
||||
* @return string The matching part or empty string on error
|
||||
*/
|
||||
public static function getUrlMatch(string $url1, string $url2)
|
||||
public static function getUrlMatch(string $url1, string $url2): string
|
||||
{
|
||||
if (($url1 == "") || ($url2 == "")) {
|
||||
return "";
|
||||
if (($url1 == '') || ($url2 == '')) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$url1 = Strings::normaliseLink($url1);
|
||||
|
@ -362,67 +367,67 @@ class Network
|
|||
$parts1 = parse_url($url1);
|
||||
$parts2 = parse_url($url2);
|
||||
|
||||
if (!isset($parts1["host"]) || !isset($parts2["host"])) {
|
||||
return "";
|
||||
if (!isset($parts1['host']) || !isset($parts2['host'])) {
|
||||
return '';
|
||||
}
|
||||
|
||||
if (empty($parts1["scheme"])) {
|
||||
$parts1["scheme"] = '';
|
||||
if (empty($parts1['scheme'])) {
|
||||
$parts1['scheme'] = '';
|
||||
}
|
||||
if (empty($parts2["scheme"])) {
|
||||
$parts2["scheme"] = '';
|
||||
if (empty($parts2['scheme'])) {
|
||||
$parts2['scheme'] = '';
|
||||
}
|
||||
|
||||
if ($parts1["scheme"] != $parts2["scheme"]) {
|
||||
return "";
|
||||
if ($parts1['scheme'] != $parts2['scheme']) {
|
||||
return '';
|
||||
}
|
||||
|
||||
if (empty($parts1["host"])) {
|
||||
$parts1["host"] = '';
|
||||
if (empty($parts1['host'])) {
|
||||
$parts1['host'] = '';
|
||||
}
|
||||
if (empty($parts2["host"])) {
|
||||
$parts2["host"] = '';
|
||||
if (empty($parts2['host'])) {
|
||||
$parts2['host'] = '';
|
||||
}
|
||||
|
||||
if ($parts1["host"] != $parts2["host"]) {
|
||||
return "";
|
||||
if ($parts1['host'] != $parts2['host']) {
|
||||
return '';
|
||||
}
|
||||
|
||||
if (empty($parts1["port"])) {
|
||||
$parts1["port"] = '';
|
||||
if (empty($parts1['port'])) {
|
||||
$parts1['port'] = '';
|
||||
}
|
||||
if (empty($parts2["port"])) {
|
||||
$parts2["port"] = '';
|
||||
if (empty($parts2['port'])) {
|
||||
$parts2['port'] = '';
|
||||
}
|
||||
|
||||
if ($parts1["port"] != $parts2["port"]) {
|
||||
return "";
|
||||
if ($parts1['port'] != $parts2['port']) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$match = $parts1["scheme"]."://".$parts1["host"];
|
||||
$match = $parts1['scheme'] . '://' . $parts1['host'];
|
||||
|
||||
if ($parts1["port"]) {
|
||||
$match .= ":".$parts1["port"];
|
||||
if ($parts1['port']) {
|
||||
$match .= ':' . $parts1['port'];
|
||||
}
|
||||
|
||||
if (empty($parts1["path"])) {
|
||||
$parts1["path"] = '';
|
||||
if (empty($parts1['path'])) {
|
||||
$parts1['path'] = '';
|
||||
}
|
||||
if (empty($parts2["path"])) {
|
||||
$parts2["path"] = '';
|
||||
if (empty($parts2['path'])) {
|
||||
$parts2['path'] = '';
|
||||
}
|
||||
|
||||
$pathparts1 = explode("/", $parts1["path"]);
|
||||
$pathparts2 = explode("/", $parts2["path"]);
|
||||
$pathparts1 = explode('/', $parts1['path']);
|
||||
$pathparts2 = explode('/', $parts2['path']);
|
||||
|
||||
$i = 0;
|
||||
$path = "";
|
||||
$path = '';
|
||||
do {
|
||||
$path1 = $pathparts1[$i] ?? '';
|
||||
$path2 = $pathparts2[$i] ?? '';
|
||||
|
||||
if ($path1 == $path2) {
|
||||
$path .= $path1."/";
|
||||
$path .= $path1 . '/';
|
||||
}
|
||||
} while (($path1 == $path2) && ($i++ <= count($pathparts1)));
|
||||
|
||||
|
@ -435,11 +440,10 @@ class Network
|
|||
* Glue url parts together
|
||||
*
|
||||
* @param array $parsed URL parts
|
||||
*
|
||||
* @return string The glued URL.
|
||||
* @return string|null The glued URL or null on error
|
||||
* @deprecated since version 2021.12, use GuzzleHttp\Psr7\Uri::fromParts($parts) instead
|
||||
*/
|
||||
public static function unparseURL(array $parsed)
|
||||
public static function unparseURL(array $parsed): string
|
||||
{
|
||||
$get = function ($key) use ($parsed) {
|
||||
return isset($parsed[$key]) ? $parsed[$key] : null;
|
||||
|
@ -452,15 +456,15 @@ class Network
|
|||
$scheme = $get('scheme');
|
||||
$query = $get('query');
|
||||
$fragment = $get('fragment');
|
||||
$authority = ($userinfo !== null ? $userinfo."@" : '') .
|
||||
$authority = ($userinfo !== null ? $userinfo . '@' : '') .
|
||||
$get('host') .
|
||||
($port ? ":$port" : '');
|
||||
|
||||
return (strlen($scheme) ? $scheme.":" : '') .
|
||||
(strlen($authority) ? "//".$authority : '') .
|
||||
return (strlen($scheme) ? $scheme . ':' : '') .
|
||||
(strlen($authority) ? '//' . $authority : '') .
|
||||
$get('path') .
|
||||
(strlen($query) ? "?".$query : '') .
|
||||
(strlen($fragment) ? "#".$fragment : '');
|
||||
(strlen($query) ? '?' . $query : '') .
|
||||
(strlen($fragment) ? '#' . $fragment : '');
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -490,11 +494,10 @@ class Network
|
|||
/**
|
||||
* Switch the scheme of an url between http and https
|
||||
*
|
||||
* @param string $url URL
|
||||
*
|
||||
* @return string switched URL
|
||||
* @param string $url
|
||||
* @return string Switched URL
|
||||
*/
|
||||
public static function switchScheme(string $url)
|
||||
public static function switchScheme(string $url): string
|
||||
{
|
||||
$scheme = parse_url($url, PHP_URL_SCHEME);
|
||||
if (empty($scheme)) {
|
||||
|
@ -517,7 +520,7 @@ class Network
|
|||
* @param array $additionalParams Associative array of parameters
|
||||
* @return string
|
||||
*/
|
||||
public static function appendQueryParam(string $path, array $additionalParams)
|
||||
public static function appendQueryParam(string $path, array $additionalParams): string
|
||||
{
|
||||
$parsed = parse_url($path);
|
||||
|
||||
|
@ -541,6 +544,7 @@ class Network
|
|||
*
|
||||
* @param string $etag The page etag
|
||||
* @param string $last_modified The page last modification UTC date
|
||||
* @return void
|
||||
* @throws \Exception
|
||||
*/
|
||||
public static function checkEtagModified(string $etag, string $last_modified)
|
||||
|
@ -577,10 +581,10 @@ class Network
|
|||
/**
|
||||
* Check if the given URL is a local link
|
||||
*
|
||||
* @param string $url
|
||||
* @return bool
|
||||
* @param string $url
|
||||
* @return bool
|
||||
*/
|
||||
public static function isLocalLink(string $url)
|
||||
public static function isLocalLink(string $url): bool
|
||||
{
|
||||
return (strpos(Strings::normaliseLink($url), Strings::normaliseLink(DI::baseUrl())) !== false);
|
||||
}
|
||||
|
@ -588,10 +592,10 @@ class Network
|
|||
/**
|
||||
* Check if the given URL is a valid HTTP/HTTPS URL
|
||||
*
|
||||
* @param string $url
|
||||
* @return bool
|
||||
* @param string $url
|
||||
* @return bool
|
||||
*/
|
||||
public static function isValidHttpUrl(string $url)
|
||||
public static function isValidHttpUrl(string $url): bool
|
||||
{
|
||||
$scheme = parse_url($url, PHP_URL_SCHEME);
|
||||
return !empty($scheme) && in_array($scheme, ['http', 'https']) && parse_url($url, PHP_URL_HOST);
|
||||
|
|
|
@ -59,7 +59,7 @@ class ParseUrl
|
|||
* @param string $accept content-type to accept
|
||||
* @return array content type
|
||||
*/
|
||||
public static function getContentType(string $url, string $accept = HttpClientAccept::DEFAULT)
|
||||
public static function getContentType(string $url, string $accept = HttpClientAccept::DEFAULT): array
|
||||
{
|
||||
$curlResult = DI::httpClient()->head($url, [HttpClientOptions::ACCEPT_CONTENT => $accept]);
|
||||
|
||||
|
@ -101,7 +101,7 @@ class ParseUrl
|
|||
* @see ParseUrl::getSiteinfo() for more information about scraping
|
||||
* embeddable content
|
||||
*/
|
||||
public static function getSiteinfoCached($url, $do_oembed = true): array
|
||||
public static function getSiteinfoCached(string $url, bool $do_oembed = true): array
|
||||
{
|
||||
if (empty($url)) {
|
||||
return [
|
||||
|
@ -180,7 +180,7 @@ class ParseUrl
|
|||
* </body>
|
||||
* @endverbatim
|
||||
*/
|
||||
public static function getSiteinfo($url, $do_oembed = true, $count = 1)
|
||||
public static function getSiteinfo(string $url, bool $do_oembed = true, int $count = 1)
|
||||
{
|
||||
if (empty($url)) {
|
||||
return [
|
||||
|
@ -543,12 +543,15 @@ class ParseUrl
|
|||
{
|
||||
if (!empty($siteinfo['images'])) {
|
||||
array_walk($siteinfo['images'], function (&$image) use ($page_url) {
|
||||
// According to the specifications someone could place a picture url into the content field as well.
|
||||
// But this doesn't seem to happen in the wild, so we don't cover it here.
|
||||
/*
|
||||
* According to the specifications someone could place a picture
|
||||
* URL into the content field as well. But this doesn't seem to
|
||||
* happen in the wild, so we don't cover it here.
|
||||
*/
|
||||
if (!empty($image['url'])) {
|
||||
$image['url'] = self::completeUrl($image['url'], $page_url);
|
||||
$photodata = Images::getInfoFromURLCached($image['url']);
|
||||
if (!empty($photodata) && ($photodata[0] > 50) && ($photodata[1] > 50)) {
|
||||
if (($photodata) && ($photodata[0] > 50) && ($photodata[1] > 50)) {
|
||||
$image['src'] = $image['url'];
|
||||
$image['width'] = $photodata[0];
|
||||
$image['height'] = $photodata[1];
|
||||
|
@ -633,15 +636,16 @@ class ParseUrl
|
|||
* @param string $string Tags
|
||||
* @return array with formatted Hashtags
|
||||
*/
|
||||
public static function convertTagsToArray($string)
|
||||
public static function convertTagsToArray(string $string): array
|
||||
{
|
||||
$arr_tags = str_getcsv($string);
|
||||
if (count($arr_tags)) {
|
||||
// add the # sign to every tag
|
||||
array_walk($arr_tags, ["self", "arrAddHashes"]);
|
||||
array_walk($arr_tags, ['self', 'arrAddHashes']);
|
||||
|
||||
return $arr_tags;
|
||||
}
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -653,9 +657,9 @@ class ParseUrl
|
|||
* @param int $k Counter for internal use
|
||||
* @return void
|
||||
*/
|
||||
private static function arrAddHashes(&$tag, $k)
|
||||
private static function arrAddHashes(string &$tag, int $k)
|
||||
{
|
||||
$tag = "#" . $tag;
|
||||
$tag = '#' . $tag;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -672,41 +676,41 @@ class ParseUrl
|
|||
*
|
||||
* @return string The url with a scheme
|
||||
*/
|
||||
private static function completeUrl($url, $scheme)
|
||||
private static function completeUrl(string $url, string $scheme): string
|
||||
{
|
||||
$urlarr = parse_url($url);
|
||||
|
||||
// If the url does allready have an scheme
|
||||
// we can stop the process here
|
||||
if (isset($urlarr["scheme"])) {
|
||||
return($url);
|
||||
if (isset($urlarr['scheme'])) {
|
||||
return $url;
|
||||
}
|
||||
|
||||
$schemearr = parse_url($scheme);
|
||||
|
||||
$complete = $schemearr["scheme"]."://".$schemearr["host"];
|
||||
$complete = $schemearr['scheme'] . '://' . $schemearr['host'];
|
||||
|
||||
if (!empty($schemearr["port"])) {
|
||||
$complete .= ":".$schemearr["port"];
|
||||
if (!empty($schemearr['port'])) {
|
||||
$complete .= ':' . $schemearr['port'];
|
||||
}
|
||||
|
||||
if (!empty($urlarr["path"])) {
|
||||
if (strpos($urlarr["path"], "/") !== 0) {
|
||||
$complete .= "/";
|
||||
if (!empty($urlarr['path'])) {
|
||||
if (strpos($urlarr['path'], '/') !== 0) {
|
||||
$complete .= '/';
|
||||
}
|
||||
|
||||
$complete .= $urlarr["path"];
|
||||
$complete .= $urlarr['path'];
|
||||
}
|
||||
|
||||
if (!empty($urlarr["query"])) {
|
||||
$complete .= "?".$urlarr["query"];
|
||||
if (!empty($urlarr['query'])) {
|
||||
$complete .= '?' . $urlarr['query'];
|
||||
}
|
||||
|
||||
if (!empty($urlarr["fragment"])) {
|
||||
$complete .= "#".$urlarr["fragment"];
|
||||
if (!empty($urlarr['fragment'])) {
|
||||
$complete .= '#' . $urlarr['fragment'];
|
||||
}
|
||||
|
||||
return($complete);
|
||||
return $complete;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -716,7 +720,7 @@ class ParseUrl
|
|||
* @param array $jsonld
|
||||
* @return array siteinfo
|
||||
*/
|
||||
private static function parseParts(array $siteinfo, array $jsonld)
|
||||
private static function parseParts(array $siteinfo, array $jsonld): array
|
||||
{
|
||||
if (!empty($jsonld['@graph']) && is_array($jsonld['@graph'])) {
|
||||
foreach ($jsonld['@graph'] as $part) {
|
||||
|
@ -761,7 +765,7 @@ class ParseUrl
|
|||
* @param array $jsonld
|
||||
* @return array siteinfo
|
||||
*/
|
||||
private static function parseJsonLd(array $siteinfo, array $jsonld)
|
||||
private static function parseJsonLd(array $siteinfo, array $jsonld): array
|
||||
{
|
||||
$type = JsonLD::fetchElement($jsonld, '@type');
|
||||
if (empty($type)) {
|
||||
|
@ -854,7 +858,7 @@ class ParseUrl
|
|||
* @param array $jsonld
|
||||
* @return array siteinfo
|
||||
*/
|
||||
private static function parseJsonLdAuthor(array $siteinfo, array $jsonld)
|
||||
private static function parseJsonLdAuthor(array $siteinfo, array $jsonld): array
|
||||
{
|
||||
$jsonldinfo = [];
|
||||
|
||||
|
@ -938,7 +942,7 @@ class ParseUrl
|
|||
* @param array $jsonld
|
||||
* @return array siteinfo
|
||||
*/
|
||||
private static function parseJsonLdArticle(array $siteinfo, array $jsonld)
|
||||
private static function parseJsonLdArticle(array $siteinfo, array $jsonld): array
|
||||
{
|
||||
$jsonldinfo = [];
|
||||
|
||||
|
@ -1008,7 +1012,7 @@ class ParseUrl
|
|||
* @param array $jsonld
|
||||
* @return array siteinfo
|
||||
*/
|
||||
private static function parseJsonLdWebPage(array $siteinfo, array $jsonld)
|
||||
private static function parseJsonLdWebPage(array $siteinfo, array $jsonld): array
|
||||
{
|
||||
$jsonldinfo = [];
|
||||
|
||||
|
@ -1047,7 +1051,7 @@ class ParseUrl
|
|||
* @param array $jsonld
|
||||
* @return array siteinfo
|
||||
*/
|
||||
private static function parseJsonLdWebSite(array $siteinfo, array $jsonld)
|
||||
private static function parseJsonLdWebSite(array $siteinfo, array $jsonld): array
|
||||
{
|
||||
$jsonldinfo = [];
|
||||
|
||||
|
@ -1085,7 +1089,7 @@ class ParseUrl
|
|||
* @param array $jsonld
|
||||
* @return array siteinfo
|
||||
*/
|
||||
private static function parseJsonLdWebOrganization(array $siteinfo, array $jsonld)
|
||||
private static function parseJsonLdWebOrganization(array $siteinfo, array $jsonld): array
|
||||
{
|
||||
$jsonldinfo = [];
|
||||
|
||||
|
@ -1131,7 +1135,7 @@ class ParseUrl
|
|||
* @param array $jsonld
|
||||
* @return array siteinfo
|
||||
*/
|
||||
private static function parseJsonLdWebPerson(array $siteinfo, array $jsonld)
|
||||
private static function parseJsonLdWebPerson(array $siteinfo, array $jsonld): array
|
||||
{
|
||||
$jsonldinfo = [];
|
||||
|
||||
|
@ -1176,7 +1180,7 @@ class ParseUrl
|
|||
* @param array $jsonld
|
||||
* @return array siteinfo
|
||||
*/
|
||||
private static function parseJsonLdMediaObject(array $siteinfo, array $jsonld, string $name)
|
||||
private static function parseJsonLdMediaObject(array $siteinfo, array $jsonld, string $name): array
|
||||
{
|
||||
$media = [];
|
||||
|
||||
|
|
|
@ -97,7 +97,8 @@ class PidFile
|
|||
*
|
||||
* @return boolean|string PID or "false" if not created
|
||||
*/
|
||||
static public function create($file) {
|
||||
static public function create(string $file)
|
||||
{
|
||||
$pid = self::pidFromFile($file);
|
||||
|
||||
// We have a process id? then we quit
|
||||
|
@ -119,7 +120,8 @@ class PidFile
|
|||
*
|
||||
* @return boolean Is it running?
|
||||
*/
|
||||
static public function delete($file) {
|
||||
static public function delete(string $file): bool
|
||||
{
|
||||
return @unlink($file);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -76,11 +76,10 @@ class Proxy
|
|||
*
|
||||
* @param string $url The URL to proxyfy
|
||||
* @param string $size One of the Proxy::SIZE_* constants
|
||||
*
|
||||
* @return string The proxyfied URL or relative path
|
||||
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
|
||||
*/
|
||||
public static function proxifyUrl($url, $size = '')
|
||||
public static function proxifyUrl(string $url, string $size = ''): string
|
||||
{
|
||||
if (!DI::config()->get('system', 'proxify_content')) {
|
||||
return $url;
|
||||
|
@ -133,11 +132,10 @@ class Proxy
|
|||
* proxy storage directory.
|
||||
*
|
||||
* @param string $html Un-proxified HTML code
|
||||
*
|
||||
* @return string Proxified HTML code
|
||||
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
|
||||
*/
|
||||
public static function proxifyHtml($html)
|
||||
public static function proxifyHtml(string $html): string
|
||||
{
|
||||
$html = str_replace(Strings::normaliseLink(DI::baseUrl()) . '/', DI::baseUrl() . '/', $html);
|
||||
|
||||
|
@ -151,7 +149,7 @@ class Proxy
|
|||
* @return boolean
|
||||
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
|
||||
*/
|
||||
public static function isLocalImage($url)
|
||||
public static function isLocalImage(string $url): bool
|
||||
{
|
||||
if (substr($url, 0, 1) == '/') {
|
||||
return true;
|
||||
|
@ -170,7 +168,7 @@ class Proxy
|
|||
* @param string $url URL to parse
|
||||
* @return array Associative array of query string parameters
|
||||
*/
|
||||
private static function parseQuery($url)
|
||||
private static function parseQuery(string $url): array
|
||||
{
|
||||
$query = parse_url($url, PHP_URL_QUERY);
|
||||
$query = html_entity_decode($query);
|
||||
|
@ -187,7 +185,7 @@ class Proxy
|
|||
* @return string Proxified HTML image tag
|
||||
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
|
||||
*/
|
||||
private static function replaceUrl(array $matches)
|
||||
private static function replaceUrl(array $matches): string
|
||||
{
|
||||
// if the picture seems to be from another picture cache then take the original source
|
||||
$queryvar = self::parseQuery($matches[2]);
|
||||
|
|
|
@ -55,7 +55,7 @@ class ReversedFileReader implements \Iterator
|
|||
* @param string $filename File to open
|
||||
* @return $this
|
||||
*/
|
||||
public function open(string $filename)
|
||||
public function open(string $filename): ReversedFileReader
|
||||
{
|
||||
$this->fh = fopen($filename, 'r');
|
||||
if (!$this->fh) {
|
||||
|
@ -73,9 +73,10 @@ class ReversedFileReader implements \Iterator
|
|||
/**
|
||||
* Read $size bytes behind last position
|
||||
*
|
||||
* @param int $size
|
||||
* @return string
|
||||
*/
|
||||
private function _read($size)
|
||||
private function _read(int $size): string
|
||||
{
|
||||
$this->pos -= $size;
|
||||
fseek($this->fh, $this->pos);
|
||||
|
@ -86,7 +87,7 @@ class ReversedFileReader implements \Iterator
|
|||
* Read next line from end of file
|
||||
* Return null if no lines are left to read
|
||||
*
|
||||
* @return ?string
|
||||
* @return string|null Depending on data being buffered
|
||||
*/
|
||||
private function _readline()
|
||||
{
|
||||
|
@ -140,7 +141,7 @@ class ReversedFileReader implements \Iterator
|
|||
* @see Iterator::key()
|
||||
* @return int
|
||||
*/
|
||||
public function key()
|
||||
public function key(): int
|
||||
{
|
||||
return $this->key;
|
||||
}
|
||||
|
@ -151,7 +152,7 @@ class ReversedFileReader implements \Iterator
|
|||
* @see Iterator::current()
|
||||
* @return string
|
||||
*/
|
||||
public function current()
|
||||
public function current(): string
|
||||
{
|
||||
return $this->value;
|
||||
}
|
||||
|
@ -162,7 +163,7 @@ class ReversedFileReader implements \Iterator
|
|||
* @see Iterator::valid()
|
||||
* @return bool
|
||||
*/
|
||||
public function valid()
|
||||
public function valid(): bool
|
||||
{
|
||||
return ! is_null($this->value);
|
||||
}
|
||||
|
|
|
@ -32,11 +32,11 @@ class Strings
|
|||
/**
|
||||
* Generates a pseudo-random string of hexadecimal characters
|
||||
*
|
||||
* @param int $size
|
||||
* @return string
|
||||
* @param int $size Size of string (default: 64)
|
||||
* @return string Pseudo-random string
|
||||
* @throws \Exception
|
||||
*/
|
||||
public static function getRandomHex($size = 64)
|
||||
public static function getRandomHex(int $size = 64): string
|
||||
{
|
||||
$byte_size = ceil($size / 2);
|
||||
|
||||
|
@ -51,10 +51,9 @@ class Strings
|
|||
* Checks, if the given string is a valid hexadecimal code
|
||||
*
|
||||
* @param string $hexCode
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function isHex($hexCode)
|
||||
public static function isHex(string $hexCode): bool
|
||||
{
|
||||
return !empty($hexCode) ? @preg_match("/^[a-f0-9]{2,}$/i", $hexCode) && !(strlen($hexCode) & 1) : false;
|
||||
}
|
||||
|
@ -75,10 +74,9 @@ class Strings
|
|||
* Generate a string that's random, but usually pronounceable. Used to generate initial passwords
|
||||
*
|
||||
* @param int $len length
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function getRandomName($len)
|
||||
public static function getRandomName(int $len): string
|
||||
{
|
||||
if ($len <= 0) {
|
||||
return '';
|
||||
|
@ -161,11 +159,10 @@ class Strings
|
|||
*
|
||||
* @param string $network Network name of the contact (e.g. dfrn, rss and so on)
|
||||
* @param string $url The contact url
|
||||
*
|
||||
* @return string Formatted network name
|
||||
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
|
||||
*/
|
||||
public static function formatNetworkName($network, $url = '')
|
||||
public static function formatNetworkName(string $network, string $url = ''): string
|
||||
{
|
||||
if ($network != '') {
|
||||
if ($url != '') {
|
||||
|
@ -176,6 +173,8 @@ class Strings
|
|||
|
||||
return $network_name;
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -187,7 +186,7 @@ class Strings
|
|||
*
|
||||
* @return string Transformed string.
|
||||
*/
|
||||
public static function deindent($text, $chr = "[\t ]", $count = NULL)
|
||||
public static function deindent(string $text, string $chr = "[\t ]", int $count = null): string
|
||||
{
|
||||
$lines = explode("\n", $text);
|
||||
|
||||
|
@ -216,7 +215,7 @@ class Strings
|
|||
*
|
||||
* @return string Size with measured units.
|
||||
*/
|
||||
public static function formatBytes($bytes, $precision = 2)
|
||||
public static function formatBytes(int $bytes, int $precision = 2): string
|
||||
{
|
||||
$units = ['B', 'KB', 'MB', 'GB', 'TB'];
|
||||
$bytes = max($bytes, 0);
|
||||
|
@ -231,10 +230,9 @@ class Strings
|
|||
* Protect percent characters in sprintf calls
|
||||
*
|
||||
* @param string $s String to transform.
|
||||
*
|
||||
* @return string Transformed string.
|
||||
*/
|
||||
public static function protectSprintf($s)
|
||||
public static function protectSprintf(string $s): string
|
||||
{
|
||||
return str_replace('%', '%%', $s);
|
||||
}
|
||||
|
@ -244,10 +242,9 @@ class Strings
|
|||
*
|
||||
* @param string $s URL to encode
|
||||
* @param boolean $strip_padding Optional. Default false
|
||||
*
|
||||
* @return string Encoded URL
|
||||
*/
|
||||
public static function base64UrlEncode($s, $strip_padding = false)
|
||||
public static function base64UrlEncode(string $s, bool $strip_padding = false): string
|
||||
{
|
||||
$s = strtr(base64_encode($s), '+/', '-_');
|
||||
|
||||
|
@ -260,18 +257,13 @@ class Strings
|
|||
|
||||
/**
|
||||
* Decode Base64 Encoded URL and translate -_ to +/
|
||||
* @param string $s URL to decode
|
||||
*
|
||||
* @param string $s URL to decode
|
||||
* @return string Decoded URL
|
||||
* @throws \Exception
|
||||
*/
|
||||
public static function base64UrlDecode($s)
|
||||
public static function base64UrlDecode(string $s): string
|
||||
{
|
||||
if (is_array($s)) {
|
||||
Logger::notice('base64url_decode: illegal input: ', ['backtrace' => debug_backtrace()]);
|
||||
return $s;
|
||||
}
|
||||
|
||||
/*
|
||||
* // Placeholder for new rev of salmon which strips base64 padding.
|
||||
* // PHP base64_decode handles the un-padded input without requiring this step
|
||||
|
@ -295,10 +287,9 @@ class Strings
|
|||
* Normalize url
|
||||
*
|
||||
* @param string $url URL to be normalized.
|
||||
*
|
||||
* @return string Normalized URL.
|
||||
*/
|
||||
public static function normaliseLink($url)
|
||||
public static function normaliseLink(string $url): string
|
||||
{
|
||||
$ret = str_replace(['https:', '//www.'], ['http:', '//'], $url);
|
||||
return rtrim($ret, '/');
|
||||
|
@ -308,10 +299,9 @@ class Strings
|
|||
* Normalize OpenID identity
|
||||
*
|
||||
* @param string $s OpenID Identity
|
||||
*
|
||||
* @return string normalized OpenId Identity
|
||||
*/
|
||||
public static function normaliseOpenID($s)
|
||||
public static function normaliseOpenID(string $s): string
|
||||
{
|
||||
return trim(str_replace(['http://', 'https://'], ['', ''], $s), '/');
|
||||
}
|
||||
|
@ -327,7 +317,7 @@ class Strings
|
|||
* @return boolean True if the URLs match, otherwise False
|
||||
*
|
||||
*/
|
||||
public static function compareLink($a, $b)
|
||||
public static function compareLink(string $a, string $b): bool
|
||||
{
|
||||
return (strcasecmp(self::normaliseLink($a), self::normaliseLink($b)) === 0);
|
||||
}
|
||||
|
@ -338,7 +328,7 @@ class Strings
|
|||
* @param string $uri
|
||||
* @return string
|
||||
*/
|
||||
public static function ensureQueryParameter($uri)
|
||||
public static function ensureQueryParameter(string $uri): string
|
||||
{
|
||||
if (strpos($uri, '?') === false && ($pos = strpos($uri, '&')) !== false) {
|
||||
$uri = substr($uri, 0, $pos) . '?' . substr($uri, $pos + 1);
|
||||
|
@ -354,7 +344,7 @@ class Strings
|
|||
* @param array $chars
|
||||
* @return bool
|
||||
*/
|
||||
public static function startsWithChars($string, array $chars)
|
||||
public static function startsWithChars(string $string, array $chars): bool
|
||||
{
|
||||
$return = in_array(substr(trim($string), 0, 1), $chars);
|
||||
|
||||
|
@ -369,7 +359,7 @@ class Strings
|
|||
* @param string $start
|
||||
* @return bool
|
||||
*/
|
||||
public static function startsWith(string $string, string $start)
|
||||
public static function startsWith(string $string, string $start): bool
|
||||
{
|
||||
$return = substr_compare($string, $start, 0, strlen($start)) === 0;
|
||||
|
||||
|
@ -384,7 +374,7 @@ class Strings
|
|||
* @param string $end
|
||||
* @return bool
|
||||
*/
|
||||
public static function endsWith(string $string, string $end)
|
||||
public static function endsWith(string $string, string $end): string
|
||||
{
|
||||
$return = substr_compare($string, $end, -strlen($end)) === 0;
|
||||
|
||||
|
@ -397,7 +387,7 @@ class Strings
|
|||
* @return string
|
||||
* @see https://daringfireball.net/2010/07/improved_regex_for_matching_urls
|
||||
*/
|
||||
public static function autoLinkRegEx()
|
||||
public static function autoLinkRegEx(): string
|
||||
{
|
||||
return '@
|
||||
(?<![=\'\]"/]) # Not preceded by [, =, \', ], ", /
|
||||
|
@ -427,7 +417,7 @@ class Strings
|
|||
* @param string $pathItem
|
||||
* @return string
|
||||
*/
|
||||
public static function sanitizeFilePathItem($pathItem)
|
||||
public static function sanitizeFilePathItem(string $pathItem): string
|
||||
{
|
||||
$pathItem = str_replace('/', '_', $pathItem);
|
||||
$pathItem = str_replace('\\', '_', $pathItem);
|
||||
|
@ -449,7 +439,7 @@ class Strings
|
|||
* @return string
|
||||
* @see substr_replace()
|
||||
*/
|
||||
public static function substringReplace(string $string, string $replacement, int $start, int $length = null)
|
||||
public static function substringReplace(string $string, string $replacement, int $start, int $length = null): string
|
||||
{
|
||||
$string_length = mb_strlen($string);
|
||||
|
||||
|
|
301
src/Util/Writer/DbaDefinitionSqlWriter.php
Normal file
301
src/Util/Writer/DbaDefinitionSqlWriter.php
Normal file
|
@ -0,0 +1,301 @@
|
|||
<?php
|
||||
/**
|
||||
* @copyright Copyright (C) 2010-2022, the Friendica project
|
||||
*
|
||||
* @license GNU AGPL version 3 or any later version
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
namespace Friendica\Util\Writer;
|
||||
|
||||
use Exception;
|
||||
use Friendica\Database\Definition\DbaDefinition;
|
||||
|
||||
/**
|
||||
* SQL writer utility for the database definition
|
||||
*/
|
||||
class DbaDefinitionSqlWriter
|
||||
{
|
||||
/**
|
||||
* Creates a complete SQL definition bases on a give DBA Definition class
|
||||
*
|
||||
* @param DbaDefinition $definition The DBA definition class
|
||||
*
|
||||
* @return string The SQL definition as a string
|
||||
*
|
||||
* @throws Exception in case of parameter failures
|
||||
*/
|
||||
public static function create(DbaDefinition $definition): string
|
||||
{
|
||||
$sqlString = "-- ------------------------------------------\n";
|
||||
$sqlString .= "-- " . FRIENDICA_PLATFORM . " " . FRIENDICA_VERSION . " (" . FRIENDICA_CODENAME . ")\n";
|
||||
$sqlString .= "-- DB_UPDATE_VERSION " . DB_UPDATE_VERSION . "\n";
|
||||
$sqlString .= "-- ------------------------------------------\n\n\n";
|
||||
|
||||
foreach ($definition->getAll() as $tableName => $tableStructure) {
|
||||
$sqlString .= "--\n";
|
||||
$sqlString .= "-- TABLE $tableName\n";
|
||||
$sqlString .= "--\n";
|
||||
$sqlString .= static::createTable($tableName, $tableStructure);
|
||||
}
|
||||
|
||||
return $sqlString;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the SQL definition of one table
|
||||
*
|
||||
* @param string $tableName The table name
|
||||
* @param array $tableStructure The table structure
|
||||
*
|
||||
* @return string The SQL definition
|
||||
*
|
||||
* @throws Exception in cases of structure failures
|
||||
*/
|
||||
public static function createTable(string $tableName, array $tableStructure): string
|
||||
{
|
||||
$engine = '';
|
||||
$comment = '';
|
||||
$sql_rows = [];
|
||||
$primary_keys = [];
|
||||
$foreign_keys = [];
|
||||
|
||||
foreach ($tableStructure['fields'] as $fieldName => $field) {
|
||||
$sql_rows[] = '`' . static::escape($fieldName) . '` ' . self::fieldCommand($field);
|
||||
if (!empty($field['primary'])) {
|
||||
$primary_keys[] = $fieldName;
|
||||
}
|
||||
if (!empty($field['foreign'])) {
|
||||
$foreign_keys[$fieldName] = $field;
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($tableStructure['indexes'])) {
|
||||
foreach ($tableStructure['indexes'] as $indexName => $fieldNames) {
|
||||
$sql_index = self::createIndex($indexName, $fieldNames, '');
|
||||
if (!is_null($sql_index)) {
|
||||
$sql_rows[] = $sql_index;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($foreign_keys as $fieldName => $parameters) {
|
||||
$sql_rows[] = self::foreignCommand($fieldName, $parameters);
|
||||
}
|
||||
|
||||
if (isset($tableStructure['engine'])) {
|
||||
$engine = ' ENGINE=' . $tableStructure['engine'];
|
||||
}
|
||||
|
||||
if (isset($tableStructure['comment'])) {
|
||||
$comment = " COMMENT='" . static::escape($tableStructure['comment']) . "'";
|
||||
}
|
||||
|
||||
$sql = implode(",\n\t", $sql_rows);
|
||||
|
||||
$sql = sprintf("CREATE TABLE IF NOT EXISTS `%s` (\n\t", static::escape($tableName)) . $sql .
|
||||
"\n)" . $engine . " DEFAULT COLLATE utf8mb4_general_ci" . $comment;
|
||||
return $sql . ";\n\n";
|
||||
}
|
||||
|
||||
/**
|
||||
* Standard escaping for SQL definitions
|
||||
*
|
||||
* @param string $sqlString the SQL string to escape
|
||||
*
|
||||
* @return string escaped SQL string
|
||||
*/
|
||||
public static function escape(string $sqlString): string
|
||||
{
|
||||
return str_replace("'", "\\'", $sqlString);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the SQL definition to add a foreign key
|
||||
*
|
||||
* @param string $keyName The foreign key name
|
||||
* @param array $parameters The given parameters of the foreign key
|
||||
*
|
||||
* @return string The SQL definition
|
||||
*/
|
||||
public static function addForeignKey(string $keyName, array $parameters): string
|
||||
{
|
||||
return sprintf("ADD %s", static::foreignCommand($keyName, $parameters));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the SQL definition to drop a foreign key
|
||||
*
|
||||
* @param string $keyName The foreign key name
|
||||
*
|
||||
* @return string The SQL definition
|
||||
*/
|
||||
public static function dropForeignKey(string $keyName): string
|
||||
{
|
||||
return sprintf("DROP FOREIGN KEY `%s`", $keyName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the SQL definition to drop an index
|
||||
*
|
||||
* @param string $indexName The index name
|
||||
*
|
||||
* @return string The SQL definition
|
||||
*/
|
||||
public static function dropIndex(string $indexName): string
|
||||
{
|
||||
return sprintf("DROP INDEX `%s`", static::escape($indexName));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the SQL definition to add a table field
|
||||
*
|
||||
* @param string $fieldName The table field name
|
||||
* @param array $parameters The parameters of the table field
|
||||
*
|
||||
* @return string The SQL definition
|
||||
*/
|
||||
public static function addTableField(string $fieldName, array $parameters): string
|
||||
{
|
||||
return sprintf("ADD `%s` %s", static::escape($fieldName), static::fieldCommand($parameters));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the SQL definition to modify a table field
|
||||
*
|
||||
* @param string $fieldName The table field name
|
||||
* @param array $parameters The paramters to modify
|
||||
*
|
||||
* @return string The SQL definition
|
||||
*/
|
||||
public static function modifyTableField(string $fieldName, array $parameters): string
|
||||
{
|
||||
return sprintf("MODIFY `%s` %s", static::escape($fieldName), self::fieldCommand($parameters, false));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns SQL statement for field
|
||||
*
|
||||
* @param array $parameters Parameters for SQL statement
|
||||
* @param boolean $create Whether to include PRIMARY KEY statement (unused)
|
||||
* @return string SQL statement part
|
||||
*/
|
||||
public static function fieldCommand(array $parameters, bool $create = true): string
|
||||
{
|
||||
$fieldstruct = $parameters['type'];
|
||||
|
||||
if (isset($parameters['Collation'])) {
|
||||
$fieldstruct .= ' COLLATE ' . $parameters['Collation'];
|
||||
}
|
||||
|
||||
if (isset($parameters['not null'])) {
|
||||
$fieldstruct .= ' NOT NULL';
|
||||
}
|
||||
|
||||
if (isset($parameters['default'])) {
|
||||
if (strpos(strtolower($parameters['type']), 'int') !== false) {
|
||||
$fieldstruct .= ' DEFAULT ' . $parameters['default'];
|
||||
} else {
|
||||
$fieldstruct .= " DEFAULT '" . $parameters['default'] . "'";
|
||||
}
|
||||
}
|
||||
if (isset($parameters['extra'])) {
|
||||
$fieldstruct .= ' ' . $parameters['extra'];
|
||||
}
|
||||
|
||||
if (isset($parameters['comment'])) {
|
||||
$fieldstruct .= " COMMENT '" . static::escape($parameters['comment']) . "'";
|
||||
}
|
||||
|
||||
/*if (($parameters['primary'] != '') && $create)
|
||||
$fieldstruct .= ' PRIMARY KEY';*/
|
||||
|
||||
return $fieldstruct;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the SQL definition to create an index
|
||||
*
|
||||
* @param string $indexName The index name
|
||||
* @param array $fieldNames The field names of this index
|
||||
* @param string $method The method to create the index (default is ADD)
|
||||
*
|
||||
* @return string The SQL definition
|
||||
* @throws Exception in cases the paramter contains invalid content
|
||||
*/
|
||||
public static function createIndex(string $indexName, array $fieldNames, string $method = 'ADD'): string
|
||||
{
|
||||
$method = strtoupper(trim($method));
|
||||
if ($method != '' && $method != 'ADD') {
|
||||
throw new Exception("Invalid parameter 'method' in self::createIndex(): '$method'");
|
||||
}
|
||||
|
||||
if (in_array($fieldNames[0], ['UNIQUE', 'FULLTEXT'])) {
|
||||
$index_type = array_shift($fieldNames);
|
||||
$method .= " " . $index_type;
|
||||
}
|
||||
|
||||
$names = "";
|
||||
foreach ($fieldNames as $fieldName) {
|
||||
if ($names != '') {
|
||||
$names .= ',';
|
||||
}
|
||||
|
||||
if (preg_match('|(.+)\((\d+)\)|', $fieldName, $matches)) {
|
||||
$names .= "`" . static::escape($matches[1]) . "`(" . intval($matches[2]) . ")";
|
||||
} else {
|
||||
$names .= "`" . static::escape($fieldName) . "`";
|
||||
}
|
||||
}
|
||||
|
||||
if ($indexName == 'PRIMARY') {
|
||||
return sprintf("%s PRIMARY KEY(%s)", $method, $names);
|
||||
}
|
||||
|
||||
|
||||
return sprintf("%s INDEX `%s` (%s)", $method, static::escape($indexName), $names);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the SQL definition for foreign keys
|
||||
*
|
||||
* @param string $foreignKeyName The foreign key name
|
||||
* @param array $parameters The parameters of the foreign key
|
||||
*
|
||||
* @return string The SQL definition
|
||||
*/
|
||||
public static function foreignCommand(string $foreignKeyName, array $parameters): string
|
||||
{
|
||||
$foreign_table = array_keys($parameters['foreign'])[0];
|
||||
$foreign_field = array_values($parameters['foreign'])[0];
|
||||
|
||||
$sql = "FOREIGN KEY (`" . $foreignKeyName . "`) REFERENCES `" . $foreign_table . "` (`" . $foreign_field . "`)";
|
||||
|
||||
if (!empty($parameters['foreign']['on update'])) {
|
||||
$sql .= " ON UPDATE " . strtoupper($parameters['foreign']['on update']);
|
||||
} else {
|
||||
$sql .= " ON UPDATE RESTRICT";
|
||||
}
|
||||
|
||||
if (!empty($parameters['foreign']['on delete'])) {
|
||||
$sql .= " ON DELETE " . strtoupper($parameters['foreign']['on delete']);
|
||||
} else {
|
||||
$sql .= " ON DELETE CASCADE";
|
||||
}
|
||||
|
||||
return $sql;
|
||||
}
|
||||
}
|
145
src/Util/Writer/DocWriter.php
Normal file
145
src/Util/Writer/DocWriter.php
Normal file
|
@ -0,0 +1,145 @@
|
|||
<?php
|
||||
/**
|
||||
* @copyright Copyright (C) 2010-2022, the Friendica project
|
||||
*
|
||||
* @license GNU AGPL version 3 or any later version
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
namespace Friendica\Util\Writer;
|
||||
|
||||
use Friendica\Core\Renderer;
|
||||
use Friendica\Database\Definition\DbaDefinition;
|
||||
use Friendica\Network\HTTPException\ServiceUnavailableException;
|
||||
|
||||
/**
|
||||
* Utility class to write content into the '/doc' directory
|
||||
*/
|
||||
class DocWriter
|
||||
{
|
||||
/**
|
||||
* Creates all database definitions as Markdown fields and create the mkdoc config file.
|
||||
*
|
||||
* @param DbaDefinition $definition The Database definition class
|
||||
* @param string $basePath The basepath of Friendica
|
||||
*
|
||||
* @return void
|
||||
* @throws ServiceUnavailableException in really unexpected cases!
|
||||
*/
|
||||
public static function writeDbDefinition(DbaDefinition $definition, string $basePath)
|
||||
{
|
||||
$tables = [];
|
||||
foreach ($definition->getAll() as $name => $definition) {
|
||||
$indexes = [
|
||||
[
|
||||
'name' => 'Name',
|
||||
'fields' => 'Fields',
|
||||
],
|
||||
[
|
||||
'name' => '-',
|
||||
'fields' => '-',
|
||||
]
|
||||
];
|
||||
|
||||
$lengths = ['name' => 4, 'fields' => 6];
|
||||
foreach ($definition['indexes'] as $key => $value) {
|
||||
$fieldlist = implode(', ', $value);
|
||||
$indexes[] = ['name' => $key, 'fields' => $fieldlist];
|
||||
$lengths['name'] = max($lengths['name'], strlen($key));
|
||||
$lengths['fields'] = max($lengths['fields'], strlen($fieldlist));
|
||||
}
|
||||
|
||||
array_walk_recursive($indexes, function (&$value, $key) use ($lengths) {
|
||||
$value = str_pad($value, $lengths[$key], $value === '-' ? '-' : ' ');
|
||||
});
|
||||
|
||||
$foreign = [];
|
||||
$fields = [
|
||||
[
|
||||
'name' => 'Field',
|
||||
'comment' => 'Description',
|
||||
'type' => 'Type',
|
||||
'null' => 'Null',
|
||||
'primary' => 'Key',
|
||||
'default' => 'Default',
|
||||
'extra' => 'Extra',
|
||||
],
|
||||
[
|
||||
'name' => '-',
|
||||
'comment' => '-',
|
||||
'type' => '-',
|
||||
'null' => '-',
|
||||
'primary' => '-',
|
||||
'default' => '-',
|
||||
'extra' => '-',
|
||||
]
|
||||
];
|
||||
$lengths = [
|
||||
'name' => 5,
|
||||
'comment' => 11,
|
||||
'type' => 4,
|
||||
'null' => 4,
|
||||
'primary' => 3,
|
||||
'default' => 7,
|
||||
'extra' => 5,
|
||||
];
|
||||
foreach ($definition['fields'] as $key => $value) {
|
||||
$field = [];
|
||||
$field['name'] = $key;
|
||||
$field['comment'] = $value['comment'] ?? '';
|
||||
$field['type'] = $value['type'];
|
||||
$field['null'] = ($value['not null'] ?? false) ? 'NO' : 'YES';
|
||||
$field['primary'] = ($value['primary'] ?? false) ? 'PRI' : '';
|
||||
$field['default'] = $value['default'] ?? 'NULL';
|
||||
$field['extra'] = $value['extra'] ?? '';
|
||||
|
||||
foreach ($field as $fieldName => $fieldvalue) {
|
||||
$lengths[$fieldName] = max($lengths[$fieldName] ?? 0, strlen($fieldvalue));
|
||||
}
|
||||
$fields[] = $field;
|
||||
|
||||
if (!empty($value['foreign'])) {
|
||||
$foreign[] = [
|
||||
'field' => $key,
|
||||
'targettable' => array_keys($value['foreign'])[0],
|
||||
'targetfield' => array_values($value['foreign'])[0]
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
array_walk_recursive($fields, function (&$value, $key) use ($lengths) {
|
||||
$value = str_pad($value, $lengths[$key], $value === '-' ? '-' : ' ');
|
||||
});
|
||||
|
||||
$tables[] = ['name' => $name, 'comment' => $definition['comment']];
|
||||
$content = Renderer::replaceMacros(Renderer::getMarkupTemplate('structure.tpl'), [
|
||||
'$name' => $name,
|
||||
'$comment' => $definition['comment'],
|
||||
'$fields' => $fields,
|
||||
'$indexes' => $indexes,
|
||||
'$foreign' => $foreign,
|
||||
]);
|
||||
$filename = $basePath . '/doc/database/db_' . $name . '.md';
|
||||
file_put_contents($filename, $content);
|
||||
}
|
||||
asort($tables);
|
||||
$content = Renderer::replaceMacros(Renderer::getMarkupTemplate('tables.tpl'), [
|
||||
'$tables' => $tables,
|
||||
]);
|
||||
$filename = $basePath . '/doc/database.md';
|
||||
file_put_contents($filename, $content);
|
||||
}
|
||||
}
|
98
src/Util/Writer/ViewDefinitionSqlWriter.php
Normal file
98
src/Util/Writer/ViewDefinitionSqlWriter.php
Normal file
|
@ -0,0 +1,98 @@
|
|||
<?php
|
||||
/**
|
||||
* @copyright Copyright (C) 2010-2022, the Friendica project
|
||||
*
|
||||
* @license GNU AGPL version 3 or any later version
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
namespace Friendica\Util\Writer;
|
||||
|
||||
use Friendica\Database\Definition\ViewDefinition;
|
||||
|
||||
/**
|
||||
* SQL writer utility for the db view definition
|
||||
*/
|
||||
class ViewDefinitionSqlWriter
|
||||
{
|
||||
/**
|
||||
* Creates a complete SQL definition bases on a give View Definition class
|
||||
*
|
||||
* @param ViewDefinition $definition The View definition class
|
||||
*
|
||||
* @return string The SQL definition as a string
|
||||
*/
|
||||
public static function create(ViewDefinition $definition): string
|
||||
{
|
||||
$sqlString = '';
|
||||
|
||||
foreach ($definition->getAll() as $viewName => $viewStructure) {
|
||||
$sqlString .= "--\n";
|
||||
$sqlString .= "-- VIEW $viewName\n";
|
||||
$sqlString .= "--\n";
|
||||
$sqlString .= static::dropView($viewName);
|
||||
$sqlString .= static::createView($viewName, $viewStructure);
|
||||
}
|
||||
|
||||
return $sqlString;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the SQL definition to drop a view
|
||||
*
|
||||
* @param string $viewName the view name
|
||||
*
|
||||
* @return string The SQL definition
|
||||
*/
|
||||
public static function dropView(string $viewName): string
|
||||
{
|
||||
return sprintf("DROP VIEW IF EXISTS `%s`", static::escape($viewName)) . ";\n";
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the SQL definition to create a new view
|
||||
*
|
||||
* @param string $viewName The view name
|
||||
* @param array $viewStructure The structure information of the view
|
||||
*
|
||||
* @return string The SQL definition
|
||||
*/
|
||||
public static function createView(string $viewName, array $viewStructure): string
|
||||
{
|
||||
$sql_rows = [];
|
||||
foreach ($viewStructure['fields'] as $fieldname => $origin) {
|
||||
if (is_string($origin)) {
|
||||
$sql_rows[] = $origin . " AS `" . static::escape($fieldname) . "`";
|
||||
} elseif (is_array($origin) && (sizeof($origin) == 2)) {
|
||||
$sql_rows[] = "`" . static::escape($origin[0]) . "`.`" . static::escape($origin[1]) . "` AS `" . static::escape($fieldname) . "`";
|
||||
}
|
||||
}
|
||||
return sprintf("CREATE VIEW `%s` AS SELECT \n\t", static::escape($viewName)) .
|
||||
implode(",\n\t", $sql_rows) . "\n\t" . $viewStructure['query'] . ";\n\n";
|
||||
}
|
||||
|
||||
/**
|
||||
* Standard escaping for SQL definitions
|
||||
*
|
||||
* @param string $sqlString the SQL string to escape
|
||||
*
|
||||
* @return string escaped SQL string
|
||||
*/
|
||||
public static function escape(string $sqlString): string
|
||||
{
|
||||
return str_replace("'", "\\'", $sqlString);
|
||||
}
|
||||
}
|
134
src/Util/XML.php
134
src/Util/XML.php
|
@ -21,6 +21,9 @@
|
|||
|
||||
namespace Friendica\Util;
|
||||
|
||||
use DOMDocument;
|
||||
use DOMElement;
|
||||
use DOMNode;
|
||||
use DOMXPath;
|
||||
use Friendica\Core\Logger;
|
||||
use Friendica\Core\System;
|
||||
|
@ -35,26 +38,25 @@ class XML
|
|||
* Creates an XML structure out of a given array
|
||||
*
|
||||
* @param array $array The array of the XML structure that will be generated
|
||||
* @param object $xml The createdXML will be returned by reference
|
||||
* @param object $xml The created XML will be returned by reference
|
||||
* @param bool $remove_header Should the XML header be removed or not?
|
||||
* @param array $namespaces List of namespaces
|
||||
* @param bool $root interally used parameter. Mustn't be used from outside.
|
||||
*
|
||||
* @return string The created XML
|
||||
* @return void
|
||||
*/
|
||||
public static function fromArray($array, &$xml, $remove_header = false, $namespaces = [], $root = true)
|
||||
public static function fromArray(array $array, &$xml, bool $remove_header = false, array $namespaces = [], bool $root = true)
|
||||
{
|
||||
if ($root) {
|
||||
foreach ($array as $key => $value) {
|
||||
foreach ($namespaces as $nskey => $nsvalue) {
|
||||
$key .= " xmlns".($nskey == "" ? "":":").$nskey.'="'.$nsvalue.'"';
|
||||
$key .= ' xmlns' . ($nskey == '' ? '' : ':') . $nskey . '="' . $nsvalue . '"';
|
||||
}
|
||||
|
||||
if (is_array($value)) {
|
||||
$root = new SimpleXMLElement("<".$key."/>");
|
||||
$root = new SimpleXMLElement('<' . $key . '/>');
|
||||
self::fromArray($value, $root, $remove_header, $namespaces, false);
|
||||
} else {
|
||||
$root = new SimpleXMLElement("<".$key.">".self::escape($value)."</".$key.">");
|
||||
$root = new SimpleXMLElement('<' . $key . '>' . self::escape($value ?? '') . '</' . $key . '>');
|
||||
}
|
||||
|
||||
$dom = dom_import_simplexml($root)->ownerDocument;
|
||||
|
@ -88,11 +90,11 @@ class XML
|
|||
continue;
|
||||
}
|
||||
|
||||
$element_parts = explode(":", $key);
|
||||
$element_parts = explode(':', $key);
|
||||
if ((count($element_parts) > 1) && isset($namespaces[$element_parts[0]])) {
|
||||
$namespace = $namespaces[$element_parts[0]];
|
||||
} elseif (isset($namespaces[""])) {
|
||||
$namespace = $namespaces[""];
|
||||
} elseif (isset($namespaces[''])) {
|
||||
$namespace = $namespaces[''];
|
||||
} else {
|
||||
$namespace = null;
|
||||
}
|
||||
|
@ -102,13 +104,13 @@ class XML
|
|||
$key = $element_parts[1];
|
||||
}
|
||||
|
||||
if (substr($key, 0, 11) == "@attributes") {
|
||||
if (substr($key, 0, 11) == '@attributes') {
|
||||
if (!isset($element) || !is_array($value)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
foreach ($value as $attr_key => $attr_value) {
|
||||
$element_parts = explode(":", $attr_key);
|
||||
$element_parts = explode(':', $attr_key);
|
||||
if ((count($element_parts) > 1) && isset($namespaces[$element_parts[0]])) {
|
||||
$namespace = $namespaces[$element_parts[0]];
|
||||
} else {
|
||||
|
@ -122,7 +124,7 @@ class XML
|
|||
}
|
||||
|
||||
if (!is_array($value)) {
|
||||
$element = $xml->addChild($key, self::escape($value), $namespace);
|
||||
$element = $xml->addChild($key, self::escape($value ?? ''), $namespace);
|
||||
} elseif (is_array($value)) {
|
||||
$element = $xml->addChild($key, null, $namespace);
|
||||
self::fromArray($value, $element, $remove_header, $namespaces, false);
|
||||
|
@ -138,7 +140,7 @@ class XML
|
|||
* @param string $elementname Name of the XML element of the target
|
||||
* @return void
|
||||
*/
|
||||
public static function copy(&$source, &$target, $elementname)
|
||||
public static function copy(&$source, &$target, string $elementname)
|
||||
{
|
||||
if (count($source->children()) == 0) {
|
||||
$target->addChild($elementname, self::escape($source));
|
||||
|
@ -153,20 +155,20 @@ class XML
|
|||
/**
|
||||
* Create an XML element
|
||||
*
|
||||
* @param \DOMDocument $doc XML root
|
||||
* @param DOMDocument $doc XML root
|
||||
* @param string $element XML element name
|
||||
* @param string $value XML value
|
||||
* @param array $attributes array containing the attributes
|
||||
*
|
||||
* @return \DOMElement XML element object
|
||||
*/
|
||||
public static function createElement(\DOMDocument $doc, $element, $value = "", $attributes = [])
|
||||
public static function createElement(DOMDocument $doc, string $element, string $value = '', array $attributes = []): DOMElement
|
||||
{
|
||||
$element = $doc->createElement($element, self::escape($value));
|
||||
|
||||
foreach ($attributes as $key => $value) {
|
||||
$attribute = $doc->createAttribute($key);
|
||||
$attribute->value = self::escape($value);
|
||||
$attribute->value = self::escape($value ?? '');
|
||||
$element->appendChild($attribute);
|
||||
}
|
||||
return $element;
|
||||
|
@ -175,22 +177,21 @@ class XML
|
|||
/**
|
||||
* Create an XML and append it to the parent object
|
||||
*
|
||||
* @param \DOMDocument $doc XML root
|
||||
* @param object $parent parent object
|
||||
* @param string $element XML element name
|
||||
* @param string $value XML value
|
||||
* @param array $attributes array containing the attributes
|
||||
* @param DOMDocument $doc XML root
|
||||
* @param DOMElement $parent parent object
|
||||
* @param string $element XML element name
|
||||
* @param string $value XML value
|
||||
* @param array $attributes Array containing the attributes
|
||||
* @return void
|
||||
*/
|
||||
public static function addElement(\DOMDocument $doc, $parent, $element, $value = "", $attributes = [])
|
||||
public static function addElement(DOMDocument $doc, DOMElement &$parent, string $element, string $value = '', array $attributes = [])
|
||||
{
|
||||
$element = self::createElement($doc, $element, $value, $attributes);
|
||||
$parent->appendChild($element);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert an XML document to a normalised, case-corrected array
|
||||
* used by webfinger
|
||||
* Convert an XML document to a normalised, case-corrected array used by webfinger
|
||||
*
|
||||
* @param object $xml_element The XML document
|
||||
* @param integer $recursion_depth recursion counter for internal use - default 0
|
||||
|
@ -198,11 +199,11 @@ class XML
|
|||
*
|
||||
* @return array | string The array from the xml element or the string
|
||||
*/
|
||||
public static function elementToArray($xml_element, &$recursion_depth = 0)
|
||||
public static function elementToArray($xml_element, int &$recursion_depth = 0)
|
||||
{
|
||||
// If we're getting too deep, bail out
|
||||
if ($recursion_depth > 512) {
|
||||
return(null);
|
||||
return null;
|
||||
}
|
||||
|
||||
$xml_element_copy = '';
|
||||
|
@ -217,7 +218,7 @@ class XML
|
|||
if (is_array($xml_element)) {
|
||||
$result_array = [];
|
||||
if (count($xml_element) <= 0) {
|
||||
return (trim(strval($xml_element_copy)));
|
||||
return trim(strval($xml_element_copy));
|
||||
}
|
||||
|
||||
foreach ($xml_element as $key => $value) {
|
||||
|
@ -233,9 +234,9 @@ class XML
|
|||
];
|
||||
}
|
||||
|
||||
return ($result_array);
|
||||
return $result_array;
|
||||
} else {
|
||||
return (trim(strval($xml_element)));
|
||||
return trim(strval($xml_element));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -261,7 +262,7 @@ class XML
|
|||
* @return array The parsed XML in an array form. Use print_r() to see the resulting array structure.
|
||||
* @throws \Exception
|
||||
*/
|
||||
public static function toArray($contents, $namespaces = true, $get_attributes = 1, $priority = 'attribute')
|
||||
public static function toArray(string $contents, bool $namespaces = true, int $get_attributes = 1, string $priority = 'attribute'): array
|
||||
{
|
||||
if (!$contents) {
|
||||
return [];
|
||||
|
@ -300,7 +301,7 @@ class XML
|
|||
Logger::debug('libxml: parse: ' . $err->code . " at " . $err->line . ":" . $err->column . " : " . $err->message);
|
||||
}
|
||||
libxml_clear_errors();
|
||||
return;
|
||||
return [];
|
||||
}
|
||||
|
||||
//Initializations
|
||||
|
@ -414,20 +415,20 @@ class XML
|
|||
}
|
||||
}
|
||||
|
||||
return($xml_array);
|
||||
return $xml_array;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a node in a XML object
|
||||
*
|
||||
* @param \DOMDocument $doc XML document
|
||||
* @param DOMDocument $doc XML document
|
||||
* @param string $node Node name
|
||||
* @return void
|
||||
*/
|
||||
public static function deleteNode(\DOMDocument $doc, $node)
|
||||
public static function deleteNode(DOMDocument $doc, string $node)
|
||||
{
|
||||
$xpath = new DOMXPath($doc);
|
||||
$list = $xpath->query("//".$node);
|
||||
$list = $xpath->query('//' . $node);
|
||||
foreach ($list as $child) {
|
||||
$child->parentNode->removeChild($child);
|
||||
}
|
||||
|
@ -436,9 +437,9 @@ class XML
|
|||
/**
|
||||
* Parse XML string
|
||||
*
|
||||
* @param string $s
|
||||
* @param boolean $suppress_log
|
||||
* @return Object
|
||||
* @param string $s XML string to parse into object
|
||||
* @param boolean $suppress_log Whether to supressing logging
|
||||
* @return SimpleXMLElement|bool SimpleXMLElement or false on failure
|
||||
*/
|
||||
public static function parseString(string $s, bool $suppress_log = false)
|
||||
{
|
||||
|
@ -458,7 +459,15 @@ class XML
|
|||
return $x;
|
||||
}
|
||||
|
||||
public static function getFirstNodeValue(DOMXPath $xpath, $element, $context = null)
|
||||
/**
|
||||
* Gets first node value
|
||||
*
|
||||
* @param DOMXPath $xpath XPath object
|
||||
* @param string $element Element name
|
||||
* @param DOMNode $context Context object or NULL
|
||||
* @return string XML node value or empty string on failure
|
||||
*/
|
||||
public static function getFirstNodeValue(DOMXPath $xpath, string $element, DOMNode $context = null)
|
||||
{
|
||||
$result = @$xpath->evaluate($element, $context);
|
||||
if (!is_object($result)) {
|
||||
|
@ -473,7 +482,15 @@ class XML
|
|||
return $first_item->nodeValue;
|
||||
}
|
||||
|
||||
public static function getFirstAttributes(DOMXPath $xpath, $element, $context = null)
|
||||
/**
|
||||
* Gets first attributes
|
||||
*
|
||||
* @param DOMXPath $xpath XPath object
|
||||
* @param string $element Element name
|
||||
* @param DOMNode $context Context object or NULL
|
||||
* @return ???|bool First element's attributes field or false on failure
|
||||
*/
|
||||
public static function getFirstAttributes(DOMXPath $xpath, string $element, DOMNode $context = null)
|
||||
{
|
||||
$result = @$xpath->query($element, $context);
|
||||
if (!is_object($result)) {
|
||||
|
@ -488,9 +505,17 @@ class XML
|
|||
return $first_item->attributes;
|
||||
}
|
||||
|
||||
public static function getFirstValue($xpath, $search, $context)
|
||||
/**
|
||||
* Gets first node's value
|
||||
*
|
||||
* @param DOMXPath $xpath XPath object
|
||||
* @param string $element Element name
|
||||
* @param DOMNode $context Context object or NULL
|
||||
* @return string First value or empty string on failure
|
||||
*/
|
||||
public static function getFirstValue(DOMXPath $xpath, string $element, DOMNode $context = null): string
|
||||
{
|
||||
$result = @$xpath->query($search, $context);
|
||||
$result = @$xpath->query($element, $context);
|
||||
if (!is_object($result)) {
|
||||
return '';
|
||||
}
|
||||
|
@ -508,32 +533,31 @@ class XML
|
|||
*
|
||||
* @param string $str
|
||||
* @return string Escaped text.
|
||||
* @todo Move this generic method to Util\Strings and also rewrite all other findingd
|
||||
*/
|
||||
public static function escape($str)
|
||||
public static function escape(string $str): string
|
||||
{
|
||||
$buffer = htmlspecialchars($str, ENT_QUOTES, 'UTF-8');
|
||||
$buffer = trim($buffer);
|
||||
|
||||
return $buffer;
|
||||
return trim(htmlspecialchars($str, ENT_QUOTES, 'UTF-8'));
|
||||
}
|
||||
|
||||
/**
|
||||
* undo an escape
|
||||
* Undo an escape
|
||||
*
|
||||
* @param string $s xml escaped text
|
||||
* @return string unescaped text
|
||||
* @todo Move this generic method to Util\Strings and also rewrite all other findingd
|
||||
*/
|
||||
public static function unescape($s)
|
||||
public static function unescape(string $s): string
|
||||
{
|
||||
$ret = htmlspecialchars_decode($s, ENT_QUOTES);
|
||||
return $ret;
|
||||
return htmlspecialchars_decode($s, ENT_QUOTES);
|
||||
}
|
||||
|
||||
/**
|
||||
* apply escape() to all values of array $val, recursively
|
||||
* Apply escape() to all values of array $val, recursively
|
||||
*
|
||||
* @param array $val
|
||||
* @return array|string
|
||||
* @param array|bool|string $val Value of type bool, array or string
|
||||
* @return array|string Returns array if array provided or string in other cases
|
||||
* @todo Move this generic method to Util\Strings
|
||||
*/
|
||||
public static function arrayEscape($val)
|
||||
{
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue