Merge remote-tracking branch 'upstream/develop' into server-detection
This commit is contained in:
commit
8b7cb5d9ef
|
@ -90,3 +90,11 @@ venv/
|
|||
#ignore avatar picture cache path
|
||||
/avatar
|
||||
|
||||
#Ignore autotest results
|
||||
autotest-results.xml
|
||||
|
||||
#ignore phpunit result cache
|
||||
tests/.phpunit.result.cache
|
||||
|
||||
#ignore .php_cs (local copy)
|
||||
.php_cs
|
||||
|
|
|
@ -9,7 +9,10 @@ depends_on:
|
|||
- database_checks
|
||||
- messages.po_check
|
||||
|
||||
platform: releaser/release # This prevents executing this pipeline at other servers than ci.friendi.ca
|
||||
# This prevents executing this pipeline at other servers than ci.friendi.ca
|
||||
labels:
|
||||
location: friendica
|
||||
type: releaser
|
||||
|
||||
skip_clone: true
|
||||
|
||||
|
|
|
@ -7,7 +7,10 @@ depends_on:
|
|||
- phpunit
|
||||
- code_standards_check
|
||||
|
||||
platform: releaser/release # This prevents executing this pipeline at other servers than ci.friendi.ca
|
||||
# This prevents executing this pipeline at other servers than ci.friendi.ca
|
||||
labels:
|
||||
location: friendica
|
||||
type: releaser
|
||||
|
||||
skip_clone: true
|
||||
|
||||
|
|
Binary file not shown.
|
@ -26,7 +26,7 @@
|
|||
* This script was taken from http://php.net/manual/en/function.pcntl-fork.php
|
||||
*/
|
||||
if (php_sapi_name() !== 'cli') {
|
||||
header($_SERVER["SERVER_PROTOCOL"] . ' 403 Forbidden');
|
||||
header($_SERVER['SERVER_PROTOCOL'] . ' 403 Forbidden');
|
||||
exit();
|
||||
}
|
||||
|
||||
|
@ -45,13 +45,13 @@ $longopts = ['foreground'];
|
|||
$options = getopt($shortopts, $longopts);
|
||||
|
||||
// Ensure that daemon.php is executed from the base path of the installation
|
||||
if (!file_exists("boot.php") && (sizeof($_SERVER["argv"]) != 0)) {
|
||||
$directory = dirname($_SERVER["argv"][0]);
|
||||
if (!file_exists('boot.php') && (sizeof($_SERVER['argv']) != 0)) {
|
||||
$directory = dirname($_SERVER['argv'][0]);
|
||||
|
||||
if (substr($directory, 0, 1) != "/") {
|
||||
$directory = $_SERVER["PWD"] . "/" . $directory;
|
||||
if (substr($directory, 0, 1) != '/') {
|
||||
$directory = $_SERVER['PWD'] . '/' . $directory;
|
||||
}
|
||||
$directory = realpath($directory . "/..");
|
||||
$directory = realpath($directory . '/..');
|
||||
|
||||
chdir($directory);
|
||||
}
|
||||
|
@ -86,16 +86,16 @@ TXT
|
|||
|
||||
$pidfile = DI::config()->get('system', 'pidfile');
|
||||
|
||||
if (in_array("start", $_SERVER["argv"])) {
|
||||
$mode = "start";
|
||||
if (in_array('start', $_SERVER['argv'])) {
|
||||
$mode = 'start';
|
||||
}
|
||||
|
||||
if (in_array("stop", $_SERVER["argv"])) {
|
||||
$mode = "stop";
|
||||
if (in_array('stop', $_SERVER['argv'])) {
|
||||
$mode = 'stop';
|
||||
}
|
||||
|
||||
if (in_array("status", $_SERVER["argv"])) {
|
||||
$mode = "status";
|
||||
if (in_array('status', $_SERVER['argv'])) {
|
||||
$mode = 'status';
|
||||
}
|
||||
|
||||
$foreground = array_key_exists('f', $options) || array_key_exists('foreground', $options);
|
||||
|
@ -104,7 +104,7 @@ if (!isset($mode)) {
|
|||
die("Please use either 'start', 'stop' or 'status'.\n");
|
||||
}
|
||||
|
||||
if (empty($_SERVER["argv"][0])) {
|
||||
if (empty($_SERVER['argv'][0])) {
|
||||
die("Unexpected script behaviour. This message should never occur.\n");
|
||||
}
|
||||
|
||||
|
@ -114,12 +114,12 @@ if (is_readable($pidfile)) {
|
|||
$pid = intval(file_get_contents($pidfile));
|
||||
}
|
||||
|
||||
if (empty($pid) && in_array($mode, ["stop", "status"])) {
|
||||
if (empty($pid) && in_array($mode, ['stop', 'status'])) {
|
||||
DI::config()->set('system', 'worker_daemon_mode', false);
|
||||
die("Pidfile wasn't found. Is the daemon running?\n");
|
||||
}
|
||||
|
||||
if ($mode == "status") {
|
||||
if ($mode == 'status') {
|
||||
if (posix_kill($pid, 0)) {
|
||||
die("Daemon process $pid is running.\n");
|
||||
}
|
||||
|
@ -130,12 +130,12 @@ if ($mode == "status") {
|
|||
die("Daemon process $pid isn't running.\n");
|
||||
}
|
||||
|
||||
if ($mode == "stop") {
|
||||
if ($mode == 'stop') {
|
||||
posix_kill($pid, SIGTERM);
|
||||
|
||||
unlink($pidfile);
|
||||
|
||||
Logger::notice("Worker daemon process was killed", ["pid" => $pid]);
|
||||
Logger::notice('Worker daemon process was killed', ['pid' => $pid]);
|
||||
|
||||
DI::config()->set('system', 'worker_daemon_mode', false);
|
||||
die("Worker daemon process $pid was killed.\n");
|
||||
|
@ -145,7 +145,7 @@ if (!empty($pid) && posix_kill($pid, 0)) {
|
|||
die("Daemon process $pid is already running.\n");
|
||||
}
|
||||
|
||||
Logger::notice('Starting worker daemon.', ["pid" => $pid]);
|
||||
Logger::notice('Starting worker daemon.', ['pid' => $pid]);
|
||||
|
||||
if (!$foreground) {
|
||||
echo "Starting worker daemon.\n";
|
||||
|
@ -194,7 +194,7 @@ $last_cron = 0;
|
|||
// Now running as a daemon.
|
||||
while (true) {
|
||||
if (!$do_cron && ($last_cron + $wait_interval) < time()) {
|
||||
Logger::info('Forcing cron worker call.', ["pid" => $pid]);
|
||||
Logger::info('Forcing cron worker call.', ['pid' => $pid]);
|
||||
$do_cron = true;
|
||||
}
|
||||
|
||||
|
@ -214,7 +214,7 @@ while (true) {
|
|||
}
|
||||
|
||||
$start = time();
|
||||
Logger::info("Sleeping", ["pid" => $pid, 'until' => gmdate(DateTimeFormat::MYSQL, $start + $wait_interval)]);
|
||||
Logger::info('Sleeping', ['pid' => $pid, 'until' => gmdate(DateTimeFormat::MYSQL, $start + $wait_interval)]);
|
||||
|
||||
do {
|
||||
$seconds = (time() - $start);
|
||||
|
@ -236,10 +236,10 @@ while (true) {
|
|||
|
||||
if ($timeout) {
|
||||
$do_cron = true;
|
||||
Logger::info("Woke up after $wait_interval seconds.", ["pid" => $pid, 'sleep' => $wait_interval]);
|
||||
Logger::info('Woke up after $wait_interval seconds.', ['pid' => $pid, 'sleep' => $wait_interval]);
|
||||
} else {
|
||||
$do_cron = false;
|
||||
Logger::info("Worker jobs are calling to be forked.", ["pid" => $pid]);
|
||||
Logger::info('Worker jobs are calling to be forked.', ['pid' => $pid]);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -15,33 +15,34 @@
|
|||
# - TEST_SELECTION= ... Specify which tests are used to run (based on the test-labeling)
|
||||
# - XDEBUG_CONFIG= ... Set some XDEBUG specific environment settings for development
|
||||
|
||||
DATABASENAME=${MYSQL_DATABASE:-test}
|
||||
DATABASEUSER=${MYSQL_USERNAME:-friendica}
|
||||
DATABASEHOST=${MYSQL_HOST:-localhost}
|
||||
BASEDIR=$PWD
|
||||
DATABASE_NAME=${FRIENDICA_MYSQL_DATABASE:-test}
|
||||
DATABASE_USER=${FRIENDICA_MYSQL_USERNAME:-friendica}
|
||||
DATABASE_HOST=${FRIENDICA_MYSQL_HOST:-localhost}
|
||||
DATABASE_PASSWORD=${FRIENDICA_MYSQL_PASSWORD:-friendica}
|
||||
BASEDIR=${PWD}
|
||||
|
||||
DBCONFIGS="mysql mariadb"
|
||||
TESTS="REDIS MEMCACHE MEMCACHED APCU NODB"
|
||||
|
||||
export MYSQL_DATABASE="$DATABASENAME"
|
||||
export MYSQL_USERNAME="$DATABASEUSER"
|
||||
export MYSQL_PASSWORD="friendica"
|
||||
export MYSQL_DATABASE="${DATABASE_NAME}"
|
||||
export MYSQL_USERNAME="${DATABASE_USER}"
|
||||
export MYSQL_PASSWORD="${DATABASE_PASSWORD}"
|
||||
|
||||
if [ -z "$PHP_EXE" ]; then
|
||||
if [ -z "${PHP_EXE}" ]; then
|
||||
PHP_EXE=php
|
||||
fi
|
||||
PHP=$(which "$PHP_EXE")
|
||||
PHP=$(which "${PHP_EXE}")
|
||||
# Use the Friendica internal composer
|
||||
COMPOSER="$BASEDIR/bin/composer.phar"
|
||||
COMPOSER="${BASEDIR}/bin/composer.phar"
|
||||
|
||||
set -e
|
||||
|
||||
_XDEBUG_CONFIG=$XDEBUG_CONFIG
|
||||
_XDEBUG_CONFIG=${XDEBUG_CONFIG}
|
||||
unset XDEBUG_CONFIG
|
||||
|
||||
function show_syntax() {
|
||||
echo -e "Syntax: ./autotest.sh [dbconfigname] [testfile]\n" >&2
|
||||
echo -e "\t\"dbconfigname\" can be one of: $DBCONFIGS" >&2
|
||||
echo -e "\t\"dbconfigname\" can be one of: ${DBCONFIGS}" >&2
|
||||
echo -e "\t\"testfile\" is the name of a test file, for example lib/template.php" >&2
|
||||
echo -e "\nDatabase environment variables:\n" >&2
|
||||
echo -e "\t\"MYSQL_HOST\" Mysql Hostname (Default: localhost)" >&2
|
||||
|
@ -57,22 +58,22 @@ function show_syntax() {
|
|||
echo -e "\nIf no arguments are specified, all tests will be run with all database configs" >&2
|
||||
}
|
||||
|
||||
if [ -x "$PHP" ]; then
|
||||
echo "Using PHP executable $PHP"
|
||||
if [ -x "${PHP}" ]; then
|
||||
echo "Using PHP executable ${PHP}"
|
||||
else
|
||||
echo "Could not find PHP executable $PHP_EXE" >&2
|
||||
echo "Could not find PHP executable ${PHP_EXE}" >&2
|
||||
exit 3
|
||||
fi
|
||||
|
||||
echo "Installing depdendencies"
|
||||
$PHP "$COMPOSER" install
|
||||
${PHP} "$COMPOSER" install
|
||||
|
||||
PHPUNIT="$BASEDIR/vendor/bin/phpunit"
|
||||
PHPUNIT="${BASEDIR}/vendor/bin/phpunit"
|
||||
|
||||
if [ -x "$PHPUNIT" ]; then
|
||||
echo "Using PHPUnit executable $PHPUNIT"
|
||||
if [ -x "${PHPUNIT}" ]; then
|
||||
echo "Using PHPUnit executable ${PHPUNIT}"
|
||||
else
|
||||
echo "Could not find PHPUnit executable after composer $PHPUNIT" >&2
|
||||
echo "Could not find PHPUnit executable after composer ${PHPUNIT}" >&2
|
||||
exit 3
|
||||
fi
|
||||
|
||||
|
@ -83,8 +84,8 @@ fi
|
|||
|
||||
if [ "$1" ]; then
|
||||
FOUND=0
|
||||
for DBCONFIG in $DBCONFIGS; do
|
||||
if [ "$1" = "$DBCONFIG" ]; then
|
||||
for DBCONFIG in ${DBCONFIGS}; do
|
||||
if [ "$1" = "${DBCONFIG}" ]; then
|
||||
FOUND=1
|
||||
break
|
||||
fi
|
||||
|
@ -103,13 +104,13 @@ fi
|
|||
|
||||
function cleanup_config() {
|
||||
|
||||
if [ -n "$DOCKER_CONTAINER_ID" ]; then
|
||||
echo "Kill the docker $DOCKER_CONTAINER_ID"
|
||||
docker stop "$DOCKER_CONTAINER_ID"
|
||||
docker rm -f "$DOCKER_CONTAINER_ID"
|
||||
if [ -n "${DOCKER_CONTAINER_ID}" ]; then
|
||||
echo "Kill the docker ${DOCKER_CONTAINER_ID}"
|
||||
docker stop "${DOCKER_CONTAINER_ID}"
|
||||
docker rm -f "${DOCKER_CONTAINER_ID}"
|
||||
fi
|
||||
|
||||
cd "$BASEDIR"
|
||||
cd "${BASEDIR}"
|
||||
|
||||
# Restore existing config
|
||||
if [ -f config/local.config-autotest-backup.php ]; then
|
||||
|
@ -122,77 +123,77 @@ trap cleanup_config EXIT
|
|||
|
||||
function execute_tests() {
|
||||
DB=$1
|
||||
echo "Setup environment for $DB testing ..."
|
||||
echo "Setup environment for ${DB} testing ..."
|
||||
# back to root folder
|
||||
cd "$BASEDIR"
|
||||
cd "${BASEDIR}"
|
||||
|
||||
# backup current config
|
||||
if [ -f config/local.config.php ]; then
|
||||
mv config/local.config.php config/local.config-autotest-backup.php
|
||||
fi
|
||||
|
||||
if [ -z "$NOINSTALL" ]; then
|
||||
if [ -z "${NOINSTALL}" ]; then
|
||||
#drop database
|
||||
if [ "$DB" == "mysql" ]; then
|
||||
if [ -n "$USEDOCKER" ]; then
|
||||
if [ "${DB}" == "mysql" ]; then
|
||||
if [ -n "${USEDOCKER}" ]; then
|
||||
echo "Fire up the mysql docker"
|
||||
DOCKER_CONTAINER_ID=$(docker run \
|
||||
-e MYSQL_ROOT_PASSWORD=friendica \
|
||||
-e MYSQL_USER="$DATABASEUSER" \
|
||||
-e MYSQL_USER="${DATABASE_USER}" \
|
||||
-e MYSQL_PASSWORD=friendica \
|
||||
-e MYSQL_DATABASE="$DATABASENAME" \
|
||||
-e MYSQL_DATABASE="${DATABASE_NAME}" \
|
||||
-d mysql)
|
||||
DATABASEHOST=$(docker inspect --format="{{.NetworkSettings.IPAddress}}" "$DOCKER_CONTAINER_ID")
|
||||
DATABASE_HOST=$(docker inspect --format="{{.NetworkSettings.IPAddress}}" "${DOCKER_CONTAINER_ID}")
|
||||
|
||||
else
|
||||
if [ -z "$DRONE" ]; then # no need to drop the DB when we are on CI
|
||||
if [ -z "${DRONE}" ]; then # no need to drop the DB when we are on CI
|
||||
if [ "mysql" != "$(mysql --version | grep -o mysql)" ]; then
|
||||
echo "Your mysql binary is not provided by mysql"
|
||||
echo "To use the docker container set the USEDOCKER environment variable"
|
||||
exit 3
|
||||
fi
|
||||
mysql -u "$DATABASEUSER" -pfriendica -e "DROP DATABASE IF EXISTS $DATABASENAME" -h $DATABASEHOST || true
|
||||
mysql -u "$DATABASEUSER" -pfriendica -e "CREATE DATABASE $DATABASENAME DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci" -h $DATABASEHOST
|
||||
mysql -u "${DATABASE_USER}" -pfriendica -e "DROP DATABASE IF EXISTS ${DATABASE_NAME}" -h ${DATABASE_HOST} || true
|
||||
mysql -u "${DATABASE_USER}" -pfriendica -e "CREATE DATABASE ${DATABASE_NAME} DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci" -h ${DATABASE_HOST}
|
||||
else
|
||||
DATABASEHOST=mysql
|
||||
DATABASE_HOST=mysql
|
||||
fi
|
||||
fi
|
||||
|
||||
echo "Waiting for MySQL $DATABASEHOST initialization..."
|
||||
if ! bin/wait-for-connection $DATABASEHOST 3306 300; then
|
||||
echo "Waiting for MySQL ${DATABASE_HOST} initialization..."
|
||||
if ! bin/wait-for-connection ${DATABASE_HOST} 3306 300; then
|
||||
echo "[ERROR] Waited 300 seconds, no response" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "MySQL is up."
|
||||
fi
|
||||
if [ "$DB" == "mariadb" ]; then
|
||||
if [ -n "$USEDOCKER" ]; then
|
||||
if [ "${DB}" == "mariadb" ]; then
|
||||
if [ -n "${USEDOCKER}" ]; then
|
||||
echo "Fire up the mariadb docker"
|
||||
DOCKER_CONTAINER_ID=$(docker run \
|
||||
-e MYSQL_ROOT_PASSWORD=friendica \
|
||||
-e MYSQL_USER="$DATABASEUSER" \
|
||||
-e MYSQL_USER="${DATABASE_USER}" \
|
||||
-e MYSQL_PASSWORD=friendica \
|
||||
-e MYSQL_DATABASE="$DATABASENAME" \
|
||||
-e MYSQL_DATABASE="${DATABASE_NAME}" \
|
||||
-d mariadb)
|
||||
DATABASEHOST=$(docker inspect --format="{{.NetworkSettings.IPAddress}}" "$DOCKER_CONTAINER_ID")
|
||||
DATABASE_HOST=$(docker inspect --format="{{.NetworkSettings.IPAddress}}" "${DOCKER_CONTAINER_ID}")
|
||||
|
||||
else
|
||||
if [ -z "$DRONE" ]; then # no need to drop the DB when we are on CI
|
||||
if [ -z "${DRONE}" ]; then # no need to drop the DB when we are on CI
|
||||
if [ "MariaDB" != "$(mysql --version | grep -o MariaDB)" ]; then
|
||||
echo "Your mysql binary is not provided by mysql"
|
||||
echo "To use the docker container set the USEDOCKER environment variable"
|
||||
exit 3
|
||||
fi
|
||||
mysql -u "$DATABASEUSER" -pfriendica -e "DROP DATABASE IF EXISTS $DATABASENAME" -h $DATABASEHOST || true
|
||||
mysql -u "$DATABASEUSER" -pfriendica -e "CREATE DATABASE $DATABASENAME DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci" -h $DATABASEHOST
|
||||
mysql -u "${DATABASE_USER}" -pfriendica -e "DROP DATABASE IF EXISTS ${DATABASE_NAME}" -h ${DATABASE_HOST} || true
|
||||
mysql -u "${DATABASE_USER}" -pfriendica -e "CREATE DATABASE ${DATABASE_NAME} DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci" -h ${DATABASE_HOST}
|
||||
else
|
||||
DATABASEHOST=mariadb
|
||||
DATABASE_HOST=mariadb
|
||||
fi
|
||||
fi
|
||||
|
||||
echo "Waiting for MariaDB $DATABASEHOST initialization..."
|
||||
if ! bin/wait-for-connection $DATABASEHOST 3306 300; then
|
||||
echo "Waiting for MariaDB ${DATABASE_HOST} initialization..."
|
||||
if ! bin/wait-for-connection ${DATABASE_HOST} 3306 300; then
|
||||
echo "[ERROR] Waited 300 seconds, no response" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
@ -200,28 +201,28 @@ function execute_tests() {
|
|||
echo "MariaDB is up."
|
||||
fi
|
||||
|
||||
if [ -n "$USEDOCKER" ]; then
|
||||
if [ -n "${USEDOCKER}" ]; then
|
||||
echo "Initialize database..."
|
||||
docker exec $DOCKER_CONTAINER_ID mysql -u root -pfriendica -e 'CREATE DATABASE IF NOT EXISTS $DATABASENAME;'
|
||||
docker exec ${DOCKER_CONTAINER_ID} mysql -u root -pfriendica -e "CREATE DATABASE IF NOT EXISTS ${DATABASE_NAME};"
|
||||
fi
|
||||
|
||||
export MYSQL_HOST="$DATABASEHOST"
|
||||
export MYSQL_HOST="${DATABASE_HOST}"
|
||||
|
||||
#call installer
|
||||
echo "Installing Friendica..."
|
||||
"$PHP" ./bin/console.php autoinstall --dbuser="$DATABASEUSER" --dbpass=friendica --dbdata="$DATABASENAME" --dbhost="$DATABASEHOST" --url=https://friendica.local --admin=admin@friendica.local
|
||||
"${PHP}" ./bin/console.php autoinstall --dbuser="${DATABASE_USER}" --dbpass=friendica --dbdata="${DATABASE_NAME}" --dbhost="${DATABASE_HOST}" --url=https://friendica.local --admin=admin@friendica.local
|
||||
fi
|
||||
|
||||
#test execution
|
||||
echo "Testing..."
|
||||
rm -fr "coverage-html"
|
||||
mkdir "coverage-html"
|
||||
if [[ "$_XDEBUG_CONFIG" ]]; then
|
||||
export XDEBUG_CONFIG=$_XDEBUG_CONFIG
|
||||
if [[ "${_XDEBUG_CONFIG}" ]]; then
|
||||
export XDEBUG_CONFIG=${_XDEBUG_CONFIG}
|
||||
fi
|
||||
|
||||
COVER=''
|
||||
if [ -z "$NOCOVERAGE" ]; then
|
||||
if [ -z "${NOCOVERAGE}" ]; then
|
||||
COVER="--coverage-clover tests/autotest-clover.xml"
|
||||
else
|
||||
echo "No coverage"
|
||||
|
@ -229,51 +230,51 @@ function execute_tests() {
|
|||
|
||||
# per default, there is no cache installed
|
||||
GROUP='--exclude-group REDIS,MEMCACHE,MEMCACHED,APCU'
|
||||
if [ "$TEST_SELECTION" == "REDIS" ]; then
|
||||
if [ "${TEST_SELECTION}" == "REDIS" ]; then
|
||||
GROUP="--group REDIS"
|
||||
fi
|
||||
if [ "$TEST_SELECTION" == "MEMCACHE" ]; then
|
||||
if [ "${TEST_SELECTION}" == "MEMCACHE" ]; then
|
||||
GROUP="--group MEMCACHE"
|
||||
fi
|
||||
if [ "$TEST_SELECTION" == "MEMCACHED" ]; then
|
||||
if [ "${TEST_SELECTION}" == "MEMCACHED" ]; then
|
||||
GROUP="--group MEMCACHED"
|
||||
fi
|
||||
if [ "$TEST_SELECTION" == "APCU" ]; then
|
||||
if [ "${TEST_SELECTION}" == "APCU" ]; then
|
||||
GROUP="--group APCU"
|
||||
fi
|
||||
if [ "$TEST_SELECTION" == "NODB" ]; then
|
||||
if [ "${TEST_SELECTION}" == "NODB" ]; then
|
||||
GROUP="--exclude-group DB,SLOWDB"
|
||||
fi
|
||||
|
||||
INPUT="$BASEDIR/tests"
|
||||
INPUT="${BASEDIR}/tests"
|
||||
if [ -n "$2" ]; then
|
||||
INPUT="$INPUT/$2"
|
||||
INPUT="${INPUT}/$2"
|
||||
fi
|
||||
|
||||
echo "${PHPUNIT[@]}" --configuration tests/phpunit.xml $GROUP $COVER --log-junit "autotest-results.xml" "$INPUT" "$3"
|
||||
"${PHPUNIT[@]}" --configuration tests/phpunit.xml $GROUP $COVER --log-junit "autotest-results.xml" "$INPUT" "$3"
|
||||
echo "${PHPUNIT[@]}" --configuration tests/phpunit.xml ${GROUP} ${COVER} --log-junit "autotest-results.xml" "${INPUT}" "$3"
|
||||
"${PHPUNIT[@]}" --configuration tests/phpunit.xml ${GROUP} ${COVER} --log-junit "autotest-results.xml" "${INPUT}" "$3"
|
||||
RESULT=$?
|
||||
|
||||
if [ -n "$DOCKER_CONTAINER_ID" ]; then
|
||||
echo "Kill the docker $DOCKER_CONTAINER_ID"
|
||||
docker stop $DOCKER_CONTAINER_ID
|
||||
docker rm -f $DOCKER_CONTAINER_ID
|
||||
unset $DOCKER_CONTAINER_ID
|
||||
if [ -n "${DOCKER_CONTAINER_ID}" ]; then
|
||||
echo "Kill the docker ${DOCKER_CONTAINER_ID}"
|
||||
docker stop ${DOCKER_CONTAINER_ID}
|
||||
docker rm -f ${DOCKER_CONTAINER_ID}
|
||||
unset ${DOCKER_CONTAINER_ID}
|
||||
fi
|
||||
}
|
||||
|
||||
#
|
||||
# Start the test execution
|
||||
#
|
||||
if [ -z "$1" ] && [ -n "$TEST_SELECTION" ]; then
|
||||
if [ -z "$1" ] && [ -n "${TEST_SELECTION}" ]; then
|
||||
# run all known database configs
|
||||
for DBCONFIG in $DBCONFIGS; do
|
||||
execute_tests "$DBCONFIG"
|
||||
for DBCONFIG in ${DBCONFIGS}; do
|
||||
execute_tests "${DBCONFIG}"
|
||||
done
|
||||
else
|
||||
FILENAME="$2"
|
||||
if [ -n "$2" ] && [ ! -f "tests/$FILENAME" ] && [ "${FILENAME:0:2}" != "--" ]; then
|
||||
FILENAME="../$FILENAME"
|
||||
if [ -n "$2" ] && [ ! -f "tests/${FILENAME}" ] && [ "${FILENAME:0:2}" != "--" ]; then
|
||||
FILENAME="../${FILENAME}"
|
||||
fi
|
||||
execute_tests "$1" "$FILENAME" "$3"
|
||||
execute_tests "$1" "${FILENAME}" "$3"
|
||||
fi
|
9
boot.php
9
boot.php
|
@ -87,8 +87,8 @@ define('PRIORITIES', [PRIORITY_CRITICAL, PRIORITY_HIGH, PRIORITY_MEDIUM, PRIORIT
|
|||
/* @}*/
|
||||
|
||||
// Normally this constant is defined - but not if "pcntl" isn't installed
|
||||
if (!defined("SIGTERM")) {
|
||||
define("SIGTERM", 15);
|
||||
if (!defined('SIGTERM')) {
|
||||
define('SIGTERM', 15);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -117,6 +117,7 @@ function local_user()
|
|||
if (!empty($_SESSION['authenticated']) && !empty($_SESSION['uid'])) {
|
||||
return intval($_SESSION['uid']);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -169,7 +170,7 @@ function remote_user()
|
|||
*
|
||||
* @param string $s - Text of notice
|
||||
*/
|
||||
function notice($s)
|
||||
function notice(string $s)
|
||||
{
|
||||
if (empty($_SESSION)) {
|
||||
return;
|
||||
|
@ -189,7 +190,7 @@ function notice($s)
|
|||
*
|
||||
* @param string $s - Text of notice
|
||||
*/
|
||||
function info($s)
|
||||
function info(string $s)
|
||||
{
|
||||
if (empty($_SESSION)) {
|
||||
return;
|
||||
|
|
|
@ -545,12 +545,12 @@
|
|||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"DivineOmega\\PasswordExposed\\": "src/"
|
||||
},
|
||||
"files": [
|
||||
"src/PasswordExposedFunction.php"
|
||||
]
|
||||
],
|
||||
"psr-4": {
|
||||
"DivineOmega\\PasswordExposed\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
|
@ -587,12 +587,12 @@
|
|||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-0": {
|
||||
"HTMLPurifier": "library/"
|
||||
},
|
||||
"files": [
|
||||
"library/HTMLPurifier.composer.php"
|
||||
],
|
||||
"psr-0": {
|
||||
"HTMLPurifier": "library/"
|
||||
},
|
||||
"exclude-from-classmap": [
|
||||
"/library/HTMLPurifier/Language/"
|
||||
]
|
||||
|
@ -839,24 +839,24 @@
|
|||
},
|
||||
{
|
||||
"name": "guzzlehttp/guzzle",
|
||||
"version": "6.5.5",
|
||||
"version": "6.5.8",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/guzzle/guzzle.git",
|
||||
"reference": "9d4290de1cfd701f38099ef7e183b64b4b7b0c5e"
|
||||
"reference": "a52f0440530b54fa079ce76e8c5d196a42cad981"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/guzzle/guzzle/zipball/9d4290de1cfd701f38099ef7e183b64b4b7b0c5e",
|
||||
"reference": "9d4290de1cfd701f38099ef7e183b64b4b7b0c5e",
|
||||
"url": "https://api.github.com/repos/guzzle/guzzle/zipball/a52f0440530b54fa079ce76e8c5d196a42cad981",
|
||||
"reference": "a52f0440530b54fa079ce76e8c5d196a42cad981",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"ext-json": "*",
|
||||
"guzzlehttp/promises": "^1.0",
|
||||
"guzzlehttp/psr7": "^1.6.1",
|
||||
"guzzlehttp/psr7": "^1.9",
|
||||
"php": ">=5.5",
|
||||
"symfony/polyfill-intl-idn": "^1.17.0"
|
||||
"symfony/polyfill-intl-idn": "^1.17"
|
||||
},
|
||||
"require-dev": {
|
||||
"ext-curl": "*",
|
||||
|
@ -873,22 +873,52 @@
|
|||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"GuzzleHttp\\": "src/"
|
||||
},
|
||||
"files": [
|
||||
"src/functions_include.php"
|
||||
]
|
||||
],
|
||||
"psr-4": {
|
||||
"GuzzleHttp\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Graham Campbell",
|
||||
"email": "hello@gjcampbell.co.uk",
|
||||
"homepage": "https://github.com/GrahamCampbell"
|
||||
},
|
||||
{
|
||||
"name": "Michael Dowling",
|
||||
"email": "mtdowling@gmail.com",
|
||||
"homepage": "https://github.com/mtdowling"
|
||||
},
|
||||
{
|
||||
"name": "Jeremy Lindblom",
|
||||
"email": "jeremeamia@gmail.com",
|
||||
"homepage": "https://github.com/jeremeamia"
|
||||
},
|
||||
{
|
||||
"name": "George Mponos",
|
||||
"email": "gmponos@gmail.com",
|
||||
"homepage": "https://github.com/gmponos"
|
||||
},
|
||||
{
|
||||
"name": "Tobias Nyholm",
|
||||
"email": "tobias.nyholm@gmail.com",
|
||||
"homepage": "https://github.com/Nyholm"
|
||||
},
|
||||
{
|
||||
"name": "Márk Sági-Kazár",
|
||||
"email": "mark.sagikazar@gmail.com",
|
||||
"homepage": "https://github.com/sagikazarmark"
|
||||
},
|
||||
{
|
||||
"name": "Tobias Schultze",
|
||||
"email": "webmaster@tubo-world.de",
|
||||
"homepage": "https://github.com/Tobion"
|
||||
}
|
||||
],
|
||||
"description": "Guzzle is a PHP HTTP client library",
|
||||
|
@ -902,7 +932,21 @@
|
|||
"rest",
|
||||
"web service"
|
||||
],
|
||||
"time": "2020-06-16T21:01:06+00:00"
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://github.com/GrahamCampbell",
|
||||
"type": "github"
|
||||
},
|
||||
{
|
||||
"url": "https://github.com/Nyholm",
|
||||
"type": "github"
|
||||
},
|
||||
{
|
||||
"url": "https://tidelift.com/funding/github/packagist/guzzlehttp/guzzle",
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2022-06-20T22:16:07+00:00"
|
||||
},
|
||||
{
|
||||
"name": "guzzlehttp/promises",
|
||||
|
@ -931,12 +975,12 @@
|
|||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"GuzzleHttp\\Promise\\": "src/"
|
||||
},
|
||||
"files": [
|
||||
"src/functions_include.php"
|
||||
]
|
||||
],
|
||||
"psr-4": {
|
||||
"GuzzleHttp\\Promise\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
|
@ -986,16 +1030,16 @@
|
|||
},
|
||||
{
|
||||
"name": "guzzlehttp/psr7",
|
||||
"version": "1.8.3",
|
||||
"version": "1.9.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/guzzle/psr7.git",
|
||||
"reference": "1afdd860a2566ed3c2b0b4a3de6e23434a79ec85"
|
||||
"reference": "e98e3e6d4f86621a9b75f623996e6bbdeb4b9318"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/guzzle/psr7/zipball/1afdd860a2566ed3c2b0b4a3de6e23434a79ec85",
|
||||
"reference": "1afdd860a2566ed3c2b0b4a3de6e23434a79ec85",
|
||||
"url": "https://api.github.com/repos/guzzle/psr7/zipball/e98e3e6d4f86621a9b75f623996e6bbdeb4b9318",
|
||||
"reference": "e98e3e6d4f86621a9b75f623996e6bbdeb4b9318",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -1016,16 +1060,16 @@
|
|||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "1.7-dev"
|
||||
"dev-master": "1.9-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"GuzzleHttp\\Psr7\\": "src/"
|
||||
},
|
||||
"files": [
|
||||
"src/functions_include.php"
|
||||
]
|
||||
],
|
||||
"psr-4": {
|
||||
"GuzzleHttp\\Psr7\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
|
@ -1088,7 +1132,7 @@
|
|||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2021-10-05T13:56:00+00:00"
|
||||
"time": "2022-06-20T21:43:03+00:00"
|
||||
},
|
||||
{
|
||||
"name": "league/html-to-markdown",
|
||||
|
@ -1471,12 +1515,12 @@
|
|||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"classmap": [
|
||||
"Mobile_Detect.php"
|
||||
],
|
||||
"psr-0": {
|
||||
"Detection": "namespaced/"
|
||||
}
|
||||
},
|
||||
"classmap": [
|
||||
"Mobile_Detect.php"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
|
@ -1611,12 +1655,12 @@
|
|||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"FastRoute\\": "src/"
|
||||
},
|
||||
"files": [
|
||||
"src/functions.php"
|
||||
]
|
||||
],
|
||||
"psr-4": {
|
||||
"FastRoute\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
|
@ -3803,16 +3847,16 @@
|
|||
},
|
||||
{
|
||||
"name": "symfony/polyfill-intl-idn",
|
||||
"version": "v1.23.0",
|
||||
"version": "v1.26.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/polyfill-intl-idn.git",
|
||||
"reference": "65bd267525e82759e7d8c4e8ceea44f398838e65"
|
||||
"reference": "59a8d271f00dd0e4c2e518104cc7963f655a1aa8"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-intl-idn/zipball/65bd267525e82759e7d8c4e8ceea44f398838e65",
|
||||
"reference": "65bd267525e82759e7d8c4e8ceea44f398838e65",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-intl-idn/zipball/59a8d271f00dd0e4c2e518104cc7963f655a1aa8",
|
||||
"reference": "59a8d271f00dd0e4c2e518104cc7963f655a1aa8",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -3826,7 +3870,7 @@
|
|||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-main": "1.23-dev"
|
||||
"dev-main": "1.26-dev"
|
||||
},
|
||||
"thanks": {
|
||||
"name": "symfony/polyfill",
|
||||
|
@ -3834,12 +3878,12 @@
|
|||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Symfony\\Polyfill\\Intl\\Idn\\": ""
|
||||
},
|
||||
"files": [
|
||||
"bootstrap.php"
|
||||
]
|
||||
],
|
||||
"psr-4": {
|
||||
"Symfony\\Polyfill\\Intl\\Idn\\": ""
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
|
@ -3883,20 +3927,20 @@
|
|||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2021-05-27T09:27:20+00:00"
|
||||
"time": "2022-05-24T11:49:31+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/polyfill-intl-normalizer",
|
||||
"version": "v1.23.0",
|
||||
"version": "v1.26.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/polyfill-intl-normalizer.git",
|
||||
"reference": "8590a5f561694770bdcd3f9b5c69dde6945028e8"
|
||||
"reference": "219aa369ceff116e673852dce47c3a41794c14bd"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/8590a5f561694770bdcd3f9b5c69dde6945028e8",
|
||||
"reference": "8590a5f561694770bdcd3f9b5c69dde6945028e8",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/219aa369ceff116e673852dce47c3a41794c14bd",
|
||||
"reference": "219aa369ceff116e673852dce47c3a41794c14bd",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -3908,7 +3952,7 @@
|
|||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-main": "1.23-dev"
|
||||
"dev-main": "1.26-dev"
|
||||
},
|
||||
"thanks": {
|
||||
"name": "symfony/polyfill",
|
||||
|
@ -3916,12 +3960,12 @@
|
|||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Symfony\\Polyfill\\Intl\\Normalizer\\": ""
|
||||
},
|
||||
"files": [
|
||||
"bootstrap.php"
|
||||
],
|
||||
"psr-4": {
|
||||
"Symfony\\Polyfill\\Intl\\Normalizer\\": ""
|
||||
},
|
||||
"classmap": [
|
||||
"Resources/stubs"
|
||||
]
|
||||
|
@ -3964,7 +4008,7 @@
|
|||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2021-02-19T12:13:01+00:00"
|
||||
"time": "2022-05-24T11:49:31+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/polyfill-php56",
|
||||
|
@ -4033,16 +4077,16 @@
|
|||
},
|
||||
{
|
||||
"name": "symfony/polyfill-php72",
|
||||
"version": "v1.23.0",
|
||||
"version": "v1.26.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/polyfill-php72.git",
|
||||
"reference": "9a142215a36a3888e30d0a9eeea9766764e96976"
|
||||
"reference": "bf44a9fd41feaac72b074de600314a93e2ae78e2"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-php72/zipball/9a142215a36a3888e30d0a9eeea9766764e96976",
|
||||
"reference": "9a142215a36a3888e30d0a9eeea9766764e96976",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-php72/zipball/bf44a9fd41feaac72b074de600314a93e2ae78e2",
|
||||
"reference": "bf44a9fd41feaac72b074de600314a93e2ae78e2",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -4051,7 +4095,7 @@
|
|||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-main": "1.23-dev"
|
||||
"dev-main": "1.26-dev"
|
||||
},
|
||||
"thanks": {
|
||||
"name": "symfony/polyfill",
|
||||
|
@ -4059,12 +4103,12 @@
|
|||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Symfony\\Polyfill\\Php72\\": ""
|
||||
},
|
||||
"files": [
|
||||
"bootstrap.php"
|
||||
]
|
||||
],
|
||||
"psr-4": {
|
||||
"Symfony\\Polyfill\\Php72\\": ""
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
|
@ -4102,7 +4146,7 @@
|
|||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2021-05-27T09:17:38+00:00"
|
||||
"time": "2022-05-24T11:49:31+00:00"
|
||||
},
|
||||
{
|
||||
"name": "ua-parser/uap-php",
|
||||
|
@ -4865,12 +4909,12 @@
|
|||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"DeepCopy\\": "src/DeepCopy/"
|
||||
},
|
||||
"files": [
|
||||
"src/DeepCopy/deep_copy.php"
|
||||
]
|
||||
],
|
||||
"psr-4": {
|
||||
"DeepCopy\\": "src/DeepCopy/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
|
@ -5618,11 +5662,11 @@
|
|||
}
|
||||
},
|
||||
"autoload": {
|
||||
"classmap": [
|
||||
"src/"
|
||||
],
|
||||
"files": [
|
||||
"src/Framework/Assert/Functions.php"
|
||||
],
|
||||
"classmap": [
|
||||
"src/"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
|
@ -6586,12 +6630,12 @@
|
|||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Symfony\\Polyfill\\Ctype\\": ""
|
||||
},
|
||||
"files": [
|
||||
"bootstrap.php"
|
||||
]
|
||||
],
|
||||
"psr-4": {
|
||||
"Symfony\\Polyfill\\Ctype\\": ""
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
|
|
11
database.sql
11
database.sql
|
@ -1,6 +1,6 @@
|
|||
-- ------------------------------------------
|
||||
-- Friendica 2022.09-dev (Giant Rhubarb)
|
||||
-- DB_UPDATE_VERSION 1469
|
||||
-- DB_UPDATE_VERSION 1473
|
||||
-- ------------------------------------------
|
||||
|
||||
|
||||
|
@ -297,6 +297,7 @@ CREATE TABLE IF NOT EXISTS `2fa_trusted_browser` (
|
|||
`cookie_hash` varchar(80) NOT NULL COMMENT 'Trusted cookie hash',
|
||||
`uid` mediumint unsigned NOT NULL COMMENT 'User ID',
|
||||
`user_agent` text COMMENT 'User agent string',
|
||||
`trusted` boolean NOT NULL DEFAULT '1' COMMENT 'Whenever this browser should be trusted or not',
|
||||
`created` datetime NOT NULL COMMENT 'Datetime the trusted browser was recorded',
|
||||
`last_used` datetime COMMENT 'Datetime the trusted browser was last used',
|
||||
PRIMARY KEY(`cookie_hash`),
|
||||
|
@ -1216,13 +1217,13 @@ CREATE TABLE IF NOT EXISTS `post-link` (
|
|||
CREATE TABLE IF NOT EXISTS `post-media` (
|
||||
`id` int unsigned NOT NULL auto_increment COMMENT 'sequential ID',
|
||||
`uri-id` int unsigned NOT NULL COMMENT 'Id of the item-uri table entry that contains the item uri',
|
||||
`url` varbinary(511) NOT NULL COMMENT 'Media URL',
|
||||
`url` varbinary(1024) NOT NULL COMMENT 'Media URL',
|
||||
`type` tinyint unsigned NOT NULL DEFAULT 0 COMMENT 'Media type',
|
||||
`mimetype` varchar(60) COMMENT '',
|
||||
`height` smallint unsigned COMMENT 'Height of the media',
|
||||
`width` smallint unsigned COMMENT 'Width of the media',
|
||||
`size` int unsigned COMMENT 'Media size',
|
||||
`preview` varbinary(255) COMMENT 'Preview URL',
|
||||
`size` bigint unsigned COMMENT 'Media size',
|
||||
`preview` varbinary(512) COMMENT 'Preview URL',
|
||||
`preview-height` smallint unsigned COMMENT 'Height of the preview picture',
|
||||
`preview-width` smallint unsigned COMMENT 'Width of the preview picture',
|
||||
`description` text COMMENT '',
|
||||
|
@ -1234,7 +1235,7 @@ CREATE TABLE IF NOT EXISTS `post-media` (
|
|||
`publisher-name` varchar(255) COMMENT 'Name of the publisher of the media',
|
||||
`publisher-image` varbinary(255) COMMENT 'Image of the publisher of the media',
|
||||
PRIMARY KEY(`id`),
|
||||
UNIQUE INDEX `uri-id-url` (`uri-id`,`url`),
|
||||
UNIQUE INDEX `uri-id-url` (`uri-id`,`url`(512)),
|
||||
INDEX `uri-id-id` (`uri-id`,`id`),
|
||||
FOREIGN KEY (`uri-id`) REFERENCES `item-uri` (`id`) ON UPDATE RESTRICT ON DELETE CASCADE
|
||||
) DEFAULT COLLATE utf8mb4_general_ci COMMENT='Attached media';
|
||||
|
|
|
@ -82,6 +82,7 @@ General
|
|||
../settings
|
||||
---------
|
||||
* o - Account
|
||||
* 2 - Two-factor authentication
|
||||
* p - Profiles
|
||||
* t - Additional features
|
||||
* w - Social Networks
|
||||
|
|
|
@ -6,13 +6,14 @@ Two-factor authentication trusted browsers
|
|||
Fields
|
||||
------
|
||||
|
||||
| Field | Description | Type | Null | Key | Default | Extra |
|
||||
| ----------- | ------------------------------------------ | ------------------ | ---- | --- | ------- | ----- |
|
||||
| cookie_hash | Trusted cookie hash | varchar(80) | NO | PRI | NULL | |
|
||||
| uid | User ID | mediumint unsigned | NO | | NULL | |
|
||||
| user_agent | User agent string | text | YES | | NULL | |
|
||||
| created | Datetime the trusted browser was recorded | datetime | NO | | NULL | |
|
||||
| last_used | Datetime the trusted browser was last used | datetime | YES | | NULL | |
|
||||
| Field | Description | Type | Null | Key | Default | Extra |
|
||||
| ----------- | ---------------------------------------------- | ------------------ | ---- | --- | ------- | ----- |
|
||||
| cookie_hash | Trusted cookie hash | varchar(80) | NO | PRI | NULL | |
|
||||
| uid | User ID | mediumint unsigned | NO | | NULL | |
|
||||
| user_agent | User agent string | text | YES | | NULL | |
|
||||
| trusted | Whenever this browser should be trusted or not | boolean | NO | | 1 | |
|
||||
| created | Datetime the trusted browser was recorded | datetime | NO | | NULL | |
|
||||
| last_used | Datetime the trusted browser was last used | datetime | YES | | NULL | |
|
||||
|
||||
Indexes
|
||||
------------
|
||||
|
|
|
@ -10,13 +10,13 @@ Fields
|
|||
| --------------- | --------------------------------------------------------- | ----------------- | ---- | --- | ------- | -------------- |
|
||||
| id | sequential ID | int unsigned | NO | PRI | NULL | auto_increment |
|
||||
| uri-id | Id of the item-uri table entry that contains the item uri | int unsigned | NO | | NULL | |
|
||||
| url | Media URL | varbinary(511) | NO | | NULL | |
|
||||
| url | Media URL | varbinary(1024) | NO | | NULL | |
|
||||
| type | Media type | tinyint unsigned | NO | | 0 | |
|
||||
| mimetype | | varchar(60) | YES | | NULL | |
|
||||
| height | Height of the media | smallint unsigned | YES | | NULL | |
|
||||
| width | Width of the media | smallint unsigned | YES | | NULL | |
|
||||
| size | Media size | int unsigned | YES | | NULL | |
|
||||
| preview | Preview URL | varbinary(255) | YES | | NULL | |
|
||||
| size | Media size | bigint unsigned | YES | | NULL | |
|
||||
| preview | Preview URL | varbinary(512) | YES | | NULL | |
|
||||
| preview-height | Height of the preview picture | smallint unsigned | YES | | NULL | |
|
||||
| preview-width | Width of the preview picture | smallint unsigned | YES | | NULL | |
|
||||
| description | | text | YES | | NULL | |
|
||||
|
@ -31,11 +31,11 @@ Fields
|
|||
Indexes
|
||||
------------
|
||||
|
||||
| Name | Fields |
|
||||
| ---------- | ------------------- |
|
||||
| PRIMARY | id |
|
||||
| uri-id-url | UNIQUE, uri-id, url |
|
||||
| uri-id-id | uri-id, id |
|
||||
| Name | Fields |
|
||||
| ---------- | ------------------------ |
|
||||
| PRIMARY | id |
|
||||
| uri-id-url | UNIQUE, uri-id, url(512) |
|
||||
| uri-id-id | uri-id, id |
|
||||
|
||||
Foreign Keys
|
||||
------------
|
||||
|
|
|
@ -302,7 +302,7 @@ function display_content(App $a, $update = false, $update_uid = 0)
|
|||
|
||||
// Preparing the meta header
|
||||
$description = trim(BBCode::toPlaintext($item['body']));
|
||||
$title = trim(BBCode::toPlaintext($item['title']));
|
||||
$title = trim(BBCode::toPlaintext($item['title'] ?? ''));
|
||||
$author_name = $item['author-name'];
|
||||
|
||||
$image = DI::baseUrl()->remove($item['author-avatar']);
|
||||
|
|
|
@ -83,7 +83,7 @@ function editpost_content(App $a)
|
|||
|
||||
Hook::callAll('jot_tool', $jotplugins);
|
||||
|
||||
$tpl = Renderer::getMarkupTemplate("jot.tpl");
|
||||
$tpl = Renderer::getMarkupTemplate('jot.tpl');
|
||||
$o .= Renderer::replaceMacros($tpl, [
|
||||
'$is_edit' => true,
|
||||
'$return_path' => '/display/' . $item['guid'],
|
||||
|
|
|
@ -47,7 +47,7 @@ function fbrowser_content(App $a)
|
|||
}
|
||||
|
||||
// Needed to match the correct template in a module that uses a different theme than the user/site/default
|
||||
$theme = Strings::sanitizeFilePathItem($_GET['theme'] ?? null);
|
||||
$theme = Strings::sanitizeFilePathItem($_GET['theme'] ?? '');
|
||||
if ($theme && is_file("view/theme/$theme/config.php")) {
|
||||
$a->setCurrentTheme($theme);
|
||||
}
|
||||
|
|
11
mod/item.php
11
mod/item.php
|
@ -439,8 +439,13 @@ function item_post(App $a) {
|
|||
// Ensure to only modify attachments that you own
|
||||
$srch = '<' . intval($contact_id) . '>';
|
||||
|
||||
$condition = ['allow_cid' => $srch, 'allow_gid' => '', 'deny_cid' => '', 'deny_gid' => '',
|
||||
'id' => $attach];
|
||||
$condition = [
|
||||
'allow_cid' => $srch,
|
||||
'allow_gid' => '',
|
||||
'deny_cid' => '',
|
||||
'deny_gid' => '',
|
||||
'id' => $attach,
|
||||
];
|
||||
if (!Attach::exists($condition)) {
|
||||
continue;
|
||||
}
|
||||
|
@ -520,7 +525,7 @@ function item_post(App $a) {
|
|||
$origin = $_REQUEST['origin'];
|
||||
}
|
||||
|
||||
$uri = Item::newURI($api_source ? $profile_uid : $uid, $guid);
|
||||
$uri = Item::newURI($guid);
|
||||
|
||||
// Fallback so that we alway have a parent uri
|
||||
if (!$thr_parent_uri || !$toplevel_item_id) {
|
||||
|
|
|
@ -187,7 +187,7 @@ function photos_post(App $a)
|
|||
}
|
||||
|
||||
if (DI::args()->getArgc() > 3 && DI::args()->getArgv()[2] === 'album') {
|
||||
if (!Strings::isHex(DI::args()->getArgv()[3])) {
|
||||
if (!Strings::isHex(DI::args()->getArgv()[3] ?? '')) {
|
||||
DI::baseUrl()->redirect('photos/' . $user['nickname'] . '/album');
|
||||
}
|
||||
$album = hex2bin(DI::args()->getArgv()[3]);
|
||||
|
@ -360,7 +360,7 @@ function photos_post(App $a)
|
|||
if (DBA::isResult($photos) && !$item_id) {
|
||||
// Create item container
|
||||
$title = '';
|
||||
$uri = Item::newURI($page_owner_uid);
|
||||
$uri = Item::newURI();
|
||||
|
||||
$arr = [];
|
||||
$arr['guid'] = System::createUUID();
|
||||
|
@ -524,7 +524,7 @@ function photos_post(App $a)
|
|||
|
||||
if (count($taginfo)) {
|
||||
foreach ($taginfo as $tagged) {
|
||||
$uri = Item::newURI($page_owner_uid);
|
||||
$uri = Item::newURI();
|
||||
|
||||
$arr = [];
|
||||
$arr['guid'] = System::createUUID();
|
||||
|
@ -728,7 +728,7 @@ function photos_post(App $a)
|
|||
$smallest = 2;
|
||||
}
|
||||
|
||||
$uri = Item::newURI($page_owner_uid);
|
||||
$uri = Item::newURI();
|
||||
|
||||
// Create item container
|
||||
$lat = $lon = null;
|
||||
|
@ -892,7 +892,7 @@ function photos_content(App $a)
|
|||
return;
|
||||
}
|
||||
|
||||
$selname = Strings::isHex($datum) ? hex2bin($datum) : '';
|
||||
$selname = (!is_null($datum) && Strings::isHex($datum)) ? hex2bin($datum) : '';
|
||||
|
||||
$albumselect = '';
|
||||
|
||||
|
@ -954,7 +954,7 @@ function photos_content(App $a)
|
|||
// Display a single photo album
|
||||
if ($datatype === 'album') {
|
||||
// if $datum is not a valid hex, redirect to the default page
|
||||
if (!Strings::isHex($datum)) {
|
||||
if (is_null($datum) || !Strings::isHex($datum)) {
|
||||
DI::baseUrl()->redirect('photos/' . $user['nickname']. '/album');
|
||||
}
|
||||
$album = hex2bin($datum);
|
||||
|
@ -977,7 +977,7 @@ function photos_content(App $a)
|
|||
|
||||
/// @TODO I have seen this many times, maybe generalize it script-wide and encapsulate it?
|
||||
$order_field = $_GET['order'] ?? '';
|
||||
if ($order_field === 'posted') {
|
||||
if ($order_field === 'created') {
|
||||
$order = 'ASC';
|
||||
} else {
|
||||
$order = 'DESC';
|
||||
|
@ -1031,10 +1031,10 @@ function photos_content(App $a)
|
|||
$drop = [DI::l10n()->t('Drop Album'), 'photos/' . $user['nickname'] . '/album/' . bin2hex($album) . '/drop'];
|
||||
}
|
||||
|
||||
if ($order_field === 'posted') {
|
||||
if ($order_field === 'created') {
|
||||
$order = [DI::l10n()->t('Show Newest First'), 'photos/' . $user['nickname'] . '/album/' . bin2hex($album), 'oldest'];
|
||||
} else {
|
||||
$order = [DI::l10n()->t('Show Oldest First'), 'photos/' . $user['nickname'] . '/album/' . bin2hex($album) . '?order=posted', 'newest'];
|
||||
$order = [DI::l10n()->t('Show Oldest First'), 'photos/' . $user['nickname'] . '/album/' . bin2hex($album) . '?order=created', 'newest'];
|
||||
}
|
||||
|
||||
$photos = [];
|
||||
|
@ -1054,7 +1054,7 @@ function photos_content(App $a)
|
|||
'id' => $rr['id'],
|
||||
'twist' => ' ' . ($twist ? 'rotleft' : 'rotright') . rand(2,4),
|
||||
'link' => 'photos/' . $user['nickname'] . '/image/' . $rr['resource-id']
|
||||
. ($order_field === 'posted' ? '?order=posted' : ''),
|
||||
. ($order_field === 'created' ? '?order=created' : ''),
|
||||
'title' => DI::l10n()->t('View Photo'),
|
||||
'src' => 'photo/' . $rr['resource-id'] . '-' . $rr['scale'] . '.' .$ext,
|
||||
'alt' => $imgalt_e,
|
||||
|
@ -1122,7 +1122,7 @@ function photos_content(App $a)
|
|||
if ($cmd === 'view' && !DI::config()->get('system', 'no_count', false)) {
|
||||
$order_field = $_GET['order'] ?? '';
|
||||
|
||||
if ($order_field === 'posted') {
|
||||
if ($order_field === 'created') {
|
||||
$params = ['order' => [$order_field]];
|
||||
} elseif (!empty($order_field)) {
|
||||
$params = ['order' => [$order_field => true]];
|
||||
|
@ -1150,10 +1150,10 @@ function photos_content(App $a)
|
|||
}
|
||||
|
||||
if (!is_null($prv)) {
|
||||
$prevlink = 'photos/' . $user['nickname'] . '/image/' . $prvnxt[$prv]['resource-id'] . ($order_field === 'posted' ? '?order=posted' : '');
|
||||
$prevlink = 'photos/' . $user['nickname'] . '/image/' . $prvnxt[$prv]['resource-id'] . ($order_field === 'created' ? '?order=created' : '');
|
||||
}
|
||||
if (!is_null($nxt)) {
|
||||
$nextlink = 'photos/' . $user['nickname'] . '/image/' . $prvnxt[$nxt]['resource-id'] . ($order_field === 'posted' ? '?order=posted' : '');
|
||||
$nextlink = 'photos/' . $user['nickname'] . '/image/' . $prvnxt[$nxt]['resource-id'] . ($order_field === 'created' ? '?order=created' : '');
|
||||
}
|
||||
|
||||
$tpl = Renderer::getMarkupTemplate('photo_edit_head.tpl');
|
||||
|
|
|
@ -73,7 +73,7 @@ function tagger_content(App $a) {
|
|||
return;
|
||||
}
|
||||
|
||||
$uri = Item::newURI($owner_uid);
|
||||
$uri = Item::newURI();
|
||||
$xterm = XML::escape($term);
|
||||
$post_type = (($item['resource-id']) ? DI::l10n()->t('photo') : DI::l10n()->t('status'));
|
||||
$targettype = (($item['resource-id']) ? Activity\ObjectType::IMAGE : Activity\ObjectType::NOTE );
|
||||
|
|
|
@ -157,9 +157,9 @@ function wall_upload_post(App $a, $desktopmode = true)
|
|||
" - size: " . $filesize . " - type: " . $filetype);
|
||||
|
||||
$imagedata = @file_get_contents($src);
|
||||
$Image = new Image($imagedata, $filetype);
|
||||
$image = new Image($imagedata, $filetype);
|
||||
|
||||
if (!$Image->isValid()) {
|
||||
if (!$image->isValid()) {
|
||||
$msg = DI::l10n()->t('Unable to process image.');
|
||||
@unlink($src);
|
||||
if ($r_json) {
|
||||
|
@ -170,18 +170,18 @@ function wall_upload_post(App $a, $desktopmode = true)
|
|||
System::exit();
|
||||
}
|
||||
|
||||
$Image->orient($src);
|
||||
$image->orient($src);
|
||||
@unlink($src);
|
||||
|
||||
$max_length = DI::config()->get('system', 'max_image_length');
|
||||
if ($max_length > 0) {
|
||||
$Image->scaleDown($max_length);
|
||||
$filesize = strlen($Image->asString());
|
||||
$image->scaleDown($max_length);
|
||||
$filesize = strlen($image->asString());
|
||||
Logger::info("File upload: Scaling picture to new size " . $max_length);
|
||||
}
|
||||
|
||||
$width = $Image->getWidth();
|
||||
$height = $Image->getHeight();
|
||||
$width = $image->getWidth();
|
||||
$height = $image->getHeight();
|
||||
|
||||
$maximagesize = DI::config()->get('system', 'maximagesize');
|
||||
|
||||
|
@ -190,10 +190,10 @@ function wall_upload_post(App $a, $desktopmode = true)
|
|||
foreach ([5120, 2560, 1280, 640] as $pixels) {
|
||||
if (($filesize > $maximagesize) && (max($width, $height) > $pixels)) {
|
||||
Logger::info('Resize', ['size' => $filesize, 'width' => $width, 'height' => $height, 'max' => $maximagesize, 'pixels' => $pixels]);
|
||||
$Image->scaleDown($pixels);
|
||||
$filesize = strlen($Image->asString());
|
||||
$width = $Image->getWidth();
|
||||
$height = $Image->getHeight();
|
||||
$image->scaleDown($pixels);
|
||||
$filesize = strlen($image->asString());
|
||||
$width = $image->getWidth();
|
||||
$height = $image->getHeight();
|
||||
}
|
||||
}
|
||||
if ($filesize > $maximagesize) {
|
||||
|
@ -220,7 +220,7 @@ function wall_upload_post(App $a, $desktopmode = true)
|
|||
|
||||
$defperm = '<' . $default_cid . '>';
|
||||
|
||||
$r = Photo::store($Image, $page_owner_uid, $visitor, $resource_id, $filename, $album, 0, Photo::DEFAULT, $defperm);
|
||||
$r = Photo::store($image, $page_owner_uid, $visitor, $resource_id, $filename, $album, 0, Photo::DEFAULT, $defperm);
|
||||
|
||||
if (!$r) {
|
||||
$msg = DI::l10n()->t('Image upload failed.');
|
||||
|
@ -233,16 +233,16 @@ function wall_upload_post(App $a, $desktopmode = true)
|
|||
}
|
||||
|
||||
if ($width > 640 || $height > 640) {
|
||||
$Image->scaleDown(640);
|
||||
$r = Photo::store($Image, $page_owner_uid, $visitor, $resource_id, $filename, $album, 1, Photo::DEFAULT, $defperm);
|
||||
$image->scaleDown(640);
|
||||
$r = Photo::store($image, $page_owner_uid, $visitor, $resource_id, $filename, $album, 1, Photo::DEFAULT, $defperm);
|
||||
if ($r) {
|
||||
$smallest = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if ($width > 320 || $height > 320) {
|
||||
$Image->scaleDown(320);
|
||||
$r = Photo::store($Image, $page_owner_uid, $visitor, $resource_id, $filename, $album, 2, Photo::DEFAULT, $defperm);
|
||||
$image->scaleDown(320);
|
||||
$r = Photo::store($image, $page_owner_uid, $visitor, $resource_id, $filename, $album, 2, Photo::DEFAULT, $defperm);
|
||||
if ($r && ($smallest == 0)) {
|
||||
$smallest = 2;
|
||||
}
|
||||
|
@ -264,8 +264,8 @@ function wall_upload_post(App $a, $desktopmode = true)
|
|||
$picture["height"] = $photo["height"];
|
||||
$picture["type"] = $photo["type"];
|
||||
$picture["albumpage"] = DI::baseUrl() . '/photos/' . $page_owner_nick . '/image/' . $resource_id;
|
||||
$picture["picture"] = DI::baseUrl() . "/photo/{$resource_id}-0." . $Image->getExt();
|
||||
$picture["preview"] = DI::baseUrl() . "/photo/{$resource_id}-{$smallest}." . $Image->getExt();
|
||||
$picture["picture"] = DI::baseUrl() . "/photo/{$resource_id}-0." . $image->getExt();
|
||||
$picture["preview"] = DI::baseUrl() . "/photo/{$resource_id}-{$smallest}." . $image->getExt();
|
||||
|
||||
if ($r_json) {
|
||||
System::jsonExit(['picture' => $picture]);
|
||||
|
@ -280,7 +280,7 @@ function wall_upload_post(App $a, $desktopmode = true)
|
|||
System::jsonExit(['ok' => true]);
|
||||
}
|
||||
|
||||
echo "\n\n" . '[url=' . DI::baseUrl() . '/photos/' . $page_owner_nick . '/image/' . $resource_id . '][img]' . DI::baseUrl() . "/photo/{$resource_id}-{$smallest}.".$Image->getExt()."[/img][/url]\n\n";
|
||||
echo "\n\n" . '[url=' . DI::baseUrl() . '/photos/' . $page_owner_nick . '/image/' . $resource_id . '][img]' . DI::baseUrl() . "/photo/{$resource_id}-{$smallest}." . $image->getExt() . "[/img][/url]\n\n";
|
||||
System::exit();
|
||||
// NOTREACHED
|
||||
}
|
||||
|
|
67
src/App.php
67
src/App.php
|
@ -145,7 +145,7 @@ class App
|
|||
$this->nickname = $nickname;
|
||||
}
|
||||
|
||||
public function isLoggedIn()
|
||||
public function isLoggedIn(): bool
|
||||
{
|
||||
return local_user() && $this->user_id && ($this->user_id == local_user());
|
||||
}
|
||||
|
@ -155,7 +155,7 @@ class App
|
|||
*
|
||||
* @return bool true if user is an admin
|
||||
*/
|
||||
public function isSiteAdmin()
|
||||
public function isSiteAdmin(): bool
|
||||
{
|
||||
$admin_email = $this->config->get('config', 'admin_email');
|
||||
|
||||
|
@ -166,18 +166,18 @@ class App
|
|||
|
||||
/**
|
||||
* Fetch the user id
|
||||
* @return int
|
||||
* @return int User id
|
||||
*/
|
||||
public function getLoggedInUserId()
|
||||
public function getLoggedInUserId(): int
|
||||
{
|
||||
return $this->user_id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch the user nick name
|
||||
* @return string
|
||||
* @return string User's nickname
|
||||
*/
|
||||
public function getLoggedInUserNickname()
|
||||
public function getLoggedInUserNickname(): string
|
||||
{
|
||||
return $this->nickname;
|
||||
}
|
||||
|
@ -198,7 +198,7 @@ class App
|
|||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getProfileOwner():int
|
||||
public function getProfileOwner(): int
|
||||
{
|
||||
return $this->profile_owner;
|
||||
}
|
||||
|
@ -219,7 +219,7 @@ class App
|
|||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getContactId():int
|
||||
public function getContactId(): int
|
||||
{
|
||||
return $this->contact_id;
|
||||
}
|
||||
|
@ -241,7 +241,7 @@ class App
|
|||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getTimeZone():string
|
||||
public function getTimeZone(): string
|
||||
{
|
||||
return $this->timezone;
|
||||
}
|
||||
|
@ -260,9 +260,9 @@ class App
|
|||
/**
|
||||
* Fetch workerqueue information
|
||||
*
|
||||
* @return array
|
||||
* @return array Worker queue
|
||||
*/
|
||||
public function getQueue()
|
||||
public function getQueue(): array
|
||||
{
|
||||
return $this->queue ?? [];
|
||||
}
|
||||
|
@ -270,8 +270,8 @@ class App
|
|||
/**
|
||||
* Fetch a specific workerqueue field
|
||||
*
|
||||
* @param string $index
|
||||
* @return mixed
|
||||
* @param string $index Work queue record to fetch
|
||||
* @return mixed Work queue item or NULL if not found
|
||||
*/
|
||||
public function getQueueValue(string $index)
|
||||
{
|
||||
|
@ -306,9 +306,9 @@ class App
|
|||
/**
|
||||
* The basepath of this app
|
||||
*
|
||||
* @return string
|
||||
* @return string Base path from configuration
|
||||
*/
|
||||
public function getBasePath()
|
||||
public function getBasePath(): string
|
||||
{
|
||||
// Don't use the basepath of the config table for basepath (it should always be the config-file one)
|
||||
return $this->config->getCache()->get('system', 'basepath');
|
||||
|
@ -396,10 +396,10 @@ class App
|
|||
/**
|
||||
* Returns the current theme name. May be overriden by the mobile theme name.
|
||||
*
|
||||
* @return string
|
||||
* @return string Current theme name or empty string in installation phase
|
||||
* @throws Exception
|
||||
*/
|
||||
public function getCurrentTheme()
|
||||
public function getCurrentTheme(): string
|
||||
{
|
||||
if ($this->mode->isInstall()) {
|
||||
return '';
|
||||
|
@ -425,10 +425,10 @@ class App
|
|||
/**
|
||||
* Returns the current mobile theme name.
|
||||
*
|
||||
* @return string
|
||||
* @return string Mobile theme name or empty string if installer
|
||||
* @throws Exception
|
||||
*/
|
||||
public function getCurrentMobileTheme()
|
||||
public function getCurrentMobileTheme(): string
|
||||
{
|
||||
if ($this->mode->isInstall()) {
|
||||
return '';
|
||||
|
@ -441,12 +441,22 @@ class App
|
|||
return $this->currentMobileTheme;
|
||||
}
|
||||
|
||||
public function setCurrentTheme($theme)
|
||||
/**
|
||||
* Setter for current theme name
|
||||
*
|
||||
* @param string $theme Name of current theme
|
||||
*/
|
||||
public function setCurrentTheme(string $theme)
|
||||
{
|
||||
$this->currentTheme = $theme;
|
||||
}
|
||||
|
||||
public function setCurrentMobileTheme($theme)
|
||||
/**
|
||||
* Setter for current mobile theme name
|
||||
*
|
||||
* @param string $theme Name of current mobile theme
|
||||
*/
|
||||
public function setCurrentMobileTheme(string $theme)
|
||||
{
|
||||
$this->currentMobileTheme = $theme;
|
||||
}
|
||||
|
@ -525,10 +535,10 @@ class App
|
|||
/**
|
||||
* Provide a sane default if nothing is chosen or the specified theme does not exist.
|
||||
*
|
||||
* @return string
|
||||
* @return string Current theme's stylsheet path
|
||||
* @throws Exception
|
||||
*/
|
||||
public function getCurrentThemeStylesheetPath()
|
||||
public function getCurrentThemeStylesheetPath(): string
|
||||
{
|
||||
return Core\Theme::getStylesheetPath($this->getCurrentTheme());
|
||||
}
|
||||
|
@ -604,9 +614,9 @@ class App
|
|||
if (!empty($_GET['zrl']) && $this->mode->isNormal() && !$this->mode->isBackend() && !local_user()) {
|
||||
// Only continue when the given profile link seems valid
|
||||
// Valid profile links contain a path with "/profile/" and no query parameters
|
||||
if ((parse_url($_GET['zrl'], PHP_URL_QUERY) == "") &&
|
||||
strstr(parse_url($_GET['zrl'], PHP_URL_PATH), "/profile/")) {
|
||||
if (Core\Session::get('visitor_home') != $_GET["zrl"]) {
|
||||
if ((parse_url($_GET['zrl'], PHP_URL_QUERY) == '') &&
|
||||
strstr(parse_url($_GET['zrl'], PHP_URL_PATH), '/profile/')) {
|
||||
if (Core\Session::get('visitor_home') != $_GET['zrl']) {
|
||||
Core\Session::set('my_url', $_GET['zrl']);
|
||||
Core\Session::set('authenticated', 0);
|
||||
|
||||
|
@ -695,7 +705,8 @@ class App
|
|||
// Initialize module that can set the current theme in the init() method, either directly or via App->setProfileOwner
|
||||
$page['page_title'] = $moduleName;
|
||||
|
||||
if (!$this->mode->isInstall() && !$this->mode->has(App\Mode::MAINTENANCEDISABLED)) {
|
||||
// The "view" module is required to show the theme CSS
|
||||
if (!$this->mode->isInstall() && !$this->mode->has(App\Mode::MAINTENANCEDISABLED) && $moduleName !== 'view') {
|
||||
$module = $router->getModule(Maintenance::class);
|
||||
} else {
|
||||
// determine the module class and save it to the module instance
|
||||
|
@ -730,7 +741,7 @@ class App
|
|||
*
|
||||
* @throws HTTPException\InternalServerErrorException
|
||||
*/
|
||||
public function redirect($toUrl)
|
||||
public function redirect(string $toUrl)
|
||||
{
|
||||
if (!empty(parse_url($toUrl, PHP_URL_SCHEME))) {
|
||||
Core\System::externalRedirect($toUrl);
|
||||
|
|
|
@ -78,7 +78,7 @@ class Arguments
|
|||
/**
|
||||
* @return string The whole command of this call
|
||||
*/
|
||||
public function getCommand()
|
||||
public function getCommand(): string
|
||||
{
|
||||
return $this->command;
|
||||
}
|
||||
|
@ -94,7 +94,7 @@ class Arguments
|
|||
/**
|
||||
* @return array All arguments of this call
|
||||
*/
|
||||
public function getArgv()
|
||||
public function getArgv(): array
|
||||
{
|
||||
return $this->argv;
|
||||
}
|
||||
|
@ -102,7 +102,7 @@ class Arguments
|
|||
/**
|
||||
* @return string The used HTTP method
|
||||
*/
|
||||
public function getMethod()
|
||||
public function getMethod(): string
|
||||
{
|
||||
return $this->method;
|
||||
}
|
||||
|
@ -110,7 +110,7 @@ class Arguments
|
|||
/**
|
||||
* @return int The count of arguments of this call
|
||||
*/
|
||||
public function getArgc()
|
||||
public function getArgc(): int
|
||||
{
|
||||
return $this->argc;
|
||||
}
|
||||
|
@ -145,7 +145,7 @@ class Arguments
|
|||
*
|
||||
* @return bool if the argument position exists
|
||||
*/
|
||||
public function has(int $position)
|
||||
public function has(int $position): bool
|
||||
{
|
||||
return array_key_exists($position, $this->argv);
|
||||
}
|
||||
|
@ -158,7 +158,7 @@ class Arguments
|
|||
*
|
||||
* @return Arguments The determined arguments
|
||||
*/
|
||||
public function determine(array $server, array $get)
|
||||
public function determine(array $server, array $get): Arguments
|
||||
{
|
||||
// removing leading / - maybe a nginx problem
|
||||
$server['QUERY_STRING'] = ltrim($server['QUERY_STRING'] ?? '', '/');
|
||||
|
|
|
@ -107,7 +107,7 @@ class BaseURL
|
|||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getHostname()
|
||||
public function getHostname(): string
|
||||
{
|
||||
return $this->hostname;
|
||||
}
|
||||
|
@ -117,7 +117,7 @@ class BaseURL
|
|||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getScheme()
|
||||
public function getScheme(): string
|
||||
{
|
||||
return $this->scheme;
|
||||
}
|
||||
|
@ -127,7 +127,7 @@ class BaseURL
|
|||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getSSLPolicy()
|
||||
public function getSSLPolicy(): int
|
||||
{
|
||||
return $this->sslPolicy;
|
||||
}
|
||||
|
@ -137,7 +137,7 @@ class BaseURL
|
|||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getUrlPath()
|
||||
public function getUrlPath(): string
|
||||
{
|
||||
return $this->urlPath;
|
||||
}
|
||||
|
@ -151,7 +151,7 @@ class BaseURL
|
|||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get($ssl = false)
|
||||
public function get(bool $ssl = false): string
|
||||
{
|
||||
if ($this->sslPolicy === self::SSL_POLICY_SELFSIGN && $ssl) {
|
||||
return Network::switchScheme($this->url);
|
||||
|
@ -168,8 +168,9 @@ class BaseURL
|
|||
* @param string? $urlPath
|
||||
*
|
||||
* @return bool true, if successful
|
||||
* @TODO Find proper types
|
||||
*/
|
||||
public function save($hostname = null, $sslPolicy = null, $urlPath = null)
|
||||
public function save($hostname = null, $sslPolicy = null, $urlPath = null): bool
|
||||
{
|
||||
$currHostname = $this->hostname;
|
||||
$currSSLPolicy = $this->sslPolicy;
|
||||
|
@ -224,11 +225,11 @@ class BaseURL
|
|||
/**
|
||||
* Save the current url as base URL
|
||||
*
|
||||
* @param $url
|
||||
* @param string $url
|
||||
*
|
||||
* @return bool true, if the save was successful
|
||||
*/
|
||||
public function saveByURL($url)
|
||||
public function saveByURL(string $url): bool
|
||||
{
|
||||
$parsed = @parse_url($url);
|
||||
|
||||
|
@ -421,7 +422,7 @@ class BaseURL
|
|||
*
|
||||
* @return string The cleaned url
|
||||
*/
|
||||
public function remove(string $origURL)
|
||||
public function remove(string $origURL): string
|
||||
{
|
||||
// Remove the hostname from the url if it is an internal link
|
||||
$nurl = Strings::normaliseLink($origURL);
|
||||
|
@ -443,9 +444,13 @@ class BaseURL
|
|||
* @param string $toUrl The destination URL (Default is empty, which is the default page of the Friendica node)
|
||||
* @param bool $ssl if true, base URL will try to get called with https:// (works just for relative paths)
|
||||
*
|
||||
* @throws HTTPException\FoundException
|
||||
* @throws HTTPException\MovedPermanentlyException
|
||||
* @throws HTTPException\TemporaryRedirectException
|
||||
*
|
||||
* @throws HTTPException\InternalServerErrorException In Case the given URL is not relative to the Friendica node
|
||||
*/
|
||||
public function redirect($toUrl = '', $ssl = false)
|
||||
public function redirect(string $toUrl = '', bool $ssl = false)
|
||||
{
|
||||
if (!empty(parse_url($toUrl, PHP_URL_SCHEME))) {
|
||||
throw new HTTPException\InternalServerErrorException("'$toUrl is not a relative path, please use System::externalRedirectTo");
|
||||
|
@ -458,8 +463,8 @@ class BaseURL
|
|||
/**
|
||||
* Returns the base url as string
|
||||
*/
|
||||
public function __toString()
|
||||
public function __toString(): string
|
||||
{
|
||||
return $this->get();
|
||||
return (string) $this->get();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -130,7 +130,7 @@ class Mode
|
|||
*
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function determine(BasePath $basepath, Database $database, Cache $configCache)
|
||||
public function determine(BasePath $basepath, Database $database, Cache $configCache): Mode
|
||||
{
|
||||
$mode = 0;
|
||||
|
||||
|
@ -178,7 +178,7 @@ class Mode
|
|||
*
|
||||
* @return Mode returns the determined mode
|
||||
*/
|
||||
public function determineRunMode(bool $isBackend, array $server, Arguments $args, MobileDetect $mobileDetect)
|
||||
public function determineRunMode(bool $isBackend, array $server, Arguments $args, MobileDetect $mobileDetect): Mode
|
||||
{
|
||||
foreach (self::BACKEND_CONTENT_TYPES as $type) {
|
||||
if (strpos(strtolower($server['HTTP_ACCEPT'] ?? ''), $type) !== false) {
|
||||
|
@ -201,7 +201,7 @@ class Mode
|
|||
*
|
||||
* @return bool returns true, if the mode is set
|
||||
*/
|
||||
public function has($mode)
|
||||
public function has(int $mode): bool
|
||||
{
|
||||
return ($this->mode & $mode) > 0;
|
||||
}
|
||||
|
@ -227,7 +227,7 @@ class Mode
|
|||
*
|
||||
* @return int Execution Mode
|
||||
*/
|
||||
public function getExecutor()
|
||||
public function getExecutor(): int
|
||||
{
|
||||
return $this->executor;
|
||||
}
|
||||
|
@ -235,9 +235,9 @@ class Mode
|
|||
/**
|
||||
* Install mode is when the local config file is missing or the DB schema hasn't been installed yet.
|
||||
*
|
||||
* @return bool
|
||||
* @return bool Whether installation mode is active (local/database configuration files present or not)
|
||||
*/
|
||||
public function isInstall()
|
||||
public function isInstall(): bool
|
||||
{
|
||||
return !$this->has(Mode::LOCALCONFIGPRESENT) ||
|
||||
!$this->has(MODE::DBCONFIGAVAILABLE);
|
||||
|
@ -248,7 +248,7 @@ class Mode
|
|||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isNormal()
|
||||
public function isNormal(): bool
|
||||
{
|
||||
return $this->has(Mode::LOCALCONFIGPRESENT) &&
|
||||
$this->has(Mode::DBAVAILABLE) &&
|
||||
|
@ -261,7 +261,7 @@ class Mode
|
|||
*
|
||||
* @return bool Is it a backend call
|
||||
*/
|
||||
public function isBackend()
|
||||
public function isBackend(): bool
|
||||
{
|
||||
return $this->isBackend;
|
||||
}
|
||||
|
@ -271,7 +271,7 @@ class Mode
|
|||
*
|
||||
* @return bool true if it was an AJAX request
|
||||
*/
|
||||
public function isAjax()
|
||||
public function isAjax(): bool
|
||||
{
|
||||
return $this->isAjax;
|
||||
}
|
||||
|
@ -281,7 +281,7 @@ class Mode
|
|||
*
|
||||
* @return bool true if it was an mobile request
|
||||
*/
|
||||
public function isMobile()
|
||||
public function isMobile(): bool
|
||||
{
|
||||
return $this->isMobile;
|
||||
}
|
||||
|
@ -291,7 +291,7 @@ class Mode
|
|||
*
|
||||
* @return bool true if it was an tablet request
|
||||
*/
|
||||
public function isTablet()
|
||||
public function isTablet(): bool
|
||||
{
|
||||
return $this->isTablet;
|
||||
}
|
||||
|
|
|
@ -195,7 +195,7 @@ class Page implements ArrayAccess
|
|||
* @param string $media
|
||||
* @see Page::initHead()
|
||||
*/
|
||||
public function registerStylesheet($path, string $media = 'screen')
|
||||
public function registerStylesheet(string $path, string $media = 'screen')
|
||||
{
|
||||
$path = Network::appendQueryParam($path, ['v' => FRIENDICA_VERSION]);
|
||||
|
||||
|
@ -288,7 +288,7 @@ class Page implements ArrayAccess
|
|||
*
|
||||
* Taken from http://webcheatsheet.com/php/get_current_page_url.php
|
||||
*/
|
||||
private function curPageURL()
|
||||
private function curPageURL(): string
|
||||
{
|
||||
$pageURL = 'http';
|
||||
if (!empty($_SERVER["HTTPS"]) && ($_SERVER["HTTPS"] == "on")) {
|
||||
|
|
|
@ -0,0 +1,152 @@
|
|||
<?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\App;
|
||||
|
||||
use Friendica\Core\Config\Capability\IManageConfigValues;
|
||||
|
||||
/**
|
||||
* Container for the whole request
|
||||
*
|
||||
* @see https://www.php-fig.org/psr/psr-7/#321-psrhttpmessageserverrequestinterface
|
||||
*
|
||||
* @todo future container class for whole requests, currently it's not :-)
|
||||
*/
|
||||
class Request
|
||||
{
|
||||
/**
|
||||
* A comma separated list of default headers that could contain the client IP in a proxy request
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const DEFAULT_FORWARD_FOR_HEADER = 'HTTP_X_FORWARDED_FOR';
|
||||
|
||||
/** @var string The remote IP address of the current request */
|
||||
protected $remoteAddress;
|
||||
|
||||
/**
|
||||
* @return string The remote IP address of the current request
|
||||
*
|
||||
* Do always use this instead of $_SERVER['REMOTE_ADDR']
|
||||
*/
|
||||
public function getRemoteAddress(): string
|
||||
{
|
||||
return $this->remoteAddress;
|
||||
}
|
||||
|
||||
public function __construct(IManageConfigValues $config, array $server = [])
|
||||
{
|
||||
$this->remoteAddress = $this->determineRemoteAddress($config, $server);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if given $remoteAddress matches given $trustedProxy.
|
||||
* If $trustedProxy is an IPv4 IP range given in CIDR notation, true will be returned if
|
||||
* $remoteAddress is an IPv4 address within that IP range.
|
||||
* Otherwise, $remoteAddress will be compared to $trustedProxy literally and the result
|
||||
* will be returned.
|
||||
*
|
||||
* @param string $trustedProxy The current, trusted proxy to check
|
||||
* @param string $remoteAddress The current remote IP address
|
||||
*
|
||||
*
|
||||
* @return boolean true if $remoteAddress matches $trustedProxy, false otherwise
|
||||
*/
|
||||
protected function matchesTrustedProxy(string $trustedProxy, string $remoteAddress): bool
|
||||
{
|
||||
$cidrre = '/^([0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3})\/([0-9]{1,2})$/';
|
||||
|
||||
if (preg_match($cidrre, $trustedProxy, $match)) {
|
||||
$net = $match[1];
|
||||
$shiftbits = min(32, max(0, 32 - intval($match[2])));
|
||||
$netnum = ip2long($net) >> $shiftbits;
|
||||
$ipnum = ip2long($remoteAddress) >> $shiftbits;
|
||||
|
||||
return $ipnum === $netnum;
|
||||
}
|
||||
|
||||
return $trustedProxy === $remoteAddress;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if given $remoteAddress matches any entry in the given array $trustedProxies.
|
||||
* For details regarding what "match" means, refer to `matchesTrustedProxy`.
|
||||
*
|
||||
* @param string[] $trustedProxies A list of the trusted proxies
|
||||
* @param string $remoteAddress The current remote IP address
|
||||
*
|
||||
* @return boolean true if $remoteAddress matches any entry in $trustedProxies, false otherwise
|
||||
*/
|
||||
protected function isTrustedProxy(array $trustedProxies, string $remoteAddress): bool
|
||||
{
|
||||
foreach ($trustedProxies as $tp) {
|
||||
if ($this->matchesTrustedProxy($tp, $remoteAddress)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines the remote address, if the connection came from a trusted proxy
|
||||
* and `forwarded_for_headers` has been configured then the IP address
|
||||
* specified in this header will be returned instead.
|
||||
*
|
||||
* @param IManageConfigValues $config
|
||||
* @param array $server The $_SERVER array
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function determineRemoteAddress(IManageConfigValues $config, array $server): string
|
||||
{
|
||||
$remoteAddress = $server['REMOTE_ADDR'] ?? '0.0.0.0';
|
||||
$trustedProxies = preg_split('/(\s*,*\s*)*,+(\s*,*\s*)*/', $config->get('proxy', 'trusted_proxies', ''));
|
||||
|
||||
if (\is_array($trustedProxies) && $this->isTrustedProxy($trustedProxies, $remoteAddress)) {
|
||||
$forwardedForHeaders = preg_split('/(\s*,*\s*)*,+(\s*,*\s*)*/', $config->get('proxy', 'forwarded_for_headers', static::DEFAULT_FORWARD_FOR_HEADER));
|
||||
|
||||
foreach ($forwardedForHeaders as $header) {
|
||||
if (isset($server[$header])) {
|
||||
foreach (explode(',', $server[$header]) as $IP) {
|
||||
$IP = trim($IP);
|
||||
|
||||
// remove brackets from IPv6 addresses
|
||||
if (strpos($IP, '[') === 0 && substr($IP, -1) === ']') {
|
||||
$IP = substr($IP, 1, -1);
|
||||
}
|
||||
|
||||
// skip trusted proxies in the list itself
|
||||
if ($this->isTrustedProxy($trustedProxies, $IP)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (filter_var($IP, FILTER_VALIDATE_IP) !== false) {
|
||||
return $IP;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $remoteAddress;
|
||||
}
|
||||
}
|
|
@ -152,7 +152,7 @@ class Router
|
|||
*
|
||||
* @throws HTTPException\InternalServerErrorException In case of invalid configs
|
||||
*/
|
||||
public function loadRoutes(array $routes)
|
||||
public function loadRoutes(array $routes): Router
|
||||
{
|
||||
$routeCollector = ($this->routeCollector ?? new RouteCollector(new Std(), new GroupCountBased()));
|
||||
|
||||
|
@ -166,6 +166,13 @@ class Router
|
|||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds multiple routes to a route collector
|
||||
*
|
||||
* @param RouteCollector $routeCollector Route collector instance
|
||||
* @param array $routes Multiple routes to be added
|
||||
* @throws HTTPException\InternalServerErrorException If route was wrong (somehow)
|
||||
*/
|
||||
private function addRoutes(RouteCollector $routeCollector, array $routes)
|
||||
{
|
||||
foreach ($routes as $route => $config) {
|
||||
|
@ -221,7 +228,7 @@ class Router
|
|||
*
|
||||
* @return bool
|
||||
*/
|
||||
private function isRoute(array $config)
|
||||
private function isRoute(array $config): bool
|
||||
{
|
||||
return
|
||||
// The config array should at least have one entry
|
||||
|
@ -253,7 +260,7 @@ class Router
|
|||
* @throws HTTPException\MethodNotAllowedException If a rule matched but the method didn't
|
||||
* @throws HTTPException\NotFoundException If no rule matched
|
||||
*/
|
||||
private function getModuleClass()
|
||||
private function getModuleClass(): string
|
||||
{
|
||||
$cmd = $this->args->getCommand();
|
||||
$cmd = '/' . ltrim($cmd, '/');
|
||||
|
|
|
@ -70,9 +70,11 @@ class BaseCollection extends \ArrayIterator
|
|||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
* Getter for total count
|
||||
*
|
||||
* @return int Total count
|
||||
*/
|
||||
public function getTotalCount()
|
||||
public function getTotalCount(): int
|
||||
{
|
||||
return $this->totalCount;
|
||||
}
|
||||
|
@ -85,7 +87,7 @@ class BaseCollection extends \ArrayIterator
|
|||
* @return array
|
||||
* @see array_column()
|
||||
*/
|
||||
public function column($column, $index_key = null)
|
||||
public function column(string $column, $index_key = null): array
|
||||
{
|
||||
return array_column($this->getArrayCopy(true), $column, $index_key);
|
||||
}
|
||||
|
@ -97,7 +99,7 @@ class BaseCollection extends \ArrayIterator
|
|||
* @return BaseCollection
|
||||
* @see array_map()
|
||||
*/
|
||||
public function map(callable $callback)
|
||||
public function map(callable $callback): BaseCollection
|
||||
{
|
||||
return new static(array_map($callback, $this->getArrayCopy()), $this->getTotalCount());
|
||||
}
|
||||
|
@ -110,7 +112,7 @@ class BaseCollection extends \ArrayIterator
|
|||
* @return BaseCollection
|
||||
* @see array_filter()
|
||||
*/
|
||||
public function filter(callable $callback = null, int $flag = 0)
|
||||
public function filter(callable $callback = null, int $flag = 0): BaseCollection
|
||||
{
|
||||
return new static(array_filter($this->getArrayCopy(), $callback, $flag));
|
||||
}
|
||||
|
|
|
@ -55,14 +55,14 @@ abstract class BaseEntity extends BaseDataTransferObject
|
|||
}
|
||||
|
||||
/**
|
||||
* @param $name
|
||||
* @param mixed $name
|
||||
* @return bool
|
||||
* @throws HTTPException\InternalServerErrorException
|
||||
*/
|
||||
public function __isset($name)
|
||||
public function __isset($name): bool
|
||||
{
|
||||
if (!property_exists($this, $name)) {
|
||||
throw new HTTPException\InternalServerErrorException('Unknown property ' . $name . ' in Entity ' . static::class);
|
||||
throw new HTTPException\InternalServerErrorException('Unknown property ' . $name . ' of type ' . gettype($name) . ' in Entity ' . static::class);
|
||||
}
|
||||
|
||||
return !empty($this->$name);
|
||||
|
|
|
@ -110,11 +110,11 @@ abstract class BaseModel extends BaseDataTransferObject
|
|||
* - $model->field (outside of class)
|
||||
* - $this->field (inside of class)
|
||||
*
|
||||
* @param $name
|
||||
* @param string $name Name of data to fetch
|
||||
* @return mixed
|
||||
* @throws HTTPException\InternalServerErrorException
|
||||
*/
|
||||
public function __get($name)
|
||||
public function __get(string $name)
|
||||
{
|
||||
$this->checkValid();
|
||||
|
||||
|
|
|
@ -102,6 +102,7 @@ abstract class BaseModule implements ICanHandleRequests
|
|||
* e.g. from protocol implementations.
|
||||
*
|
||||
* @param string[] $request The $_REQUEST content
|
||||
* @return void
|
||||
*/
|
||||
protected function rawContent(array $request = [])
|
||||
{
|
||||
|
@ -117,6 +118,7 @@ abstract class BaseModule implements ICanHandleRequests
|
|||
* XML feed or a JSON output.
|
||||
*
|
||||
* @param string[] $request The $_REQUEST content
|
||||
* @return string
|
||||
*/
|
||||
protected function content(array $request = []): string
|
||||
{
|
||||
|
@ -130,6 +132,7 @@ abstract class BaseModule implements ICanHandleRequests
|
|||
* Doesn't display any content
|
||||
*
|
||||
* @param string[] $request The $_REQUEST content
|
||||
* @return void
|
||||
*/
|
||||
protected function delete(array $request = [])
|
||||
{
|
||||
|
@ -142,6 +145,7 @@ abstract class BaseModule implements ICanHandleRequests
|
|||
* Doesn't display any content
|
||||
*
|
||||
* @param string[] $request The $_REQUEST content
|
||||
* @return void
|
||||
*/
|
||||
protected function patch(array $request = [])
|
||||
{
|
||||
|
@ -154,7 +158,7 @@ abstract class BaseModule implements ICanHandleRequests
|
|||
* Doesn't display any content
|
||||
*
|
||||
* @param string[] $request The $_REQUEST content
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function post(array $request = [])
|
||||
{
|
||||
|
@ -168,6 +172,7 @@ abstract class BaseModule implements ICanHandleRequests
|
|||
* Doesn't display any content
|
||||
*
|
||||
* @param string[] $request The $_REQUEST content
|
||||
* @return void
|
||||
*/
|
||||
protected function put(array $request = [])
|
||||
{
|
||||
|
@ -279,12 +284,12 @@ abstract class BaseModule implements ICanHandleRequests
|
|||
/**
|
||||
* Fetch a request value and apply default values and check against minimal and maximal values
|
||||
*
|
||||
* @param array $input
|
||||
* @param string $parameter
|
||||
* @param mixed $default
|
||||
* @param mixed $minimal_value
|
||||
* @param mixed $maximum_value
|
||||
* @return mixed
|
||||
* @param array $input Input fields
|
||||
* @param string $parameter Parameter
|
||||
* @param mixed $default Default
|
||||
* @param mixed $minimal_value Minimal value
|
||||
* @param mixed $maximum_value Maximum value
|
||||
* @return mixed null on error anything else on success (?)
|
||||
*/
|
||||
public function getRequestValue(array $input, string $parameter, $default = null, $minimal_value = null, $maximum_value = null)
|
||||
{
|
||||
|
@ -320,7 +325,7 @@ abstract class BaseModule implements ICanHandleRequests
|
|||
return $value;
|
||||
}
|
||||
|
||||
/*
|
||||
/**
|
||||
* Functions used to protect against Cross-Site Request Forgery
|
||||
* The security token has to base on at least one value that an attacker can't know - here it's the session ID and the private key.
|
||||
* In this implementation, a security token is reusable (if the user submits a form, goes back and resubmits the form, maybe with small changes;
|
||||
|
@ -330,8 +335,11 @@ abstract class BaseModule implements ICanHandleRequests
|
|||
* If the new page contains by any chance external elements, then the used security token is exposed by the referrer.
|
||||
* Actually, important actions should not be triggered by Links / GET-Requests at all, but sometimes they still are,
|
||||
* so this mechanism brings in some damage control (the attacker would be able to forge a request to a form of this type, but not to forms of other types).
|
||||
*
|
||||
* @param string $typename Type name
|
||||
* @return string Security hash with timestamp
|
||||
*/
|
||||
public static function getFormSecurityToken($typename = '')
|
||||
public static function getFormSecurityToken(string $typename = ''): string
|
||||
{
|
||||
$user = User::getById(DI::app()->getLoggedInUserId(), ['guid', 'prvkey']);
|
||||
$timestamp = time();
|
||||
|
@ -340,7 +348,14 @@ abstract class BaseModule implements ICanHandleRequests
|
|||
return $timestamp . '.' . $sec_hash;
|
||||
}
|
||||
|
||||
public static function checkFormSecurityToken($typename = '', $formname = 'form_security_token')
|
||||
/**
|
||||
* Checks if form's security (CSRF) token is valid.
|
||||
*
|
||||
* @param string $typename ???
|
||||
* @param string $formname Name of form/field (???)
|
||||
* @return bool Whether it is valid
|
||||
*/
|
||||
public static function checkFormSecurityToken(string $typename = '', string $formname = 'form_security_token'): bool
|
||||
{
|
||||
$hash = null;
|
||||
|
||||
|
@ -372,12 +387,12 @@ abstract class BaseModule implements ICanHandleRequests
|
|||
return ($sec_hash == $x[1]);
|
||||
}
|
||||
|
||||
public static function getFormSecurityStandardErrorMessage()
|
||||
public static function getFormSecurityStandardErrorMessage(): string
|
||||
{
|
||||
return DI::l10n()->t("The form security token was not correct. This probably happened because the form has been opened for too long \x28>3 hours\x29 before submitting it.") . EOL;
|
||||
}
|
||||
|
||||
public static function checkFormSecurityTokenRedirectOnError($err_redirect, $typename = '', $formname = 'form_security_token')
|
||||
public static function checkFormSecurityTokenRedirectOnError(string $err_redirect, string $typename = '', string $formname = 'form_security_token')
|
||||
{
|
||||
if (!self::checkFormSecurityToken($typename, $formname)) {
|
||||
Logger::notice('checkFormSecurityToken failed: user ' . DI::app()->getLoggedInUserNickname() . ' - form element ' . $typename);
|
||||
|
@ -387,7 +402,7 @@ abstract class BaseModule implements ICanHandleRequests
|
|||
}
|
||||
}
|
||||
|
||||
public static function checkFormSecurityTokenForbiddenOnError($typename = '', $formname = 'form_security_token')
|
||||
public static function checkFormSecurityTokenForbiddenOnError(string $typename = '', string $formname = 'form_security_token')
|
||||
{
|
||||
if (!self::checkFormSecurityToken($typename, $formname)) {
|
||||
Logger::notice('checkFormSecurityToken failed: user ' . DI::app()->getLoggedInUserNickname() . ' - form element ' . $typename);
|
||||
|
@ -397,7 +412,7 @@ abstract class BaseModule implements ICanHandleRequests
|
|||
}
|
||||
}
|
||||
|
||||
protected static function getContactFilterTabs(string $baseUrl, string $current, bool $displayCommonTab)
|
||||
protected static function getContactFilterTabs(string $baseUrl, string $current, bool $displayCommonTab): array
|
||||
{
|
||||
$tabs = [
|
||||
[
|
||||
|
|
|
@ -82,7 +82,7 @@ HELP;
|
|||
AddonCore::loadAddons();
|
||||
}
|
||||
|
||||
protected function doExecute()
|
||||
protected function doExecute(): int
|
||||
{
|
||||
if ($this->getOption('v')) {
|
||||
$this->out('Class: ' . __CLASS__);
|
||||
|
@ -116,8 +116,7 @@ HELP;
|
|||
/**
|
||||
* Lists plugins
|
||||
*
|
||||
* @return int Return code of this command
|
||||
*
|
||||
* @return int|bool Return code of this command, false on error (?)
|
||||
* @throws \Exception
|
||||
*/
|
||||
private function list()
|
||||
|
@ -165,10 +164,9 @@ HELP;
|
|||
* Enables an addon
|
||||
*
|
||||
* @return int Return code of this command
|
||||
*
|
||||
* @throws \Exception
|
||||
*/
|
||||
private function enable()
|
||||
private function enable(): int
|
||||
{
|
||||
$addonname = $this->getArgument(1);
|
||||
|
||||
|
@ -190,10 +188,9 @@ HELP;
|
|||
* Disables an addon
|
||||
*
|
||||
* @return int Return code of this command
|
||||
*
|
||||
* @throws \Exception
|
||||
*/
|
||||
private function disable()
|
||||
private function disable(): int
|
||||
{
|
||||
$addonname = $this->getArgument(1);
|
||||
|
||||
|
|
|
@ -80,7 +80,7 @@ HELP;
|
|||
$this->l10n = $l10n;
|
||||
}
|
||||
|
||||
protected function doExecute()
|
||||
protected function doExecute(): int
|
||||
{
|
||||
if ($this->getOption('v')) {
|
||||
$this->out('Class: ' . __CLASS__);
|
||||
|
|
|
@ -110,7 +110,7 @@ HELP;
|
|||
$this->dba = $dba;
|
||||
}
|
||||
|
||||
protected function doExecute()
|
||||
protected function doExecute(): int
|
||||
{
|
||||
// Initialise the app
|
||||
$this->out("Initializing setup...");
|
||||
|
@ -225,7 +225,7 @@ HELP;
|
|||
|
||||
$installer->resetChecks();
|
||||
|
||||
if (!$installer->installDatabase($basePathConf)) {
|
||||
if (!$installer->installDatabase()) {
|
||||
$errorMessage = $this->extractErrors($installer->getChecks());
|
||||
throw new RuntimeException($errorMessage);
|
||||
}
|
||||
|
|
|
@ -90,7 +90,7 @@ HELP;
|
|||
$this->cache = $cache;
|
||||
}
|
||||
|
||||
protected function doExecute()
|
||||
protected function doExecute(): int
|
||||
{
|
||||
if ($this->getOption('v')) {
|
||||
$this->out('Executable: ' . $this->executable);
|
||||
|
|
|
@ -102,7 +102,7 @@ HELP;
|
|||
$this->config = $config;
|
||||
}
|
||||
|
||||
protected function doExecute()
|
||||
protected function doExecute(): int
|
||||
{
|
||||
if ($this->getOption('v')) {
|
||||
$this->out('Executable: ' . $this->executable);
|
||||
|
|
|
@ -76,7 +76,7 @@ HELP;
|
|||
$this->appMode = $appMode;
|
||||
}
|
||||
|
||||
protected function doExecute()
|
||||
protected function doExecute(): int
|
||||
{
|
||||
if ($this->getOption('v')) {
|
||||
$this->out('Class: ' . __CLASS__);
|
||||
|
|
|
@ -45,7 +45,7 @@ HELP;
|
|||
return $help;
|
||||
}
|
||||
|
||||
protected function doExecute()
|
||||
protected function doExecute(): int
|
||||
{
|
||||
if ($this->getOption('v')) {
|
||||
$this->out('Class: ' . __CLASS__);
|
||||
|
|
|
@ -25,6 +25,12 @@ use Friendica\Core\Config\ValueObject\Cache;
|
|||
use Friendica\Core\Update;
|
||||
use Friendica\Database\Database;
|
||||
use Friendica\Database\DBStructure;
|
||||
use Friendica\Database\Definition\DbaDefinition;
|
||||
use Friendica\Database\Definition\ViewDefinition;
|
||||
use Friendica\Util\BasePath;
|
||||
use Friendica\Util\Writer\DbaDefinitionSqlWriter;
|
||||
use Friendica\Util\Writer\DocWriter;
|
||||
use Friendica\Util\Writer\ViewDefinitionSqlWriter;
|
||||
use RuntimeException;
|
||||
|
||||
/**
|
||||
|
@ -34,15 +40,21 @@ class DatabaseStructure extends \Asika\SimpleConsole\Console
|
|||
{
|
||||
protected $helpOptions = ['h', 'help', '?'];
|
||||
|
||||
/**
|
||||
* @var Database
|
||||
*/
|
||||
/** @var Database */
|
||||
private $dba;
|
||||
/**
|
||||
* @var Cache
|
||||
*/
|
||||
|
||||
/** @var Cache */
|
||||
private $configCache;
|
||||
|
||||
/** @var DbaDefinition */
|
||||
private $dbaDefinition;
|
||||
|
||||
/** @var ViewDefinition */
|
||||
private $viewDefinition;
|
||||
|
||||
/** @var string */
|
||||
private $basePath;
|
||||
|
||||
protected function getHelp()
|
||||
{
|
||||
$help = <<<HELP
|
||||
|
@ -71,15 +83,18 @@ HELP;
|
|||
return $help;
|
||||
}
|
||||
|
||||
public function __construct(Database $dba, Cache $configCache, $argv = null)
|
||||
public function __construct(Database $dba, DbaDefinition $dbaDefinition, ViewDefinition $viewDefinition, BasePath $basePath, Cache $configCache, $argv = null)
|
||||
{
|
||||
parent::__construct($argv);
|
||||
|
||||
$this->dba = $dba;
|
||||
$this->dbaDefinition = $dbaDefinition;
|
||||
$this->viewDefinition = $viewDefinition;
|
||||
$this->configCache = $configCache;
|
||||
$this->basePath = $basePath->getPath();
|
||||
}
|
||||
|
||||
protected function doExecute()
|
||||
protected function doExecute(): int
|
||||
{
|
||||
if ($this->getOption('v')) {
|
||||
$this->out('Class: ' . __CLASS__);
|
||||
|
@ -120,10 +135,9 @@ HELP;
|
|||
$output = ob_get_clean();
|
||||
break;
|
||||
case "dumpsql":
|
||||
DBStructure::writeStructure();
|
||||
ob_start();
|
||||
DBStructure::printStructure($basePath);
|
||||
$output = ob_get_clean();
|
||||
DocWriter::writeDbDefinition($this->dbaDefinition, $this->basePath);
|
||||
$output = DbaDefinitionSqlWriter::create($this->dbaDefinition);
|
||||
$output .= ViewDefinitionSqlWriter::create($this->viewDefinition);
|
||||
break;
|
||||
case "toinnodb":
|
||||
ob_start();
|
||||
|
|
|
@ -71,7 +71,7 @@ HELP;
|
|||
return $help;
|
||||
}
|
||||
|
||||
protected function doExecute()
|
||||
protected function doExecute(): int
|
||||
{
|
||||
if ($this->getOption('v')) {
|
||||
$this->out('Class: ' . __CLASS__);
|
||||
|
|
|
@ -49,7 +49,7 @@ HELP;
|
|||
return $help;
|
||||
}
|
||||
|
||||
protected function doExecute()
|
||||
protected function doExecute(): int
|
||||
{
|
||||
if ($this->getOption('v')) {
|
||||
$this->out('Class: ' . __CLASS__);
|
||||
|
|
|
@ -85,7 +85,7 @@ HELP;
|
|||
$this->l10n = $l10n;
|
||||
}
|
||||
|
||||
protected function doExecute()
|
||||
protected function doExecute(): int
|
||||
{
|
||||
if ($this->getOption('v')) {
|
||||
$this->out('Class: ' . __CLASS__);
|
||||
|
|
|
@ -70,7 +70,7 @@ HELP;
|
|||
$this->l10n = $l10n;
|
||||
}
|
||||
|
||||
protected function doExecute()
|
||||
protected function doExecute(): int
|
||||
{
|
||||
if ($this->getOption('v')) {
|
||||
$this->out('Class: ' . __CLASS__);
|
||||
|
|
|
@ -75,7 +75,7 @@ HELP;
|
|||
$this->dba =$dba;
|
||||
}
|
||||
|
||||
protected function doExecute()
|
||||
protected function doExecute(): int
|
||||
{
|
||||
if ($this->getOption('v')) {
|
||||
$this->out('Class: ' . __CLASS__);
|
||||
|
|
|
@ -84,7 +84,7 @@ HELP;
|
|||
$this->lock = $lock;
|
||||
}
|
||||
|
||||
protected function doExecute()
|
||||
protected function doExecute(): int
|
||||
{
|
||||
if ($this->getOption('v')) {
|
||||
$this->out('Executable: ' . $this->executable);
|
||||
|
|
|
@ -77,7 +77,7 @@ HELP;
|
|||
$this->config = $config;
|
||||
}
|
||||
|
||||
protected function doExecute()
|
||||
protected function doExecute(): int
|
||||
{
|
||||
if ($this->getOption('v')) {
|
||||
$this->out('Class: ' . __CLASS__);
|
||||
|
|
|
@ -67,7 +67,7 @@ HELP;
|
|||
$this->l10n = $l10n;
|
||||
}
|
||||
|
||||
protected function doExecute()
|
||||
protected function doExecute(): int
|
||||
{
|
||||
$duplicates = $this->dba->p("SELECT COUNT(*) AS `total`, `uri-id`, MAX(`url`) AS `url` FROM `contact` WHERE `uid` = 0 GROUP BY `uri-id` HAVING total > 1");
|
||||
while ($duplicate = $this->dba->fetch($duplicates)) {
|
||||
|
|
|
@ -85,7 +85,7 @@ HELP;
|
|||
$this->config = $config;
|
||||
}
|
||||
|
||||
protected function doExecute()
|
||||
protected function doExecute(): int
|
||||
{
|
||||
if (!$this->config->get('system', 'avatar_cache')) {
|
||||
$this->err($this->l10n->t('The avatar cache needs to be enabled to use this command.'));
|
||||
|
|
|
@ -63,7 +63,7 @@ HELP;
|
|||
return $help;
|
||||
}
|
||||
|
||||
protected function doExecute()
|
||||
protected function doExecute(): int
|
||||
{
|
||||
if ($this->getOption('v')) {
|
||||
$this->out('Class: ' . __CLASS__);
|
||||
|
|
|
@ -50,7 +50,7 @@ HELP;
|
|||
return $help;
|
||||
}
|
||||
|
||||
protected function doExecute()
|
||||
protected function doExecute(): int
|
||||
{
|
||||
if ($this->getOption('v')) {
|
||||
$this->out('Class: ' . __CLASS__);
|
||||
|
|
|
@ -69,7 +69,7 @@ HELP;
|
|||
$this->l10n = $l10n;
|
||||
}
|
||||
|
||||
protected function doExecute()
|
||||
protected function doExecute(): int
|
||||
{
|
||||
$a = \Friendica\DI::app();
|
||||
|
||||
|
|
|
@ -76,7 +76,7 @@ HELP;
|
|||
$this->dba = $dba;
|
||||
}
|
||||
|
||||
protected function doExecute()
|
||||
protected function doExecute(): int
|
||||
{
|
||||
if ($this->getOption('v')) {
|
||||
$this->out('Executable: ' . $this->executable);
|
||||
|
|
|
@ -74,7 +74,7 @@ HELP;
|
|||
$this->config = $config;
|
||||
}
|
||||
|
||||
protected function doExecute()
|
||||
protected function doExecute(): int
|
||||
{
|
||||
if (count($this->args) == 0) {
|
||||
$this->out($this->getHelp());
|
||||
|
|
|
@ -79,7 +79,7 @@ HELP;
|
|||
$this->config = $config;
|
||||
}
|
||||
|
||||
protected function doExecute()
|
||||
protected function doExecute(): int
|
||||
{
|
||||
if (count($this->args) == 0) {
|
||||
$this->printBlockedServers($this->config);
|
||||
|
|
|
@ -69,7 +69,7 @@ HELP;
|
|||
return $help;
|
||||
}
|
||||
|
||||
protected function doExecute()
|
||||
protected function doExecute(): int
|
||||
{
|
||||
if ($this->getOption('v')) {
|
||||
$this->out('Executable: ' . $this->executable);
|
||||
|
|
|
@ -42,7 +42,7 @@ HELP;
|
|||
return $help;
|
||||
}
|
||||
|
||||
protected function doExecute()
|
||||
protected function doExecute(): int
|
||||
{
|
||||
if ($this->getOption('v')) {
|
||||
$this->out('Class: ' . __CLASS__);
|
||||
|
|
|
@ -60,7 +60,7 @@ HELP;
|
|||
$this->config = $config;
|
||||
}
|
||||
|
||||
protected function doExecute()
|
||||
protected function doExecute(): int
|
||||
{
|
||||
if ($this->getOption('v')) {
|
||||
$this->out('Class: ' . __CLASS__);
|
||||
|
|
|
@ -97,7 +97,7 @@ HELP;
|
|||
$this->pConfig = $pConfig;
|
||||
}
|
||||
|
||||
protected function doExecute()
|
||||
protected function doExecute(): int
|
||||
{
|
||||
if ($this->getOption('v')) {
|
||||
$this->out('Class: ' . __CLASS__);
|
||||
|
|
|
@ -123,7 +123,7 @@ class Avatar
|
|||
return $fields;
|
||||
}
|
||||
|
||||
private static function getFilename(string $url)
|
||||
private static function getFilename(string $url): string
|
||||
{
|
||||
$guid = Item::guidFromUri($url, parse_url($url, PHP_URL_HOST));
|
||||
|
||||
|
|
|
@ -52,7 +52,7 @@ class LocalRelationship extends BaseFactory implements ICanCreateFromTableRow
|
|||
$row['hub-verify'] ?? '',
|
||||
$row['protocol'] ?? Protocol::PHANTOM,
|
||||
$row['rating'] ?? null,
|
||||
$row['priority'] ?? null
|
||||
$row['priority'] ?? 0
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -49,7 +49,7 @@ class BoundariesPager extends Pager
|
|||
* @param string $last_item_id The id† of the last item in the displayed item list
|
||||
* @param integer $itemsPerPage An optional number of items per page to override the default value
|
||||
*/
|
||||
public function __construct(L10n $l10n, $queryString, $first_item_id = null, $last_item_id = null, $itemsPerPage = 50)
|
||||
public function __construct(L10n $l10n, string $queryString, string $first_item_id = null, string $last_item_id = null, int $itemsPerPage = 50)
|
||||
{
|
||||
parent::__construct($l10n, $queryString, $itemsPerPage);
|
||||
|
||||
|
@ -73,12 +73,12 @@ class BoundariesPager extends Pager
|
|||
}
|
||||
}
|
||||
|
||||
public function getStart()
|
||||
public function getStart(): int
|
||||
{
|
||||
throw new \BadMethodCallException();
|
||||
}
|
||||
|
||||
public function getPage()
|
||||
public function getPage(): int
|
||||
{
|
||||
throw new \BadMethodCallException();
|
||||
}
|
||||
|
@ -102,7 +102,7 @@ class BoundariesPager extends Pager
|
|||
* @return string HTML string of the pager
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function renderMinimal(int $itemCount)
|
||||
public function renderMinimal(int $itemCount): string
|
||||
{
|
||||
$displayedItemCount = max(0, intval($itemCount));
|
||||
|
||||
|
@ -130,7 +130,10 @@ class BoundariesPager extends Pager
|
|||
return Renderer::replaceMacros($tpl, ['pager' => $data]);
|
||||
}
|
||||
|
||||
public function renderFull($itemCount)
|
||||
/**
|
||||
* Unsupported method, must be type-compatible
|
||||
*/
|
||||
public function renderFull(int $itemCount): string
|
||||
{
|
||||
throw new \BadMethodCallException();
|
||||
}
|
||||
|
|
|
@ -41,7 +41,7 @@ class ContactSelector
|
|||
* @param boolean $disabled optional, default false
|
||||
* @return string
|
||||
*/
|
||||
public static function pollInterval($current, $disabled = false)
|
||||
public static function pollInterval(string $current, bool $disabled = false): string
|
||||
{
|
||||
$dis = (($disabled) ? ' disabled="disabled" ' : '');
|
||||
$o = '';
|
||||
|
@ -84,7 +84,7 @@ class ContactSelector
|
|||
* @return string Server URL
|
||||
* @throws \Exception
|
||||
*/
|
||||
private static function getServerURLForProfile($profile)
|
||||
private static function getServerURLForProfile(string $profile): string
|
||||
{
|
||||
if (!empty(self::$server_url[$profile])) {
|
||||
return self::$server_url[$profile];
|
||||
|
@ -111,13 +111,16 @@ class ContactSelector
|
|||
}
|
||||
|
||||
/**
|
||||
* Determines network name
|
||||
*
|
||||
* @param string $network network of the contact
|
||||
* @param string $profile optional, default empty
|
||||
* @param string $protocol (Optional) Protocol that is used for the transmission
|
||||
* @param int $gsid Server id
|
||||
* @return string
|
||||
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
|
||||
*/
|
||||
public static function networkToName($network, $profile = '', $protocol = '', $gsid = 0)
|
||||
public static function networkToName(string $network, string $profile = '', string $protocol = '', int $gsid = null): string
|
||||
{
|
||||
$nets = [
|
||||
Protocol::DFRN => DI::l10n()->t('DFRN'),
|
||||
|
@ -179,12 +182,15 @@ class ContactSelector
|
|||
}
|
||||
|
||||
/**
|
||||
* Determines network's icon name
|
||||
*
|
||||
* @param string $network network
|
||||
* @param string $profile optional, default empty
|
||||
* @return string
|
||||
* @param int $gsid Server id
|
||||
* @return string Name for network icon
|
||||
* @throws \Exception
|
||||
*/
|
||||
public static function networkToIcon($network, $profile = "", $gsid = 0)
|
||||
public static function networkToIcon(string $network, string $profile = "", int $gsid = null): string
|
||||
{
|
||||
$nets = [
|
||||
Protocol::DFRN => 'friendica',
|
||||
|
|
|
@ -154,7 +154,7 @@ class Conversation
|
|||
}
|
||||
|
||||
// Skip when the causer of the parent is the same as the author of the announce
|
||||
if (($verb == Activity::ANNOUNCE) && !empty($thread_parent['causer-id'] && ($thread_parent['causer-id'] == $activity['author-id']))) {
|
||||
if (($verb == Activity::ANNOUNCE) && !empty($thread_parent['causer-id']) && ($thread_parent['causer-id'] == $activity['author-id'])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -189,7 +189,7 @@ class Conversation
|
|||
* @return string formatted text
|
||||
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
|
||||
*/
|
||||
public function formatActivity(array $links, $verb, $id)
|
||||
public function formatActivity(array $links, string $verb, int $id): string
|
||||
{
|
||||
$this->profiler->startRecording('rendering');
|
||||
$o = '';
|
||||
|
@ -275,7 +275,7 @@ class Conversation
|
|||
return $o;
|
||||
}
|
||||
|
||||
public function statusEditor(array $x = [], $notes_cid = 0, $popup = false)
|
||||
public function statusEditor(array $x = [], int $notes_cid = 0, bool $popup = false): string
|
||||
{
|
||||
$user = User::getById($this->app->getLoggedInUserId(), ['uid', 'nickname', 'allow_location', 'default-location']);
|
||||
if (empty($user['uid'])) {
|
||||
|
@ -414,8 +414,8 @@ class Conversation
|
|||
* figures out how to determine page owner and other contextual items
|
||||
* that are based on unique features of the calling module.
|
||||
* @param array $items
|
||||
* @param $mode
|
||||
* @param $update
|
||||
* @param string $mode
|
||||
* @param $update @TODO Which type?
|
||||
* @param bool $preview
|
||||
* @param string $order
|
||||
* @param int $uid
|
||||
|
@ -423,7 +423,7 @@ class Conversation
|
|||
* @throws ImagickException
|
||||
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
|
||||
*/
|
||||
public function create(array $items, $mode, $update, $preview = false, $order = 'commented', $uid = 0)
|
||||
public function create(array $items, string $mode, $update, bool $preview = false, string $order = 'commented', int $uid = 0): string
|
||||
{
|
||||
$this->profiler->startRecording('rendering');
|
||||
|
||||
|
@ -582,7 +582,7 @@ class Conversation
|
|||
|
||||
$uriids[] = $item['uri-id'];
|
||||
|
||||
if (!$this->item->visibleActivity($item)) {
|
||||
if (!$this->item->isVisibleActivity($item)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -745,7 +745,7 @@ class Conversation
|
|||
continue;
|
||||
}
|
||||
|
||||
if (!$this->item->visibleActivity($item)) {
|
||||
if (!$this->item->isVisibleActivity($item)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -784,7 +784,7 @@ class Conversation
|
|||
return $o;
|
||||
}
|
||||
|
||||
private function getBlocklist()
|
||||
private function getBlocklist(): array
|
||||
{
|
||||
if (!local_user()) {
|
||||
return [];
|
||||
|
@ -816,7 +816,7 @@ class Conversation
|
|||
*
|
||||
* @return array items with parents and comments
|
||||
*/
|
||||
private function addRowInformation(array $row, array $activity, array $thr_parent)
|
||||
private function addRowInformation(array $row, array $activity, array $thr_parent): array
|
||||
{
|
||||
$this->profiler->startRecording('rendering');
|
||||
|
||||
|
@ -911,7 +911,7 @@ class Conversation
|
|||
* @return array items with parents and comments
|
||||
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
|
||||
*/
|
||||
private function addChildren(array $parents, bool $block_authors, string $order, int $uid, string $mode)
|
||||
private function addChildren(array $parents, bool $block_authors, string $order, int $uid, string $mode): array
|
||||
{
|
||||
$this->profiler->startRecording('rendering');
|
||||
if (count($parents) > 1) {
|
||||
|
@ -1005,7 +1005,7 @@ class Conversation
|
|||
* @param bool $recursive
|
||||
* @return array
|
||||
*/
|
||||
private function getItemChildren(array &$item_list, array $parent, $recursive = true)
|
||||
private function getItemChildren(array &$item_list, array $parent, bool $recursive = true): array
|
||||
{
|
||||
$this->profiler->startRecording('rendering');
|
||||
$children = [];
|
||||
|
@ -1040,7 +1040,7 @@ class Conversation
|
|||
* @param array $items
|
||||
* @return array
|
||||
*/
|
||||
private function sortItemChildren(array $items)
|
||||
private function sortItemChildren(array $items): array
|
||||
{
|
||||
$this->profiler->startRecording('rendering');
|
||||
$result = $items;
|
||||
|
@ -1086,7 +1086,7 @@ class Conversation
|
|||
* @param array $parent A tree-like array of items
|
||||
* @return array
|
||||
*/
|
||||
private function smartFlattenConversation(array $parent)
|
||||
private function smartFlattenConversation(array $parent): array
|
||||
{
|
||||
$this->profiler->startRecording('rendering');
|
||||
if (!isset($parent['children']) || count($parent['children']) == 0) {
|
||||
|
@ -1142,7 +1142,7 @@ class Conversation
|
|||
* @return array
|
||||
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
|
||||
*/
|
||||
private function convSort(array $item_list, $order)
|
||||
private function convSort(array $item_list, string $order): array
|
||||
{
|
||||
$this->profiler->startRecording('rendering');
|
||||
$parents = [];
|
||||
|
@ -1222,7 +1222,7 @@ class Conversation
|
|||
* @param array $b
|
||||
* @return int
|
||||
*/
|
||||
private function sortThrFeaturedReceived(array $a, array $b)
|
||||
private function sortThrFeaturedReceived(array $a, array $b): int
|
||||
{
|
||||
if ($b['featured'] && !$a['featured']) {
|
||||
return 1;
|
||||
|
@ -1240,7 +1240,7 @@ class Conversation
|
|||
* @param array $b
|
||||
* @return int
|
||||
*/
|
||||
private function sortThrFeaturedCommented(array $a, array $b)
|
||||
private function sortThrFeaturedCommented(array $a, array $b): int
|
||||
{
|
||||
if ($b['featured'] && !$a['featured']) {
|
||||
return 1;
|
||||
|
@ -1258,7 +1258,7 @@ class Conversation
|
|||
* @param array $b
|
||||
* @return int
|
||||
*/
|
||||
private function sortThrReceived(array $a, array $b)
|
||||
private function sortThrReceived(array $a, array $b): int
|
||||
{
|
||||
return strcmp($b['received'], $a['received']);
|
||||
}
|
||||
|
@ -1270,7 +1270,7 @@ class Conversation
|
|||
* @param array $b
|
||||
* @return int
|
||||
*/
|
||||
private function sortThrReceivedRev(array $a, array $b)
|
||||
private function sortThrReceivedRev(array $a, array $b): int
|
||||
{
|
||||
return strcmp($a['received'], $b['received']);
|
||||
}
|
||||
|
@ -1282,7 +1282,7 @@ class Conversation
|
|||
* @param array $b
|
||||
* @return int
|
||||
*/
|
||||
private function sortThrCommented(array $a, array $b)
|
||||
private function sortThrCommented(array $a, array $b): int
|
||||
{
|
||||
return strcmp($b['commented'], $a['commented']);
|
||||
}
|
||||
|
@ -1294,7 +1294,7 @@ class Conversation
|
|||
* @param array $b
|
||||
* @return int
|
||||
*/
|
||||
private function sortThrCreated(array $a, array $b)
|
||||
private function sortThrCreated(array $a, array $b): int
|
||||
{
|
||||
return strcmp($b['created'], $a['created']);
|
||||
}
|
||||
|
|
|
@ -85,7 +85,7 @@ class Item
|
|||
* ]
|
||||
* ]
|
||||
*/
|
||||
public function determineCategoriesTerms(array $item, int $uid = 0)
|
||||
public function determineCategoriesTerms(array $item, int $uid = 0): array
|
||||
{
|
||||
$categories = [];
|
||||
$folders = [];
|
||||
|
@ -141,16 +141,16 @@ class Item
|
|||
* This function removes the tag $tag from the text $body and replaces it with
|
||||
* the appropriate link.
|
||||
*
|
||||
* @param string $body the text to replace the tag in
|
||||
* @param integer $profile_uid the user id to replace the tag for (0 = anyone)
|
||||
* @param string $tag the tag to replace
|
||||
* @param string $network The network of the post
|
||||
* @param string $body the text to replace the tag in
|
||||
* @param int $profile_uid the user id to replace the tag for (0 = anyone)
|
||||
* @param string $tag the tag to replace
|
||||
* @param string $network The network of the post
|
||||
*
|
||||
* @return array|bool ['replaced' => $replaced, 'contact' => $contact];
|
||||
* @return array|bool ['replaced' => $replaced, 'contact' => $contact] or "false" on if already replaced
|
||||
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
|
||||
* @throws \ImagickException
|
||||
*/
|
||||
public static function replaceTag(&$body, $profile_uid, $tag, $network = '')
|
||||
public static function replaceTag(string &$body, int $profile_uid, string $tag, string $network = '')
|
||||
{
|
||||
$replaced = false;
|
||||
|
||||
|
@ -244,16 +244,17 @@ class Item
|
|||
/**
|
||||
* Render actions localized
|
||||
*
|
||||
* @param $item
|
||||
* @param array $item
|
||||
* @return void
|
||||
* @throws ImagickException
|
||||
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
|
||||
*/
|
||||
public function localize(&$item)
|
||||
public function localize(array &$item)
|
||||
{
|
||||
$this->profiler->startRecording('rendering');
|
||||
/// @todo The following functionality needs to be cleaned up.
|
||||
if (!empty($item['verb'])) {
|
||||
$xmlhead = "<" . "?xml version='1.0' encoding='UTF-8' ?" . ">";
|
||||
$xmlhead = '<?xml version="1.0" encoding="UTF-8" ?>';
|
||||
|
||||
if (stristr($item['verb'], Activity::POKE)) {
|
||||
$verb = urldecode(substr($item['verb'], strpos($item['verb'],'#') + 1));
|
||||
|
@ -261,7 +262,7 @@ class Item
|
|||
$this->profiler->stopRecording();
|
||||
return;
|
||||
}
|
||||
if ($item['object-type'] == "" || $item['object-type'] !== Activity\ObjectType::PERSON) {
|
||||
if ($item['object-type'] == '' || $item['object-type'] !== Activity\ObjectType::PERSON) {
|
||||
$this->profiler->stopRecording();
|
||||
return;
|
||||
}
|
||||
|
@ -270,18 +271,22 @@ class Item
|
|||
|
||||
$Bname = $obj->title;
|
||||
$Blink = $obj->id;
|
||||
$Bphoto = "";
|
||||
$Bphoto = '';
|
||||
|
||||
foreach ($obj->link as $l) {
|
||||
$atts = $l->attributes();
|
||||
switch ($atts['rel']) {
|
||||
case "alternate": $Blink = $atts['href'];
|
||||
case "photo": $Bphoto = $atts['href'];
|
||||
case 'alternate': $Blink = $atts['href'];
|
||||
case 'photo': $Bphoto = $atts['href'];
|
||||
}
|
||||
}
|
||||
|
||||
$author = ['uid' => 0, 'id' => $item['author-id'],
|
||||
'network' => $item['author-network'], 'url' => $item['author-link']];
|
||||
$author = [
|
||||
'uid' => 0,
|
||||
'id' => $item['author-id'],
|
||||
'network' => $item['author-network'],
|
||||
'url' => $item['author-link'],
|
||||
];
|
||||
$A = '[url=' . Contact::magicLinkByContact($author) . ']' . $item['author-name'] . '[/url]';
|
||||
|
||||
if (!empty($Blink)) {
|
||||
|
@ -290,7 +295,7 @@ class Item
|
|||
$B = '';
|
||||
}
|
||||
|
||||
if ($Bphoto != "" && !empty($Blink)) {
|
||||
if ($Bphoto != '' && !empty($Blink)) {
|
||||
$Bphoto = '[url=' . Contact::magicLink($Blink) . '][img=80x80]' . $Bphoto . '[/img][/url]';
|
||||
}
|
||||
|
||||
|
@ -305,9 +310,7 @@ class Item
|
|||
$txt = str_replace($poked_t, $this->l10n->t($verb), $txt);
|
||||
|
||||
// then do the sprintf on the translation string
|
||||
|
||||
$item['body'] = sprintf($txt, $A, $B) . "\n\n\n" . $Bphoto;
|
||||
|
||||
}
|
||||
|
||||
if ($this->activity->match($item['verb'], Activity::TAG)) {
|
||||
|
@ -319,12 +322,20 @@ class Item
|
|||
return;
|
||||
}
|
||||
|
||||
$author_arr = ['uid' => 0, 'id' => $item['author-id'],
|
||||
'network' => $item['author-network'], 'url' => $item['author-link']];
|
||||
$author_arr = [
|
||||
'uid' => 0,
|
||||
'id' => $item['author-id'],
|
||||
'network' => $item['author-network'],
|
||||
'url' => $item['author-link'],
|
||||
];
|
||||
$author = '[url=' . Contact::magicLinkByContact($author_arr) . ']' . $item['author-name'] . '[/url]';
|
||||
|
||||
$author_arr = ['uid' => 0, 'id' => $obj['author-id'],
|
||||
'network' => $obj['author-network'], 'url' => $obj['author-link']];
|
||||
$author_arr = [
|
||||
'uid' => 0,
|
||||
'id' => $obj['author-id'],
|
||||
'network' => $obj['author-network'],
|
||||
'url' => $obj['author-link'],
|
||||
];
|
||||
$objauthor = '[url=' . Contact::magicLinkByContact($author_arr) . ']' . $obj['author-name'] . '[/url]';
|
||||
|
||||
switch ($obj['verb']) {
|
||||
|
@ -337,6 +348,7 @@ class Item
|
|||
$post_type = $this->l10n->t('status');
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
if ($obj['resource-id']) {
|
||||
$post_type = $this->l10n->t('photo');
|
||||
|
@ -360,25 +372,29 @@ class Item
|
|||
$this->profiler->stopRecording();
|
||||
}
|
||||
|
||||
public function photoMenu($item, string $formSecurityToken)
|
||||
/**
|
||||
* Renders photo menu based on item
|
||||
*
|
||||
* @param array $item
|
||||
* @param string $formSecurityToken
|
||||
* @return string
|
||||
*/
|
||||
public function photoMenu(array $item, string $formSecurityToken): string
|
||||
{
|
||||
$this->profiler->startRecording('rendering');
|
||||
$sub_link = '';
|
||||
$poke_link = '';
|
||||
$contact_url = '';
|
||||
$pm_url = '';
|
||||
$status_link = '';
|
||||
$photos_link = '';
|
||||
$posts_link = '';
|
||||
$block_link = '';
|
||||
$ignore_link = '';
|
||||
$sub_link = $poke_link = $contact_url = $pm_url = $status_link = '';
|
||||
$photos_link = $posts_link = $block_link = $ignore_link = '';
|
||||
|
||||
if (local_user() && local_user() == $item['uid'] && $item['gravity'] == GRAVITY_PARENT && !$item['self'] && !$item['mention']) {
|
||||
$sub_link = 'javascript:doFollowThread(' . $item['id'] . '); return false;';
|
||||
}
|
||||
|
||||
$author = ['uid' => 0, 'id' => $item['author-id'],
|
||||
'network' => $item['author-network'], 'url' => $item['author-link']];
|
||||
$author = [
|
||||
'uid' => 0,
|
||||
'id' => $item['author-id'],
|
||||
'network' => $item['author-network'],
|
||||
'url' => $item['author-link'],
|
||||
];
|
||||
$profile_link = Contact::magicLinkByContact($author, $item['author-link']);
|
||||
$sparkle = (strpos($profile_link, 'redir/') === 0);
|
||||
|
||||
|
@ -435,7 +451,7 @@ class Item
|
|||
}
|
||||
|
||||
if ($network == Protocol::DFRN) {
|
||||
$menu[$this->l10n->t("Poke")] = $poke_link;
|
||||
$menu[$this->l10n->t('Poke')] = $poke_link;
|
||||
}
|
||||
|
||||
if ((($cid == 0) || ($rel == Contact::FOLLOWER)) &&
|
||||
|
@ -465,24 +481,28 @@ class Item
|
|||
return $o;
|
||||
}
|
||||
|
||||
public function visibleActivity($item) {
|
||||
|
||||
/**
|
||||
* Checks if the activity is visible to current user
|
||||
*
|
||||
* @param array $item Activity item
|
||||
* @return bool Whether the item is visible to the user
|
||||
*/
|
||||
public function isVisibleActivity(array $item): bool
|
||||
{
|
||||
// Empty verb or hidden?
|
||||
if (empty($item['verb']) || $this->activity->isHidden($item['verb'])) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// @TODO below if() block can be rewritten to a single line: $isVisible = allConditionsHere;
|
||||
if ($this->activity->match($item['verb'], Activity::FOLLOW) &&
|
||||
// Check conditions
|
||||
return (!($this->activity->match($item['verb'], Activity::FOLLOW) &&
|
||||
$item['object-type'] === Activity\ObjectType::NOTE &&
|
||||
empty($item['self']) &&
|
||||
$item['uid'] == local_user()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
$item['uid'] == local_user())
|
||||
);
|
||||
}
|
||||
|
||||
public function expandTags(array $item, bool $setPermissions = false)
|
||||
public function expandTags(array $item, bool $setPermissions = false): array
|
||||
{
|
||||
// Look for any tags and linkify them
|
||||
$item['inform'] = '';
|
||||
|
|
|
@ -62,7 +62,7 @@ class Nav
|
|||
*
|
||||
* @param string $item
|
||||
*/
|
||||
public static function setSelected($item)
|
||||
public static function setSelected(string $item)
|
||||
{
|
||||
self::$selected[$item] = 'selected';
|
||||
}
|
||||
|
@ -74,7 +74,7 @@ class Nav
|
|||
* @return string
|
||||
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
|
||||
*/
|
||||
public static function build(App $a)
|
||||
public static function build(App $a): string
|
||||
{
|
||||
// Placeholder div for popup panel
|
||||
$nav = '<div id="panel" style="display: none;"></div>';
|
||||
|
@ -106,7 +106,7 @@ class Nav
|
|||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function getAppMenu()
|
||||
public static function getAppMenu(): array
|
||||
{
|
||||
if (is_null(self::$app_menu)) {
|
||||
self::populateAppMenu();
|
||||
|
@ -117,6 +117,8 @@ class Nav
|
|||
|
||||
/**
|
||||
* Fills the apps static variable with apps that require a menu
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private static function populateAppMenu()
|
||||
{
|
||||
|
|
|
@ -49,7 +49,13 @@ use Friendica\Util\Strings;
|
|||
*/
|
||||
class OEmbed
|
||||
{
|
||||
public static function replaceCallback($matches)
|
||||
/**
|
||||
* Callback for fetching URL, checking allowance and returning formatted HTML
|
||||
*
|
||||
* @param array $matches
|
||||
* @return string Formatted HTML
|
||||
*/
|
||||
public static function replaceCallback(array $matches): string
|
||||
{
|
||||
$embedurl = $matches[1];
|
||||
$j = self::fetchURL($embedurl, !self::isAllowedURL($embedurl));
|
||||
|
@ -68,7 +74,7 @@ class OEmbed
|
|||
* @return \Friendica\Object\OEmbed
|
||||
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
|
||||
*/
|
||||
public static function fetchURL($embedurl, bool $no_rich_type = false, bool $use_parseurl = true)
|
||||
public static function fetchURL(string $embedurl, bool $no_rich_type = false, bool $use_parseurl = true): \Friendica\Object\OEmbed
|
||||
{
|
||||
$embedurl = trim($embedurl, '\'"');
|
||||
|
||||
|
@ -209,12 +215,18 @@ class OEmbed
|
|||
return $oembed;
|
||||
}
|
||||
|
||||
private static function formatObject(\Friendica\Object\OEmbed $oembed)
|
||||
/**
|
||||
* Returns a formatted string from OEmbed object
|
||||
*
|
||||
* @param \Friendica\Object\OEmbed $oembed
|
||||
* @return string
|
||||
*/
|
||||
private static function formatObject(\Friendica\Object\OEmbed $oembed): string
|
||||
{
|
||||
$ret = '<div class="oembed ' . $oembed->type . '">';
|
||||
|
||||
switch ($oembed->type) {
|
||||
case "video":
|
||||
case 'video':
|
||||
if ($oembed->thumbnail_url) {
|
||||
$tw = (isset($oembed->thumbnail_width) && intval($oembed->thumbnail_width)) ? $oembed->thumbnail_width : 200;
|
||||
$th = (isset($oembed->thumbnail_height) && intval($oembed->thumbnail_height)) ? $oembed->thumbnail_height : 180;
|
||||
|
@ -236,14 +248,14 @@ class OEmbed
|
|||
}
|
||||
break;
|
||||
|
||||
case "photo":
|
||||
case 'photo':
|
||||
$ret .= '<img width="' . $oembed->width . '" src="' . Proxy::proxifyUrl($oembed->url) . '">';
|
||||
break;
|
||||
|
||||
case "link":
|
||||
case 'link':
|
||||
break;
|
||||
|
||||
case "rich":
|
||||
case 'rich':
|
||||
$ret .= Proxy::proxifyHtml($oembed->html);
|
||||
break;
|
||||
}
|
||||
|
@ -292,9 +304,15 @@ class OEmbed
|
|||
return str_replace("\n", "", $ret);
|
||||
}
|
||||
|
||||
public static function BBCode2HTML($text)
|
||||
/**
|
||||
* Converts BBCode to HTML code
|
||||
*
|
||||
* @param string $text
|
||||
* @return string
|
||||
*/
|
||||
public static function BBCode2HTML(string $text): string
|
||||
{
|
||||
$stopoembed = DI::config()->get("system", "no_oembed");
|
||||
$stopoembed = DI::config()->get('system', 'no_oembed');
|
||||
if ($stopoembed == true) {
|
||||
return preg_replace("/\[embed\](.+?)\[\/embed\]/is", "<!-- oembed $1 --><i>" . DI::l10n()->t('Embedding disabled') . " : $1</i><!-- /oembed $1 -->", $text);
|
||||
}
|
||||
|
@ -305,14 +323,13 @@ class OEmbed
|
|||
* Find <span class='oembed'>..<a href='url' rel='oembed'>..</a></span>
|
||||
* and replace it with [embed]url[/embed]
|
||||
*
|
||||
* @param $text
|
||||
* @param string $text
|
||||
* @return string
|
||||
*/
|
||||
public static function HTML2BBCode($text)
|
||||
public static function HTML2BBCode(string $text): string
|
||||
{
|
||||
// start parser only if 'oembed' is in text
|
||||
if (strpos($text, "oembed")) {
|
||||
|
||||
if (strpos($text, 'oembed')) {
|
||||
// convert non ascii chars to html entities
|
||||
$html_text = mb_convert_encoding($text, 'HTML-ENTITIES', mb_detect_encoding($text));
|
||||
|
||||
|
@ -323,17 +340,17 @@ class OEmbed
|
|||
}
|
||||
$xpath = new DOMXPath($dom);
|
||||
|
||||
$xattr = self::buildXPath("class", "oembed");
|
||||
$xattr = self::buildXPath('class', 'oembed');
|
||||
$entries = $xpath->query("//div[$xattr]");
|
||||
|
||||
$xattr = "@rel='oembed'"; //oe_build_xpath("rel","oembed");
|
||||
foreach ($entries as $e) {
|
||||
$href = $xpath->evaluate("a[$xattr]/@href", $e)->item(0)->nodeValue;
|
||||
if (!is_null($href)) {
|
||||
$e->parentNode->replaceChild(new DOMText("[embed]" . $href . "[/embed]"), $e);
|
||||
$e->parentNode->replaceChild(new DOMText('[embed]' . $href . '[/embed]'), $e);
|
||||
}
|
||||
}
|
||||
return self::getInnerHTML($dom->getElementsByTagName("body")->item(0));
|
||||
return self::getInnerHTML($dom->getElementsByTagName('body')->item(0));
|
||||
} else {
|
||||
return $text;
|
||||
}
|
||||
|
@ -346,7 +363,7 @@ class OEmbed
|
|||
* @return boolean
|
||||
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
|
||||
*/
|
||||
public static function isAllowedURL($url)
|
||||
public static function isAllowedURL(string $url): bool
|
||||
{
|
||||
if (!DI::config()->get('system', 'no_oembed_rich_content')) {
|
||||
return true;
|
||||
|
@ -367,7 +384,14 @@ class OEmbed
|
|||
return Network::isDomainAllowed($domain, $allowed);
|
||||
}
|
||||
|
||||
public static function getHTML($url, $title = null)
|
||||
/**
|
||||
* Returns a formmated HTML code from given URL and sets optional title
|
||||
*
|
||||
* @param string $url URL to fetch
|
||||
* @param string $title Optional title (default: what comes from OEmbed object)
|
||||
* @return string Formatted HTML
|
||||
*/
|
||||
public static function getHTML(string $url, string $title = '')
|
||||
{
|
||||
$o = self::fetchURL($url, !self::isAllowedURL($url));
|
||||
|
||||
|
@ -401,12 +425,12 @@ class OEmbed
|
|||
* @param string $src Original remote URL to embed
|
||||
* @param string $width
|
||||
* @param string $height
|
||||
* @return string formatted HTML
|
||||
* @return string Formatted HTML
|
||||
*
|
||||
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
|
||||
* @see oembed_format_object()
|
||||
*/
|
||||
private static function iframe($src, $width, $height)
|
||||
private static function iframe(string $src, string $width, string $height): string
|
||||
{
|
||||
if (!$height || strstr($height, '%')) {
|
||||
$height = '200';
|
||||
|
@ -427,7 +451,7 @@ class OEmbed
|
|||
* @param string $value Value to search in a space-separated list
|
||||
* @return string
|
||||
*/
|
||||
private static function buildXPath($attr, $value)
|
||||
private static function buildXPath(string $attr, $value): string
|
||||
{
|
||||
// https://www.westhoffswelt.de/blog/2009/6/9/select-html-elements-with-more-than-one-css-class-using-xpath
|
||||
return "contains(normalize-space(@$attr), ' $value ') or substring(normalize-space(@$attr), 1, string-length('$value') + 1) = '$value ' or substring(normalize-space(@$attr), string-length(@$attr) - string-length('$value')) = ' $value' or @$attr = '$value'";
|
||||
|
@ -439,7 +463,7 @@ class OEmbed
|
|||
* @param DOMNode $node
|
||||
* @return string
|
||||
*/
|
||||
private static function getInnerHTML(DOMNode $node)
|
||||
private static function getInnerHTML(DOMNode $node): string
|
||||
{
|
||||
$innerHTML = '';
|
||||
$children = $node->childNodes;
|
||||
|
|
|
@ -64,7 +64,7 @@ class PageInfo
|
|||
* @return string
|
||||
* @throws HTTPException\InternalServerErrorException
|
||||
*/
|
||||
public static function appendDataToBody(string $body, array $data, bool $no_photos = false)
|
||||
public static function appendDataToBody(string $body, array $data, bool $no_photos = false): string
|
||||
{
|
||||
// Only one [attachment] tag per body is allowed
|
||||
$existingAttachmentPos = strpos($body, '[attachment');
|
||||
|
@ -90,7 +90,7 @@ class PageInfo
|
|||
* @return string
|
||||
* @throws HTTPException\InternalServerErrorException
|
||||
*/
|
||||
public static function getFooterFromUrl(string $url, bool $no_photos = false, string $photo = '', bool $keywords = false, string $keyword_denylist = '')
|
||||
public static function getFooterFromUrl(string $url, bool $no_photos = false, string $photo = '', bool $keywords = false, string $keyword_denylist = ''): string
|
||||
{
|
||||
$data = self::queryUrl($url, $photo, $keywords, $keyword_denylist);
|
||||
|
||||
|
@ -103,7 +103,7 @@ class PageInfo
|
|||
* @return string
|
||||
* @throws HTTPException\InternalServerErrorException
|
||||
*/
|
||||
public static function getFooterFromData(array $data, bool $no_photos = false)
|
||||
public static function getFooterFromData(array $data, bool $no_photos = false): string
|
||||
{
|
||||
Hook::callAll('page_info_data', $data);
|
||||
|
||||
|
@ -220,7 +220,7 @@ class PageInfo
|
|||
* @return array
|
||||
* @throws HTTPException\InternalServerErrorException
|
||||
*/
|
||||
public static function getTagsFromUrl(string $url, string $photo = '', string $keyword_denylist = '')
|
||||
public static function getTagsFromUrl(string $url, string $photo = '', string $keyword_denylist = ''): array
|
||||
{
|
||||
$data = self::queryUrl($url, $photo, true, $keyword_denylist);
|
||||
|
||||
|
@ -282,7 +282,7 @@ class PageInfo
|
|||
* @param string $url
|
||||
* @return string
|
||||
*/
|
||||
protected static function stripTrailingUrlFromBody(string $body, string $url)
|
||||
protected static function stripTrailingUrlFromBody(string $body, string $url): string
|
||||
{
|
||||
$quotedUrl = preg_quote($url, '#');
|
||||
$body = preg_replace_callback("#(?:
|
||||
|
|
|
@ -48,11 +48,11 @@ class Pager
|
|||
*
|
||||
* Guesses the page number from the GET parameter 'page'.
|
||||
*
|
||||
* @param L10n $l10n
|
||||
* @param string $queryString The query string of the current page
|
||||
* @param integer $itemsPerPage An optional number of items per page to override the default value
|
||||
* @param L10n $l10n
|
||||
* @param string $queryString The query string of the current page
|
||||
* @param int $itemsPerPage An optional number of items per page to override the default value
|
||||
*/
|
||||
public function __construct(L10n $l10n, $queryString, $itemsPerPage = 50)
|
||||
public function __construct(L10n $l10n, string $queryString, int $itemsPerPage = 50)
|
||||
{
|
||||
$this->l10n = $l10n;
|
||||
|
||||
|
@ -64,9 +64,9 @@ class Pager
|
|||
/**
|
||||
* Returns the start offset for a LIMIT clause. Starts at 0.
|
||||
*
|
||||
* @return integer
|
||||
* @return int
|
||||
*/
|
||||
public function getStart()
|
||||
public function getStart(): int
|
||||
{
|
||||
return max(0, ($this->page * $this->itemsPerPage) - $this->itemsPerPage);
|
||||
}
|
||||
|
@ -74,9 +74,9 @@ class Pager
|
|||
/**
|
||||
* Returns the number of items per page
|
||||
*
|
||||
* @return integer
|
||||
* @return int
|
||||
*/
|
||||
public function getItemsPerPage()
|
||||
public function getItemsPerPage(): int
|
||||
{
|
||||
return $this->itemsPerPage;
|
||||
}
|
||||
|
@ -86,7 +86,7 @@ class Pager
|
|||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getPage()
|
||||
public function getPage(): int
|
||||
{
|
||||
return $this->page;
|
||||
}
|
||||
|
@ -108,9 +108,9 @@ class Pager
|
|||
/**
|
||||
* Sets the number of items per page, 1 minimum.
|
||||
*
|
||||
* @param integer $itemsPerPage
|
||||
* @param int $itemsPerPage
|
||||
*/
|
||||
public function setItemsPerPage($itemsPerPage)
|
||||
public function setItemsPerPage(int $itemsPerPage)
|
||||
{
|
||||
$this->itemsPerPage = max(1, intval($itemsPerPage));
|
||||
}
|
||||
|
@ -118,11 +118,11 @@ class Pager
|
|||
/**
|
||||
* Sets the current page number. Starts at 1.
|
||||
*
|
||||
* @param integer $page
|
||||
* @param int $page
|
||||
*/
|
||||
public function setPage($page)
|
||||
public function setPage(int $page)
|
||||
{
|
||||
$this->page = max(1, intval($page));
|
||||
$this->page = max(1, $page);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -132,7 +132,7 @@ class Pager
|
|||
*
|
||||
* @param string $queryString
|
||||
*/
|
||||
public function setQueryString($queryString)
|
||||
public function setQueryString(string $queryString)
|
||||
{
|
||||
$stripped = preg_replace('/([&?]page=[0-9]*)/', '', $queryString);
|
||||
|
||||
|
@ -160,7 +160,7 @@ class Pager
|
|||
* @return string HTML string of the pager
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function renderMinimal(int $itemCount)
|
||||
public function renderMinimal(int $itemCount): string
|
||||
{
|
||||
$displayedItemCount = max(0, intval($itemCount));
|
||||
|
||||
|
@ -199,13 +199,13 @@ class Pager
|
|||
*
|
||||
* $html = $pager->renderFull();
|
||||
*
|
||||
* @param integer $itemCount The total number of items including those note displayed on the page
|
||||
* @param int $itemCount The total number of items including those note displayed on the page
|
||||
* @return string HTML string of the pager
|
||||
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
|
||||
*/
|
||||
public function renderFull($itemCount)
|
||||
public function renderFull(int $itemCount): string
|
||||
{
|
||||
$totalItemCount = max(0, intval($itemCount));
|
||||
$totalItemCount = max(0, $itemCount);
|
||||
|
||||
$data = [];
|
||||
|
||||
|
|
|
@ -39,10 +39,9 @@ class Smilies
|
|||
* @param array $b Array of emoticons
|
||||
* @param string $smiley The text smilie
|
||||
* @param string $representation The replacement
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public static function add(&$b, $smiley, $representation)
|
||||
public static function add(array &$b, string $smiley, string $representation)
|
||||
{
|
||||
$found = array_search($smiley, $b['texts']);
|
||||
|
||||
|
@ -66,7 +65,7 @@ class Smilies
|
|||
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
|
||||
* @hook smilie ('texts' => smilies texts array, 'icons' => smilies html array)
|
||||
*/
|
||||
public static function getList()
|
||||
public static function getList(): array
|
||||
{
|
||||
$texts = [
|
||||
'<3',
|
||||
|
@ -169,7 +168,7 @@ class Smilies
|
|||
*
|
||||
* @return string $subject with all substrings in the $search array replaced by the values in the $replace array
|
||||
*/
|
||||
private static function strOrigReplace($search, $replace, $subject)
|
||||
private static function strOrigReplace(array $search, array $replace, string $subject): string
|
||||
{
|
||||
return strtr($subject, array_combine($search, $replace));
|
||||
}
|
||||
|
@ -191,7 +190,7 @@ class Smilies
|
|||
* @return string HTML Output of the Smilie
|
||||
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
|
||||
*/
|
||||
public static function replace($s, $no_images = false)
|
||||
public static function replace(string $s, bool $no_images = false): string
|
||||
{
|
||||
$smilies = self::getList();
|
||||
|
||||
|
@ -211,7 +210,7 @@ class Smilies
|
|||
* @return string
|
||||
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
|
||||
*/
|
||||
public static function replaceFromArray($text, array $smilies, $no_images = false)
|
||||
public static function replaceFromArray(string $text, array $smilies, bool $no_images = false): string
|
||||
{
|
||||
if (intval(DI::config()->get('system', 'no_smilies'))
|
||||
|| (local_user() && intval(DI::pConfig()->get(local_user(), 'system', 'no_smilies')))
|
||||
|
@ -234,7 +233,7 @@ class Smilies
|
|||
$smilies = $cleaned;
|
||||
}
|
||||
|
||||
$text = preg_replace_callback('/<(3+)/', 'self::pregHeart', $text);
|
||||
$text = preg_replace_callback('/<(3+)/', 'self::heartReplaceCallback', $text);
|
||||
$text = self::strOrigReplace($smilies['texts'], $smilies['icons'], $text);
|
||||
|
||||
$text = preg_replace_callback('/<(code)>(.*?)<\/code>/ism', 'self::decode', $text);
|
||||
|
@ -244,22 +243,24 @@ class Smilies
|
|||
}
|
||||
|
||||
/**
|
||||
* @param string $m string
|
||||
* Encodes smiley match array to BASE64 string
|
||||
*
|
||||
* @param array $m Match array
|
||||
* @return string base64 encoded string
|
||||
*/
|
||||
private static function encode($m)
|
||||
private static function encode(array $m): string
|
||||
{
|
||||
return '<' . $m[1] . '>' . Strings::base64UrlEncode($m[2]) . '</' . $m[1] . '>';
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $m string
|
||||
* Decodes a previously BASE64-encoded match array to a string
|
||||
*
|
||||
* @param array $m Matches array
|
||||
* @return string base64 decoded string
|
||||
* @throws \Exception
|
||||
*/
|
||||
private static function decode($m)
|
||||
private static function decode(array $m): string
|
||||
{
|
||||
return '<' . $m[1] . '>' . Strings::base64UrlDecode($m[2]) . '</' . $m[1] . '>';
|
||||
}
|
||||
|
@ -268,24 +269,20 @@ class Smilies
|
|||
/**
|
||||
* expand <3333 to the correct number of hearts
|
||||
*
|
||||
* @param string $x string
|
||||
*
|
||||
* @param array $matches
|
||||
* @return string HTML Output
|
||||
*
|
||||
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
|
||||
*/
|
||||
private static function pregHeart($x)
|
||||
private static function heartReplaceCallback(array $matches): string
|
||||
{
|
||||
if (strlen($x[1]) == 1) {
|
||||
return $x[0];
|
||||
if (strlen($matches[1]) == 1) {
|
||||
return $matches[0];
|
||||
}
|
||||
|
||||
$t = '';
|
||||
for ($cnt = 0; $cnt < strlen($x[1]); $cnt ++) {
|
||||
for ($cnt = 0; $cnt < strlen($matches[1]); $cnt ++) {
|
||||
$t .= '❤';
|
||||
}
|
||||
|
||||
$r = str_replace($x[0], $t, $x[0]);
|
||||
return $r;
|
||||
return str_replace($matches[0], $t, $matches[0]);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -81,7 +81,7 @@ class BBCode
|
|||
* 'description' -> Description of the attachment
|
||||
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
|
||||
*/
|
||||
private static function getOldAttachmentData($body)
|
||||
private static function getOldAttachmentData(string $body): array
|
||||
{
|
||||
$post = [];
|
||||
|
||||
|
@ -152,7 +152,7 @@ class BBCode
|
|||
* 'description' -> Description of the attachment
|
||||
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
|
||||
*/
|
||||
public static function getAttachmentData($body)
|
||||
public static function getAttachmentData(string $body): array
|
||||
{
|
||||
DI::profiler()->startRecording('rendering');
|
||||
$data = [
|
||||
|
@ -187,26 +187,31 @@ class BBCode
|
|||
case 'publisher_name':
|
||||
$data['provider_name'] = html_entity_decode($value, ENT_QUOTES, 'UTF-8');
|
||||
break;
|
||||
|
||||
case 'publisher_url':
|
||||
$data['provider_url'] = html_entity_decode($value, ENT_QUOTES, 'UTF-8');
|
||||
break;
|
||||
|
||||
case 'author_name':
|
||||
$data['author_name'] = html_entity_decode($value, ENT_QUOTES, 'UTF-8');
|
||||
if ($data['provider_name'] == $data['author_name']) {
|
||||
$data['author_name'] = '';
|
||||
}
|
||||
break;
|
||||
|
||||
case 'author_url':
|
||||
$data['author_url'] = html_entity_decode($value, ENT_QUOTES, 'UTF-8');
|
||||
if ($data['provider_url'] == $data['author_url']) {
|
||||
$data['author_url'] = '';
|
||||
}
|
||||
break;
|
||||
|
||||
case 'title':
|
||||
$value = self::convert(html_entity_decode($value, ENT_QUOTES, 'UTF-8'), false, true);
|
||||
$value = html_entity_decode($value, ENT_QUOTES, 'UTF-8');
|
||||
$value = str_replace(['[', ']'], ['[', ']'], $value);
|
||||
$data['title'] = $value;
|
||||
|
||||
default:
|
||||
$data[$field] = html_entity_decode($value, ENT_QUOTES, 'UTF-8');
|
||||
break;
|
||||
|
@ -241,7 +246,7 @@ class BBCode
|
|||
return $data;
|
||||
}
|
||||
|
||||
public static function getAttachedData($body, $item = [])
|
||||
public static function getAttachedData(string $body, array $item = []): array
|
||||
{
|
||||
/*
|
||||
- text:
|
||||
|
@ -303,7 +308,7 @@ class BBCode
|
|||
// Workaround:
|
||||
// Sometimes photo posts to the own album are not detected at the start.
|
||||
// So we seem to cannot use the cache for these cases. That's strange.
|
||||
if (($data['type'] != 'photo') && strstr($pictures[0][1], "/photos/")) {
|
||||
if (($data['type'] != 'photo') && strstr($pictures[0][1], '/photos/')) {
|
||||
$data = ParseUrl::getSiteinfo($pictures[0][1]);
|
||||
}
|
||||
|
||||
|
@ -320,7 +325,7 @@ class BBCode
|
|||
$post['text'] = trim(str_replace($pictures[0][0], '', $body));
|
||||
} else {
|
||||
$imgdata = Images::getInfoFromURLCached($pictures[0][1]);
|
||||
if ($imgdata && substr($imgdata['mime'], 0, 6) == 'image/') {
|
||||
if (($imgdata) && substr($imgdata['mime'], 0, 6) == 'image/') {
|
||||
$post['type'] = 'photo';
|
||||
$post['image'] = $pictures[0][1];
|
||||
$post['preview'] = $pictures[0][2];
|
||||
|
@ -390,7 +395,7 @@ class BBCode
|
|||
}
|
||||
|
||||
if (!isset($post['type'])) {
|
||||
$post['type'] = "text";
|
||||
$post['type'] = 'text';
|
||||
$post['text'] = trim($body);
|
||||
}
|
||||
|
||||
|
@ -419,10 +424,9 @@ class BBCode
|
|||
*
|
||||
* @param string $body
|
||||
* @param boolean $no_link_desc No link description
|
||||
*
|
||||
* @return string with replaced body
|
||||
*/
|
||||
public static function removeAttachment($body, $no_link_desc = false)
|
||||
public static function removeAttachment(string $body, bool $no_link_desc = false): string
|
||||
{
|
||||
return preg_replace_callback("/\s*\[attachment (.*?)\](.*?)\[\/attachment\]\s*/ism",
|
||||
function ($match) use ($body, $no_link_desc) {
|
||||
|
@ -442,12 +446,11 @@ class BBCode
|
|||
/**
|
||||
* Converts a BBCode text into plaintext
|
||||
*
|
||||
* @param $text
|
||||
* @param string $text
|
||||
* @param bool $keep_urls Whether to keep URLs in the resulting plaintext
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function toPlaintext($text, $keep_urls = true)
|
||||
public static function toPlaintext(string $text, bool $keep_urls = true): string
|
||||
{
|
||||
DI::profiler()->startRecording('rendering');
|
||||
// Remove pictures in advance to avoid unneeded proxy calls
|
||||
|
@ -463,7 +466,7 @@ class BBCode
|
|||
return $naked_text;
|
||||
}
|
||||
|
||||
private static function proxyUrl($image, $simplehtml = self::INTERNAL, $uriid = 0, $size = '')
|
||||
private static function proxyUrl(string $image, int $simplehtml = self::INTERNAL, int $uriid = 0, string $size = ''): string
|
||||
{
|
||||
// Only send proxied pictures to API and for internal display
|
||||
if (!in_array($simplehtml, [self::INTERNAL, self::API])) {
|
||||
|
@ -483,7 +486,7 @@ class BBCode
|
|||
* @param string $srctext The body with images
|
||||
* @return string The body with possibly scaled images
|
||||
*/
|
||||
public static function scaleExternalImages(string $srctext)
|
||||
public static function scaleExternalImages(string $srctext): string
|
||||
{
|
||||
DI::profiler()->startRecording('rendering');
|
||||
$s = $srctext;
|
||||
|
@ -551,7 +554,7 @@ class BBCode
|
|||
* @return string
|
||||
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
|
||||
*/
|
||||
public static function limitBodySize($body)
|
||||
public static function limitBodySize(string $body): string
|
||||
{
|
||||
DI::profiler()->startRecording('rendering');
|
||||
$maxlen = DI::config()->get('config', 'max_import_size', 0);
|
||||
|
@ -646,7 +649,7 @@ class BBCode
|
|||
* @return string
|
||||
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
|
||||
*/
|
||||
public static function convertAttachment($text, $simplehtml = self::INTERNAL, $tryoembed = true, array $data = [], $uriid = 0)
|
||||
public static function convertAttachment(string $text, int $simplehtml = self::INTERNAL, bool $tryoembed = true, array $data = [], int $uriid = 0): string
|
||||
{
|
||||
DI::profiler()->startRecording('rendering');
|
||||
$data = $data ?: self::getAttachmentData($text);
|
||||
|
@ -659,10 +662,10 @@ class BBCode
|
|||
$data['title'] = strip_tags($data['title']);
|
||||
$data['title'] = str_replace(['http://', 'https://'], '', $data['title']);
|
||||
} else {
|
||||
$data['title'] = null;
|
||||
$data['title'] = '';
|
||||
}
|
||||
|
||||
if (((strpos($data['text'], "[img=") !== false) || (strpos($data['text'], "[img]") !== false) || DI::config()->get('system', 'always_show_preview')) && !empty($data['image'])) {
|
||||
if (((strpos($data['text'], '[img=') !== false) || (strpos($data['text'], '[img]') !== false) || DI::config()->get('system', 'always_show_preview')) && !empty($data['image'])) {
|
||||
$data['preview'] = $data['image'];
|
||||
$data['image'] = '';
|
||||
}
|
||||
|
@ -716,14 +719,14 @@ class BBCode
|
|||
return trim(($data['text'] ?? '') . ' ' . $return . ' ' . ($data['after'] ?? ''));
|
||||
}
|
||||
|
||||
public static function removeShareInformation($Text, $plaintext = false, $nolink = false)
|
||||
public static function removeShareInformation(string $text, bool $plaintext = false, bool $nolink = false): string
|
||||
{
|
||||
DI::profiler()->startRecording('rendering');
|
||||
$data = self::getAttachmentData($Text);
|
||||
$data = self::getAttachmentData($text);
|
||||
|
||||
if (!$data) {
|
||||
DI::profiler()->stopRecording();
|
||||
return $Text;
|
||||
return $text;
|
||||
} elseif ($nolink) {
|
||||
DI::profiler()->stopRecording();
|
||||
return $data['text'] . ($data['after'] ?? '');
|
||||
|
@ -767,7 +770,7 @@ class BBCode
|
|||
* @param array $match Array with the matching values
|
||||
* @return string reformatted link including HTML codes
|
||||
*/
|
||||
private static function convertUrlForActivityPubCallback($match)
|
||||
private static function convertUrlForActivityPubCallback(array $match): string
|
||||
{
|
||||
$url = $match[1];
|
||||
|
||||
|
@ -789,10 +792,9 @@ class BBCode
|
|||
* @param string $url URL that is about to be reformatted
|
||||
* @return string reformatted link including HTML codes
|
||||
*/
|
||||
private static function convertUrlForActivityPub($url)
|
||||
private static function convertUrlForActivityPub(string $url): string
|
||||
{
|
||||
$html = '<a href="%s" target="_blank" rel="noopener noreferrer">%s</a>';
|
||||
return sprintf($html, $url, self::getStyledURL($url));
|
||||
return sprintf('<a href="%s" target="_blank" rel="noopener noreferrer">%s</a>', $url, self::getStyledURL($url));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -801,7 +803,7 @@ class BBCode
|
|||
* @param string $url URL that is about to be reformatted
|
||||
* @return string reformatted link
|
||||
*/
|
||||
private static function getStyledURL($url)
|
||||
private static function getStyledURL(string $url): string
|
||||
{
|
||||
$parts = parse_url($url);
|
||||
$scheme = $parts['scheme'] . '://';
|
||||
|
@ -818,8 +820,11 @@ class BBCode
|
|||
* [noparse][i]italic[/i][/noparse] turns into
|
||||
* [noparse][ i ]italic[ /i ][/noparse],
|
||||
* to hide them from parser.
|
||||
*
|
||||
* @param array $match
|
||||
* @return string
|
||||
*/
|
||||
private static function escapeNoparseCallback($match)
|
||||
private static function escapeNoparseCallback(array $match): string
|
||||
{
|
||||
$whole_match = $match[0];
|
||||
$captured = $match[1];
|
||||
|
@ -832,8 +837,11 @@ class BBCode
|
|||
* The previously spacefied [noparse][ i ]italic[ /i ][/noparse],
|
||||
* now turns back and the [noparse] tags are trimed
|
||||
* returning [i]italic[/i]
|
||||
*
|
||||
* @param array $match
|
||||
* @return string
|
||||
*/
|
||||
private static function unescapeNoparseCallback($match)
|
||||
private static function unescapeNoparseCallback(array $match): string
|
||||
{
|
||||
$captured = $match[1];
|
||||
$unspacefied = preg_replace("/\[ (.*?)\ ]/", "[$1]", $captured);
|
||||
|
@ -849,7 +857,7 @@ class BBCode
|
|||
* @param int $occurrences Number of first occurrences to skip
|
||||
* @return boolean|array
|
||||
*/
|
||||
public static function getTagPosition($text, $name, $occurrences = 0)
|
||||
public static function getTagPosition(string $text, string $name, int $occurrences = 0)
|
||||
{
|
||||
DI::profiler()->startRecording('rendering');
|
||||
if ($occurrences < 0) {
|
||||
|
@ -913,7 +921,7 @@ class BBCode
|
|||
* @param string $text Text to search
|
||||
* @return string
|
||||
*/
|
||||
public static function pregReplaceInTag($pattern, $replace, $name, $text)
|
||||
public static function pregReplaceInTag(string $pattern, string $replace, string $name, string $text): string
|
||||
{
|
||||
DI::profiler()->startRecording('rendering');
|
||||
$occurrences = 0;
|
||||
|
@ -936,7 +944,7 @@ class BBCode
|
|||
return $text;
|
||||
}
|
||||
|
||||
private static function extractImagesFromItemBody($body)
|
||||
private static function extractImagesFromItemBody(string $body): array
|
||||
{
|
||||
$saved_image = [];
|
||||
$orig_body = $body;
|
||||
|
@ -977,7 +985,7 @@ class BBCode
|
|||
return ['body' => $new_body, 'images' => $saved_image];
|
||||
}
|
||||
|
||||
private static function interpolateSavedImagesIntoItemBody($uriid, $body, array $images)
|
||||
private static function interpolateSavedImagesIntoItemBody(int $uriid, string $body, array $images): string
|
||||
{
|
||||
$newbody = $body;
|
||||
|
||||
|
@ -995,29 +1003,51 @@ class BBCode
|
|||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param string $text A BBCode string
|
||||
* @return array share attributes
|
||||
* @param string $text A BBCode string
|
||||
* @return array Empty array if no share tag is present or the following array, missing attributes end up empty strings:
|
||||
* - comment: Text before the opening share tag
|
||||
* - shared : Text inside the share tags
|
||||
* - author : (Optional) Display name of the shared author
|
||||
* - profile: (Optional) Profile page URL of the shared author
|
||||
* - avatar : (Optional) Profile picture URL of the shared author
|
||||
* - link : (Optional) Canonical URL of the shared post
|
||||
* - posted : (Optional) Date the shared post was initially posted ("Y-m-d H:i:s" in GMT)
|
||||
* - guid : (Optional) Shared post GUID if any
|
||||
*/
|
||||
public static function fetchShareAttributes($text)
|
||||
public static function fetchShareAttributes(string $text): array
|
||||
{
|
||||
DI::profiler()->startRecording('rendering');
|
||||
// See Issue https://github.com/friendica/friendica/issues/10454
|
||||
// Hashtags in usernames are expanded to links. This here is a quick fix.
|
||||
$text = preg_replace('/([@!#])\[url\=.*?\](.*?)\[\/url\]/ism', '$1$2', $text);
|
||||
$text = preg_replace('~([@!#])\[url=.*?](.*?)\[/url]~ism', '$1$2', $text);
|
||||
|
||||
$attributes = [];
|
||||
if (!preg_match("/(.*?)\[share(.*?)\](.*)\[\/share\]/ism", $text, $matches)) {
|
||||
if (!preg_match('~(.*?)\[share(.*?)](.*)\[/share]~ism', $text, $matches)) {
|
||||
DI::profiler()->stopRecording();
|
||||
return $attributes;
|
||||
return [];
|
||||
}
|
||||
|
||||
$attribute_string = $matches[2];
|
||||
$attributes = self::extractShareAttributes($matches[2]);
|
||||
|
||||
$attributes['comment'] = trim($matches[1]);
|
||||
$attributes['shared'] = trim($matches[3]);
|
||||
|
||||
DI::profiler()->stopRecording();
|
||||
return $attributes;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see BBCode::fetchShareAttributes()
|
||||
* @param string $shareString Internal opening share tag string matched by the regular expression
|
||||
* @return array A fixed attribute array where missing attribute are represented by empty strings
|
||||
*/
|
||||
private static function extractShareAttributes(string $shareString): array
|
||||
{
|
||||
$attributes = [];
|
||||
foreach (['author', 'profile', 'avatar', 'link', 'posted', 'guid'] as $field) {
|
||||
preg_match("/$field=(['\"])(.+?)\\1/ism", $attribute_string, $matches);
|
||||
preg_match("/$field=(['\"])(.+?)\\1/ism", $shareString, $matches);
|
||||
$attributes[$field] = html_entity_decode($matches[2] ?? '', ENT_QUOTES, 'UTF-8');
|
||||
}
|
||||
DI::profiler()->stopRecording();
|
||||
|
||||
return $attributes;
|
||||
}
|
||||
|
||||
|
@ -1040,18 +1070,13 @@ class BBCode
|
|||
* @param callable $callback
|
||||
* @return string The BBCode string with all [share] blocks replaced
|
||||
*/
|
||||
public static function convertShare($text, callable $callback, int $uriid = 0)
|
||||
public static function convertShare(string $text, callable $callback, int $uriid = 0): string
|
||||
{
|
||||
DI::profiler()->startRecording('rendering');
|
||||
$return = preg_replace_callback(
|
||||
"/(.*?)\[share(.*?)\](.*)\[\/share\]/ism",
|
||||
'~(.*?)\[share(.*?)](.*)\[/share]~ism',
|
||||
function ($match) use ($callback, $uriid) {
|
||||
$attribute_string = $match[2];
|
||||
$attributes = [];
|
||||
foreach (['author', 'profile', 'avatar', 'link', 'posted', 'guid'] as $field) {
|
||||
preg_match("/$field=(['\"])(.+?)\\1/ism", $attribute_string, $matches);
|
||||
$attributes[$field] = html_entity_decode($matches[2] ?? '', ENT_QUOTES, 'UTF-8');
|
||||
}
|
||||
$attributes = self::extractShareAttributes($match[2]);
|
||||
|
||||
$author_contact = Contact::getByURL($attributes['profile'], false, ['id', 'url', 'addr', 'name', 'micro']);
|
||||
$author_contact['url'] = ($author_contact['url'] ?? $attributes['profile']);
|
||||
|
@ -1086,7 +1111,7 @@ class BBCode
|
|||
* @param integer $uriid
|
||||
* @return string
|
||||
*/
|
||||
private static function convertImages(string $text, int $simplehtml, int $uriid = 0):string
|
||||
private static function convertImages(string $text, int $simplehtml, int $uriid = 0): string
|
||||
{
|
||||
DI::profiler()->startRecording('rendering');
|
||||
$return = preg_replace_callback(
|
||||
|
@ -1129,7 +1154,7 @@ class BBCode
|
|||
* @return string
|
||||
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
|
||||
*/
|
||||
private static function convertShareCallback(array $attributes, array $author_contact, $content, $is_quote_share, $simplehtml)
|
||||
private static function convertShareCallback(array $attributes, array $author_contact, string $content, bool $is_quote_share, int $simplehtml): string
|
||||
{
|
||||
DI::profiler()->startRecording('rendering');
|
||||
$mention = $attributes['author'] . ' (' . ($author_contact['addr'] ?? '') . ')';
|
||||
|
@ -1198,7 +1223,7 @@ class BBCode
|
|||
return $text;
|
||||
}
|
||||
|
||||
private static function removePictureLinksCallback($match)
|
||||
private static function removePictureLinksCallback(array $match): string
|
||||
{
|
||||
$cache_key = 'remove:' . $match[1];
|
||||
$text = DI::cache()->get($cache_key);
|
||||
|
@ -1212,9 +1237,9 @@ class BBCode
|
|||
}
|
||||
|
||||
if (substr($mimetype, 0, 6) == 'image/') {
|
||||
$text = "[url=" . $match[1] . ']' . $match[1] . "[/url]";
|
||||
$text = '[url=' . $match[1] . ']' . $match[1] . '[/url]';
|
||||
} else {
|
||||
$text = "[url=" . $match[2] . ']' . $match[2] . "[/url]";
|
||||
$text = '[url=' . $match[2] . ']' . $match[2] . '[/url]';
|
||||
|
||||
// if its not a picture then look if its a page that contains a picture link
|
||||
$body = DI::httpClient()->fetch($match[1], HttpClientAccept::HTML, 0);
|
||||
|
@ -1226,7 +1251,7 @@ class BBCode
|
|||
$doc = new DOMDocument();
|
||||
@$doc->loadHTML($body);
|
||||
$xpath = new DOMXPath($doc);
|
||||
$list = $xpath->query("//meta[@name]");
|
||||
$list = $xpath->query('//meta[@name]');
|
||||
foreach ($list as $node) {
|
||||
$attr = [];
|
||||
|
||||
|
@ -1247,16 +1272,28 @@ class BBCode
|
|||
return $text;
|
||||
}
|
||||
|
||||
private static function expandLinksCallback($match)
|
||||
/**
|
||||
* Callback: Expands links from given $match array
|
||||
*
|
||||
* @param arrat $match Array with link match
|
||||
* @return string BBCode
|
||||
*/
|
||||
private static function expandLinksCallback(array $match): string
|
||||
{
|
||||
if (($match[3] == '') || ($match[2] == $match[3]) || stristr($match[2], $match[3])) {
|
||||
return ($match[1] . "[url]" . $match[2] . "[/url]");
|
||||
return ($match[1] . '[url]' . $match[2] . '[/url]');
|
||||
} else {
|
||||
return ($match[1] . $match[3] . " [url]" . $match[2] . "[/url]");
|
||||
return ($match[1] . $match[3] . ' [url]' . $match[2] . '[/url]');
|
||||
}
|
||||
}
|
||||
|
||||
private static function cleanPictureLinksCallback($match)
|
||||
/**
|
||||
* Callback: Cleans picture links
|
||||
*
|
||||
* @param arrat $match Array with link match
|
||||
* @return string BBCode
|
||||
*/
|
||||
private static function cleanPictureLinksCallback(array $match): string
|
||||
{
|
||||
// When the picture link is the own photo path then we can avoid fetching the link
|
||||
$own_photo_url = preg_quote(Strings::normaliseLink(DI::baseUrl()->get()) . '/photos/');
|
||||
|
@ -1302,7 +1339,7 @@ class BBCode
|
|||
$doc = new DOMDocument();
|
||||
@$doc->loadHTML($body);
|
||||
$xpath = new DOMXPath($doc);
|
||||
$list = $xpath->query("//meta[@name]");
|
||||
$list = $xpath->query('//meta[@name]');
|
||||
foreach ($list as $node) {
|
||||
$attr = [];
|
||||
if ($node->attributes->length) {
|
||||
|
@ -1325,7 +1362,13 @@ class BBCode
|
|||
return $text;
|
||||
}
|
||||
|
||||
public static function cleanPictureLinks($text)
|
||||
/**
|
||||
* Cleans picture links
|
||||
*
|
||||
* @param string $text HTML/BBCode string
|
||||
* @return string Cleaned HTML/BBCode
|
||||
*/
|
||||
public static function cleanPictureLinks(string $text): string
|
||||
{
|
||||
DI::profiler()->startRecording('rendering');
|
||||
$return = preg_replace_callback("&\[url=([^\[\]]*)\]\[img=(.*)\](.*)\[\/img\]\[\/url\]&Usi", 'self::cleanPictureLinksCallback', $text);
|
||||
|
@ -1334,7 +1377,13 @@ class BBCode
|
|||
return $return;
|
||||
}
|
||||
|
||||
public static function removeLinks(string $bbcode)
|
||||
/**
|
||||
* Removes links
|
||||
*
|
||||
* @param string $text HTML/BBCode string
|
||||
* @return string Cleaned HTML/BBCode
|
||||
*/
|
||||
public static function removeLinks(string $bbcode): string
|
||||
{
|
||||
DI::profiler()->startRecording('rendering');
|
||||
$bbcode = preg_replace("/\[img\=(.*?)\](.*?)\[\/img\]/ism", ' $1 ', $bbcode);
|
||||
|
@ -1350,10 +1399,10 @@ class BBCode
|
|||
/**
|
||||
* Replace names in mentions with nicknames
|
||||
*
|
||||
* @param string $body
|
||||
* @param string $body HTML/BBCode
|
||||
* @return string Body with replaced mentions
|
||||
*/
|
||||
public static function setMentionsToNicknames(string $body):string
|
||||
public static function setMentionsToNicknames(string $body): string
|
||||
{
|
||||
DI::profiler()->startRecording('rendering');
|
||||
$regexp = "/([@!])\[url\=([^\[\]]*)\].*?\[\/url\]/ism";
|
||||
|
@ -1366,10 +1415,10 @@ class BBCode
|
|||
* Callback function to replace a Friendica style mention in a mention with the nickname
|
||||
*
|
||||
* @param array $match Matching values for the callback
|
||||
* @return string Replaced mention
|
||||
* @return string Replaced mention or empty string
|
||||
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
|
||||
*/
|
||||
private static function mentionCallback($match)
|
||||
private static function mentionCallback(array $match): string
|
||||
{
|
||||
if (empty($match[2])) {
|
||||
return '';
|
||||
|
@ -1407,7 +1456,7 @@ class BBCode
|
|||
* @return string
|
||||
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
|
||||
*/
|
||||
public static function convertForUriId(int $uriid = null, string $text = null, int $simple_html = self::INTERNAL)
|
||||
public static function convertForUriId(int $uriid = null, string $text = null, int $simple_html = self::INTERNAL): string
|
||||
{
|
||||
$try_oembed = ($simple_html == self::INTERNAL);
|
||||
|
||||
|
@ -1437,10 +1486,10 @@ class BBCode
|
|||
* @param int $simple_html
|
||||
* @param bool $for_plaintext
|
||||
* @param int $uriid
|
||||
* @return string
|
||||
* @return string Converted code or empty string
|
||||
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
|
||||
*/
|
||||
public static function convert(string $text = null, $try_oembed = true, $simple_html = self::INTERNAL, $for_plaintext = false, $uriid = 0)
|
||||
public static function convert(string $text = null, bool $try_oembed = true, int $simple_html = self::INTERNAL, bool $for_plaintext = false, int $uriid = 0): string
|
||||
{
|
||||
// Accounting for null default column values
|
||||
if (is_null($text) || $text === '') {
|
||||
|
@ -1462,10 +1511,10 @@ class BBCode
|
|||
* $match[1] = $url
|
||||
* $match[2] = $title or absent
|
||||
*/
|
||||
$try_oembed_callback = function ($match)
|
||||
$try_oembed_callback = function (array $match)
|
||||
{
|
||||
$url = $match[1];
|
||||
$title = $match[2] ?? null;
|
||||
$title = $match[2] ?? '';
|
||||
|
||||
try {
|
||||
$return = OEmbed::getHTML($url, $title);
|
||||
|
@ -1788,7 +1837,7 @@ class BBCode
|
|||
|
||||
$text = preg_replace("/\[crypt\](.*?)\[\/crypt\]/ism", '<br><img src="' .DI::baseUrl() . '/images/lock_icon.gif" alt="' . DI::l10n()->t('Encrypted content') . '" title="' . DI::l10n()->t('Encrypted content') . '" /><br>', $text);
|
||||
$text = preg_replace("/\[crypt(.*?)\](.*?)\[\/crypt\]/ism", '<br><img src="' .DI::baseUrl() . '/images/lock_icon.gif" alt="' . DI::l10n()->t('Encrypted content') . '" title="' . '$1' . ' ' . DI::l10n()->t('Encrypted content') . '" /><br>', $text);
|
||||
//$Text = preg_replace("/\[crypt=(.*?)\](.*?)\[\/crypt\]/ism", '<br><img src="' .DI::baseUrl() . '/images/lock_icon.gif" alt="' . DI::l10n()->t('Encrypted content') . '" title="' . '$1' . ' ' . DI::l10n()->t('Encrypted content') . '" /><br>', $Text);
|
||||
//$text = preg_replace("/\[crypt=(.*?)\](.*?)\[\/crypt\]/ism", '<br><img src="' .DI::baseUrl() . '/images/lock_icon.gif" alt="' . DI::l10n()->t('Encrypted content') . '" title="' . '$1' . ' ' . DI::l10n()->t('Encrypted content') . '" /><br>', $text);
|
||||
|
||||
// Simplify "video" element
|
||||
$text = preg_replace('(\[video[^\]]*?\ssrc\s?=\s?([^\s\]]+)[^\]]*?\].*?\[/video\])ism', '[video]$1[/video]', $text);
|
||||
|
@ -1916,8 +1965,8 @@ class BBCode
|
|||
|
||||
if (in_array($simple_html, [self::OSTATUS, self::TWITTER])) {
|
||||
$text = preg_replace_callback("/([^#@!])\[url\=([^\]]*)\](.*?)\[\/url\]/ism", "self::expandLinksCallback", $text);
|
||||
//$Text = preg_replace("/[^#@!]\[url\=([^\]]*)\](.*?)\[\/url\]/ism", ' $2 [url]$1[/url]', $Text);
|
||||
$text = preg_replace("/\[bookmark\=([^\]]*)\](.*?)\[\/bookmark\]/ism", ' $2 [url]$1[/url]',$text);
|
||||
//$text = preg_replace("/[^#@!]\[url\=([^\]]*)\](.*?)\[\/url\]/ism", ' $2 [url]$1[/url]', $text);
|
||||
$text = preg_replace("/\[bookmark\=([^\]]*)\](.*?)\[\/bookmark\]/ism", ' $2 [url]$1[/url]', $text);
|
||||
}
|
||||
|
||||
// Perform URL Search
|
||||
|
@ -2142,7 +2191,7 @@ class BBCode
|
|||
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
|
||||
* @throws \ImagickException
|
||||
*/
|
||||
private static function bbCodeMention2DiasporaCallback($match)
|
||||
private static function bbCodeMention2DiasporaCallback(array $match): string
|
||||
{
|
||||
$contact = Contact::getByURL($match[3], false, ['addr']);
|
||||
if (empty($contact['addr'])) {
|
||||
|
@ -2164,7 +2213,7 @@ class BBCode
|
|||
* @return string
|
||||
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
|
||||
*/
|
||||
public static function toMarkdown($text, $for_diaspora = true)
|
||||
public static function toMarkdown(string $text, bool $for_diaspora = true): string
|
||||
{
|
||||
DI::profiler()->startRecording('rendering');
|
||||
$original_text = $text;
|
||||
|
@ -2201,7 +2250,7 @@ class BBCode
|
|||
$tagline .= '#' . $tag . ' ';
|
||||
}
|
||||
}
|
||||
$text = $text . " " . $tagline;
|
||||
$text = $text . ' ' . $tagline;
|
||||
}
|
||||
} else {
|
||||
$text = self::convert($text, false, self::CONNECTORS);
|
||||
|
@ -2246,10 +2295,9 @@ class BBCode
|
|||
* Returns array of tags found, or empty array.
|
||||
*
|
||||
* @param string $string Post content
|
||||
*
|
||||
* @return array List of tag and person names
|
||||
*/
|
||||
public static function getTags($string)
|
||||
public static function getTags(string $string): array
|
||||
{
|
||||
DI::profiler()->startRecording('rendering');
|
||||
$ret = [];
|
||||
|
@ -2309,13 +2357,13 @@ class BBCode
|
|||
/**
|
||||
* Expand tags to URLs, checks the tag is at the start of a line or preceded by a non-word character
|
||||
*
|
||||
* @param string $body
|
||||
* @param string $body HTML/BBCode
|
||||
* @return string body with expanded tags
|
||||
*/
|
||||
public static function expandTags(string $body)
|
||||
public static function expandTags(string $body): string
|
||||
{
|
||||
return preg_replace_callback("/(?<=\W|^)([!#@])([^\^ \x0D\x0A,;:?'\"]*[^\^ \x0D\x0A,;:?!'\".])/",
|
||||
function ($match) {
|
||||
function (array $match) {
|
||||
switch ($match[1]) {
|
||||
case '!':
|
||||
case '@':
|
||||
|
@ -2326,6 +2374,7 @@ class BBCode
|
|||
return $match[1] . $match[2];
|
||||
}
|
||||
break;
|
||||
|
||||
case '#':
|
||||
default:
|
||||
return $match[1] . '[url=' . DI::baseUrl() . '/search?tag=' . $match[2] . ']' . $match[2] . '[/url]';
|
||||
|
@ -2336,7 +2385,7 @@ class BBCode
|
|||
/**
|
||||
* Perform a custom function on a text after having escaped blocks enclosed in the provided tag list.
|
||||
*
|
||||
* @param string $text
|
||||
* @param string $text HTML/BBCode
|
||||
* @param array $tagList A list of tag names, e.g ['noparse', 'nobb', 'pre']
|
||||
* @param callable $callback
|
||||
* @return string
|
||||
|
@ -2352,14 +2401,14 @@ class BBCode
|
|||
/**
|
||||
* Replaces mentions in the provided message body in BBCode links for the provided user and network if any
|
||||
*
|
||||
* @param $body
|
||||
* @param $profile_uid
|
||||
* @param $network
|
||||
* @return string
|
||||
* @param string $body HTML/BBCode
|
||||
* @param int $profile_uid Profile user id
|
||||
* @param string $network Network name
|
||||
* @return string HTML/BBCode with inserted images
|
||||
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
|
||||
* @throws \ImagickException
|
||||
*/
|
||||
public static function setMentions($body, $profile_uid = 0, $network = '')
|
||||
public static function setMentions(string $body, $profile_uid = 0, $network = '')
|
||||
{
|
||||
DI::profiler()->startRecording('rendering');
|
||||
$body = self::performWithEscapedTags($body, ['noparse', 'pre', 'code', 'img'], function ($body) use ($profile_uid, $network) {
|
||||
|
@ -2406,7 +2455,7 @@ class BBCode
|
|||
* @return string
|
||||
* @TODO Rewrite to handle over whole record array
|
||||
*/
|
||||
public static function getShareOpeningTag(string $author, string $profile, string $avatar, string $link, string $posted, string $guid = null)
|
||||
public static function getShareOpeningTag(string $author, string $profile, string $avatar, string $link, string $posted, string $guid = null): string
|
||||
{
|
||||
DI::profiler()->startRecording('rendering');
|
||||
$header = "[share author='" . str_replace(["'", "[", "]"], ["'", "[", "]"], $author) .
|
||||
|
@ -2438,8 +2487,7 @@ class BBCode
|
|||
* @param string|null $tags
|
||||
* @return string
|
||||
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
|
||||
*@see ParseUrl::getSiteinfoCached
|
||||
*
|
||||
* @see ParseUrl::getSiteinfoCached
|
||||
*/
|
||||
public static function embedURL(string $url, bool $tryAttachment = true, string $title = null, string $description = null, string $tags = null): string
|
||||
{
|
||||
|
|
|
@ -61,7 +61,7 @@ class HTML
|
|||
* inner value from an attribute value and disregard the tag children.
|
||||
* @return bool Whether a replacement was done
|
||||
*/
|
||||
private static function tagToBBCodeSub(DOMDocument $doc, string $tag, array $attributes, string $startbb, string $endbb, bool $ignoreChildren = false)
|
||||
private static function tagToBBCodeSub(DOMDocument $doc, string $tag, array $attributes, string $startbb, string $endbb, bool $ignoreChildren = false): bool
|
||||
{
|
||||
$savestart = str_replace('$', '\x01', $startbb);
|
||||
$replace = false;
|
||||
|
@ -141,8 +141,16 @@ class HTML
|
|||
* @return string
|
||||
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
|
||||
*/
|
||||
public static function toBBCode($message, $basepath = '')
|
||||
public static function toBBCode(string $message, string $basepath = ''): string
|
||||
{
|
||||
/*
|
||||
* Check if message is empty to prevent a lot code below being executed
|
||||
* for just an empty message.
|
||||
*/
|
||||
if (empty($message)) {
|
||||
return '';
|
||||
}
|
||||
|
||||
DI::profiler()->startRecording('rendering');
|
||||
$message = str_replace("\r", "", $message);
|
||||
|
||||
|
@ -409,7 +417,7 @@ class HTML
|
|||
*
|
||||
* @return string The expanded URL
|
||||
*/
|
||||
private static function qualifyURLsSub($matches, $basepath)
|
||||
private static function qualifyURLsSub(array $matches, string $basepath): string
|
||||
{
|
||||
$base = parse_url($basepath);
|
||||
unset($base['query']);
|
||||
|
@ -436,7 +444,7 @@ class HTML
|
|||
*
|
||||
* @return string Body with expanded URLs
|
||||
*/
|
||||
private static function qualifyURLs($body, $basepath)
|
||||
private static function qualifyURLs(string $body, string $basepath): string
|
||||
{
|
||||
$URLSearchString = "^\[\]";
|
||||
|
||||
|
@ -462,7 +470,7 @@ class HTML
|
|||
return $body;
|
||||
}
|
||||
|
||||
private static function breakLines($line, $level, $wraplength = 75)
|
||||
private static function breakLines(string $line, int $level, int $wraplength = 75): string
|
||||
{
|
||||
if ($wraplength == 0) {
|
||||
$wraplength = 2000000;
|
||||
|
@ -503,7 +511,7 @@ class HTML
|
|||
return implode("\n", $newlines);
|
||||
}
|
||||
|
||||
private static function quoteLevel($message, $wraplength = 75)
|
||||
private static function quoteLevel(string $message, int $wraplength = 75): string
|
||||
{
|
||||
$lines = explode("\n", $message);
|
||||
|
||||
|
@ -539,7 +547,7 @@ class HTML
|
|||
return implode("\n", $newlines);
|
||||
}
|
||||
|
||||
private static function collectURLs($message)
|
||||
private static function collectURLs(string $message): array
|
||||
{
|
||||
$pattern = '/<a.*?href="(.*?)".*?>(.*?)<\/a>/is';
|
||||
preg_match_all($pattern, $message, $result, PREG_SET_ORDER);
|
||||
|
@ -585,7 +593,7 @@ class HTML
|
|||
* @param bool $compact True: Completely strips image tags; False: Keeps image URLs
|
||||
* @return string
|
||||
*/
|
||||
public static function toPlaintext(string $html, $wraplength = 75, $compact = false)
|
||||
public static function toPlaintext(string $html, int $wraplength = 75, bool $compact = false): string
|
||||
{
|
||||
DI::profiler()->startRecording('rendering');
|
||||
$message = str_replace("\r", "", $html);
|
||||
|
@ -705,7 +713,7 @@ class HTML
|
|||
* @param string $html
|
||||
* @return string
|
||||
*/
|
||||
public static function toMarkdown($html)
|
||||
public static function toMarkdown(string $html): string
|
||||
{
|
||||
DI::profiler()->startRecording('rendering');
|
||||
$converter = new HtmlConverter(['hard_break' => true]);
|
||||
|
@ -721,7 +729,7 @@ class HTML
|
|||
* @param string $s
|
||||
* @return string
|
||||
*/
|
||||
public static function toBBCodeVideo($s)
|
||||
public static function toBBCodeVideo(string $s): string
|
||||
{
|
||||
$s = preg_replace(
|
||||
'#<object[^>]+>(.*?)https?://www.youtube.com/((?:v|cp)/[A-Za-z0-9\-_=]+)(.*?)</object>#ism',
|
||||
|
@ -751,7 +759,7 @@ class HTML
|
|||
* @param string $base base url
|
||||
* @return string
|
||||
*/
|
||||
public static function relToAbs($text, $base)
|
||||
public static function relToAbs(string $text, string $base): string
|
||||
{
|
||||
if (empty($base)) {
|
||||
return $text;
|
||||
|
@ -790,7 +798,7 @@ class HTML
|
|||
* @return string html for loader
|
||||
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
|
||||
*/
|
||||
public static function scrollLoader()
|
||||
public static function scrollLoader(): string
|
||||
{
|
||||
$tpl = Renderer::getMarkupTemplate("scroll_loader.tpl");
|
||||
return Renderer::replaceMacros($tpl, [
|
||||
|
@ -819,7 +827,7 @@ class HTML
|
|||
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
|
||||
* @throws \ImagickException
|
||||
*/
|
||||
public static function micropro($contact, $redirect = false, $class = '', $textmode = false)
|
||||
public static function micropro(array $contact, bool $redirect = false, string $class = '', bool $textmode = false): string
|
||||
{
|
||||
// Use the contact URL if no address is available
|
||||
if (empty($contact['addr'])) {
|
||||
|
@ -859,13 +867,12 @@ class HTML
|
|||
*
|
||||
* @param string $s Search query.
|
||||
* @param string $id HTML id
|
||||
* @param string $url Search url.
|
||||
* @param bool $aside Display the search widgit aside.
|
||||
*
|
||||
* @return string Formatted HTML.
|
||||
* @throws \Exception
|
||||
*/
|
||||
public static function search($s, $id = 'search-box', $aside = true)
|
||||
public static function search(string $s, string $id = 'search-box', bool $aside = true): string
|
||||
{
|
||||
$mode = 'text';
|
||||
|
||||
|
@ -906,7 +913,7 @@ class HTML
|
|||
* @param string $s
|
||||
* @return string
|
||||
*/
|
||||
public static function toLink($s)
|
||||
public static function toLink(string $s): string
|
||||
{
|
||||
$s = preg_replace("/(https?\:\/\/[a-zA-Z0-9\:\/\-\?\&\;\.\=\_\~\#\'\%\$\!\+]*)/", ' <a href="$1" target="_blank" rel="noopener noreferrer">$1</a>', $s);
|
||||
$s = preg_replace("/\<(.*?)(src|href)=(.*?)\&\;(.*?)\>/ism", '<$1$2=$3&$4>', $s);
|
||||
|
@ -923,7 +930,7 @@ class HTML
|
|||
* @return string
|
||||
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
|
||||
*/
|
||||
public static function applyContentFilter($html, array $reasons)
|
||||
public static function applyContentFilter(string $html, array $reasons): string
|
||||
{
|
||||
if (count($reasons)) {
|
||||
$tpl = Renderer::getMarkupTemplate('wall/content_filter.tpl');
|
||||
|
@ -943,7 +950,7 @@ class HTML
|
|||
* @param string $s
|
||||
* @return string
|
||||
*/
|
||||
public static function unamp($s)
|
||||
public static function unamp(string $s): string
|
||||
{
|
||||
return str_replace('&', '&', $s);
|
||||
}
|
||||
|
|
|
@ -36,7 +36,7 @@ class Plaintext
|
|||
*
|
||||
* @todo For Twitter URLs aren't shortened, but they have to be calculated as if.
|
||||
*/
|
||||
public static function shorten(string $msg, int $limit, int $uid = 0):string
|
||||
public static function shorten(string $msg, int $limit, int $uid = 0): string
|
||||
{
|
||||
$ellipsis = html_entity_decode("…", ENT_QUOTES, 'UTF-8');
|
||||
|
||||
|
|
|
@ -45,7 +45,7 @@ class Widget
|
|||
* @return string
|
||||
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
|
||||
*/
|
||||
public static function follow($value = "")
|
||||
public static function follow(string $value = ''): string
|
||||
{
|
||||
return Renderer::replaceMacros(Renderer::getMarkupTemplate('widget/follow.tpl'), array(
|
||||
'$connect' => DI::l10n()->t('Add New Contact'),
|
||||
|
@ -58,8 +58,10 @@ class Widget
|
|||
|
||||
/**
|
||||
* Return Find People widget
|
||||
*
|
||||
* @return string HTML code respresenting "People Widget"
|
||||
*/
|
||||
public static function findPeople()
|
||||
public static function findPeople(): string
|
||||
{
|
||||
$global_dir = Search::getGlobalDirectory();
|
||||
|
||||
|
@ -97,7 +99,7 @@ class Widget
|
|||
*
|
||||
* @return array Unsupported networks
|
||||
*/
|
||||
public static function unavailableNetworks()
|
||||
public static function unavailableNetworks(): array
|
||||
{
|
||||
// Always hide content from these networks
|
||||
$networks = [Protocol::PHANTOM, Protocol::FACEBOOK, Protocol::APPNET, Protocol::ZOT];
|
||||
|
@ -154,7 +156,7 @@ class Widget
|
|||
* @return string
|
||||
* @throws \Exception
|
||||
*/
|
||||
private static function filter($type, $title, $desc, $all, $baseUrl, array $options, $selected = null)
|
||||
private static function filter(string $type, string $title, string $desc, string $all, string $baseUrl, array $options, string $selected = null): string
|
||||
{
|
||||
$queryString = parse_url($baseUrl, PHP_URL_QUERY);
|
||||
$queryArray = [];
|
||||
|
@ -191,7 +193,7 @@ class Widget
|
|||
* @return string
|
||||
* @throws \Exception
|
||||
*/
|
||||
public static function groups($baseurl, $selected = '')
|
||||
public static function groups(string $baseurl, string $selected = ''): string
|
||||
{
|
||||
if (!local_user()) {
|
||||
return '';
|
||||
|
@ -223,7 +225,7 @@ class Widget
|
|||
* @return string
|
||||
* @throws \Exception
|
||||
*/
|
||||
public static function contactRels($baseurl, $selected = '')
|
||||
public static function contactRels(string $baseurl, string $selected = ''): string
|
||||
{
|
||||
if (!local_user()) {
|
||||
return '';
|
||||
|
@ -254,7 +256,7 @@ class Widget
|
|||
* @return string
|
||||
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
|
||||
*/
|
||||
public static function networks($baseurl, $selected = '')
|
||||
public static function networks(string $baseurl, string $selected = ''): string
|
||||
{
|
||||
if (!local_user()) {
|
||||
return '';
|
||||
|
@ -292,10 +294,10 @@ class Widget
|
|||
*
|
||||
* @param string $baseurl baseurl
|
||||
* @param string $selected optional, default empty
|
||||
* @return string|void
|
||||
* @return string
|
||||
* @throws \Exception
|
||||
*/
|
||||
public static function fileAs($baseurl, $selected = '')
|
||||
public static function fileAs(string $baseurl, string $selected = ''): string
|
||||
{
|
||||
if (!local_user()) {
|
||||
return '';
|
||||
|
@ -323,10 +325,10 @@ class Widget
|
|||
* @param int $uid Id of the user owning the categories
|
||||
* @param string $baseurl Base page URL
|
||||
* @param string $selected Selected category
|
||||
* @return string|void
|
||||
* @return string
|
||||
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
|
||||
*/
|
||||
public static function categories(int $uid, string $baseurl, string $selected = '')
|
||||
public static function categories(int $uid, string $baseurl, string $selected = ''): string
|
||||
{
|
||||
if (!Feature::isEnabled($uid, 'categories')) {
|
||||
return '';
|
||||
|
@ -353,11 +355,11 @@ class Widget
|
|||
*
|
||||
* @param int $uid Viewed profile user ID
|
||||
* @param string $nickname Viewed profile user nickname
|
||||
* @return string|void
|
||||
* @return string
|
||||
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
|
||||
* @throws \ImagickException
|
||||
*/
|
||||
public static function commonFriendsVisitor(int $uid, string $nickname)
|
||||
public static function commonFriendsVisitor(int $uid, string $nickname): string
|
||||
{
|
||||
if (local_user() == $uid) {
|
||||
return '';
|
||||
|
@ -414,7 +416,7 @@ class Widget
|
|||
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
|
||||
* @throws \ImagickException
|
||||
*/
|
||||
public static function tagCloud(int $uid, int $limit = 50)
|
||||
public static function tagCloud(int $uid, int $limit = 50): string
|
||||
{
|
||||
if (empty($uid)) {
|
||||
return '';
|
||||
|
@ -439,7 +441,7 @@ class Widget
|
|||
* @return string
|
||||
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
|
||||
*/
|
||||
public static function postedByYear(string $url, int $uid, bool $wall)
|
||||
public static function postedByYear(string $url, int $uid, bool $wall): string
|
||||
{
|
||||
$o = '';
|
||||
|
||||
|
@ -510,10 +512,10 @@ class Widget
|
|||
* The account type value is added as a parameter to the url
|
||||
*
|
||||
* @param string $base Basepath
|
||||
* @param int $accounttype Acount type
|
||||
* @param string $accounttype Account type
|
||||
* @return string
|
||||
*/
|
||||
public static function accounttypes(string $base, $accounttype)
|
||||
public static function accountTypes(string $base, string $accounttype): string
|
||||
{
|
||||
$accounts = [
|
||||
['ref' => 'person', 'name' => DI::l10n()->t('Persons')],
|
||||
|
|
|
@ -124,7 +124,7 @@ class Addon
|
|||
* @return void
|
||||
* @throws \Exception
|
||||
*/
|
||||
public static function uninstall($addon)
|
||||
public static function uninstall(string $addon)
|
||||
{
|
||||
$addon = Strings::sanitizeFilePathItem($addon);
|
||||
|
||||
|
@ -149,7 +149,7 @@ class Addon
|
|||
* @return bool
|
||||
* @throws \Exception
|
||||
*/
|
||||
public static function install($addon)
|
||||
public static function install(string $addon): bool
|
||||
{
|
||||
$addon = Strings::sanitizeFilePathItem($addon);
|
||||
|
||||
|
@ -185,6 +185,8 @@ class Addon
|
|||
|
||||
/**
|
||||
* reload all updated addons
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public static function reload()
|
||||
{
|
||||
|
@ -222,7 +224,7 @@ class Addon
|
|||
* @return array with the addon information
|
||||
* @throws \Exception
|
||||
*/
|
||||
public static function getInfo($addon)
|
||||
public static function getInfo(string $addon): array
|
||||
{
|
||||
$addon = Strings::sanitizeFilePathItem($addon);
|
||||
|
||||
|
@ -287,7 +289,7 @@ class Addon
|
|||
* @param string $addon
|
||||
* @return boolean
|
||||
*/
|
||||
public static function isEnabled($addon)
|
||||
public static function isEnabled(string $addon): bool
|
||||
{
|
||||
return in_array($addon, self::$addons);
|
||||
}
|
||||
|
@ -297,7 +299,7 @@ class Addon
|
|||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function getEnabledList()
|
||||
public static function getEnabledList(): array
|
||||
{
|
||||
return self::$addons;
|
||||
}
|
||||
|
@ -308,7 +310,7 @@ class Addon
|
|||
* @return array
|
||||
* @throws \Exception
|
||||
*/
|
||||
public static function getVisibleList()
|
||||
public static function getVisibleList(): array
|
||||
{
|
||||
$visible_addons = [];
|
||||
$stmt = DBA::select('addon', ['name'], ['hidden' => false, 'installed' => true]);
|
||||
|
|
|
@ -68,6 +68,17 @@ class MemcacheCache extends AbstractCache implements ICanCacheInMemory
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Memcache doesn't allow spaces in keys
|
||||
*
|
||||
* @param string $key
|
||||
* @return string
|
||||
*/
|
||||
protected function getCacheKey(string $key): string
|
||||
{
|
||||
return str_replace(' ', '_', parent::getCacheKey($key));
|
||||
}
|
||||
|
||||
/**
|
||||
* (@inheritdoc)
|
||||
*/
|
||||
|
|
|
@ -93,6 +93,17 @@ class MemcachedCache extends AbstractCache implements ICanCacheInMemory
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Memcached doesn't allow spaces in keys
|
||||
*
|
||||
* @param string $key
|
||||
* @return string
|
||||
*/
|
||||
protected function getCacheKey(string $key): string
|
||||
{
|
||||
return str_replace(' ', '_', parent::getCacheKey($key));
|
||||
}
|
||||
|
||||
/**
|
||||
* (@inheritdoc)
|
||||
*/
|
||||
|
|
|
@ -121,7 +121,7 @@ HELP;
|
|||
$this->dice = $dice;
|
||||
}
|
||||
|
||||
protected function doExecute()
|
||||
protected function doExecute(): int
|
||||
{
|
||||
if ($this->getOption('v')) {
|
||||
$this->out('Executable: ' . $this->executable);
|
||||
|
|
|
@ -49,6 +49,8 @@ class Hook
|
|||
|
||||
/**
|
||||
* Load hooks
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public static function loadHooks()
|
||||
{
|
||||
|
@ -69,8 +71,9 @@ class Hook
|
|||
* @param string $hook
|
||||
* @param string $file
|
||||
* @param string $function
|
||||
* @return void
|
||||
*/
|
||||
public static function add($hook, $file, $function)
|
||||
public static function add(string $hook, string $file, string $function)
|
||||
{
|
||||
if (!array_key_exists($hook, self::$hooks)) {
|
||||
self::$hooks[$hook] = [];
|
||||
|
@ -90,7 +93,7 @@ class Hook
|
|||
* @return mixed|bool
|
||||
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
|
||||
*/
|
||||
public static function register($hook, $file, $function, $priority = 0)
|
||||
public static function register(string $hook, string $file, string $function, int $priority = 0)
|
||||
{
|
||||
$file = str_replace(DI::app()->getBasePath() . DIRECTORY_SEPARATOR, '', $file);
|
||||
|
||||
|
@ -111,7 +114,7 @@ class Hook
|
|||
* @return boolean
|
||||
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
|
||||
*/
|
||||
public static function unregister($hook, $file, $function)
|
||||
public static function unregister(string $hook, string $file, string $function): bool
|
||||
{
|
||||
$relative_file = str_replace(DI::app()->getBasePath() . DIRECTORY_SEPARATOR, '', $file);
|
||||
|
||||
|
@ -120,8 +123,8 @@ class Hook
|
|||
self::delete($condition);
|
||||
|
||||
$condition = ['hook' => $hook, 'file' => $relative_file, 'function' => $function];
|
||||
$result = self::delete($condition);
|
||||
return $result;
|
||||
|
||||
return self::delete($condition);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -130,7 +133,7 @@ class Hook
|
|||
* @param string $name Name of the hook
|
||||
* @return array
|
||||
*/
|
||||
public static function getByName($name)
|
||||
public static function getByName(string $name): array
|
||||
{
|
||||
$return = [];
|
||||
|
||||
|
@ -149,9 +152,10 @@ class Hook
|
|||
* @param integer $priority of the hook
|
||||
* @param string $name of the hook to call
|
||||
* @param mixed $data to transmit to the callback handler
|
||||
* @return void
|
||||
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
|
||||
*/
|
||||
public static function fork($priority, $name, $data = null)
|
||||
public static function fork(int $priority, string $name, $data = null)
|
||||
{
|
||||
if (array_key_exists($name, self::$hooks)) {
|
||||
foreach (self::$hooks[$name] as $hook) {
|
||||
|
@ -184,9 +188,10 @@ class Hook
|
|||
*
|
||||
* @param string $name of the hook to call
|
||||
* @param string|array &$data to transmit to the callback handler
|
||||
* @return void
|
||||
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
|
||||
*/
|
||||
public static function callAll($name, &$data = null)
|
||||
public static function callAll(string $name, &$data = null)
|
||||
{
|
||||
if (array_key_exists($name, self::$hooks)) {
|
||||
foreach (self::$hooks[$name] as $hook) {
|
||||
|
@ -202,9 +207,10 @@ class Hook
|
|||
* @param string $name of the hook to call
|
||||
* @param array $hook Hook data
|
||||
* @param string|array &$data to transmit to the callback handler
|
||||
* @return void
|
||||
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
|
||||
*/
|
||||
public static function callSingle(App $a, $name, $hook, &$data = null)
|
||||
public static function callSingle(App $a, string $name, array $hook, &$data = null)
|
||||
{
|
||||
// Don't run a theme's hook if the user isn't using the theme
|
||||
if (strpos($hook[0], 'view/theme/') !== false && strpos($hook[0], 'view/theme/' . $a->getCurrentTheme()) === false) {
|
||||
|
@ -229,7 +235,7 @@ class Hook
|
|||
* @param string $name Name of the addon
|
||||
* @return boolean
|
||||
*/
|
||||
public static function isAddonApp($name)
|
||||
public static function isAddonApp(string $name): bool
|
||||
{
|
||||
$name = Strings::sanitizeFilePathItem($name);
|
||||
|
||||
|
@ -253,7 +259,7 @@ class Hook
|
|||
* @return bool
|
||||
* @throws \Exception
|
||||
*/
|
||||
public static function delete(array $condition)
|
||||
public static function delete(array $condition): bool
|
||||
{
|
||||
$result = DBA::delete('hook', $condition);
|
||||
|
||||
|
@ -273,7 +279,7 @@ class Hook
|
|||
* @return bool
|
||||
* @throws \Exception
|
||||
*/
|
||||
private static function insert(array $condition)
|
||||
private static function insert(array $condition): bool
|
||||
{
|
||||
$result = DBA::insert('hook', $condition);
|
||||
|
||||
|
|
|
@ -189,14 +189,12 @@ class Installer
|
|||
/***
|
||||
* Installs the DB-Scheme for Friendica
|
||||
*
|
||||
* @param string $basePath The base path of this application
|
||||
*
|
||||
* @return bool true if the installation was successful, otherwise false
|
||||
* @throws Exception
|
||||
*/
|
||||
public function installDatabase($basePath)
|
||||
public function installDatabase(): bool
|
||||
{
|
||||
$result = DBStructure::install($basePath);
|
||||
$result = DBStructure::install();
|
||||
|
||||
if ($result) {
|
||||
$txt = DI::l10n()->t('You may need to import the file "database.sql" manually using phpmyadmin or mysql.') . EOL;
|
||||
|
@ -656,7 +654,7 @@ class Installer
|
|||
* @return bool true if the check was successful, otherwise false
|
||||
* @throws Exception
|
||||
*/
|
||||
public function checkDB(Database $dba)
|
||||
public function checkDB(Database $dba): bool
|
||||
{
|
||||
$dba->reconnect();
|
||||
|
||||
|
|
|
@ -128,7 +128,7 @@ class L10n
|
|||
private function setLangFromSession(IHandleSessions $session)
|
||||
{
|
||||
if ($session->get('language') !== $this->lang) {
|
||||
$this->loadTranslationTable($session->get('language'));
|
||||
$this->loadTranslationTable($session->get('language') ?? $this->lang);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -140,10 +140,10 @@ class L10n
|
|||
* Uses an App object shim since all the strings files refer to $a->strings
|
||||
*
|
||||
* @param string $lang language code to load
|
||||
*
|
||||
* @return void
|
||||
* @throws \Exception
|
||||
*/
|
||||
private function loadTranslationTable($lang)
|
||||
private function loadTranslationTable(string $lang)
|
||||
{
|
||||
$lang = Strings::sanitizeFilePathItem($lang);
|
||||
|
||||
|
@ -183,7 +183,7 @@ class L10n
|
|||
*
|
||||
* @return string The two-letter language code
|
||||
*/
|
||||
public static function detectLanguage(array $server, array $get, string $sysLang = self::DEFAULT)
|
||||
public static function detectLanguage(array $server, array $get, string $sysLang = self::DEFAULT): string
|
||||
{
|
||||
$lang_variable = $server['HTTP_ACCEPT_LANGUAGE'] ?? null;
|
||||
|
||||
|
@ -269,7 +269,7 @@ class L10n
|
|||
*
|
||||
* @return string
|
||||
*/
|
||||
public function t($s, ...$vars)
|
||||
public function t(string $s, ...$vars): string
|
||||
{
|
||||
if (empty($s)) {
|
||||
return '';
|
||||
|
@ -307,7 +307,7 @@ class L10n
|
|||
* @return string
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function tt(string $singular, string $plural, int $count)
|
||||
public function tt(string $singular, string $plural, int $count): string
|
||||
{
|
||||
$s = null;
|
||||
|
||||
|
@ -352,7 +352,7 @@ class L10n
|
|||
*
|
||||
* @return bool
|
||||
*/
|
||||
private function stringPluralSelectDefault($n)
|
||||
private function stringPluralSelectDefault(int $n): bool
|
||||
{
|
||||
return $n != 1;
|
||||
}
|
||||
|
@ -369,7 +369,7 @@ class L10n
|
|||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function getAvailableLanguages()
|
||||
public static function getAvailableLanguages(): array
|
||||
{
|
||||
$langs = [];
|
||||
$strings_file_paths = glob('view/lang/*/strings.php');
|
||||
|
@ -391,10 +391,9 @@ class L10n
|
|||
* Translate days and months names.
|
||||
*
|
||||
* @param string $s String with day or month name.
|
||||
*
|
||||
* @return string Translated string.
|
||||
*/
|
||||
public function getDay($s)
|
||||
public function getDay(string $s): string
|
||||
{
|
||||
$ret = str_replace(['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday'],
|
||||
[$this->t('Monday'), $this->t('Tuesday'), $this->t('Wednesday'), $this->t('Thursday'), $this->t('Friday'), $this->t('Saturday'), $this->t('Sunday')],
|
||||
|
@ -411,10 +410,9 @@ class L10n
|
|||
* Translate short days and months names.
|
||||
*
|
||||
* @param string $s String with short day or month name.
|
||||
*
|
||||
* @return string Translated string.
|
||||
*/
|
||||
public function getDayShort($s)
|
||||
public function getDayShort(string $s): string
|
||||
{
|
||||
$ret = str_replace(['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],
|
||||
[$this->t('Mon'), $this->t('Tue'), $this->t('Wed'), $this->t('Thu'), $this->t('Fri'), $this->t('Sat'), $this->t('Sun')],
|
||||
|
@ -435,7 +433,7 @@ class L10n
|
|||
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
|
||||
* @hook poke_verbs pokes array
|
||||
*/
|
||||
public function getPokeVerbs()
|
||||
public function getPokeVerbs(): array
|
||||
{
|
||||
// index is present tense verb
|
||||
// value is array containing past tense verb, translation of present, translation of past
|
||||
|
@ -461,7 +459,7 @@ class L10n
|
|||
* @return static A new L10n instance
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function withLang(string $lang)
|
||||
public function withLang(string $lang): L10n
|
||||
{
|
||||
// Don't create a new instance for same language
|
||||
if ($lang === $this->lang) {
|
||||
|
|
|
@ -47,7 +47,7 @@ class Logger
|
|||
/**
|
||||
* @return LoggerInterface
|
||||
*/
|
||||
private static function getWorker()
|
||||
private static function getInstance()
|
||||
{
|
||||
if (self::$type === self::TYPE_LOGGER) {
|
||||
return DI::logger();
|
||||
|
@ -66,7 +66,7 @@ class Logger
|
|||
public static function enableWorker(string $functionName)
|
||||
{
|
||||
self::$type = self::TYPE_WORKER;
|
||||
self::getWorker()->setFunctionName($functionName);
|
||||
self::getInstance()->setFunctionName($functionName);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -82,15 +82,14 @@ class Logger
|
|||
*
|
||||
* @see LoggerInterface::emergency()
|
||||
*
|
||||
* @param string $message
|
||||
* @param array $context
|
||||
*
|
||||
* @param string $message Message to log
|
||||
* @param array $context Optional variables
|
||||
* @return void
|
||||
* @throws \Exception
|
||||
*/
|
||||
public static function emergency($message, $context = [])
|
||||
public static function emergency(string $message, array $context = [])
|
||||
{
|
||||
self::getWorker()->emergency($message, $context);
|
||||
self::getInstance()->emergency($message, $context);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -100,15 +99,14 @@ class Logger
|
|||
* Example: Entire website down, database unavailable, etc. This should
|
||||
* trigger the SMS alerts and wake you up.
|
||||
*
|
||||
* @param string $message
|
||||
* @param array $context
|
||||
*
|
||||
* @param string $message Message to log
|
||||
* @param array $context Optional variables
|
||||
* @return void
|
||||
* @throws \Exception
|
||||
*/
|
||||
public static function alert($message, $context = [])
|
||||
public static function alert(string $message, array $context = [])
|
||||
{
|
||||
self::getWorker()->alert($message, $context);
|
||||
self::getInstance()->alert($message, $context);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -117,15 +115,14 @@ class Logger
|
|||
*
|
||||
* Example: Application component unavailable, unexpected exception.
|
||||
*
|
||||
* @param string $message
|
||||
* @param array $context
|
||||
*
|
||||
* @param string $message Message to log
|
||||
* @param array $context Optional variables
|
||||
* @return void
|
||||
* @throws \Exception
|
||||
*/
|
||||
public static function critical($message, $context = [])
|
||||
public static function critical(string $message, array $context = [])
|
||||
{
|
||||
self::getWorker()->critical($message, $context);
|
||||
self::getInstance()->critical($message, $context);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -133,15 +130,14 @@ class Logger
|
|||
* be logged and monitored.
|
||||
* @see LoggerInterface::error()
|
||||
*
|
||||
* @param string $message
|
||||
* @param array $context
|
||||
*
|
||||
* @param string $message Message to log
|
||||
* @param array $context Optional variables
|
||||
* @return void
|
||||
* @throws \Exception
|
||||
*/
|
||||
public static function error($message, $context = [])
|
||||
public static function error(string $message, array $context = [])
|
||||
{
|
||||
self::getWorker()->error($message, $context);
|
||||
self::getInstance()->error($message, $context);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -151,30 +147,28 @@ class Logger
|
|||
* Example: Use of deprecated APIs, poor use of an API, undesirable things
|
||||
* that are not necessarily wrong.
|
||||
*
|
||||
* @param string $message
|
||||
* @param array $context
|
||||
*
|
||||
* @param string $message Message to log
|
||||
* @param array $context Optional variables
|
||||
* @return void
|
||||
* @throws \Exception
|
||||
*/
|
||||
public static function warning($message, $context = [])
|
||||
public static function warning(string $message, array $context = [])
|
||||
{
|
||||
self::getWorker()->warning($message, $context);
|
||||
self::getInstance()->warning($message, $context);
|
||||
}
|
||||
|
||||
/**
|
||||
* Normal but significant events.
|
||||
* @see LoggerInterface::notice()
|
||||
*
|
||||
* @param string $message
|
||||
* @param array $context
|
||||
*
|
||||
* @param string $message Message to log
|
||||
* @param array $context Optional variables
|
||||
* @return void
|
||||
* @throws \Exception
|
||||
*/
|
||||
public static function notice($message, $context = [])
|
||||
public static function notice(string $message, array $context = [])
|
||||
{
|
||||
self::getWorker()->notice($message, $context);
|
||||
self::getInstance()->notice($message, $context);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -189,24 +183,23 @@ class Logger
|
|||
* @return void
|
||||
* @throws \Exception
|
||||
*/
|
||||
public static function info($message, $context = [])
|
||||
public static function info(string $message, array $context = [])
|
||||
{
|
||||
self::getWorker()->info($message, $context);
|
||||
self::getInstance()->info($message, $context);
|
||||
}
|
||||
|
||||
/**
|
||||
* Detailed debug information.
|
||||
* @see LoggerInterface::debug()
|
||||
*
|
||||
* @param string $message
|
||||
* @param array $context
|
||||
*
|
||||
* @param string $message Message to log
|
||||
* @param array $context Optional variables
|
||||
* @return void
|
||||
* @throws \Exception
|
||||
*/
|
||||
public static function debug($message, $context = [])
|
||||
public static function debug(string $message, array $context = [])
|
||||
{
|
||||
self::getWorker()->debug($message, $context);
|
||||
self::getInstance()->debug($message, $context);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -216,12 +209,13 @@ class Logger
|
|||
* to isolate particular elements they are targetting
|
||||
* personally without background noise
|
||||
*
|
||||
* @param string $msg
|
||||
* @param string $level
|
||||
* @param string $message Message to log
|
||||
* @param string $level Logging level
|
||||
* @return void
|
||||
* @throws \Exception
|
||||
*/
|
||||
public static function devLog($msg, $level = LogLevel::DEBUG)
|
||||
public static function devLog(string $message, string $level = LogLevel::DEBUG)
|
||||
{
|
||||
DI::devLogger()->log($level, $msg);
|
||||
DI::devLogger()->log($level, $message);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
|
||||
namespace Friendica\Core\Logger\Type\Monolog;
|
||||
|
||||
use Friendica\App\Request;
|
||||
use Monolog\Handler;
|
||||
use Monolog\Logger;
|
||||
|
||||
|
@ -38,15 +39,22 @@ class DevelopHandler extends Handler\AbstractHandler
|
|||
private $developerIp;
|
||||
|
||||
/**
|
||||
* @param string $developerIp The IP of the developer who wants to debug
|
||||
* @param int $level The minimum logging level at which this handler will be triggered
|
||||
* @param bool $bubble Whether the messages that are handled can bubble up the stack or not
|
||||
* @var string The IP of the current request
|
||||
*/
|
||||
public function __construct($developerIp, $level = Logger::DEBUG, bool $bubble = true)
|
||||
private $remoteAddress;
|
||||
|
||||
/**
|
||||
* @param Request $request The current http request
|
||||
* @param string $developerIp The IP of the developer who wants to debug
|
||||
* @param int $level The minimum logging level at which this handler will be triggered
|
||||
* @param bool $bubble Whether the messages that are handled can bubble up the stack or not
|
||||
*/
|
||||
public function __construct(Request $request, $developerIp, int $level = Logger::DEBUG, bool $bubble = true)
|
||||
{
|
||||
parent::__construct($level, $bubble);
|
||||
|
||||
$this->developerIp = $developerIp;
|
||||
$this->developerIp = $developerIp;
|
||||
$this->remoteAddress = $request->getRemoteAddress();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -59,7 +67,7 @@ class DevelopHandler extends Handler\AbstractHandler
|
|||
}
|
||||
|
||||
/// Just in case the remote IP is the same as the developer IP log the output
|
||||
if (!is_null($this->developerIp) && $_SERVER['REMOTE_ADDR'] != $this->developerIp) {
|
||||
if (!is_null($this->developerIp) && $this->remoteAddress != $this->developerIp) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -71,7 +71,7 @@ class Renderer
|
|||
* @return string
|
||||
* @throws ServiceUnavailableException
|
||||
*/
|
||||
public static function replaceMacros(string $template, array $vars = [])
|
||||
public static function replaceMacros(string $template, array $vars = []): string
|
||||
{
|
||||
DI::profiler()->startRecording('rendering');
|
||||
|
||||
|
|
|
@ -441,6 +441,12 @@ class System
|
|||
*
|
||||
* @param string $url The new Location to redirect
|
||||
* @param int $code The redirection code, which is used (Default is 302)
|
||||
*
|
||||
* @throws FoundException
|
||||
* @throws MovedPermanentlyException
|
||||
* @throws TemporaryRedirectException
|
||||
*
|
||||
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
|
||||
*/
|
||||
public static function externalRedirect($url, $code = 302)
|
||||
{
|
||||
|
|
|
@ -32,7 +32,7 @@ require_once 'boot.php';
|
|||
*/
|
||||
class Theme
|
||||
{
|
||||
public static function getAllowedList()
|
||||
public static function getAllowedList(): array
|
||||
{
|
||||
$allowed_themes_str = DI::config()->get('system', 'allowed_themes');
|
||||
$allowed_themes_raw = explode(',', str_replace(' ', '', $allowed_themes_str));
|
||||
|
@ -69,7 +69,7 @@ class Theme
|
|||
* @param string $theme the name of the theme
|
||||
* @return array
|
||||
*/
|
||||
public static function getInfo($theme)
|
||||
public static function getInfo(string $theme): array
|
||||
{
|
||||
$theme = Strings::sanitizeFilePathItem($theme);
|
||||
|
||||
|
@ -133,7 +133,7 @@ class Theme
|
|||
* @return string
|
||||
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
|
||||
*/
|
||||
public static function getScreenshot($theme)
|
||||
public static function getScreenshot(string $theme): string
|
||||
{
|
||||
$theme = Strings::sanitizeFilePathItem($theme);
|
||||
|
||||
|
@ -146,7 +146,13 @@ class Theme
|
|||
return DI::baseUrl() . '/images/blank.png';
|
||||
}
|
||||
|
||||
public static function uninstall($theme)
|
||||
/**
|
||||
* Uninstalls given theme name
|
||||
*
|
||||
* @param string $theme Name of theme
|
||||
* @return bool true on success
|
||||
*/
|
||||
public static function uninstall(string $theme)
|
||||
{
|
||||
$theme = Strings::sanitizeFilePathItem($theme);
|
||||
|
||||
|
@ -167,10 +173,18 @@ class Theme
|
|||
if ($key !== false) {
|
||||
unset($allowed_themes[$key]);
|
||||
Theme::setAllowedList($allowed_themes);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static function install($theme)
|
||||
/**
|
||||
* Installs given theme name
|
||||
*
|
||||
* @param string $theme Name of theme
|
||||
* @return bool true on success
|
||||
*/
|
||||
public static function install(string $theme): bool
|
||||
{
|
||||
$theme = Strings::sanitizeFilePathItem($theme);
|
||||
|
||||
|
@ -208,7 +222,7 @@ class Theme
|
|||
* @return string Path to the file or empty string if the file isn't found
|
||||
* @throws \Exception
|
||||
*/
|
||||
public static function getPathForFile($file)
|
||||
public static function getPathForFile(string $file): string
|
||||
{
|
||||
$a = DI::app();
|
||||
|
||||
|
@ -237,10 +251,9 @@ class Theme
|
|||
* Provide a sane default if nothing is chosen or the specified theme does not exist.
|
||||
*
|
||||
* @param string $theme Theme name
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function getStylesheetPath($theme)
|
||||
public static function getStylesheetPath(string $theme): string
|
||||
{
|
||||
$theme = Strings::sanitizeFilePathItem($theme);
|
||||
|
||||
|
@ -263,10 +276,10 @@ class Theme
|
|||
/**
|
||||
* Returns the path of the provided theme
|
||||
*
|
||||
* @param $theme
|
||||
* @param string $theme Theme name
|
||||
* @return string|null
|
||||
*/
|
||||
public static function getConfigFile($theme)
|
||||
public static function getConfigFile(string $theme)
|
||||
{
|
||||
$theme = Strings::sanitizeFilePathItem($theme);
|
||||
|
||||
|
@ -285,11 +298,11 @@ class Theme
|
|||
/**
|
||||
* Returns the background color of the provided theme if available.
|
||||
*
|
||||
* @param string $theme
|
||||
* @param string $theme Theme name
|
||||
* @param int|null $uid Current logged-in user id
|
||||
* @return string|null
|
||||
*/
|
||||
public static function getBackgroundColor(string $theme, $uid = null)
|
||||
public static function getBackgroundColor(string $theme, int $uid = null)
|
||||
{
|
||||
$theme = Strings::sanitizeFilePathItem($theme);
|
||||
|
||||
|
|
|
@ -41,7 +41,7 @@ class Update
|
|||
* @param string $basePath The base path of this application
|
||||
* @param boolean $via_worker Is the check run via the worker?
|
||||
* @param App\Mode $mode The current app mode
|
||||
*
|
||||
* @return void
|
||||
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
|
||||
*/
|
||||
public static function check(string $basePath, bool $via_worker, App\Mode $mode)
|
||||
|
@ -73,7 +73,7 @@ class Update
|
|||
}
|
||||
|
||||
// The postupdate has to completed version 1288 for the new post views to take over
|
||||
$postupdate = DI::config()->get("system", "post_update_version", NEW_TABLE_STRUCTURE_VERSION);
|
||||
$postupdate = DI::config()->get('system', 'post_update_version', NEW_TABLE_STRUCTURE_VERSION);
|
||||
if ($postupdate < NEW_TABLE_STRUCTURE_VERSION) {
|
||||
$error = DI::l10n()->t('Updates from postupdate version %s are not supported. Please update at least to version 2021.01 and wait until the postupdate finished version 1383.', $postupdate);
|
||||
if (DI::mode()->getExecutor() == Mode::INDEX) {
|
||||
|
@ -85,9 +85,11 @@ class Update
|
|||
|
||||
if ($build < DB_UPDATE_VERSION) {
|
||||
if ($via_worker) {
|
||||
// Calling the database update directly via the worker enables us to perform database changes to the workerqueue table itself.
|
||||
// This is a fallback, since normally the database update will be performed by a worker job.
|
||||
// This worker job doesn't work for changes to the "workerqueue" table itself.
|
||||
/*
|
||||
* Calling the database update directly via the worker enables us to perform database changes to the workerqueue table itself.
|
||||
* This is a fallback, since normally the database update will be performed by a worker job.
|
||||
* This worker job doesn't work for changes to the "workerqueue" table itself.
|
||||
*/
|
||||
self::run($basePath);
|
||||
} else {
|
||||
Worker::add(PRIORITY_CRITICAL, 'DBUpdate');
|
||||
|
@ -103,11 +105,10 @@ class Update
|
|||
* @param bool $override Overrides any running/stuck updates
|
||||
* @param bool $verbose Run the Update-Check verbose
|
||||
* @param bool $sendMail Sends a Mail to the administrator in case of success/failure
|
||||
*
|
||||
* @return string Empty string if the update is successful, error messages otherwise
|
||||
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
|
||||
*/
|
||||
public static function run(string $basePath, bool $force = false, bool $override = false, bool $verbose = false, bool $sendMail = true)
|
||||
public static function run(string $basePath, bool $force = false, bool $override = false, bool $verbose = false, bool $sendMail = true): string
|
||||
{
|
||||
// In force mode, we release the dbupdate lock first
|
||||
// Necessary in case of an stuck update
|
||||
|
@ -228,11 +229,10 @@ class Update
|
|||
* @param int $version the DB version number of the function
|
||||
* @param string $prefix the prefix of the function (update, pre_update)
|
||||
* @param bool $sendMail whether to send emails on success/failure
|
||||
|
||||
* @return bool true, if the update function worked
|
||||
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
|
||||
*/
|
||||
public static function runUpdateFunction(int $version, string $prefix, bool $sendMail = true)
|
||||
public static function runUpdateFunction(int $version, string $prefix, bool $sendMail = true): bool
|
||||
{
|
||||
$funcname = $prefix . '_' . $version;
|
||||
|
||||
|
@ -284,6 +284,7 @@ class Update
|
|||
*
|
||||
* @param int $update_id number of failed update
|
||||
* @param string $error_message error message
|
||||
* @return void
|
||||
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
|
||||
*/
|
||||
private static function updateFailed(int $update_id, string $error_message) {
|
||||
|
|
|
@ -86,7 +86,7 @@ class UserImport
|
|||
* @return array|bool
|
||||
* @throws \Exception
|
||||
*/
|
||||
private static function dbImportAssoc($table, $arr)
|
||||
private static function dbImportAssoc(string $table, array $arr)
|
||||
{
|
||||
if (isset($arr['id'])) {
|
||||
unset($arr['id']);
|
||||
|
@ -105,10 +105,11 @@ class UserImport
|
|||
* Import account file exported from mod/uexport
|
||||
*
|
||||
* @param array $file array from $_FILES
|
||||
* @return void
|
||||
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
|
||||
* @throws \ImagickException
|
||||
*/
|
||||
public static function importAccount($file)
|
||||
public static function importAccount(array $file)
|
||||
{
|
||||
Logger::notice("Start user import from " . $file['tmp_name']);
|
||||
/*
|
||||
|
|
|
@ -60,7 +60,7 @@ class Worker
|
|||
* @return void
|
||||
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
|
||||
*/
|
||||
public static function processQueue($run_cron, Process $process)
|
||||
public static function processQueue(bool $run_cron, Process $process)
|
||||
{
|
||||
self::$up_start = microtime(true);
|
||||
|
||||
|
@ -169,7 +169,7 @@ class Worker
|
|||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public static function isReady()
|
||||
public static function isReady(): bool
|
||||
{
|
||||
// Count active workers and compare them with a maximum value that depends on the load
|
||||
if (self::tooMuchWorkers()) {
|
||||
|
@ -204,7 +204,7 @@ class Worker
|
|||
* @return boolean Returns "true" if tasks are existing
|
||||
* @throws \Exception
|
||||
*/
|
||||
public static function entriesExists()
|
||||
public static function entriesExists(): bool
|
||||
{
|
||||
$stamp = (float)microtime(true);
|
||||
$exists = DBA::exists('workerqueue', ["NOT `done` AND `pid` = 0 AND `next_try` < ?", DateTimeFormat::utcNow()]);
|
||||
|
@ -218,7 +218,7 @@ class Worker
|
|||
* @return integer Number of deferred entries in the worker queue
|
||||
* @throws \Exception
|
||||
*/
|
||||
private static function deferredEntries()
|
||||
private static function deferredEntries(): int
|
||||
{
|
||||
$stamp = (float)microtime(true);
|
||||
$count = DBA::count('workerqueue', ["NOT `done` AND `pid` = 0 AND `retrial` > ?", 0]);
|
||||
|
@ -233,7 +233,7 @@ class Worker
|
|||
* @return integer Number of non executed entries in the worker queue
|
||||
* @throws \Exception
|
||||
*/
|
||||
private static function totalEntries()
|
||||
private static function totalEntries(): int
|
||||
{
|
||||
$stamp = (float)microtime(true);
|
||||
$count = DBA::count('workerqueue', ['done' => false, 'pid' => 0]);
|
||||
|
@ -248,7 +248,7 @@ class Worker
|
|||
* @return integer Number of active worker processes
|
||||
* @throws \Exception
|
||||
*/
|
||||
private static function highestPriority()
|
||||
private static function highestPriority(): int
|
||||
{
|
||||
$stamp = (float)microtime(true);
|
||||
$condition = ["`pid` = 0 AND NOT `done` AND `next_try` < ?", DateTimeFormat::utcNow()];
|
||||
|
@ -269,7 +269,7 @@ class Worker
|
|||
* @return integer Is there a process running with that priority?
|
||||
* @throws \Exception
|
||||
*/
|
||||
private static function processWithPriorityActive($priority)
|
||||
private static function processWithPriorityActive(int $priority): int
|
||||
{
|
||||
$condition = ["`priority` <= ? AND `pid` != 0 AND NOT `done`", $priority];
|
||||
return DBA::exists('workerqueue', $condition);
|
||||
|
@ -281,7 +281,7 @@ class Worker
|
|||
* @param mixed $file
|
||||
* @return bool
|
||||
*/
|
||||
private static function validateInclude(&$file)
|
||||
private static function validateInclude(&$file): bool
|
||||
{
|
||||
$orig_file = $file;
|
||||
|
||||
|
@ -321,7 +321,7 @@ class Worker
|
|||
* @return boolean "true" if further processing should be stopped
|
||||
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
|
||||
*/
|
||||
public static function execute($queue)
|
||||
public static function execute(array $queue): bool
|
||||
{
|
||||
$mypid = getmypid();
|
||||
|
||||
|
@ -454,7 +454,7 @@ class Worker
|
|||
* @return void
|
||||
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
|
||||
*/
|
||||
private static function execFunction($queue, $funcname, $argv, $method_call)
|
||||
private static function execFunction(array $queue, string $funcname, array $argv, bool $method_call)
|
||||
{
|
||||
$a = DI::app();
|
||||
|
||||
|
@ -543,7 +543,7 @@ class Worker
|
|||
* @return bool Are more than 3/4 of the maximum connections used?
|
||||
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
|
||||
*/
|
||||
private static function maxConnectionsReached()
|
||||
private static function maxConnectionsReached(): bool
|
||||
{
|
||||
// Fetch the max value from the config. This is needed when the system cannot detect the correct value by itself.
|
||||
$max = DI::config()->get("system", "max_connections");
|
||||
|
@ -627,7 +627,7 @@ class Worker
|
|||
* @return bool Are there too much workers running?
|
||||
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
|
||||
*/
|
||||
private static function tooMuchWorkers()
|
||||
private static function tooMuchWorkers(): bool
|
||||
{
|
||||
$queues = DI::config()->get("system", "worker_queues", 10);
|
||||
|
||||
|
@ -751,7 +751,7 @@ class Worker
|
|||
* @return integer Number of active worker processes
|
||||
* @throws \Exception
|
||||
*/
|
||||
private static function activeWorkers()
|
||||
private static function activeWorkers(): int
|
||||
{
|
||||
$stamp = (float)microtime(true);
|
||||
$count = DI::process()->countCommand('Worker.php');
|
||||
|
@ -766,7 +766,7 @@ class Worker
|
|||
* @return array List of worker process ids
|
||||
* @throws \Exception
|
||||
*/
|
||||
private static function getWorkerPIDList()
|
||||
private static function getWorkerPIDList(): array
|
||||
{
|
||||
$ids = [];
|
||||
$stamp = (float)microtime(true);
|
||||
|
@ -787,7 +787,7 @@ class Worker
|
|||
/**
|
||||
* Returns waiting jobs for the current process id
|
||||
*
|
||||
* @return array waiting workerqueue jobs
|
||||
* @return array|bool waiting workerqueue jobs or FALSE on failture
|
||||
* @throws \Exception
|
||||
*/
|
||||
private static function getWaitingJobForPID()
|
||||
|
@ -809,7 +809,7 @@ class Worker
|
|||
* @return array array with next jobs
|
||||
* @throws \Exception
|
||||
*/
|
||||
private static function nextProcess(int $limit)
|
||||
private static function nextProcess(int $limit): array
|
||||
{
|
||||
$priority = self::nextPriority();
|
||||
if (empty($priority)) {
|
||||
|
@ -844,7 +844,7 @@ class Worker
|
|||
/**
|
||||
* Returns the priority of the next workerqueue job
|
||||
*
|
||||
* @return string priority
|
||||
* @return string|bool priority or FALSE on failure
|
||||
* @throws \Exception
|
||||
*/
|
||||
private static function nextPriority()
|
||||
|
@ -915,7 +915,7 @@ class Worker
|
|||
/**
|
||||
* Find and claim the next worker process for us
|
||||
*
|
||||
* @return boolean Have we found something?
|
||||
* @return void
|
||||
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
|
||||
*/
|
||||
private static function findWorkerProcesses()
|
||||
|
@ -993,7 +993,7 @@ class Worker
|
|||
* @return array worker processes
|
||||
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
|
||||
*/
|
||||
public static function workerProcess()
|
||||
public static function workerProcess(): array
|
||||
{
|
||||
// There can already be jobs for us in the queue.
|
||||
$waiting = self::getWaitingJobForPID();
|
||||
|
@ -1003,7 +1003,7 @@ class Worker
|
|||
|
||||
$stamp = (float)microtime(true);
|
||||
if (!DI::lock()->acquire(self::LOCK_PROCESS)) {
|
||||
return false;
|
||||
return [];
|
||||
}
|
||||
self::$lock_duration += (microtime(true) - $stamp);
|
||||
|
||||
|
@ -1011,7 +1011,9 @@ class Worker
|
|||
|
||||
DI::lock()->release(self::LOCK_PROCESS);
|
||||
|
||||
return self::getWaitingJobForPID();
|
||||
// Prevents "Return value of Friendica\Core\Worker::workerProcess() must be of the type array, bool returned"
|
||||
$process = self::getWaitingJobForPID();
|
||||
return (is_array($process) ? $process : []);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1097,7 +1099,7 @@ class Worker
|
|||
* @return void
|
||||
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
|
||||
*/
|
||||
public static function spawnWorker($do_cron = false)
|
||||
public static function spawnWorker(bool $do_cron = false)
|
||||
{
|
||||
if (Worker\Daemon::isMode() && DI::config()->get('system', 'worker_fork')) {
|
||||
self::forkProcess($do_cron);
|
||||
|
@ -1231,7 +1233,7 @@ class Worker
|
|||
return $added;
|
||||
}
|
||||
|
||||
public static function countWorkersByCommand(string $command)
|
||||
public static function countWorkersByCommand(string $command): int
|
||||
{
|
||||
return DBA::count('workerqueue', ['done' => false, 'pid' => 0, 'command' => $command]);
|
||||
}
|
||||
|
@ -1244,7 +1246,7 @@ class Worker
|
|||
* @param integer $max_level maximum retrial level
|
||||
* @return integer the next retrial level value
|
||||
*/
|
||||
private static function getNextRetrial($queue, $max_level)
|
||||
private static function getNextRetrial(array $queue, int $max_level): int
|
||||
{
|
||||
$created = strtotime($queue['created']);
|
||||
$retrial_time = time() - $created;
|
||||
|
@ -1314,9 +1316,10 @@ class Worker
|
|||
/**
|
||||
* Check if the system is inside the defined maintenance window
|
||||
*
|
||||
* @param bool $check_last_execution Whether check last execution
|
||||
* @return boolean
|
||||
*/
|
||||
public static function isInMaintenanceWindow(bool $check_last_execution = false)
|
||||
public static function isInMaintenanceWindow(bool $check_last_execution = false): bool
|
||||
{
|
||||
// Calculate the seconds of the start end end of the maintenance window
|
||||
$start = strtotime(DI::config()->get('system', 'maintenance_start')) % 86400;
|
||||
|
|
18
src/DI.php
18
src/DI.php
|
@ -65,11 +65,27 @@ abstract class DI
|
|||
/**
|
||||
* @return Database\Database
|
||||
*/
|
||||
public static function dba()
|
||||
public static function dba(): Database\Database
|
||||
{
|
||||
return self::$dice->create(Database\Database::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Friendica\Database\Definition\DbaDefinition
|
||||
*/
|
||||
public static function dbaDefinition(): Database\Definition\DbaDefinition
|
||||
{
|
||||
return self::$dice->create(Database\Definition\DbaDefinition::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Friendica\Database\Definition\ViewDefinition
|
||||
*/
|
||||
public static function viewDefinition(): Database\Definition\ViewDefinition
|
||||
{
|
||||
return self::$dice->create(Database\Definition\ViewDefinition::class);
|
||||
}
|
||||
|
||||
//
|
||||
// "App" namespace instances
|
||||
//
|
||||
|
|
|
@ -42,7 +42,7 @@ class DBA
|
|||
*/
|
||||
const NULL_DATETIME = '0001-01-01 00:00:00';
|
||||
|
||||
public static function connect()
|
||||
public static function connect(): bool
|
||||
{
|
||||
return DI::dba()->connect();
|
||||
}
|
||||
|
@ -58,7 +58,7 @@ class DBA
|
|||
/**
|
||||
* Perform a reconnect of an existing database connection
|
||||
*/
|
||||
public static function reconnect()
|
||||
public static function reconnect(): bool
|
||||
{
|
||||
return DI::dba()->reconnect();
|
||||
}
|
||||
|
@ -77,7 +77,7 @@ class DBA
|
|||
*
|
||||
* @return string with either "pdo" or "mysqli"
|
||||
*/
|
||||
public static function getDriver()
|
||||
public static function getDriver(): string
|
||||
{
|
||||
return DI::dba()->getDriver();
|
||||
}
|
||||
|
@ -90,7 +90,7 @@ class DBA
|
|||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function serverInfo()
|
||||
public static function serverInfo(): string
|
||||
{
|
||||
return DI::dba()->serverInfo();
|
||||
}
|
||||
|
@ -101,7 +101,7 @@ class DBA
|
|||
* @return string
|
||||
* @throws \Exception
|
||||
*/
|
||||
public static function databaseName()
|
||||
public static function databaseName(): string
|
||||
{
|
||||
return DI::dba()->databaseName();
|
||||
}
|
||||
|
@ -112,7 +112,7 @@ class DBA
|
|||
* @param string $str
|
||||
* @return string escaped string
|
||||
*/
|
||||
public static function escape($str)
|
||||
public static function escape(string $str): string
|
||||
{
|
||||
return DI::dba()->escape($str);
|
||||
}
|
||||
|
@ -122,7 +122,7 @@ class DBA
|
|||
*
|
||||
* @return boolean is the database connected?
|
||||
*/
|
||||
public static function connected()
|
||||
public static function connected(): bool
|
||||
{
|
||||
return DI::dba()->connected();
|
||||
}
|
||||
|
@ -138,7 +138,7 @@ class DBA
|
|||
* @param string $sql An SQL string without the values
|
||||
* @return string The input SQL string modified if necessary.
|
||||
*/
|
||||
public static function anyValueFallback($sql)
|
||||
public static function anyValueFallback(string $sql): string
|
||||
{
|
||||
return DI::dba()->anyValueFallback($sql);
|
||||
}
|
||||
|
@ -152,7 +152,7 @@ class DBA
|
|||
* @param string $sql An SQL string without the values
|
||||
* @return string The input SQL string modified if necessary.
|
||||
*/
|
||||
public static function cleanQuery($sql)
|
||||
public static function cleanQuery(string $sql): string
|
||||
{
|
||||
$search = ["\t", "\n", "\r", " "];
|
||||
$replace = [' ', ' ', ' ', ' '];
|
||||
|
@ -169,7 +169,7 @@ class DBA
|
|||
* @param array $args Parameter array
|
||||
* @return array universalized parameter array
|
||||
*/
|
||||
public static function getParam($args)
|
||||
public static function getParam(array $args): array
|
||||
{
|
||||
unset($args[0]);
|
||||
|
||||
|
@ -192,7 +192,7 @@ class DBA
|
|||
* @return bool|object statement object or result object
|
||||
* @throws \Exception
|
||||
*/
|
||||
public static function p($sql)
|
||||
public static function p(string $sql)
|
||||
{
|
||||
$params = self::getParam(func_get_args());
|
||||
|
||||
|
@ -208,8 +208,8 @@ class DBA
|
|||
* @return boolean Was the query successfull? False is returned only if an error occurred
|
||||
* @throws \Exception
|
||||
*/
|
||||
public static function e($sql) {
|
||||
|
||||
public static function e(string $sql): bool
|
||||
{
|
||||
$params = self::getParam(func_get_args());
|
||||
|
||||
return DI::dba()->e($sql, $params);
|
||||
|
@ -218,13 +218,12 @@ class DBA
|
|||
/**
|
||||
* Check if data exists
|
||||
*
|
||||
* @param string|array $table Table name or array [schema => table]
|
||||
* @param array $condition array of fields for condition
|
||||
*
|
||||
* @param string $table Table name in format schema.table (while scheme is optiona)
|
||||
* @param array $condition Array of fields for condition
|
||||
* @return boolean Are there rows for that condition?
|
||||
* @throws \Exception
|
||||
*/
|
||||
public static function exists($table, $condition)
|
||||
public static function exists(string $table, array $condition): bool
|
||||
{
|
||||
return DI::dba()->exists($table, $condition);
|
||||
}
|
||||
|
@ -238,7 +237,7 @@ class DBA
|
|||
* @return array first row of query
|
||||
* @throws \Exception
|
||||
*/
|
||||
public static function fetchFirst($sql)
|
||||
public static function fetchFirst(string $sql)
|
||||
{
|
||||
$params = self::getParam(func_get_args());
|
||||
|
||||
|
@ -250,7 +249,7 @@ class DBA
|
|||
*
|
||||
* @return int Number of rows
|
||||
*/
|
||||
public static function affectedRows()
|
||||
public static function affectedRows(): int
|
||||
{
|
||||
return DI::dba()->affectedRows();
|
||||
}
|
||||
|
@ -261,7 +260,7 @@ class DBA
|
|||
* @param object Statement object
|
||||
* @return int Number of columns
|
||||
*/
|
||||
public static function columnCount($stmt)
|
||||
public static function columnCount($stmt): int
|
||||
{
|
||||
return DI::dba()->columnCount($stmt);
|
||||
}
|
||||
|
@ -271,7 +270,7 @@ class DBA
|
|||
* @param PDOStatement|mysqli_result|mysqli_stmt Statement object
|
||||
* @return int Number of rows
|
||||
*/
|
||||
public static function numRows($stmt)
|
||||
public static function numRows($stmt): int
|
||||
{
|
||||
return DI::dba()->numRows($stmt);
|
||||
}
|
||||
|
@ -290,14 +289,13 @@ class DBA
|
|||
/**
|
||||
* Insert a row into a table
|
||||
*
|
||||
* @param string|array $table Table name or array [schema => table]
|
||||
* @param array $param parameter array
|
||||
* @param int $duplicate_mode What to do on a duplicated entry
|
||||
*
|
||||
* @param string $table Table name in format schema.table (while scheme is optiona)
|
||||
* @param array $param parameter array
|
||||
* @param int $duplicate_mode What to do on a duplicated entry
|
||||
* @return boolean was the insert successful?
|
||||
* @throws \Exception
|
||||
*/
|
||||
public static function insert($table, array $param, int $duplicate_mode = Database::INSERT_DEFAULT)
|
||||
public static function insert(string $table, array $param, int $duplicate_mode = Database::INSERT_DEFAULT): bool
|
||||
{
|
||||
return DI::dba()->insert($table, $param, $duplicate_mode);
|
||||
}
|
||||
|
@ -306,13 +304,12 @@ class DBA
|
|||
* Inserts a row with the provided data in the provided table.
|
||||
* If the data corresponds to an existing row through a UNIQUE or PRIMARY index constraints, it updates the row instead.
|
||||
*
|
||||
* @param string|array $table Table name or array [schema => table]
|
||||
* @param array $param parameter array
|
||||
*
|
||||
* @param string $table Table name in format schema.table (while scheme is optiona)
|
||||
* @param array $param parameter array
|
||||
* @return boolean was the insert successful?
|
||||
* @throws \Exception
|
||||
*/
|
||||
public static function replace($table, $param)
|
||||
public static function replace(string $table, array $param): bool
|
||||
{
|
||||
return DI::dba()->replace($table, $param);
|
||||
}
|
||||
|
@ -322,7 +319,7 @@ class DBA
|
|||
*
|
||||
* @return integer Last inserted id
|
||||
*/
|
||||
public static function lastInsertId()
|
||||
public static function lastInsertId(): int
|
||||
{
|
||||
return DI::dba()->lastInsertId();
|
||||
}
|
||||
|
@ -332,12 +329,11 @@ class DBA
|
|||
*
|
||||
* This function can be extended in the future to accept a table array as well.
|
||||
*
|
||||
* @param string|array $table Table name or array [schema => table]
|
||||
*
|
||||
* @param string $table Table name in format schema.table (while scheme is optiona)
|
||||
* @return boolean was the lock successful?
|
||||
* @throws \Exception
|
||||
*/
|
||||
public static function lock($table)
|
||||
public static function lock(string $table): bool
|
||||
{
|
||||
return DI::dba()->lock($table);
|
||||
}
|
||||
|
@ -348,7 +344,7 @@ class DBA
|
|||
* @return boolean was the unlock successful?
|
||||
* @throws \Exception
|
||||
*/
|
||||
public static function unlock()
|
||||
public static function unlock(): bool
|
||||
{
|
||||
return DI::dba()->unlock();
|
||||
}
|
||||
|
@ -358,7 +354,7 @@ class DBA
|
|||
*
|
||||
* @return boolean Was the command executed successfully?
|
||||
*/
|
||||
public static function transaction()
|
||||
public static function transaction(): bool
|
||||
{
|
||||
return DI::dba()->transaction();
|
||||
}
|
||||
|
@ -368,7 +364,7 @@ class DBA
|
|||
*
|
||||
* @return boolean Was the command executed successfully?
|
||||
*/
|
||||
public static function commit()
|
||||
public static function commit(): bool
|
||||
{
|
||||
return DI::dba()->commit();
|
||||
}
|
||||
|
@ -378,7 +374,7 @@ class DBA
|
|||
*
|
||||
* @return boolean Was the command executed successfully?
|
||||
*/
|
||||
public static function rollback()
|
||||
public static function rollback(): bool
|
||||
{
|
||||
return DI::dba()->rollback();
|
||||
}
|
||||
|
@ -386,13 +382,13 @@ class DBA
|
|||
/**
|
||||
* Delete a row from a table
|
||||
*
|
||||
* @param string|array $table Table name
|
||||
* @param array $conditions Field condition(s)
|
||||
* @param string $table Table name
|
||||
* @param array $conditions Field condition(s)
|
||||
*
|
||||
* @return boolean was the delete successful?
|
||||
* @throws \Exception
|
||||
*/
|
||||
public static function delete($table, array $conditions, array $options = [])
|
||||
public static function delete(string $table, array $conditions, array $options = []): bool
|
||||
{
|
||||
return DI::dba()->delete($table, $conditions, $options);
|
||||
}
|
||||
|
@ -418,7 +414,7 @@ class DBA
|
|||
* Only set $old_fields to a boolean value when you are sure that you will update a single row.
|
||||
* When you set $old_fields to "true" then $fields must contain all relevant fields!
|
||||
*
|
||||
* @param string|array $table Table name or array [schema => table]
|
||||
* @param string $table Table name in format schema.table (while scheme is optiona)
|
||||
* @param array $fields contains the fields that are updated
|
||||
* @param array $condition condition array with the key values
|
||||
* @param array|boolean $old_fields array with the old field values that are about to be replaced (true = update on duplicate, false = don't update identical fields)
|
||||
|
@ -427,7 +423,7 @@ class DBA
|
|||
* @return boolean was the update successfull?
|
||||
* @throws \Exception
|
||||
*/
|
||||
public static function update($table, $fields, $condition, $old_fields = [], $params = [])
|
||||
public static function update(string $table, array $fields, array $condition, $old_fields = [], array $params = []): bool
|
||||
{
|
||||
return DI::dba()->update($table, $fields, $condition, $old_fields, $params);
|
||||
}
|
||||
|
@ -435,7 +431,7 @@ class DBA
|
|||
/**
|
||||
* Retrieve a single record from a table and returns it in an associative array
|
||||
*
|
||||
* @param string|array $table Table name or array [schema => table]
|
||||
* @param string|array $table Table name in format schema.table (while scheme is optiona)
|
||||
* @param array $fields
|
||||
* @param array $condition
|
||||
* @param array $params
|
||||
|
@ -443,7 +439,7 @@ class DBA
|
|||
* @throws \Exception
|
||||
* @see self::select
|
||||
*/
|
||||
public static function selectFirst($table, array $fields = [], array $condition = [], $params = [])
|
||||
public static function selectFirst($table, array $fields = [], array $condition = [], array $params = [])
|
||||
{
|
||||
return DI::dba()->selectFirst($table, $fields, $condition, $params);
|
||||
}
|
||||
|
@ -451,16 +447,16 @@ class DBA
|
|||
/**
|
||||
* Select rows from a table and fills an array with the data
|
||||
*
|
||||
* @param string|array $table Table name or array [schema => table]
|
||||
* @param array $fields Array of selected fields, empty for all
|
||||
* @param array $condition Array of fields for condition
|
||||
* @param array $params Array of several parameters
|
||||
* @param string $table Table name in format schema.table (while scheme is optiona)
|
||||
* @param array $fields Array of selected fields, empty for all
|
||||
* @param array $condition Array of fields for condition
|
||||
* @param array $params Array of several parameters
|
||||
*
|
||||
* @return array Data array
|
||||
* @throws \Exception
|
||||
* @see self::select
|
||||
*/
|
||||
public static function selectToArray($table, array $fields = [], array $condition = [], array $params = [])
|
||||
public static function selectToArray(string $table, array $fields = [], array $condition = [], array $params = [])
|
||||
{
|
||||
return DI::dba()->selectToArray($table, $fields, $condition, $params);
|
||||
}
|
||||
|
@ -468,10 +464,10 @@ class DBA
|
|||
/**
|
||||
* Select rows from a table
|
||||
*
|
||||
* @param string|array $table Table name or array [schema => table]
|
||||
* @param array $fields Array of selected fields, empty for all
|
||||
* @param array $condition Array of fields for condition
|
||||
* @param array $params Array of several parameters
|
||||
* @param string $table Table name in format schema.table (while scheme is optiona)
|
||||
* @param array $fields Array of selected fields, empty for all
|
||||
* @param array $condition Array of fields for condition
|
||||
* @param array $params Array of several parameters
|
||||
*
|
||||
* @return boolean|object
|
||||
*
|
||||
|
@ -488,7 +484,7 @@ class DBA
|
|||
* $data = DBA::select($table, $fields, $condition, $params);
|
||||
* @throws \Exception
|
||||
*/
|
||||
public static function select($table, array $fields = [], array $condition = [], array $params = [])
|
||||
public static function select(string $table, array $fields = [], array $condition = [], array $params = [])
|
||||
{
|
||||
return DI::dba()->select($table, $fields, $condition, $params);
|
||||
}
|
||||
|
@ -496,9 +492,9 @@ class DBA
|
|||
/**
|
||||
* Counts the rows from a table satisfying the provided condition
|
||||
*
|
||||
* @param string|array $table Table name or array [schema => table]
|
||||
* @param array $condition array of fields for condition
|
||||
* @param array $params Array of several parameters
|
||||
* @param string $table Table name in format schema.table (while scheme is optiona)
|
||||
* @param array $condition array of fields for condition
|
||||
* @param array $params Array of several parameters
|
||||
*
|
||||
* @return int
|
||||
*
|
||||
|
@ -512,7 +508,7 @@ class DBA
|
|||
* $count = DBA::count($table, $condition);
|
||||
* @throws \Exception
|
||||
*/
|
||||
public static function count($table, array $condition = [], array $params = [])
|
||||
public static function count(string $table, array $condition = [], array $params = []): int
|
||||
{
|
||||
return DI::dba()->count($table, $condition, $params);
|
||||
}
|
||||
|
@ -525,37 +521,30 @@ class DBA
|
|||
* - [table1, table2, ...]
|
||||
* - [schema1 => table1, schema2 => table2, table3, ...]
|
||||
*
|
||||
* @param string|array $tables
|
||||
* @param array $tables Table names
|
||||
* @return string
|
||||
*/
|
||||
public static function buildTableString($tables)
|
||||
public static function buildTableString(array $tables): string
|
||||
{
|
||||
if (is_string($tables)) {
|
||||
$tables = [$tables];
|
||||
}
|
||||
|
||||
$quotedTables = [];
|
||||
|
||||
foreach ($tables as $schema => $table) {
|
||||
if (is_numeric($schema)) {
|
||||
$quotedTables[] = self::quoteIdentifier($table);
|
||||
} else {
|
||||
$quotedTables[] = self::quoteIdentifier($schema) . '.' . self::quoteIdentifier($table);
|
||||
}
|
||||
}
|
||||
|
||||
return implode(', ', $quotedTables);
|
||||
// Quote each entry
|
||||
return implode(',', array_map(['self', 'quoteIdentifier'], $tables));
|
||||
}
|
||||
|
||||
/**
|
||||
* Escape an identifier (table or field name)
|
||||
* Escape an identifier (table or field name) optional with a schema like (schema.)table
|
||||
*
|
||||
* @param $identifier
|
||||
* @return string
|
||||
* @param $identifier Table, field name
|
||||
* @return string Quotes table or field name
|
||||
*/
|
||||
public static function quoteIdentifier($identifier)
|
||||
public static function quoteIdentifier(string $identifier): string
|
||||
{
|
||||
return '`' . str_replace('`', '``', $identifier) . '`';
|
||||
return implode(
|
||||
'.',
|
||||
array_map(
|
||||
function (string $identifier) { return '`' . str_replace('`', '``', $identifier) . '`'; },
|
||||
explode('.', $identifier)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -576,7 +565,7 @@ class DBA
|
|||
* @param array $condition
|
||||
* @return string
|
||||
*/
|
||||
public static function buildCondition(array &$condition = [])
|
||||
public static function buildCondition(array &$condition = []): string
|
||||
{
|
||||
$condition = self::collapseCondition($condition);
|
||||
|
||||
|
@ -600,7 +589,7 @@ class DBA
|
|||
* @param array $condition
|
||||
* @return array
|
||||
*/
|
||||
public static function collapseCondition(array $condition)
|
||||
public static function collapseCondition(array $condition): array
|
||||
{
|
||||
// Ensures an always true condition is returned
|
||||
if (count($condition) < 1) {
|
||||
|
@ -675,7 +664,7 @@ class DBA
|
|||
* @return array A collapsed condition
|
||||
* @see DBA::collapseCondition() for the condition array formats
|
||||
*/
|
||||
public static function mergeConditions(array ...$conditions)
|
||||
public static function mergeConditions(array ...$conditions): array
|
||||
{
|
||||
if (count($conditions) == 1) {
|
||||
return current($conditions);
|
||||
|
@ -724,7 +713,7 @@ class DBA
|
|||
* @param array $params
|
||||
* @return string
|
||||
*/
|
||||
public static function buildParameter(array $params = [])
|
||||
public static function buildParameter(array $params = []): string
|
||||
{
|
||||
$groupby_string = '';
|
||||
if (!empty($params['group_by'])) {
|
||||
|
@ -771,7 +760,7 @@ class DBA
|
|||
*
|
||||
* @return array Data array
|
||||
*/
|
||||
public static function toArray($stmt, $do_close = true, int $count = 0)
|
||||
public static function toArray($stmt, bool $do_close = true, int $count = 0): array
|
||||
{
|
||||
return DI::dba()->toArray($stmt, $do_close, $count);
|
||||
}
|
||||
|
@ -783,7 +772,7 @@ class DBA
|
|||
* @param array $fields
|
||||
* @return array casted fields
|
||||
*/
|
||||
public static function castFields(string $table, array $fields)
|
||||
public static function castFields(string $table, array $fields): array
|
||||
{
|
||||
return DI::dba()->castFields($table, $fields);
|
||||
}
|
||||
|
@ -793,7 +782,7 @@ class DBA
|
|||
*
|
||||
* @return string Error number (0 if no error)
|
||||
*/
|
||||
public static function errorNo()
|
||||
public static function errorNo(): int
|
||||
{
|
||||
return DI::dba()->errorNo();
|
||||
}
|
||||
|
@ -803,7 +792,7 @@ class DBA
|
|||
*
|
||||
* @return string Error message ('' if no error)
|
||||
*/
|
||||
public static function errorMessage()
|
||||
public static function errorMessage(): string
|
||||
{
|
||||
return DI::dba()->errorMessage();
|
||||
}
|
||||
|
@ -814,7 +803,7 @@ class DBA
|
|||
* @param object $stmt statement object
|
||||
* @return boolean was the close successful?
|
||||
*/
|
||||
public static function close($stmt)
|
||||
public static function close($stmt): bool
|
||||
{
|
||||
return DI::dba()->close($stmt);
|
||||
}
|
||||
|
@ -827,7 +816,7 @@ class DBA
|
|||
* 'amount' => Number of concurrent database processes
|
||||
* @throws \Exception
|
||||
*/
|
||||
public static function processlist()
|
||||
public static function processlist(): array
|
||||
{
|
||||
return DI::dba()->processlist();
|
||||
}
|
||||
|
@ -847,10 +836,9 @@ class DBA
|
|||
* Checks if $array is a filled array with at least one entry.
|
||||
*
|
||||
* @param mixed $array A filled array with at least one entry
|
||||
*
|
||||
* @return boolean Whether $array is a filled array or an object with rows
|
||||
*/
|
||||
public static function isResult($array)
|
||||
public static function isResult($array): bool
|
||||
{
|
||||
return DI::dba()->isResult($array);
|
||||
}
|
||||
|
@ -862,7 +850,7 @@ class DBA
|
|||
* @param boolean $add_quotation add quotation marks for string values
|
||||
* @return void
|
||||
*/
|
||||
public static function escapeArray(&$arr, $add_quotation = false)
|
||||
public static function escapeArray(&$arr, bool $add_quotation = false)
|
||||
{
|
||||
DI::dba()->escapeArray($arr, $add_quotation);
|
||||
}
|
||||
|
|
|
@ -22,13 +22,12 @@
|
|||
namespace Friendica\Database;
|
||||
|
||||
use Exception;
|
||||
use Friendica\Core\Hook;
|
||||
use Friendica\Core\Logger;
|
||||
use Friendica\Core\Renderer;
|
||||
use Friendica\DI;
|
||||
use Friendica\Model\Item;
|
||||
use Friendica\Model\User;
|
||||
use Friendica\Util\DateTimeFormat;
|
||||
use Friendica\Util\Writer\DbaDefinitionSqlWriter;
|
||||
|
||||
/**
|
||||
* This class contains functions that doesn't need to know if pdo, mysqli or whatever is used.
|
||||
|
@ -42,13 +41,6 @@ class DBStructure
|
|||
const RENAME_COLUMN = 0;
|
||||
const RENAME_PRIMARY_KEY = 1;
|
||||
|
||||
/**
|
||||
* Database structure definition loaded from config/dbstructure.config.php
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private static $definition = [];
|
||||
|
||||
/**
|
||||
* Set a database version to trigger update functions
|
||||
*
|
||||
|
@ -73,7 +65,7 @@ class DBStructure
|
|||
*/
|
||||
public static function dropTables(bool $execute)
|
||||
{
|
||||
$postupdate = DI::config()->get("system", "post_update_version", PostUpdate::VERSION);
|
||||
$postupdate = DI::config()->get('system', 'post_update_version', PostUpdate::VERSION);
|
||||
if ($postupdate < PostUpdate::VERSION) {
|
||||
echo DI::l10n()->t('The post update is at version %d, it has to be at %d to safely drop the tables.', $postupdate, PostUpdate::VERSION);
|
||||
return;
|
||||
|
@ -84,7 +76,7 @@ class DBStructure
|
|||
'deliverq', 'dsprphotoq', 'ffinder', 'sign', 'spam', 'term', 'user-item', 'thread', 'item', 'challenge',
|
||||
'auth_codes', 'tokens', 'clients', 'profile_check', 'host'];
|
||||
|
||||
$tables = DBA::selectToArray(['INFORMATION_SCHEMA' => 'TABLES'], ['TABLE_NAME'],
|
||||
$tables = DBA::selectToArray('INFORMATION_SCHEMA.TABLES', ['TABLE_NAME'],
|
||||
['TABLE_SCHEMA' => DBA::databaseName(), 'TABLE_TYPE' => 'BASE TABLE']);
|
||||
|
||||
if (empty($tables)) {
|
||||
|
@ -119,13 +111,13 @@ class DBStructure
|
|||
public static function convertToInnoDB()
|
||||
{
|
||||
$tables = DBA::selectToArray(
|
||||
['information_schema' => 'tables'],
|
||||
'information_schema.tables',
|
||||
['table_name'],
|
||||
['engine' => 'MyISAM', 'table_schema' => DBA::databaseName()]
|
||||
);
|
||||
|
||||
$tables = array_merge($tables, DBA::selectToArray(
|
||||
['information_schema' => 'tables'],
|
||||
'information_schema.tables',
|
||||
['table_name'],
|
||||
['engine' => 'InnoDB', 'ROW_FORMAT' => ['COMPACT', 'REDUNDANT'], 'table_schema' => DBA::databaseName()]
|
||||
));
|
||||
|
@ -153,7 +145,7 @@ class DBStructure
|
|||
*
|
||||
* @return string Error message
|
||||
*/
|
||||
private static function printUpdateError($message)
|
||||
private static function printUpdateError(string $message): string
|
||||
{
|
||||
echo DI::l10n()->t("\nError %d occurred during database update:\n%s\n",
|
||||
DBA::errorNo(), DBA::errorMessage());
|
||||
|
@ -161,334 +153,15 @@ class DBStructure
|
|||
return DI::l10n()->t('Errors encountered performing database changes: ') . $message . EOL;
|
||||
}
|
||||
|
||||
public static function writeStructure()
|
||||
{
|
||||
$tables = [];
|
||||
foreach (self::definition(null) 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 = DI::basePath() . '/doc/database/db_' . $name . '.md';
|
||||
file_put_contents($filename, $content);
|
||||
}
|
||||
asort($tables);
|
||||
$content = Renderer::replaceMacros(Renderer::getMarkupTemplate('tables.tpl'), [
|
||||
'$tables' => $tables,
|
||||
]);
|
||||
$filename = DI::basePath() . '/doc/database.md';
|
||||
file_put_contents($filename, $content);
|
||||
}
|
||||
|
||||
public static function printStructure($basePath)
|
||||
{
|
||||
$database = self::definition($basePath, false);
|
||||
|
||||
echo "-- ------------------------------------------\n";
|
||||
echo "-- " . FRIENDICA_PLATFORM . " " . FRIENDICA_VERSION . " (" . FRIENDICA_CODENAME, ")\n";
|
||||
echo "-- DB_UPDATE_VERSION " . DB_UPDATE_VERSION . "\n";
|
||||
echo "-- ------------------------------------------\n\n\n";
|
||||
foreach ($database as $name => $structure) {
|
||||
echo "--\n";
|
||||
echo "-- TABLE $name\n";
|
||||
echo "--\n";
|
||||
self::createTable($name, $structure, true, false);
|
||||
|
||||
echo "\n";
|
||||
}
|
||||
|
||||
View::printStructure($basePath);
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads the database structure definition from the static/dbstructure.config.php file.
|
||||
* On first pass, defines DB_UPDATE_VERSION constant.
|
||||
*
|
||||
* @see static/dbstructure.config.php
|
||||
* @param boolean $with_addons_structure Whether to tack on addons additional tables
|
||||
* @param string $basePath The base path of this application
|
||||
* @return array
|
||||
* @throws Exception
|
||||
*/
|
||||
public static function definition($basePath, $with_addons_structure = true)
|
||||
{
|
||||
if (!self::$definition) {
|
||||
if (empty($basePath)) {
|
||||
$basePath = DI::app()->getBasePath();
|
||||
}
|
||||
|
||||
$filename = $basePath . '/static/dbstructure.config.php';
|
||||
|
||||
if (!is_readable($filename)) {
|
||||
throw new Exception('Missing database structure config file static/dbstructure.config.php');
|
||||
}
|
||||
|
||||
$definition = require $filename;
|
||||
|
||||
if (!$definition) {
|
||||
throw new Exception('Corrupted database structure config file static/dbstructure.config.php');
|
||||
}
|
||||
|
||||
self::$definition = $definition;
|
||||
} else {
|
||||
$definition = self::$definition;
|
||||
}
|
||||
|
||||
if ($with_addons_structure) {
|
||||
Hook::callAll('dbstructure_definition', $definition);
|
||||
}
|
||||
|
||||
return $definition;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get field data for the given table
|
||||
*
|
||||
* @param string $table
|
||||
* @param array $data data fields
|
||||
* @return array fields for the given
|
||||
*/
|
||||
public static function getFieldsForTable(string $table, array $data = [])
|
||||
{
|
||||
$definition = DBStructure::definition('', false);
|
||||
if (empty($definition[$table])) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$fieldnames = array_keys($definition[$table]['fields']);
|
||||
|
||||
$fields = [];
|
||||
|
||||
// Assign all field that are present in the table
|
||||
foreach ($fieldnames as $field) {
|
||||
if (isset($data[$field])) {
|
||||
// Limit the length of varchar, varbinary, char and binrary fields
|
||||
if (is_string($data[$field]) && preg_match("/char\((\d*)\)/", $definition[$table]['fields'][$field]['type'], $result)) {
|
||||
$data[$field] = mb_substr($data[$field], 0, $result[1]);
|
||||
} elseif (is_string($data[$field]) && preg_match("/binary\((\d*)\)/", $definition[$table]['fields'][$field]['type'], $result)) {
|
||||
$data[$field] = substr($data[$field], 0, $result[1]);
|
||||
}
|
||||
$fields[$field] = $data[$field];
|
||||
}
|
||||
}
|
||||
|
||||
return $fields;
|
||||
}
|
||||
|
||||
private static function createTable($name, $structure, $verbose, $action)
|
||||
{
|
||||
$r = true;
|
||||
|
||||
$engine = "";
|
||||
$comment = "";
|
||||
$sql_rows = [];
|
||||
$primary_keys = [];
|
||||
$foreign_keys = [];
|
||||
|
||||
foreach ($structure["fields"] as $fieldname => $field) {
|
||||
$sql_rows[] = "`" . DBA::escape($fieldname) . "` " . self::FieldCommand($field);
|
||||
if (!empty($field['primary'])) {
|
||||
$primary_keys[] = $fieldname;
|
||||
}
|
||||
if (!empty($field['foreign'])) {
|
||||
$foreign_keys[$fieldname] = $field;
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($structure["indexes"])) {
|
||||
foreach ($structure["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($name, $fieldname, $parameters);
|
||||
}
|
||||
|
||||
if (isset($structure["engine"])) {
|
||||
$engine = " ENGINE=" . $structure["engine"];
|
||||
}
|
||||
|
||||
if (isset($structure["comment"])) {
|
||||
$comment = " COMMENT='" . DBA::escape($structure["comment"]) . "'";
|
||||
}
|
||||
|
||||
$sql = implode(",\n\t", $sql_rows);
|
||||
|
||||
$sql = sprintf("CREATE TABLE IF NOT EXISTS `%s` (\n\t", DBA::escape($name)) . $sql .
|
||||
"\n)" . $engine . " DEFAULT COLLATE utf8mb4_general_ci" . $comment;
|
||||
if ($verbose) {
|
||||
echo $sql . ";\n";
|
||||
}
|
||||
|
||||
if ($action) {
|
||||
$r = DBA::e($sql);
|
||||
}
|
||||
|
||||
return $r;
|
||||
}
|
||||
|
||||
private static function FieldCommand($parameters, $create = true)
|
||||
{
|
||||
$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 '" . DBA::escape($parameters["comment"]) . "'";
|
||||
}
|
||||
|
||||
/*if (($parameters["primary"] != "") && $create)
|
||||
$fieldstruct .= " PRIMARY KEY";*/
|
||||
|
||||
return ($fieldstruct);
|
||||
}
|
||||
|
||||
private static function createIndex($indexname, $fieldnames, $method = "ADD")
|
||||
{
|
||||
$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 .= "`" . DBA::escape($matches[1]) . "`(" . intval($matches[2]) . ")";
|
||||
} else {
|
||||
$names .= "`" . DBA::escape($fieldname) . "`";
|
||||
}
|
||||
}
|
||||
|
||||
if ($indexname == "PRIMARY") {
|
||||
return sprintf("%s PRIMARY KEY(%s)", $method, $names);
|
||||
}
|
||||
|
||||
|
||||
$sql = sprintf("%s INDEX `%s` (%s)", $method, DBA::escape($indexname), $names);
|
||||
return ($sql);
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform a database structure dryrun (means: just simulating)
|
||||
*
|
||||
* @return string Empty string if the update is successful, error messages otherwise
|
||||
* @throws Exception
|
||||
*/
|
||||
public static function dryRun()
|
||||
public static function dryRun(): string
|
||||
{
|
||||
self::update(DI::app()->getBasePath(), true, false);
|
||||
return self::update(true, false);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -500,13 +173,13 @@ class DBStructure
|
|||
* @return string Empty string if the update is successful, error messages otherwise
|
||||
* @throws Exception
|
||||
*/
|
||||
public static function performUpdate(bool $enable_maintenance_mode = true, bool $verbose = false)
|
||||
public static function performUpdate(bool $enable_maintenance_mode = true, bool $verbose = false): string
|
||||
{
|
||||
if ($enable_maintenance_mode) {
|
||||
DI::config()->set('system', 'maintenance', 1);
|
||||
}
|
||||
|
||||
$status = self::update(DI::app()->getBasePath(), $verbose, true);
|
||||
$status = self::update($verbose, true);
|
||||
|
||||
if ($enable_maintenance_mode) {
|
||||
DI::config()->set('system', 'maintenance', 0);
|
||||
|
@ -519,20 +192,17 @@ class DBStructure
|
|||
/**
|
||||
* Updates DB structure from the installation and returns eventual errors messages
|
||||
*
|
||||
* @param string $basePath The base path of this application
|
||||
*
|
||||
* @return string Empty string if the update is successful, error messages otherwise
|
||||
* @throws Exception
|
||||
*/
|
||||
public static function install(string $basePath)
|
||||
public static function install(): string
|
||||
{
|
||||
return self::update($basePath, false, true, true);
|
||||
return self::update(false, true, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates DB structure and returns eventual errors messages
|
||||
*
|
||||
* @param string $basePath The base path of this application
|
||||
* @param bool $verbose
|
||||
* @param bool $action Whether to actually apply the update
|
||||
* @param bool $install Is this the initial update during the installation?
|
||||
|
@ -541,7 +211,7 @@ class DBStructure
|
|||
* @return string Empty string if the update is successful, error messages otherwise
|
||||
* @throws Exception
|
||||
*/
|
||||
private static function update($basePath, $verbose, $action, $install = false, array $tables = null, array $definition = null)
|
||||
private static function update(bool $verbose, bool $action, bool $install = false, array $tables = null, array $definition = null): string
|
||||
{
|
||||
$in_maintenance_mode = DI::config()->get('system', 'maintenance');
|
||||
|
||||
|
@ -579,7 +249,7 @@ class DBStructure
|
|||
|
||||
// Get the definition
|
||||
if (is_null($definition)) {
|
||||
$definition = self::definition($basePath);
|
||||
$definition = DI::dbaDefinition()->getAll();
|
||||
}
|
||||
|
||||
// MySQL >= 5.7.4 doesn't support the IGNORE keyword in ALTER TABLE statements
|
||||
|
@ -593,11 +263,17 @@ class DBStructure
|
|||
// Compare it
|
||||
foreach ($definition as $name => $structure) {
|
||||
$is_new_table = false;
|
||||
$sql3 = "";
|
||||
$sql3 = "";
|
||||
if (!isset($database[$name])) {
|
||||
$r = self::createTable($name, $structure, $verbose, $action);
|
||||
if (!DBA::isResult($r)) {
|
||||
$errors .= self::printUpdateError($name);
|
||||
$sql = DbaDefinitionSqlWriter::createTable($name, $structure, $verbose, $action);
|
||||
if ($verbose) {
|
||||
echo $sql;
|
||||
}
|
||||
if ($action) {
|
||||
$r = DBA::e($sql);
|
||||
if (!DBA::isResult($r)) {
|
||||
$errors .= self::printUpdateError($name);
|
||||
}
|
||||
}
|
||||
$is_new_table = true;
|
||||
} else {
|
||||
|
@ -606,15 +282,15 @@ class DBStructure
|
|||
* or the definition differ from current status
|
||||
* and index name doesn't start with "local_"
|
||||
*/
|
||||
foreach ($database[$name]["indexes"] as $indexname => $fieldnames) {
|
||||
$current_index_definition = implode(",", $fieldnames);
|
||||
if (isset($structure["indexes"][$indexname])) {
|
||||
$new_index_definition = implode(",", $structure["indexes"][$indexname]);
|
||||
foreach ($database[$name]["indexes"] as $indexName => $fieldNames) {
|
||||
$current_index_definition = implode(",", $fieldNames);
|
||||
if (isset($structure["indexes"][$indexName])) {
|
||||
$new_index_definition = implode(",", $structure["indexes"][$indexName]);
|
||||
} else {
|
||||
$new_index_definition = "__NOT_SET__";
|
||||
}
|
||||
if ($current_index_definition != $new_index_definition && substr($indexname, 0, 6) != 'local_') {
|
||||
$sql2 = self::dropIndex($indexname);
|
||||
if ($current_index_definition != $new_index_definition && substr($indexName, 0, 6) != 'local_') {
|
||||
$sql2 = DbaDefinitionSqlWriter::dropIndex($indexName);
|
||||
if ($sql3 == "") {
|
||||
$sql3 = "ALTER" . $ignore . " TABLE `" . $name . "` " . $sql2;
|
||||
} else {
|
||||
|
@ -623,9 +299,9 @@ class DBStructure
|
|||
}
|
||||
}
|
||||
// Compare the field structure field by field
|
||||
foreach ($structure["fields"] as $fieldname => $parameters) {
|
||||
if (!isset($database[$name]["fields"][$fieldname])) {
|
||||
$sql2 = self::addTableField($fieldname, $parameters);
|
||||
foreach ($structure["fields"] as $fieldName => $parameters) {
|
||||
if (!isset($database[$name]["fields"][$fieldName])) {
|
||||
$sql2 = DbaDefinitionSqlWriter::addTableField($fieldName, $parameters);
|
||||
if ($sql3 == "") {
|
||||
$sql3 = "ALTER" . $ignore . " TABLE `" . $name . "` " . $sql2;
|
||||
} else {
|
||||
|
@ -633,7 +309,7 @@ class DBStructure
|
|||
}
|
||||
} else {
|
||||
// Compare the field definition
|
||||
$field_definition = $database[$name]["fields"][$fieldname];
|
||||
$field_definition = $database[$name]["fields"][$fieldName];
|
||||
|
||||
// Remove the relation data that is used for the referential integrity
|
||||
unset($parameters['relation']);
|
||||
|
@ -651,9 +327,9 @@ class DBStructure
|
|||
}
|
||||
|
||||
$current_field_definition = DBA::cleanQuery(implode(",", $field_definition));
|
||||
$new_field_definition = DBA::cleanQuery(implode(",", $parameters));
|
||||
$new_field_definition = DBA::cleanQuery(implode(",", $parameters));
|
||||
if ($current_field_definition != $new_field_definition) {
|
||||
$sql2 = self::modifyTableField($fieldname, $parameters);
|
||||
$sql2 = DbaDefinitionSqlWriter::modifyTableField($fieldName, $parameters);
|
||||
if ($sql3 == "") {
|
||||
$sql3 = "ALTER" . $ignore . " TABLE `" . $name . "` " . $sql2;
|
||||
} else {
|
||||
|
@ -670,15 +346,15 @@ class DBStructure
|
|||
* Don't create keys if table is new
|
||||
*/
|
||||
if (!$is_new_table) {
|
||||
foreach ($structure["indexes"] as $indexname => $fieldnames) {
|
||||
if (isset($database[$name]["indexes"][$indexname])) {
|
||||
$current_index_definition = implode(",", $database[$name]["indexes"][$indexname]);
|
||||
foreach ($structure["indexes"] as $indexName => $fieldNames) {
|
||||
if (isset($database[$name]["indexes"][$indexName])) {
|
||||
$current_index_definition = implode(",", $database[$name]["indexes"][$indexName]);
|
||||
} else {
|
||||
$current_index_definition = "__NOT_SET__";
|
||||
}
|
||||
$new_index_definition = implode(",", $fieldnames);
|
||||
$new_index_definition = implode(",", $fieldNames);
|
||||
if ($current_index_definition != $new_index_definition) {
|
||||
$sql2 = self::createIndex($indexname, $fieldnames);
|
||||
$sql2 = DbaDefinitionSqlWriter::createIndex($indexName, $fieldNames);
|
||||
|
||||
if ($sql2 != "") {
|
||||
if ($sql3 == "") {
|
||||
|
@ -694,17 +370,17 @@ class DBStructure
|
|||
|
||||
// Foreign keys
|
||||
// Compare the field structure field by field
|
||||
foreach ($structure["fields"] as $fieldname => $parameters) {
|
||||
foreach ($structure["fields"] as $fieldName => $parameters) {
|
||||
if (empty($parameters['foreign'])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$constraint = self::getConstraintName($name, $fieldname, $parameters);
|
||||
$constraint = self::getConstraintName($name, $fieldName, $parameters);
|
||||
|
||||
unset($existing_foreign_keys[$constraint]);
|
||||
|
||||
if (empty($database[$name]['foreign_keys'][$constraint])) {
|
||||
$sql2 = self::addForeignKey($name, $fieldname, $parameters);
|
||||
$sql2 = DbaDefinitionSqlWriter::addForeignKey($fieldName, $parameters);
|
||||
|
||||
if ($sql3 == "") {
|
||||
$sql3 = "ALTER" . $ignore . " TABLE `" . $name . "` " . $sql2;
|
||||
|
@ -715,7 +391,7 @@ class DBStructure
|
|||
}
|
||||
|
||||
foreach ($existing_foreign_keys as $param) {
|
||||
$sql2 = self::dropForeignKey($param['CONSTRAINT_NAME']);
|
||||
$sql2 = DbaDefinitionSqlWriter::dropForeignKey($param['CONSTRAINT_NAME']);
|
||||
|
||||
if ($sql3 == "") {
|
||||
$sql3 = "ALTER" . $ignore . " TABLE `" . $name . "` " . $sql2;
|
||||
|
@ -767,9 +443,9 @@ class DBStructure
|
|||
|
||||
// Now have a look at the field collations
|
||||
// Compare the field structure field by field
|
||||
foreach ($structure["fields"] as $fieldname => $parameters) {
|
||||
foreach ($structure["fields"] as $fieldName => $parameters) {
|
||||
// Compare the field definition
|
||||
$field_definition = ($database[$name]["fields"][$fieldname] ?? '') ?: ['Collation' => ''];
|
||||
$field_definition = ($database[$name]["fields"][$fieldName] ?? '') ?: ['Collation' => ''];
|
||||
|
||||
// Define the default collation if not given
|
||||
if (!isset($parameters['Collation']) && !empty($field_definition['Collation'])) {
|
||||
|
@ -779,7 +455,7 @@ class DBStructure
|
|||
}
|
||||
|
||||
if ($field_definition['Collation'] != $parameters['Collation']) {
|
||||
$sql2 = self::modifyTableField($fieldname, $parameters);
|
||||
$sql2 = DbaDefinitionSqlWriter::modifyTableField($fieldName, $parameters);
|
||||
if (($sql3 == "") || (substr($sql3, -2, 2) == "; ")) {
|
||||
$sql3 .= "ALTER" . $ignore . " TABLE `" . $name . "` " . $sql2;
|
||||
} else {
|
||||
|
@ -826,23 +502,29 @@ class DBStructure
|
|||
return $errors;
|
||||
}
|
||||
|
||||
private static function tableStructure($table)
|
||||
/**
|
||||
* Returns an array with table structure information
|
||||
*
|
||||
* @param string $table Name of table
|
||||
* @return array Table structure information
|
||||
*/
|
||||
private static function tableStructure(string $table): array
|
||||
{
|
||||
// This query doesn't seem to be executable as a prepared statement
|
||||
$indexes = DBA::toArray(DBA::p("SHOW INDEX FROM " . DBA::quoteIdentifier($table)));
|
||||
|
||||
$fields = DBA::selectToArray(['INFORMATION_SCHEMA' => 'COLUMNS'],
|
||||
$fields = DBA::selectToArray('INFORMATION_SCHEMA.COLUMNS',
|
||||
['COLUMN_NAME', 'COLUMN_TYPE', 'IS_NULLABLE', 'COLUMN_DEFAULT', 'EXTRA',
|
||||
'COLUMN_KEY', 'COLLATION_NAME', 'COLUMN_COMMENT'],
|
||||
["`TABLE_SCHEMA` = ? AND `TABLE_NAME` = ?",
|
||||
DBA::databaseName(), $table]);
|
||||
|
||||
$foreign_keys = DBA::selectToArray(['INFORMATION_SCHEMA' => 'KEY_COLUMN_USAGE'],
|
||||
$foreign_keys = DBA::selectToArray('INFORMATION_SCHEMA.KEY_COLUMN_USAGE',
|
||||
['COLUMN_NAME', 'CONSTRAINT_NAME', 'REFERENCED_TABLE_NAME', 'REFERENCED_COLUMN_NAME'],
|
||||
["`TABLE_SCHEMA` = ? AND `TABLE_NAME` = ? AND `REFERENCED_TABLE_SCHEMA` IS NOT NULL",
|
||||
DBA::databaseName(), $table]);
|
||||
|
||||
$table_status = DBA::selectFirst(['INFORMATION_SCHEMA' => 'TABLES'],
|
||||
$table_status = DBA::selectFirst('INFORMATION_SCHEMA.TABLES',
|
||||
['ENGINE', 'TABLE_COLLATION', 'TABLE_COMMENT'],
|
||||
["`TABLE_SCHEMA` = ? AND `TABLE_NAME` = ?",
|
||||
DBA::databaseName(), $table]);
|
||||
|
@ -909,65 +591,20 @@ class DBStructure
|
|||
}
|
||||
}
|
||||
|
||||
return ["fields" => $fielddata, "indexes" => $indexdata,
|
||||
"foreign_keys" => $foreigndata, "table_status" => $table_status];
|
||||
return [
|
||||
'fields' => $fielddata,
|
||||
'indexes' => $indexdata,
|
||||
'foreign_keys' => $foreigndata,
|
||||
'table_status' => $table_status
|
||||
];
|
||||
}
|
||||
|
||||
private static function dropIndex($indexname)
|
||||
{
|
||||
$sql = sprintf("DROP INDEX `%s`", DBA::escape($indexname));
|
||||
return ($sql);
|
||||
}
|
||||
|
||||
private static function addTableField($fieldname, $parameters)
|
||||
{
|
||||
$sql = sprintf("ADD `%s` %s", DBA::escape($fieldname), self::FieldCommand($parameters));
|
||||
return ($sql);
|
||||
}
|
||||
|
||||
private static function modifyTableField($fieldname, $parameters)
|
||||
{
|
||||
$sql = sprintf("MODIFY `%s` %s", DBA::escape($fieldname), self::FieldCommand($parameters, false));
|
||||
return ($sql);
|
||||
}
|
||||
|
||||
private static function getConstraintName(string $tablename, string $fieldname, array $parameters)
|
||||
private static function getConstraintName(string $tableName, string $fieldName, array $parameters): string
|
||||
{
|
||||
$foreign_table = array_keys($parameters['foreign'])[0];
|
||||
$foreign_field = array_values($parameters['foreign'])[0];
|
||||
|
||||
return $tablename . "-" . $fieldname. "-" . $foreign_table. "-" . $foreign_field;
|
||||
}
|
||||
|
||||
private static function foreignCommand(string $tablename, string $fieldname, array $parameters) {
|
||||
$foreign_table = array_keys($parameters['foreign'])[0];
|
||||
$foreign_field = array_values($parameters['foreign'])[0];
|
||||
|
||||
$sql = "FOREIGN KEY (`" . $fieldname . "`) 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;
|
||||
}
|
||||
|
||||
private static function addForeignKey(string $tablename, string $fieldname, array $parameters)
|
||||
{
|
||||
return sprintf("ADD %s", self::foreignCommand($tablename, $fieldname, $parameters));
|
||||
}
|
||||
|
||||
private static function dropForeignKey(string $constraint)
|
||||
{
|
||||
return sprintf("DROP FOREIGN KEY `%s`", $constraint);
|
||||
return $tableName . '-' . $fieldName. '-' . $foreign_table. '-' . $foreign_field;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -983,7 +620,7 @@ class DBStructure
|
|||
* @return boolean Was the renaming successful?
|
||||
* @throws Exception
|
||||
*/
|
||||
public static function rename($table, $columns, $type = self::RENAME_COLUMN)
|
||||
public static function rename(string $table, array $columns, int $type = self::RENAME_COLUMN): bool
|
||||
{
|
||||
if (empty($table) || empty($columns)) {
|
||||
return false;
|
||||
|
@ -1019,7 +656,7 @@ class DBStructure
|
|||
return false;
|
||||
}
|
||||
|
||||
$sql .= ";";
|
||||
$sql .= ';';
|
||||
|
||||
$stmt = DBA::p($sql);
|
||||
|
||||
|
@ -1043,7 +680,7 @@ class DBStructure
|
|||
* @return boolean Does the table exist?
|
||||
* @throws Exception
|
||||
*/
|
||||
public static function existsColumn($table, $columns = [])
|
||||
public static function existsColumn(string $table, array $columns = []): bool
|
||||
{
|
||||
if (empty($table)) {
|
||||
return false;
|
||||
|
@ -1079,39 +716,33 @@ class DBStructure
|
|||
/**
|
||||
* Check if a foreign key exists for the given table field
|
||||
*
|
||||
* @param string $table
|
||||
* @param string $field
|
||||
* @return boolean
|
||||
* @param string $table Table name
|
||||
* @param string $field Field name
|
||||
* @return boolean Wether a foreign key exists
|
||||
*/
|
||||
public static function existsForeignKeyForField(string $table, string $field)
|
||||
public static function existsForeignKeyForField(string $table, string $field): bool
|
||||
{
|
||||
return DBA::exists(['INFORMATION_SCHEMA' => 'KEY_COLUMN_USAGE'],
|
||||
return DBA::exists('INFORMATION_SCHEMA.KEY_COLUMN_USAGE',
|
||||
["`TABLE_SCHEMA` = ? AND `TABLE_NAME` = ? AND `COLUMN_NAME` = ? AND `REFERENCED_TABLE_SCHEMA` IS NOT NULL",
|
||||
DBA::databaseName(), $table, $field]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a table exists
|
||||
*
|
||||
* @param string|array $table Table name
|
||||
* Check if a table exists
|
||||
*
|
||||
* @param string $table Single table name (please loop yourself)
|
||||
* @return boolean Does the table exist?
|
||||
* @throws Exception
|
||||
*/
|
||||
public static function existsTable($table)
|
||||
public static function existsTable(string $table): bool
|
||||
{
|
||||
if (empty($table)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (is_array($table)) {
|
||||
$condition = ['table_schema' => key($table), 'table_name' => current($table)];
|
||||
} else {
|
||||
$condition = ['table_schema' => DBA::databaseName(), 'table_name' => $table];
|
||||
}
|
||||
$condition = ['table_schema' => DBA::databaseName(), 'table_name' => $table];
|
||||
|
||||
$result = DBA::exists(['information_schema' => 'tables'], $condition);
|
||||
|
||||
return $result;
|
||||
return DBA::exists('information_schema.tables', $condition);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1122,7 +753,7 @@ class DBStructure
|
|||
* @return array An array of the table columns
|
||||
* @throws Exception
|
||||
*/
|
||||
public static function getColumns($table)
|
||||
public static function getColumns(string $table): array
|
||||
{
|
||||
$stmtColumns = DBA::p("SHOW COLUMNS FROM `" . $table . "`");
|
||||
return DBA::toArray($stmtColumns);
|
||||
|
@ -1130,6 +761,9 @@ class DBStructure
|
|||
|
||||
/**
|
||||
* Check if initial database values do exist - or create them
|
||||
*
|
||||
* @param bool $verbose Whether to output messages
|
||||
* @return void
|
||||
*/
|
||||
public static function checkInitialValues(bool $verbose = false)
|
||||
{
|
||||
|
@ -1163,9 +797,9 @@ class DBStructure
|
|||
|
||||
if (self::existsTable('user') && !DBA::exists('user', ['uid' => 0])) {
|
||||
$user = [
|
||||
"verified" => true,
|
||||
"page-flags" => User::PAGE_FLAGS_SOAPBOX,
|
||||
"account-type" => User::ACCOUNT_TYPE_RELAY,
|
||||
'verified' => true,
|
||||
'page-flags' => User::PAGE_FLAGS_SOAPBOX,
|
||||
'account-type' => User::ACCOUNT_TYPE_RELAY,
|
||||
];
|
||||
DBA::insert('user', $user);
|
||||
$lastid = DBA::lastInsertId();
|
||||
|
@ -1265,12 +899,14 @@ class DBStructure
|
|||
*
|
||||
* @return boolean
|
||||
*/
|
||||
private static function isUpdating()
|
||||
private static function isUpdating(): bool
|
||||
{
|
||||
$isUpdate = false;
|
||||
|
||||
$processes = DBA::select(['information_schema' => 'processlist'], ['info'],
|
||||
['db' => DBA::databaseName(), 'command' => ['Query', 'Execute']]);
|
||||
$processes = DBA::select('information_schema.processlist', ['info'], [
|
||||
'db' => DBA::databaseName(),
|
||||
'command' => ['Query', 'Execute']
|
||||
]);
|
||||
|
||||
while ($process = DBA::fetch($processes)) {
|
||||
$parts = explode(' ', $process['info']);
|
||||
|
|
|
@ -23,9 +23,12 @@ namespace Friendica\Database;
|
|||
|
||||
use Friendica\Core\Config\ValueObject\Cache;
|
||||
use Friendica\Core\System;
|
||||
use Friendica\Database\Definition\DbaDefinition;
|
||||
use Friendica\Database\Definition\ViewDefinition;
|
||||
use Friendica\Network\HTTPException\ServiceUnavailableException;
|
||||
use Friendica\Util\DateTimeFormat;
|
||||
use Friendica\Util\Profiler;
|
||||
use InvalidArgumentException;
|
||||
use mysqli;
|
||||
use mysqli_result;
|
||||
use mysqli_stmt;
|
||||
|
@ -63,7 +66,7 @@ class Database
|
|||
protected $server_info = '';
|
||||
/** @var PDO|mysqli */
|
||||
protected $connection;
|
||||
protected $driver;
|
||||
protected $driver = '';
|
||||
protected $pdo_emulate_prepares = false;
|
||||
private $error = false;
|
||||
private $errorno = 0;
|
||||
|
@ -72,23 +75,29 @@ class Database
|
|||
protected $in_retrial = false;
|
||||
protected $testmode = false;
|
||||
private $relation = [];
|
||||
/** @var DbaDefinition */
|
||||
protected $dbaDefinition;
|
||||
/** @var ViewDefinition */
|
||||
protected $viewDefinition;
|
||||
|
||||
public function __construct(Cache $configCache, Profiler $profiler, LoggerInterface $logger)
|
||||
public function __construct(Cache $configCache, Profiler $profiler, DbaDefinition $dbaDefinition, ViewDefinition $viewDefinition, LoggerInterface $logger)
|
||||
{
|
||||
// We are storing these values for being able to perform a reconnect
|
||||
$this->configCache = $configCache;
|
||||
$this->profiler = $profiler;
|
||||
$this->logger = $logger;
|
||||
$this->configCache = $configCache;
|
||||
$this->profiler = $profiler;
|
||||
$this->logger = $logger;
|
||||
$this->dbaDefinition = $dbaDefinition;
|
||||
$this->viewDefinition = $viewDefinition;
|
||||
|
||||
$this->connect();
|
||||
|
||||
if ($this->isConnected()) {
|
||||
// Loads DB_UPDATE_VERSION constant
|
||||
DBStructure::definition($configCache->get('system', 'basepath'), false);
|
||||
}
|
||||
}
|
||||
|
||||
public function connect()
|
||||
/**
|
||||
* Tries to connect to database
|
||||
*
|
||||
* @return bool Success
|
||||
*/
|
||||
public function connect(): bool
|
||||
{
|
||||
if (!is_null($this->connection) && $this->connected()) {
|
||||
return $this->connected;
|
||||
|
@ -175,7 +184,7 @@ class Database
|
|||
|
||||
// No suitable SQL driver was found.
|
||||
if (!$this->connected) {
|
||||
$this->driver = null;
|
||||
$this->driver = '';
|
||||
$this->connection = null;
|
||||
}
|
||||
|
||||
|
@ -227,7 +236,7 @@ class Database
|
|||
}
|
||||
}
|
||||
|
||||
$this->driver = null;
|
||||
$this->driver = '';
|
||||
$this->connected = false;
|
||||
}
|
||||
|
||||
|
@ -255,7 +264,7 @@ class Database
|
|||
*
|
||||
* @return string with either "pdo" or "mysqli"
|
||||
*/
|
||||
public function getDriver()
|
||||
public function getDriver(): string
|
||||
{
|
||||
return $this->driver;
|
||||
}
|
||||
|
@ -266,9 +275,9 @@ class Database
|
|||
* This function discriminate between the deprecated mysql API and the current
|
||||
* object-oriented mysqli API. Example of returned string: 5.5.46-0+deb8u1
|
||||
*
|
||||
* @return string
|
||||
* @return string Database server information
|
||||
*/
|
||||
public function serverInfo()
|
||||
public function serverInfo(): string
|
||||
{
|
||||
if ($this->server_info == '') {
|
||||
switch ($this->driver) {
|
||||
|
@ -286,10 +295,10 @@ class Database
|
|||
/**
|
||||
* Returns the selected database name
|
||||
*
|
||||
* @return string
|
||||
* @return string Database name
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function databaseName()
|
||||
public function databaseName(): string
|
||||
{
|
||||
$ret = $this->p("SELECT DATABASE() AS `db`");
|
||||
$data = $this->toArray($ret);
|
||||
|
@ -300,10 +309,10 @@ class Database
|
|||
* Analyze a database query and log this if some conditions are met.
|
||||
*
|
||||
* @param string $query The database query that will be analyzed
|
||||
*
|
||||
* @return void
|
||||
* @throws \Exception
|
||||
*/
|
||||
private function logIndex($query)
|
||||
private function logIndex(string $query)
|
||||
{
|
||||
|
||||
if (!$this->configCache->get('system', 'db_log_index')) {
|
||||
|
@ -359,11 +368,10 @@ class Database
|
|||
* Removes every not allowlisted character from the identifier string
|
||||
*
|
||||
* @param string $identifier
|
||||
*
|
||||
* @return string sanitized identifier
|
||||
* @throws \Exception
|
||||
*/
|
||||
private function sanitizeIdentifier($identifier)
|
||||
private function sanitizeIdentifier(string $identifier): string
|
||||
{
|
||||
return preg_replace('/[^A-Za-z0-9_\-]+/', '', $identifier);
|
||||
}
|
||||
|
@ -383,11 +391,21 @@ class Database
|
|||
}
|
||||
}
|
||||
|
||||
public function isConnected()
|
||||
/**
|
||||
* Returns connected flag
|
||||
*
|
||||
* @return bool Whether connection to database was success
|
||||
*/
|
||||
public function isConnected(): bool
|
||||
{
|
||||
return $this->connected;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks connection status
|
||||
*
|
||||
* @return bool Whether connection to database was success
|
||||
*/
|
||||
public function connected()
|
||||
{
|
||||
$connected = false;
|
||||
|
@ -424,7 +442,7 @@ class Database
|
|||
*
|
||||
* @return string The input SQL string modified if necessary.
|
||||
*/
|
||||
public function anyValueFallback($sql)
|
||||
public function anyValueFallback(string $sql): string
|
||||
{
|
||||
$server_info = $this->serverInfo();
|
||||
if (version_compare($server_info, '5.7.5', '<') ||
|
||||
|
@ -442,7 +460,7 @@ class Database
|
|||
*
|
||||
* @return string The replaced SQL query
|
||||
*/
|
||||
private function replaceParameters($sql, $args)
|
||||
private function replaceParameters(string $sql, array $args): string
|
||||
{
|
||||
$offset = 0;
|
||||
foreach ($args as $param => $value) {
|
||||
|
@ -476,7 +494,7 @@ class Database
|
|||
* @return bool|object statement object or result object
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function p($sql)
|
||||
public function p(string $sql)
|
||||
{
|
||||
|
||||
$this->profiler->startRecording('database');
|
||||
|
@ -541,7 +559,7 @@ class Database
|
|||
if (!$retval = $this->connection->query($this->replaceParameters($sql, $args))) {
|
||||
$errorInfo = $this->connection->errorInfo();
|
||||
$this->error = $errorInfo[2];
|
||||
$this->errorno = $errorInfo[1];
|
||||
$this->errorno = (int) $errorInfo[1];
|
||||
$retval = false;
|
||||
$is_error = true;
|
||||
break;
|
||||
|
@ -554,7 +572,7 @@ class Database
|
|||
if (!$stmt = $this->connection->prepare($sql)) {
|
||||
$errorInfo = $this->connection->errorInfo();
|
||||
$this->error = $errorInfo[2];
|
||||
$this->errorno = $errorInfo[1];
|
||||
$this->errorno = (int) $errorInfo[1];
|
||||
$retval = false;
|
||||
$is_error = true;
|
||||
break;
|
||||
|
@ -574,7 +592,7 @@ class Database
|
|||
if (!$stmt->execute()) {
|
||||
$errorInfo = $stmt->errorInfo();
|
||||
$this->error = $errorInfo[2];
|
||||
$this->errorno = $errorInfo[1];
|
||||
$this->errorno = (int) $errorInfo[1];
|
||||
$retval = false;
|
||||
$is_error = true;
|
||||
} else {
|
||||
|
@ -709,7 +727,7 @@ class Database
|
|||
}
|
||||
|
||||
$this->error = $error;
|
||||
$this->errorno = $errorno;
|
||||
$this->errorno = (int) $errorno;
|
||||
}
|
||||
|
||||
$this->profiler->stopRecording();
|
||||
|
@ -741,8 +759,9 @@ class Database
|
|||
* @return boolean Was the query successfull? False is returned only if an error occurred
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function e($sql)
|
||||
public function e(string $sql): bool
|
||||
{
|
||||
$retval = false;
|
||||
|
||||
$this->profiler->startRecording('database_write');
|
||||
|
||||
|
@ -804,13 +823,14 @@ class Database
|
|||
/**
|
||||
* Check if data exists
|
||||
*
|
||||
* @param string|array $table Table name or array [schema => table]
|
||||
* @param array $condition array of fields for condition
|
||||
* @param string $table Table name in format schema.table (while scheme is optiona)
|
||||
* @param array $condition Array of fields for condition
|
||||
*
|
||||
* @return boolean Are there rows for that condition?
|
||||
* @throws \Exception
|
||||
* @todo Please unwrap the DBStructure::existsTable() call so this method has one behavior only: checking existence on records
|
||||
*/
|
||||
public function exists($table, $condition)
|
||||
public function exists(string $table, array $condition): bool
|
||||
{
|
||||
if (empty($table)) {
|
||||
return false;
|
||||
|
@ -850,10 +870,10 @@ class Database
|
|||
*
|
||||
* @param string $sql SQL statement
|
||||
*
|
||||
* @return array first row of query
|
||||
* @return array|bool first row of query or false on failure
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function fetchFirst($sql)
|
||||
public function fetchFirst(string $sql)
|
||||
{
|
||||
$params = DBA::getParam(func_get_args());
|
||||
|
||||
|
@ -875,7 +895,7 @@ class Database
|
|||
*
|
||||
* @return int Number of rows
|
||||
*/
|
||||
public function affectedRows()
|
||||
public function affectedRows(): int
|
||||
{
|
||||
return $this->affected_rows;
|
||||
}
|
||||
|
@ -887,7 +907,7 @@ class Database
|
|||
*
|
||||
* @return int Number of columns
|
||||
*/
|
||||
public function columnCount($stmt)
|
||||
public function columnCount($stmt): int
|
||||
{
|
||||
if (!is_object($stmt)) {
|
||||
return 0;
|
||||
|
@ -908,7 +928,7 @@ class Database
|
|||
*
|
||||
* @return int Number of rows
|
||||
*/
|
||||
public function numRows($stmt)
|
||||
public function numRows($stmt): int
|
||||
{
|
||||
if (!is_object($stmt)) {
|
||||
return 0;
|
||||
|
@ -927,7 +947,7 @@ class Database
|
|||
*
|
||||
* @param bool|PDOStatement|mysqli_stmt $stmt statement object
|
||||
*
|
||||
* @return array|false current row
|
||||
* @return array|bool Current row or false on failure
|
||||
*/
|
||||
public function fetch($stmt)
|
||||
{
|
||||
|
@ -987,14 +1007,14 @@ class Database
|
|||
/**
|
||||
* Insert a row into a table. Field value objects will be cast as string.
|
||||
*
|
||||
* @param string|array $table Table name or array [schema => table]
|
||||
* @param array $param parameter array
|
||||
* @param int $duplicate_mode What to do on a duplicated entry
|
||||
* @param string $table Table name in format schema.table (while scheme is optiona)
|
||||
* @param array $param parameter array
|
||||
* @param int $duplicate_mode What to do on a duplicated entry
|
||||
*
|
||||
* @return boolean was the insert successful?
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function insert($table, array $param, int $duplicate_mode = self::INSERT_DEFAULT)
|
||||
public function insert(string $table, array $param, int $duplicate_mode = self::INSERT_DEFAULT): bool
|
||||
{
|
||||
if (empty($table) || empty($param)) {
|
||||
$this->logger->info('Table and fields have to be set');
|
||||
|
@ -1003,7 +1023,7 @@ class Database
|
|||
|
||||
$param = $this->castFields($table, $param);
|
||||
|
||||
$table_string = DBA::buildTableString($table);
|
||||
$table_string = DBA::buildTableString([$table]);
|
||||
|
||||
$fields_string = implode(', ', array_map([DBA::class, 'quoteIdentifier'], array_keys($param)));
|
||||
|
||||
|
@ -1038,13 +1058,12 @@ class Database
|
|||
* Inserts a row with the provided data in the provided table.
|
||||
* If the data corresponds to an existing row through a UNIQUE or PRIMARY index constraints, it updates the row instead.
|
||||
*
|
||||
* @param string|array $table Table name or array [schema => table]
|
||||
* @param array $param parameter array
|
||||
*
|
||||
* @param string $table Table name in format schema.table (while scheme is optiona)
|
||||
* @param array $param parameter array
|
||||
* @return boolean was the insert successful?
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function replace($table, array $param)
|
||||
public function replace(string $table, array $param): bool
|
||||
{
|
||||
if (empty($table) || empty($param)) {
|
||||
$this->logger->info('Table and fields have to be set');
|
||||
|
@ -1053,7 +1072,7 @@ class Database
|
|||
|
||||
$param = $this->castFields($table, $param);
|
||||
|
||||
$table_string = DBA::buildTableString($table);
|
||||
$table_string = DBA::buildTableString([$table]);
|
||||
|
||||
$fields_string = implode(', ', array_map([DBA::class, 'quoteIdentifier'], array_keys($param)));
|
||||
|
||||
|
@ -1069,7 +1088,7 @@ class Database
|
|||
*
|
||||
* @return integer Last inserted id
|
||||
*/
|
||||
public function lastInsertId()
|
||||
public function lastInsertId(): int
|
||||
{
|
||||
switch ($this->driver) {
|
||||
case self::PDO:
|
||||
|
@ -1087,12 +1106,11 @@ class Database
|
|||
*
|
||||
* This function can be extended in the future to accept a table array as well.
|
||||
*
|
||||
* @param string|array $table Table name or array [schema => table]
|
||||
*
|
||||
* @param string $table Table name in format schema.table (while scheme is optiona)
|
||||
* @return boolean was the lock successful?
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function lock($table)
|
||||
public function lock(string $table): bool
|
||||
{
|
||||
// See here: https://dev.mysql.com/doc/refman/5.7/en/lock-tables-and-transactions.html
|
||||
if ($this->driver == self::PDO) {
|
||||
|
@ -1102,7 +1120,7 @@ class Database
|
|||
$this->connection->autocommit(false);
|
||||
}
|
||||
|
||||
$success = $this->e("LOCK TABLES " . DBA::buildTableString($table) . " WRITE");
|
||||
$success = $this->e("LOCK TABLES " . DBA::buildTableString([$table]) . " WRITE");
|
||||
|
||||
if ($this->driver == self::PDO) {
|
||||
$this->connection->setAttribute(PDO::ATTR_EMULATE_PREPARES, $this->pdo_emulate_prepares);
|
||||
|
@ -1126,7 +1144,7 @@ class Database
|
|||
* @return boolean was the unlock successful?
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function unlock()
|
||||
public function unlock(): bool
|
||||
{
|
||||
// See here: https://dev.mysql.com/doc/refman/5.7/en/lock-tables-and-transactions.html
|
||||
$this->performCommit();
|
||||
|
@ -1177,7 +1195,12 @@ class Database
|
|||
return true;
|
||||
}
|
||||
|
||||
protected function performCommit()
|
||||
/**
|
||||
* Performs the commit
|
||||
*
|
||||
* @return boolean Was the command executed successfully?
|
||||
*/
|
||||
protected function performCommit(): bool
|
||||
{
|
||||
switch ($this->driver) {
|
||||
case self::PDO:
|
||||
|
@ -1199,7 +1222,7 @@ class Database
|
|||
*
|
||||
* @return boolean Was the command executed successfully?
|
||||
*/
|
||||
public function commit()
|
||||
public function commit(): bool
|
||||
{
|
||||
if (!$this->performCommit()) {
|
||||
return false;
|
||||
|
@ -1213,7 +1236,7 @@ class Database
|
|||
*
|
||||
* @return boolean Was the command executed successfully?
|
||||
*/
|
||||
public function rollback()
|
||||
public function rollback(): bool
|
||||
{
|
||||
$ret = false;
|
||||
|
||||
|
@ -1230,6 +1253,7 @@ class Database
|
|||
$ret = $this->connection->rollback();
|
||||
break;
|
||||
}
|
||||
|
||||
$this->in_transaction = false;
|
||||
return $ret;
|
||||
}
|
||||
|
@ -1243,14 +1267,14 @@ class Database
|
|||
* @return boolean was the delete successful?
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function delete($table, array $conditions)
|
||||
public function delete(string $table, array $conditions): bool
|
||||
{
|
||||
if (empty($table) || empty($conditions)) {
|
||||
$this->logger->info('Table and conditions have to be set');
|
||||
return false;
|
||||
}
|
||||
|
||||
$table_string = DBA::buildTableString($table);
|
||||
$table_string = DBA::buildTableString([$table]);
|
||||
|
||||
$condition_string = DBA::buildCondition($conditions);
|
||||
|
||||
|
@ -1280,7 +1304,7 @@ class Database
|
|||
* Only set $old_fields to a boolean value when you are sure that you will update a single row.
|
||||
* When you set $old_fields to "true" then $fields must contain all relevant fields!
|
||||
*
|
||||
* @param string|array $table Table name or array [schema => table]
|
||||
* @param string $table Table name in format schema.table (while scheme is optiona)
|
||||
* @param array $fields contains the fields that are updated
|
||||
* @param array $condition condition array with the key values
|
||||
* @param array|boolean $old_fields array with the old field values that are about to be replaced (true = update on duplicate, false = don't update identical fields)
|
||||
|
@ -1288,8 +1312,9 @@ class Database
|
|||
*
|
||||
* @return boolean was the update successfull?
|
||||
* @throws \Exception
|
||||
* @todo Implement "bool $update_on_duplicate" to avoid mixed type for $old_fields
|
||||
*/
|
||||
public function update($table, $fields, $condition, $old_fields = [], $params = [])
|
||||
public function update(string $table, array $fields, array $condition, $old_fields = [], array $params = [])
|
||||
{
|
||||
if (empty($table) || empty($fields) || empty($condition)) {
|
||||
$this->logger->info('Table, fields and condition have to be set');
|
||||
|
@ -1322,7 +1347,7 @@ class Database
|
|||
|
||||
$fields = $this->castFields($table, $fields);
|
||||
|
||||
$table_string = DBA::buildTableString($table);
|
||||
$table_string = DBA::buildTableString([$table]);
|
||||
|
||||
$condition_string = DBA::buildCondition($condition);
|
||||
|
||||
|
@ -1345,16 +1370,16 @@ class Database
|
|||
/**
|
||||
* Retrieve a single record from a table and returns it in an associative array
|
||||
*
|
||||
* @param string|array $table
|
||||
* @param array $fields
|
||||
* @param array $condition
|
||||
* @param array $params
|
||||
* @param string $table Table name in format schema.table (while scheme is optiona)
|
||||
* @param array $fields Array of selected fields, empty for all
|
||||
* @param array $condition Array of fields for condition
|
||||
* @param array $params Array of several parameters
|
||||
*
|
||||
* @return bool|array
|
||||
* @throws \Exception
|
||||
* @see $this->select
|
||||
*/
|
||||
public function selectFirst($table, array $fields = [], array $condition = [], $params = [])
|
||||
public function selectFirst(string $table, array $fields = [], array $condition = [], array $params = [])
|
||||
{
|
||||
$params['limit'] = 1;
|
||||
$result = $this->select($table, $fields, $condition, $params);
|
||||
|
@ -1371,16 +1396,15 @@ class Database
|
|||
/**
|
||||
* Select rows from a table and fills an array with the data
|
||||
*
|
||||
* @param string|array $table Table name or array [schema => table]
|
||||
* @param array $fields Array of selected fields, empty for all
|
||||
* @param array $condition Array of fields for condition
|
||||
* @param array $params Array of several parameters
|
||||
*
|
||||
* @param string $table Table name in format schema.table (while scheme is optiona)
|
||||
* @param array $fields Array of selected fields, empty for all
|
||||
* @param array $condition Array of fields for condition
|
||||
* @param array $params Array of several parameters
|
||||
* @return array Data array
|
||||
* @throws \Exception
|
||||
* @see self::select
|
||||
*/
|
||||
public function selectToArray($table, array $fields = [], array $condition = [], array $params = [])
|
||||
public function selectToArray(string $table, array $fields = [], array $condition = [], array $params = [])
|
||||
{
|
||||
return $this->toArray($this->select($table, $fields, $condition, $params));
|
||||
}
|
||||
|
@ -1390,9 +1414,9 @@ class Database
|
|||
*
|
||||
* @param array $fields
|
||||
* @param array $options
|
||||
* @return array
|
||||
* @return array Escaped fields
|
||||
*/
|
||||
private function escapeFields(array $fields, array $options)
|
||||
private function escapeFields(array $fields, array $options): array
|
||||
{
|
||||
// In the case of a "GROUP BY" we have to add all the ORDER fields to the fieldlist.
|
||||
// This needs to done to apply the "ANY_VALUE(...)" treatment from below to them.
|
||||
|
@ -1446,14 +1470,14 @@ class Database
|
|||
*
|
||||
* $data = DBA::select($table, $fields, $condition, $params);
|
||||
*
|
||||
* @param string|array $table Table name or array [schema => table]
|
||||
* @param array $fields Array of selected fields, empty for all
|
||||
* @param array $condition Array of fields for condition
|
||||
* @param array $params Array of several parameters
|
||||
* @param string $table Table name in format schema.table (while scheme is optiona)
|
||||
* @param array $fields Array of selected fields, empty for all
|
||||
* @param array $condition Array of fields for condition
|
||||
* @param array $params Array of several parameters
|
||||
* @return boolean|object
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function select($table, array $fields = [], array $condition = [], array $params = [])
|
||||
public function select(string $table, array $fields = [], array $condition = [], array $params = [])
|
||||
{
|
||||
if (empty($table)) {
|
||||
return false;
|
||||
|
@ -1466,7 +1490,7 @@ class Database
|
|||
$select_string = '*';
|
||||
}
|
||||
|
||||
$table_string = DBA::buildTableString($table);
|
||||
$table_string = DBA::buildTableString([$table]);
|
||||
|
||||
$condition_string = DBA::buildCondition($condition);
|
||||
|
||||
|
@ -1486,11 +1510,11 @@ class Database
|
|||
/**
|
||||
* Counts the rows from a table satisfying the provided condition
|
||||
*
|
||||
* @param string|array $table Table name or array [schema => table]
|
||||
* @param array $condition Array of fields for condition
|
||||
* @param array $params Array of several parameters
|
||||
* @param string $table Table name in format schema.table (while scheme is optiona)
|
||||
* @param array $condition Array of fields for condition
|
||||
* @param array $params Array of several parameters
|
||||
*
|
||||
* @return int
|
||||
* @return int Count of rows
|
||||
*
|
||||
* Example:
|
||||
* $table = "post";
|
||||
|
@ -1502,13 +1526,13 @@ class Database
|
|||
* $count = DBA::count($table, $condition);
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function count($table, array $condition = [], array $params = [])
|
||||
public function count(string $table, array $condition = [], array $params = []): int
|
||||
{
|
||||
if (empty($table)) {
|
||||
return false;
|
||||
throw new InvalidArgumentException('Parameter "table" cannot be empty.');
|
||||
}
|
||||
|
||||
$table_string = DBA::buildTableString($table);
|
||||
$table_string = DBA::buildTableString([$table]);
|
||||
|
||||
$condition_string = DBA::buildCondition($condition);
|
||||
|
||||
|
@ -1541,7 +1565,7 @@ class Database
|
|||
*
|
||||
* @return array Data array
|
||||
*/
|
||||
public function toArray($stmt, $do_close = true, int $count = 0)
|
||||
public function toArray($stmt, bool $do_close = true, int $count = 0): array
|
||||
{
|
||||
if (is_bool($stmt)) {
|
||||
return [];
|
||||
|
@ -1569,7 +1593,8 @@ class Database
|
|||
* @param array $fields
|
||||
* @return array casted fields
|
||||
*/
|
||||
public function castFields(string $table, array $fields) {
|
||||
public function castFields(string $table, array $fields): array
|
||||
{
|
||||
// When there is no data, we don't need to do something
|
||||
if (empty($fields)) {
|
||||
return $fields;
|
||||
|
@ -1587,15 +1612,15 @@ class Database
|
|||
|
||||
$types = [];
|
||||
|
||||
$tables = DBStructure::definition('', false);
|
||||
$tables = $this->dbaDefinition->getAll();
|
||||
if (empty($tables[$table])) {
|
||||
// When a matching table wasn't found we check if it is a view
|
||||
$views = View::definition('', false);
|
||||
$views = $this->viewDefinition->getAll();
|
||||
if (empty($views[$table])) {
|
||||
return $fields;
|
||||
}
|
||||
|
||||
foreach(array_keys($fields) as $field) {
|
||||
foreach (array_keys($fields) as $field) {
|
||||
if (!empty($views[$table]['fields'][$field])) {
|
||||
$viewdef = $views[$table]['fields'][$field];
|
||||
if (!empty($tables[$viewdef[0]]['fields'][$viewdef[1]]['type'])) {
|
||||
|
@ -1632,7 +1657,7 @@ class Database
|
|||
*
|
||||
* @return string Error number (0 if no error)
|
||||
*/
|
||||
public function errorNo()
|
||||
public function errorNo(): int
|
||||
{
|
||||
return $this->errorno;
|
||||
}
|
||||
|
@ -1642,7 +1667,7 @@ class Database
|
|||
*
|
||||
* @return string Error message ('' if no error)
|
||||
*/
|
||||
public function errorMessage()
|
||||
public function errorMessage(): string
|
||||
{
|
||||
return $this->error;
|
||||
}
|
||||
|
@ -1654,7 +1679,7 @@ class Database
|
|||
*
|
||||
* @return boolean was the close successful?
|
||||
*/
|
||||
public function close($stmt)
|
||||
public function close($stmt): bool
|
||||
{
|
||||
|
||||
$this->profiler->startRecording('database');
|
||||
|
@ -1696,38 +1721,39 @@ class Database
|
|||
* 'amount' => Number of concurrent database processes
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function processlist()
|
||||
public function processlist(): array
|
||||
{
|
||||
$ret = $this->p("SHOW PROCESSLIST");
|
||||
$ret = $this->p('SHOW PROCESSLIST');
|
||||
$data = $this->toArray($ret);
|
||||
|
||||
$processes = 0;
|
||||
$states = [];
|
||||
foreach ($data as $process) {
|
||||
$state = trim($process["State"]);
|
||||
$state = trim($process['State']);
|
||||
|
||||
// Filter out all non blocking processes
|
||||
if (!in_array($state, ["", "init", "statistics", "updating"])) {
|
||||
if (!in_array($state, ['', 'init', 'statistics', 'updating'])) {
|
||||
++$states[$state];
|
||||
++$processes;
|
||||
}
|
||||
}
|
||||
|
||||
$statelist = "";
|
||||
$statelist = '';
|
||||
foreach ($states as $state => $usage) {
|
||||
if ($statelist != "") {
|
||||
$statelist .= ", ";
|
||||
if ($statelist != '') {
|
||||
$statelist .= ', ';
|
||||
}
|
||||
$statelist .= $state . ": " . $usage;
|
||||
$statelist .= $state . ': ' . $usage;
|
||||
}
|
||||
return (["list" => $statelist, "amount" => $processes]);
|
||||
return (['list' => $statelist, 'amount' => $processes]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch a database variable
|
||||
*
|
||||
* @param string $name
|
||||
* @return string content
|
||||
* @return string|null content or null if inexistent
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function getVariable(string $name)
|
||||
{
|
||||
|
@ -1739,10 +1765,9 @@ class Database
|
|||
* Checks if $array is a filled array with at least one entry.
|
||||
*
|
||||
* @param mixed $array A filled array with at least one entry
|
||||
*
|
||||
* @return boolean Whether $array is a filled array or an object with rows
|
||||
*/
|
||||
public function isResult($array)
|
||||
public function isResult($array): bool
|
||||
{
|
||||
// It could be a return value from an update statement
|
||||
if (is_bool($array)) {
|
||||
|
@ -1762,10 +1787,9 @@ class Database
|
|||
* @param mixed $value Array value
|
||||
* @param string $key Array key
|
||||
* @param boolean $add_quotation add quotation marks for string values
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private function escapeArrayCallback(&$value, $key, $add_quotation)
|
||||
private function escapeArrayCallback(&$value, string $key, bool $add_quotation)
|
||||
{
|
||||
if (!$add_quotation) {
|
||||
if (is_bool($value)) {
|
||||
|
@ -1790,10 +1814,9 @@ class Database
|
|||
*
|
||||
* @param mixed $arr Array with values to be escaped
|
||||
* @param boolean $add_quotation add quotation marks for string values
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function escapeArray(&$arr, $add_quotation = false)
|
||||
public function escapeArray(&$arr, bool $add_quotation = false)
|
||||
{
|
||||
array_walk($arr, [$this, 'escapeArrayCallback'], $add_quotation);
|
||||
}
|
||||
|
@ -1801,13 +1824,14 @@ class Database
|
|||
/**
|
||||
* Replaces a string in the provided fields of the provided table
|
||||
*
|
||||
* @param string $table_name
|
||||
* @param string $table Table name
|
||||
* @param array $fields List of field names in the provided table
|
||||
* @param string $search
|
||||
* @param string $replace
|
||||
* @param string $search String to search for
|
||||
* @param string $replace String to replace with
|
||||
* @return void
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function replaceInTableFields(string $table_name, array $fields, string $search, string $replace)
|
||||
public function replaceInTableFields(string $table, array $fields, string $search, string $replace)
|
||||
{
|
||||
$search = $this->escape($search);
|
||||
$replace = $this->escape($replace);
|
||||
|
@ -1820,9 +1844,10 @@ class Database
|
|||
|
||||
$upds = implode(', ', $upd);
|
||||
|
||||
$r = $this->e(sprintf("UPDATE %s SET %s;", $table_name, $upds));
|
||||
$r = $this->e(sprintf("UPDATE %s SET %s;", DBA::quoteIdentifier($table), $upds));
|
||||
|
||||
if (!$this->isResult($r)) {
|
||||
throw new \RuntimeException("Failed updating `$table_name`: " . $this->errorMessage());
|
||||
throw new \RuntimeException("Failed updating `$table`: " . $this->errorMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,126 @@
|
|||
<?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\Database\Definition;
|
||||
|
||||
use Exception;
|
||||
use Friendica\Core\Hook;
|
||||
|
||||
/**
|
||||
* Stores the whole database definition
|
||||
*/
|
||||
class DbaDefinition
|
||||
{
|
||||
/** @var string The relative path of the db structure config file */
|
||||
const DBSTRUCTURE_RELATIVE_PATH = '/static/dbstructure.config.php';
|
||||
|
||||
/** @var array The complete DB definition as an array */
|
||||
protected $definition;
|
||||
|
||||
/** @var string */
|
||||
protected $configFile;
|
||||
|
||||
/**
|
||||
* @param string $basePath The basepath of the dbstructure file (loads relative path in case of null)
|
||||
*
|
||||
* @throws Exception in case the config file isn't available/readable
|
||||
*/
|
||||
public function __construct(string $basePath)
|
||||
{
|
||||
$this->configFile = $basePath . static::DBSTRUCTURE_RELATIVE_PATH;
|
||||
|
||||
if (!is_readable($this->configFile)) {
|
||||
throw new Exception('Missing database structure config file static/dbstructure.config.php at basePath=' . $basePath);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array Returns the whole Definition as an array
|
||||
*/
|
||||
public function getAll(): array
|
||||
{
|
||||
return $this->definition;
|
||||
}
|
||||
|
||||
/**
|
||||
* Truncate field data for the given table
|
||||
*
|
||||
* @param string $table Name of the table to load field definitions for
|
||||
* @param array $data data fields
|
||||
*
|
||||
* @return array fields for the given
|
||||
*/
|
||||
public function truncateFieldsForTable(string $table, array $data): array
|
||||
{
|
||||
$definition = $this->definition;
|
||||
if (empty($definition[$table])) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$fieldNames = array_keys($definition[$table]['fields']);
|
||||
|
||||
$fields = [];
|
||||
|
||||
// Assign all field that are present in the table
|
||||
foreach ($fieldNames as $field) {
|
||||
if (isset($data[$field])) {
|
||||
// Limit the length of varchar, varbinary, char and binrary fields
|
||||
if (is_string($data[$field]) && preg_match("/char\((\d*)\)/", $definition[$table]['fields'][$field]['type'], $result)) {
|
||||
$data[$field] = mb_substr($data[$field], 0, $result[1]);
|
||||
} elseif (is_string($data[$field]) && preg_match("/binary\((\d*)\)/", $definition[$table]['fields'][$field]['type'], $result)) {
|
||||
$data[$field] = substr($data[$field], 0, $result[1]);
|
||||
}
|
||||
$fields[$field] = $data[$field];
|
||||
}
|
||||
}
|
||||
|
||||
return $fields;
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads the database structure definition from the static/dbstructure.config.php file.
|
||||
* On first pass, defines DB_UPDATE_VERSION constant.
|
||||
*
|
||||
* @param bool $withAddonStructure Whether to tack on addons additional tables
|
||||
*
|
||||
* @throws Exception in case the definition cannot be found
|
||||
*
|
||||
* @see static/dbstructure.config.php
|
||||
*
|
||||
* @return self The current instance
|
||||
*/
|
||||
public function load(bool $withAddonStructure = false): self
|
||||
{
|
||||
$definition = require $this->configFile;
|
||||
|
||||
if (!$definition) {
|
||||
throw new Exception('Corrupted database structure config file static/dbstructure.config.php');
|
||||
}
|
||||
|
||||
if ($withAddonStructure) {
|
||||
Hook::callAll('dbstructure_definition', $definition);
|
||||
}
|
||||
|
||||
$this->definition = $definition;
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,91 @@
|
|||
<?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\Database\Definition;
|
||||
|
||||
use Exception;
|
||||
use Friendica\Core\Hook;
|
||||
|
||||
/**
|
||||
* Stores the whole View definitions
|
||||
*/
|
||||
class ViewDefinition
|
||||
{
|
||||
/** @var string the relative path to the database view config file */
|
||||
const DBSTRUCTURE_RELATIVE_PATH = '/static/dbview.config.php';
|
||||
|
||||
/** @var array The complete view definition as an array */
|
||||
protected $definition;
|
||||
|
||||
/** @var string */
|
||||
protected $configFile;
|
||||
|
||||
/**
|
||||
* @param string $basePath The basepath of the dbview file (loads relative path in case of null)
|
||||
*
|
||||
* @throws Exception in case the config file isn't available/readable
|
||||
*/
|
||||
public function __construct(string $basePath)
|
||||
{
|
||||
$this->configFile = $basePath . static::DBSTRUCTURE_RELATIVE_PATH;
|
||||
|
||||
if (!is_readable($this->configFile)) {
|
||||
throw new Exception('Missing database structure config file static/dbview.config.php at basePath=' . $basePath);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array Returns the whole Definition as an array
|
||||
*/
|
||||
public function getAll(): array
|
||||
{
|
||||
return $this->definition;
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads the database structure definition from the static/dbview.config.php file.
|
||||
* On first pass, defines DB_UPDATE_VERSION constant.
|
||||
*
|
||||
* @param bool $withAddonStructure Whether to tack on addons additional tables
|
||||
*
|
||||
* @throws Exception in case the definition cannot be found
|
||||
*
|
||||
* @see static/dbview.config.php
|
||||
*
|
||||
* @return self The current instance
|
||||
*/
|
||||
public function load(bool $withAddonStructure = false): self
|
||||
{
|
||||
$definition = require $this->configFile;
|
||||
|
||||
if (!$definition) {
|
||||
throw new Exception('Corrupted database structure config file static/dbstructure.config.php');
|
||||
}
|
||||
|
||||
if ($withAddonStructure) {
|
||||
Hook::callAll('dbview_definition', $definition);
|
||||
}
|
||||
|
||||
$this->definition = $definition;
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
|
@ -133,7 +133,7 @@ class PostUpdate
|
|||
}
|
||||
|
||||
$max_item_delivery_data = DBA::selectFirst('item-delivery-data', ['iid'], ['queue_count > 0 OR queue_done > 0'], ['order' => ['iid']]);
|
||||
$max_iid = $max_item_delivery_data['iid'];
|
||||
$max_iid = $max_item_delivery_data['iid'] ?? 0;
|
||||
|
||||
Logger::info('Start update1297 with max iid: ' . $max_iid);
|
||||
|
||||
|
@ -538,7 +538,7 @@ class PostUpdate
|
|||
private static function update1347()
|
||||
{
|
||||
// Was the script completed?
|
||||
if (DI::config()->get("system", "post_update_version") >= 1347) {
|
||||
if (DI::config()->get('system', 'post_update_version') >= 1347) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -547,7 +547,7 @@ class PostUpdate
|
|||
return true;
|
||||
}
|
||||
|
||||
$id = DI::config()->get("system", "post_update_version_1347_id", 0);
|
||||
$id = DI::config()->get('system', 'post_update_version_1347_id', 0);
|
||||
|
||||
Logger::info('Start', ['item' => $id]);
|
||||
|
||||
|
@ -582,12 +582,12 @@ class PostUpdate
|
|||
}
|
||||
DBA::close($items);
|
||||
|
||||
DI::config()->set("system", "post_update_version_1347_id", $id);
|
||||
DI::config()->set('system', 'post_update_version_1347_id', $id);
|
||||
|
||||
Logger::info('Processed', ['rows' => $rows, 'last' => $id]);
|
||||
|
||||
if ($start_id == $id) {
|
||||
DI::config()->set("system", "post_update_version", 1347);
|
||||
DI::config()->set('system', 'post_update_version', 1347);
|
||||
Logger::info('Done');
|
||||
return true;
|
||||
}
|
||||
|
@ -605,11 +605,11 @@ class PostUpdate
|
|||
private static function update1348()
|
||||
{
|
||||
// Was the script completed?
|
||||
if (DI::config()->get("system", "post_update_version") >= 1348) {
|
||||
if (DI::config()->get('system', 'post_update_version') >= 1348) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$id = DI::config()->get("system", "post_update_version_1348_id", 0);
|
||||
$id = DI::config()->get('system', 'post_update_version_1348_id', 0);
|
||||
|
||||
Logger::info('Start', ['contact' => $id]);
|
||||
|
||||
|
@ -635,12 +635,12 @@ class PostUpdate
|
|||
}
|
||||
DBA::close($contacts);
|
||||
|
||||
DI::config()->set("system", "post_update_version_1348_id", $id);
|
||||
DI::config()->set('system', 'post_update_version_1348_id', $id);
|
||||
|
||||
Logger::info('Processed', ['rows' => $rows, 'last' => $id]);
|
||||
|
||||
if ($start_id == $id) {
|
||||
DI::config()->set("system", "post_update_version", 1348);
|
||||
DI::config()->set('system', 'post_update_version', 1348);
|
||||
Logger::info('Done');
|
||||
return true;
|
||||
}
|
||||
|
@ -658,11 +658,11 @@ class PostUpdate
|
|||
private static function update1349()
|
||||
{
|
||||
// Was the script completed?
|
||||
if (DI::config()->get("system", "post_update_version") >= 1349) {
|
||||
if (DI::config()->get('system', 'post_update_version') >= 1349) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$id = DI::config()->get("system", "post_update_version_1349_id", '');
|
||||
$id = DI::config()->get('system', 'post_update_version_1349_id', '');
|
||||
|
||||
Logger::info('Start', ['apcontact' => $id]);
|
||||
|
||||
|
@ -688,12 +688,12 @@ class PostUpdate
|
|||
}
|
||||
DBA::close($apcontacts);
|
||||
|
||||
DI::config()->set("system", "post_update_version_1349_id", $id);
|
||||
DI::config()->set('system', 'post_update_version_1349_id', $id);
|
||||
|
||||
Logger::info('Processed', ['rows' => $rows, 'last' => $id]);
|
||||
|
||||
if ($start_id == $id) {
|
||||
DI::config()->set("system", "post_update_version", 1349);
|
||||
DI::config()->set('system', 'post_update_version', 1349);
|
||||
Logger::info('Done');
|
||||
return true;
|
||||
}
|
||||
|
@ -711,7 +711,7 @@ class PostUpdate
|
|||
private static function update1383()
|
||||
{
|
||||
// Was the script completed?
|
||||
if (DI::config()->get("system", "post_update_version") >= 1383) {
|
||||
if (DI::config()->get('system', 'post_update_version') >= 1383) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -737,7 +737,7 @@ class PostUpdate
|
|||
}
|
||||
DBA::close($photos);
|
||||
|
||||
DI::config()->set("system", "post_update_version", 1383);
|
||||
DI::config()->set('system', 'post_update_version', 1383);
|
||||
Logger::info('Done', ['deleted' => $deleted]);
|
||||
return true;
|
||||
}
|
||||
|
@ -752,7 +752,7 @@ class PostUpdate
|
|||
private static function update1384()
|
||||
{
|
||||
// Was the script completed?
|
||||
if (DI::config()->get("system", "post_update_version") >= 1384) {
|
||||
if (DI::config()->get('system', 'post_update_version') >= 1384) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -782,7 +782,7 @@ class PostUpdate
|
|||
Logger::info('Processed', ['rows' => $rows]);
|
||||
|
||||
if ($rows <= 100) {
|
||||
DI::config()->set("system", "post_update_version", 1384);
|
||||
DI::config()->set('system', 'post_update_version', 1384);
|
||||
Logger::info('Done');
|
||||
return true;
|
||||
}
|
||||
|
@ -800,12 +800,12 @@ class PostUpdate
|
|||
private static function update1400()
|
||||
{
|
||||
// Was the script completed?
|
||||
if (DI::config()->get("system", "post_update_version") >= 1400) {
|
||||
if (DI::config()->get('system', 'post_update_version') >= 1400) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!DBStructure::existsTable('item')) {
|
||||
DI::config()->set("system", "post_update_version", 1400);
|
||||
DI::config()->set('system', 'post_update_version', 1400);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -829,7 +829,7 @@ class PostUpdate
|
|||
Logger::info('Processed', ['rows' => $rows]);
|
||||
|
||||
if ($rows <= 100) {
|
||||
DI::config()->set("system", "post_update_version", 1400);
|
||||
DI::config()->set('system', 'post_update_version', 1400);
|
||||
Logger::info('Done');
|
||||
return true;
|
||||
}
|
||||
|
@ -847,7 +847,7 @@ class PostUpdate
|
|||
private static function update1424()
|
||||
{
|
||||
// Was the script completed?
|
||||
if (DI::config()->get("system", "post_update_version") >= 1424) {
|
||||
if (DI::config()->get('system', 'post_update_version') >= 1424) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -871,7 +871,7 @@ class PostUpdate
|
|||
Logger::info('Processed', ['rows' => $rows]);
|
||||
|
||||
if ($rows <= 100) {
|
||||
DI::config()->set("system", "post_update_version", 1424);
|
||||
DI::config()->set('system', 'post_update_version', 1424);
|
||||
Logger::info('Done');
|
||||
return true;
|
||||
}
|
||||
|
@ -889,7 +889,7 @@ class PostUpdate
|
|||
private static function update1425()
|
||||
{
|
||||
// Was the script completed?
|
||||
if (DI::config()->get("system", "post_update_version") >= 1425) {
|
||||
if (DI::config()->get('system', 'post_update_version') >= 1425) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -918,7 +918,7 @@ class PostUpdate
|
|||
Logger::info('Processed', ['rows' => $rows]);
|
||||
|
||||
if ($rows <= 100) {
|
||||
DI::config()->set("system", "post_update_version", 1425);
|
||||
DI::config()->set('system', 'post_update_version', 1425);
|
||||
Logger::info('Done');
|
||||
return true;
|
||||
}
|
||||
|
@ -936,7 +936,7 @@ class PostUpdate
|
|||
private static function update1426()
|
||||
{
|
||||
// Was the script completed?
|
||||
if (DI::config()->get("system", "post_update_version") >= 1426) {
|
||||
if (DI::config()->get('system', 'post_update_version') >= 1426) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -965,7 +965,7 @@ class PostUpdate
|
|||
Logger::info('Processed', ['rows' => $rows]);
|
||||
|
||||
if ($rows <= 100) {
|
||||
DI::config()->set("system", "post_update_version", 1426);
|
||||
DI::config()->set('system', 'post_update_version', 1426);
|
||||
Logger::info('Done');
|
||||
return true;
|
||||
}
|
||||
|
@ -983,7 +983,7 @@ class PostUpdate
|
|||
private static function update1427()
|
||||
{
|
||||
// Was the script completed?
|
||||
if (DI::config()->get("system", "post_update_version") >= 1427) {
|
||||
if (DI::config()->get('system', 'post_update_version') >= 1427) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -1012,7 +1012,7 @@ class PostUpdate
|
|||
Logger::info('Processed', ['rows' => $rows]);
|
||||
|
||||
if ($rows <= 100) {
|
||||
DI::config()->set("system", "post_update_version", 1427);
|
||||
DI::config()->set('system', 'post_update_version', 1427);
|
||||
Logger::info('Done');
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -21,136 +21,44 @@
|
|||
|
||||
namespace Friendica\Database;
|
||||
|
||||
use Exception;
|
||||
use Friendica\Core\Hook;
|
||||
use Friendica\DI;
|
||||
use Friendica\Util\Writer\ViewDefinitionSqlWriter;
|
||||
|
||||
class View
|
||||
{
|
||||
/**
|
||||
* view definition loaded from static/dbview.config.php
|
||||
* Creates a view
|
||||
*
|
||||
* @var array
|
||||
* @param bool $verbose Whether to show SQL statements
|
||||
* @param bool $action Whether to execute SQL statements
|
||||
* @return void
|
||||
*/
|
||||
private static $definition = [];
|
||||
|
||||
/**
|
||||
* Loads the database structure definition from the static/dbview.config.php file.
|
||||
* On first pass, defines DB_UPDATE_VERSION constant.
|
||||
*
|
||||
* @see static/dbview.config.php
|
||||
* @param boolean $with_addons_structure Whether to tack on addons additional tables
|
||||
* @param string $basePath The base path of this application
|
||||
* @return array
|
||||
* @throws Exception
|
||||
*/
|
||||
public static function definition($basePath = '', $with_addons_structure = true)
|
||||
{
|
||||
if (!self::$definition) {
|
||||
if (empty($basePath)) {
|
||||
$basePath = DI::app()->getBasePath();
|
||||
}
|
||||
|
||||
$filename = $basePath . '/static/dbview.config.php';
|
||||
|
||||
if (!is_readable($filename)) {
|
||||
throw new Exception('Missing database view config file static/dbview.config.php');
|
||||
}
|
||||
|
||||
$definition = require $filename;
|
||||
|
||||
if (!$definition) {
|
||||
throw new Exception('Corrupted database view config file static/dbview.config.php');
|
||||
}
|
||||
|
||||
self::$definition = $definition;
|
||||
} else {
|
||||
$definition = self::$definition;
|
||||
}
|
||||
|
||||
if ($with_addons_structure) {
|
||||
Hook::callAll('dbview_definition', $definition);
|
||||
}
|
||||
|
||||
return $definition;
|
||||
}
|
||||
|
||||
public static function create(bool $verbose, bool $action)
|
||||
{
|
||||
// Delete previously used views that aren't used anymore
|
||||
foreach(['post-view', 'post-thread-view'] as $view) {
|
||||
foreach (['post-view', 'post-thread-view'] as $view) {
|
||||
if (self::isView($view)) {
|
||||
$sql = sprintf("DROP VIEW IF EXISTS `%s`", DBA::escape($view));
|
||||
if (!empty($sql) && $verbose) {
|
||||
echo $sql . ";\n";
|
||||
}
|
||||
|
||||
|
||||
if (!empty($sql) && $action) {
|
||||
DBA::e($sql);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$definition = self::definition();
|
||||
$definition = DI::viewDefinition()->getAll();
|
||||
|
||||
foreach ($definition as $name => $structure) {
|
||||
self::createview($name, $structure, $verbose, $action);
|
||||
}
|
||||
}
|
||||
|
||||
public static function printStructure($basePath)
|
||||
{
|
||||
$database = self::definition($basePath, false);
|
||||
|
||||
foreach ($database as $name => $structure) {
|
||||
echo "--\n";
|
||||
echo "-- VIEW $name\n";
|
||||
echo "--\n";
|
||||
self::createView($name, $structure, true, false);
|
||||
|
||||
echo "\n";
|
||||
}
|
||||
}
|
||||
|
||||
private static function createview($name, $structure, $verbose, $action)
|
||||
{
|
||||
$r = true;
|
||||
|
||||
$sql_rows = [];
|
||||
foreach ($structure["fields"] as $fieldname => $origin) {
|
||||
if (is_string($origin)) {
|
||||
$sql_rows[] = $origin . " AS `" . DBA::escape($fieldname) . "`";
|
||||
} elseif (is_array($origin) && (sizeof($origin) == 2)) {
|
||||
$sql_rows[] = "`" . DBA::escape($origin[0]) . "`.`" . DBA::escape($origin[1]) . "` AS `" . DBA::escape($fieldname) . "`";
|
||||
if (self::isView($name)) {
|
||||
DBA::e(sprintf("DROP VIEW IF EXISTS `%s`", DBA::escape($name)));
|
||||
} elseif (self::isTable($name)) {
|
||||
DBA::e(sprintf("DROP TABLE IF EXISTS `%s`", DBA::escape($name)));
|
||||
}
|
||||
DBA::e(ViewDefinitionSqlWriter::createView($name, $structure));
|
||||
}
|
||||
|
||||
if (self::isView($name)) {
|
||||
$sql = sprintf("DROP VIEW IF EXISTS `%s`", DBA::escape($name));
|
||||
} elseif (self::isTable($name)) {
|
||||
$sql = sprintf("DROP TABLE IF EXISTS `%s`", DBA::escape($name));
|
||||
}
|
||||
|
||||
if (!empty($sql) && $verbose) {
|
||||
echo $sql . ";\n";
|
||||
}
|
||||
|
||||
if (!empty($sql) && $action) {
|
||||
DBA::e($sql);
|
||||
}
|
||||
|
||||
$sql = sprintf("CREATE VIEW `%s` AS SELECT \n\t", DBA::escape($name)) .
|
||||
implode(",\n\t", $sql_rows) . "\n\t" . $structure['query'];
|
||||
|
||||
if ($verbose) {
|
||||
echo $sql . ";\n";
|
||||
}
|
||||
|
||||
if ($action) {
|
||||
$r = DBA::e($sql);
|
||||
}
|
||||
|
||||
return $r;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -159,9 +67,9 @@ class View
|
|||
* @param string $view
|
||||
* @return boolean "true" if it's a view
|
||||
*/
|
||||
private static function isView(string $view)
|
||||
private static function isView(string $view): bool
|
||||
{
|
||||
$status = DBA::selectFirst(['INFORMATION_SCHEMA' => 'TABLES'], ['TABLE_TYPE'],
|
||||
$status = DBA::selectFirst('INFORMATION_SCHEMA.TABLES', ['TABLE_TYPE'],
|
||||
['TABLE_SCHEMA' => DBA::databaseName(), 'TABLE_NAME' => $view]);
|
||||
|
||||
if (empty($status['TABLE_TYPE'])) {
|
||||
|
@ -177,9 +85,9 @@ class View
|
|||
* @param string $table
|
||||
* @return boolean "true" if it's a table
|
||||
*/
|
||||
private static function isTable(string $table)
|
||||
private static function isTable(string $table): bool
|
||||
{
|
||||
$status = DBA::selectFirst(['INFORMATION_SCHEMA' => 'TABLES'], ['TABLE_TYPE'],
|
||||
$status = DBA::selectFirst('INFORMATION_SCHEMA.TABLES', ['TABLE_TYPE'],
|
||||
['TABLE_SCHEMA' => DBA::databaseName(), 'TABLE_NAME' => $table]);
|
||||
|
||||
if (empty($status['TABLE_TYPE'])) {
|
||||
|
|
|
@ -57,12 +57,17 @@ class Account extends BaseFactory
|
|||
* @throws HTTPException\InternalServerErrorException
|
||||
* @throws ImagickException|HTTPException\NotFoundException
|
||||
*/
|
||||
public function createFromContactId(int $contactId, $uid = 0): \Friendica\Object\Api\Mastodon\Account
|
||||
public function createFromContactId(int $contactId, int $uid = 0): \Friendica\Object\Api\Mastodon\Account
|
||||
{
|
||||
$contact = Contact::getById($contactId, ['uri-id']);
|
||||
|
||||
if (empty($contact)) {
|
||||
throw new HTTPException\NotFoundException('Contact ' . $contactId . ' not found');
|
||||
}
|
||||
if (empty($contact['uri-id'])) {
|
||||
throw new HTTPException\NotFoundException('Contact ' . $contactId . ' has no uri-id set');
|
||||
}
|
||||
|
||||
return self::createFromUriId($contact['uri-id'], $uid);
|
||||
}
|
||||
|
||||
|
@ -74,7 +79,7 @@ class Account extends BaseFactory
|
|||
* @throws HTTPException\InternalServerErrorException
|
||||
* @throws ImagickException|HTTPException\NotFoundException
|
||||
*/
|
||||
public function createFromUriId(int $contactUriId, $uid = 0): \Friendica\Object\Api\Mastodon\Account
|
||||
public function createFromUriId(int $contactUriId, int $uid = 0): \Friendica\Object\Api\Mastodon\Account
|
||||
{
|
||||
$account = DBA::selectFirst('account-user-view', [], ['uri-id' => $contactUriId, 'uid' => [0, $uid]], ['order' => ['id' => true]]);
|
||||
if (empty($account)) {
|
||||
|
|
|
@ -190,7 +190,7 @@ class Status extends BaseFactory
|
|||
*/
|
||||
public function createFromMailId(int $id): \Friendica\Object\Api\Mastodon\Status
|
||||
{
|
||||
$item = ActivityPub\Transmitter::ItemArrayFromMail($id, true);
|
||||
$item = ActivityPub\Transmitter::getItemArrayFromMail($id, true);
|
||||
if (empty($item)) {
|
||||
$this->mstdnErrorFactory->RecordNotFound();
|
||||
}
|
||||
|
|
|
@ -70,6 +70,7 @@ class Status extends BaseFactory
|
|||
/**
|
||||
* @param int $uriId Uri-ID of the item
|
||||
* @param int $uid Item user
|
||||
* @param bool $include_entities Whether to include entities
|
||||
*
|
||||
* @return \Friendica\Object\Api\Twitter\Status
|
||||
* @throws HTTPException\InternalServerErrorException
|
||||
|
@ -90,12 +91,13 @@ class Status extends BaseFactory
|
|||
/**
|
||||
* @param int $uriId Uri-ID of the item
|
||||
* @param int $uid Item user
|
||||
* @param bool $include_entities Whether to include entities
|
||||
*
|
||||
* @return \Friendica\Object\Api\Twitter\Status
|
||||
* @throws HTTPException\InternalServerErrorException
|
||||
* @throws ImagickException|HTTPException\NotFoundException
|
||||
*/
|
||||
public function createFromUriId(int $uriId, $uid = 0, $include_entities = false): \Friendica\Object\Api\Twitter\Status
|
||||
public function createFromUriId(int $uriId, int $uid = 0, bool $include_entities = false): \Friendica\Object\Api\Twitter\Status
|
||||
{
|
||||
$fields = ['parent-uri-id', 'uri-id', 'uid', 'author-id', 'author-link', 'author-network', 'owner-id', 'causer-id',
|
||||
'starred', 'app', 'title', 'body', 'raw-body', 'created', 'network','post-reason', 'language', 'gravity',
|
||||
|
@ -110,6 +112,7 @@ class Status extends BaseFactory
|
|||
/**
|
||||
* @param array $item item array
|
||||
* @param int $uid Item user
|
||||
* @param bool $include_entities Whether to include entities
|
||||
*
|
||||
* @return \Friendica\Object\Api\Twitter\Status
|
||||
* @throws HTTPException\InternalServerErrorException
|
||||
|
|
|
@ -51,7 +51,7 @@ class User extends BaseFactory
|
|||
* @throws HTTPException\InternalServerErrorException
|
||||
* @throws \ImagickException
|
||||
*/
|
||||
public function createFromContactId(int $contactId, $uid = 0, $skip_status = true, $include_user_entities = true)
|
||||
public function createFromContactId(int $contactId, int $uid = 0, bool $skip_status = true, bool $include_user_entities = true)
|
||||
{
|
||||
$cdata = Contact::getPublicAndUserContactID($contactId, $uid);
|
||||
if (!empty($cdata)) {
|
||||
|
@ -78,7 +78,7 @@ class User extends BaseFactory
|
|||
return new \Friendica\Object\Api\Twitter\User($publicContact, $apcontact, $userContact, $status, $include_user_entities);
|
||||
}
|
||||
|
||||
public function createFromUserId(int $uid, $skip_status = true, $include_user_entities = true)
|
||||
public function createFromUserId(int $uid, bool $skip_status = true, bool $include_user_entities = true)
|
||||
{
|
||||
return $this->createFromContactId(Contact::getPublicIdByUserId($uid), $uid, $skip_status, $include_user_entities);
|
||||
}
|
||||
|
|
|
@ -57,7 +57,7 @@ class LegacyModule extends BaseModule
|
|||
* @param string $file_path
|
||||
* @throws \Exception
|
||||
*/
|
||||
private function setModuleFile($file_path)
|
||||
private function setModuleFile(string $file_path)
|
||||
{
|
||||
if (!is_readable($file_path)) {
|
||||
throw new \Exception(DI::l10n()->t('Legacy module file not found: %s', $file_path));
|
||||
|
@ -87,7 +87,7 @@ class LegacyModule extends BaseModule
|
|||
* @return string
|
||||
* @throws \Exception
|
||||
*/
|
||||
private function runModuleFunction(string $function_suffix)
|
||||
private function runModuleFunction(string $function_suffix): string
|
||||
{
|
||||
$function_name = $this->moduleName . '_' . $function_suffix;
|
||||
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user