Reworked profile field handling.
This commit is contained in:
parent
a3bb615f0d
commit
fe1562fd86
15 changed files with 676 additions and 537 deletions
268
composer.lock
generated
268
composer.lock
generated
|
@ -8,26 +8,30 @@
|
|||
"packages": [
|
||||
{
|
||||
"name": "chillerlan/php-qrcode",
|
||||
"version": "3.1.0",
|
||||
"version": "3.1.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/chillerlan/php-qrcode.git",
|
||||
"reference": "71368715f54bb9012b25634b510d938af7b04cc9"
|
||||
"reference": "8d20f2bfc65543a551f306ba00d465f7d7910d14"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/chillerlan/php-qrcode/zipball/71368715f54bb9012b25634b510d938af7b04cc9",
|
||||
"reference": "71368715f54bb9012b25634b510d938af7b04cc9",
|
||||
"url": "https://api.github.com/repos/chillerlan/php-qrcode/zipball/8d20f2bfc65543a551f306ba00d465f7d7910d14",
|
||||
"reference": "8d20f2bfc65543a551f306ba00d465f7d7910d14",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"chillerlan/php-settings-container": "^1.0",
|
||||
"chillerlan/php-settings-container": "^1.1",
|
||||
"ext-gd": "*",
|
||||
"ext-json": "*",
|
||||
"ext-mbstring": "*",
|
||||
"php": "^7.2"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^8.0"
|
||||
"phpunit/phpunit": "^8.3"
|
||||
},
|
||||
"suggest": {
|
||||
"chillerlan/php-authenticator": "Yet another Google authenticator! Also creates URIs for mobile apps."
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
|
@ -50,7 +54,7 @@
|
|||
"homepage": "https://github.com/kazuhikoarase"
|
||||
},
|
||||
{
|
||||
"name": "smiley",
|
||||
"name": "Smiley",
|
||||
"email": "smiley@chillerlan.net",
|
||||
"homepage": "https://github.com/codemasher"
|
||||
},
|
||||
|
@ -68,20 +72,20 @@
|
|||
"qrcode",
|
||||
"qrcode-generator"
|
||||
],
|
||||
"time": "2019-04-19T15:51:02+00:00"
|
||||
"time": "2019-08-09T20:45:07+00:00"
|
||||
},
|
||||
{
|
||||
"name": "chillerlan/php-settings-container",
|
||||
"version": "1.1.0",
|
||||
"version": "1.2.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/chillerlan/php-settings-container.git",
|
||||
"reference": "bab35c989468069fb6ee196925c98f8d3b53f407"
|
||||
"reference": "b9b0431dffd74102ee92348a63b4c33fc8ba639b"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/chillerlan/php-settings-container/zipball/bab35c989468069fb6ee196925c98f8d3b53f407",
|
||||
"reference": "bab35c989468069fb6ee196925c98f8d3b53f407",
|
||||
"url": "https://api.github.com/repos/chillerlan/php-settings-container/zipball/b9b0431dffd74102ee92348a63b4c33fc8ba639b",
|
||||
"reference": "b9b0431dffd74102ee92348a63b4c33fc8ba639b",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -89,7 +93,7 @@
|
|||
"php": "^7.2"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^8.1"
|
||||
"phpunit/phpunit": "^8.3"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
|
@ -103,7 +107,7 @@
|
|||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "smiley",
|
||||
"name": "Smiley",
|
||||
"email": "smiley@chillerlan.net",
|
||||
"homepage": "https://github.com/codemasher"
|
||||
}
|
||||
|
@ -116,29 +120,29 @@
|
|||
"container",
|
||||
"helper"
|
||||
],
|
||||
"time": "2019-05-04T21:53:59+00:00"
|
||||
"time": "2019-09-10T00:09:44+00:00"
|
||||
},
|
||||
{
|
||||
"name": "composer/ca-bundle",
|
||||
"version": "1.1.4",
|
||||
"version": "1.2.4",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/composer/ca-bundle.git",
|
||||
"reference": "558f321c52faeb4828c03e7dc0cfe39a09e09a2d"
|
||||
"reference": "10bb96592168a0f8e8f6dcde3532d9fa50b0b527"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/composer/ca-bundle/zipball/558f321c52faeb4828c03e7dc0cfe39a09e09a2d",
|
||||
"reference": "558f321c52faeb4828c03e7dc0cfe39a09e09a2d",
|
||||
"url": "https://api.github.com/repos/composer/ca-bundle/zipball/10bb96592168a0f8e8f6dcde3532d9fa50b0b527",
|
||||
"reference": "10bb96592168a0f8e8f6dcde3532d9fa50b0b527",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"ext-openssl": "*",
|
||||
"ext-pcre": "*",
|
||||
"php": "^5.3.2 || ^7.0"
|
||||
"php": "^5.3.2 || ^7.0 || ^8.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.5",
|
||||
"phpunit/phpunit": "^4.8.35 || ^5.7 || 6.5 - 8",
|
||||
"psr/log": "^1.0",
|
||||
"symfony/process": "^2.5 || ^3.0 || ^4.0"
|
||||
},
|
||||
|
@ -172,20 +176,20 @@
|
|||
"ssl",
|
||||
"tls"
|
||||
],
|
||||
"time": "2019-01-28T09:30:10+00:00"
|
||||
"time": "2019-08-30T08:44:50+00:00"
|
||||
},
|
||||
{
|
||||
"name": "composer/installers",
|
||||
"version": "v1.6.0",
|
||||
"version": "v1.7.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/composer/installers.git",
|
||||
"reference": "cfcca6b1b60bc4974324efb5783c13dca6932b5b"
|
||||
"reference": "141b272484481432cda342727a427dc1e206bfa0"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/composer/installers/zipball/cfcca6b1b60bc4974324efb5783c13dca6932b5b",
|
||||
"reference": "cfcca6b1b60bc4974324efb5783c13dca6932b5b",
|
||||
"url": "https://api.github.com/repos/composer/installers/zipball/141b272484481432cda342727a427dc1e206bfa0",
|
||||
"reference": "141b272484481432cda342727a427dc1e206bfa0",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -241,6 +245,7 @@
|
|||
"RadPHP",
|
||||
"SMF",
|
||||
"Thelia",
|
||||
"Whmcs",
|
||||
"WolfCMS",
|
||||
"agl",
|
||||
"aimeos",
|
||||
|
@ -263,6 +268,7 @@
|
|||
"installer",
|
||||
"itop",
|
||||
"joomla",
|
||||
"known",
|
||||
"kohana",
|
||||
"laravel",
|
||||
"lavalite",
|
||||
|
@ -292,34 +298,39 @@
|
|||
"zend",
|
||||
"zikula"
|
||||
],
|
||||
"time": "2018-08-27T06:10:37+00:00"
|
||||
"time": "2019-08-12T15:00:31+00:00"
|
||||
},
|
||||
{
|
||||
"name": "doctrine/lexer",
|
||||
"version": "v1.0.1",
|
||||
"version": "1.2.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/doctrine/lexer.git",
|
||||
"reference": "83893c552fd2045dd78aef794c31e694c37c0b8c"
|
||||
"reference": "5242d66dbeb21a30dd8a3e66bf7a73b66e05e1f6"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/doctrine/lexer/zipball/83893c552fd2045dd78aef794c31e694c37c0b8c",
|
||||
"reference": "83893c552fd2045dd78aef794c31e694c37c0b8c",
|
||||
"url": "https://api.github.com/repos/doctrine/lexer/zipball/5242d66dbeb21a30dd8a3e66bf7a73b66e05e1f6",
|
||||
"reference": "5242d66dbeb21a30dd8a3e66bf7a73b66e05e1f6",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.3.2"
|
||||
"php": "^7.2"
|
||||
},
|
||||
"require-dev": {
|
||||
"doctrine/coding-standard": "^6.0",
|
||||
"phpstan/phpstan": "^0.11.8",
|
||||
"phpunit/phpunit": "^8.2"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "1.0.x-dev"
|
||||
"dev-master": "1.2.x-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-0": {
|
||||
"Doctrine\\Common\\Lexer\\": "lib/"
|
||||
"psr-4": {
|
||||
"Doctrine\\Common\\Lexer\\": "lib/Doctrine/Common/Lexer"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
|
@ -327,39 +338,42 @@
|
|||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Roman Borschel",
|
||||
"email": "roman@code-factory.org"
|
||||
},
|
||||
{
|
||||
"name": "Guilherme Blanco",
|
||||
"email": "guilhermeblanco@gmail.com"
|
||||
},
|
||||
{
|
||||
"name": "Roman Borschel",
|
||||
"email": "roman@code-factory.org"
|
||||
},
|
||||
{
|
||||
"name": "Johannes Schmitt",
|
||||
"email": "schmittjoh@gmail.com"
|
||||
}
|
||||
],
|
||||
"description": "Base library for a lexer that can be used in Top-Down, Recursive Descent Parsers.",
|
||||
"homepage": "http://www.doctrine-project.org",
|
||||
"description": "PHP Doctrine Lexer parser library that can be used in Top-Down, Recursive Descent Parsers.",
|
||||
"homepage": "https://www.doctrine-project.org/projects/lexer.html",
|
||||
"keywords": [
|
||||
"annotations",
|
||||
"docblock",
|
||||
"lexer",
|
||||
"parser"
|
||||
"parser",
|
||||
"php"
|
||||
],
|
||||
"time": "2014-09-09T13:34:57+00:00"
|
||||
"time": "2019-10-30T14:39:59+00:00"
|
||||
},
|
||||
{
|
||||
"name": "egulias/email-validator",
|
||||
"version": "2.1.7",
|
||||
"version": "2.1.11",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/egulias/EmailValidator.git",
|
||||
"reference": "709f21f92707308cdf8f9bcfa1af4cb26586521e"
|
||||
"reference": "92dd169c32f6f55ba570c309d83f5209cefb5e23"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/egulias/EmailValidator/zipball/709f21f92707308cdf8f9bcfa1af4cb26586521e",
|
||||
"reference": "709f21f92707308cdf8f9bcfa1af4cb26586521e",
|
||||
"url": "https://api.github.com/repos/egulias/EmailValidator/zipball/92dd169c32f6f55ba570c309d83f5209cefb5e23",
|
||||
"reference": "92dd169c32f6f55ba570c309d83f5209cefb5e23",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -369,7 +383,8 @@
|
|||
"require-dev": {
|
||||
"dominicsayers/isemail": "dev-master",
|
||||
"phpunit/phpunit": "^4.8.35||^5.7||^6.0",
|
||||
"satooshi/php-coveralls": "^1.0.1"
|
||||
"satooshi/php-coveralls": "^1.0.1",
|
||||
"symfony/phpunit-bridge": "^4.4@dev"
|
||||
},
|
||||
"suggest": {
|
||||
"ext-intl": "PHP Internationalization Libraries are required to use the SpoofChecking validation"
|
||||
|
@ -377,7 +392,7 @@
|
|||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "2.0.x-dev"
|
||||
"dev-master": "2.1.x-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
|
@ -403,7 +418,7 @@
|
|||
"validation",
|
||||
"validator"
|
||||
],
|
||||
"time": "2018-12-04T22:38:24+00:00"
|
||||
"time": "2019-08-13T17:33:27+00:00"
|
||||
},
|
||||
{
|
||||
"name": "erusev/parsedown",
|
||||
|
@ -453,16 +468,16 @@
|
|||
},
|
||||
{
|
||||
"name": "filp/whoops",
|
||||
"version": "2.3.1",
|
||||
"version": "2.5.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/filp/whoops.git",
|
||||
"reference": "bc0fd11bc455cc20ee4b5edabc63ebbf859324c7"
|
||||
"reference": "cde50e6720a39fdacb240159d3eea6865d51fd96"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/filp/whoops/zipball/bc0fd11bc455cc20ee4b5edabc63ebbf859324c7",
|
||||
"reference": "bc0fd11bc455cc20ee4b5edabc63ebbf859324c7",
|
||||
"url": "https://api.github.com/repos/filp/whoops/zipball/cde50e6720a39fdacb240159d3eea6865d51fd96",
|
||||
"reference": "cde50e6720a39fdacb240159d3eea6865d51fd96",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -510,7 +525,7 @@
|
|||
"throwable",
|
||||
"whoops"
|
||||
],
|
||||
"time": "2018-10-23T09:00:00+00:00"
|
||||
"time": "2019-08-07T09:00:00+00:00"
|
||||
},
|
||||
{
|
||||
"name": "geoip2/geoip2",
|
||||
|
@ -625,25 +640,26 @@
|
|||
},
|
||||
{
|
||||
"name": "maxmind-db/reader",
|
||||
"version": "v1.4.1",
|
||||
"version": "v1.5.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/maxmind/MaxMind-DB-Reader-php.git",
|
||||
"reference": "eb83d0ee1c1f9b8a340206302136bc81ee02ae74"
|
||||
"reference": "bd436094fc0a9b0558a899fb80b0ae34fe1808a0"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/maxmind/MaxMind-DB-Reader-php/zipball/eb83d0ee1c1f9b8a340206302136bc81ee02ae74",
|
||||
"reference": "eb83d0ee1c1f9b8a340206302136bc81ee02ae74",
|
||||
"url": "https://api.github.com/repos/maxmind/MaxMind-DB-Reader-php/zipball/bd436094fc0a9b0558a899fb80b0ae34fe1808a0",
|
||||
"reference": "bd436094fc0a9b0558a899fb80b0ae34fe1808a0",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.4"
|
||||
"php": ">=5.6"
|
||||
},
|
||||
"require-dev": {
|
||||
"friendsofphp/php-cs-fixer": "2.*",
|
||||
"phpunit/phpunit": "4.* || 5.*",
|
||||
"satooshi/php-coveralls": "1.0.*",
|
||||
"php-coveralls/php-coveralls": "^2.1",
|
||||
"phpunit/phpcov": "^3.0",
|
||||
"phpunit/phpunit": "5.*",
|
||||
"squizlabs/php_codesniffer": "3.*"
|
||||
},
|
||||
"suggest": {
|
||||
|
@ -665,7 +681,7 @@
|
|||
{
|
||||
"name": "Gregory J. Oschwald",
|
||||
"email": "goschwald@maxmind.com",
|
||||
"homepage": "http://www.maxmind.com/"
|
||||
"homepage": "https://www.maxmind.com/"
|
||||
}
|
||||
],
|
||||
"description": "MaxMind DB Reader API",
|
||||
|
@ -677,7 +693,7 @@
|
|||
"geolocation",
|
||||
"maxmind"
|
||||
],
|
||||
"time": "2019-01-04T19:55:56+00:00"
|
||||
"time": "2019-09-30T22:56:38+00:00"
|
||||
},
|
||||
{
|
||||
"name": "maxmind/web-service-common",
|
||||
|
@ -727,16 +743,16 @@
|
|||
},
|
||||
{
|
||||
"name": "psr/log",
|
||||
"version": "1.1.0",
|
||||
"version": "1.1.2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/php-fig/log.git",
|
||||
"reference": "6c001f1daafa3a3ac1d8ff69ee4db8e799a654dd"
|
||||
"reference": "446d54b4cb6bf489fc9d75f55843658e6f25d801"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/php-fig/log/zipball/6c001f1daafa3a3ac1d8ff69ee4db8e799a654dd",
|
||||
"reference": "6c001f1daafa3a3ac1d8ff69ee4db8e799a654dd",
|
||||
"url": "https://api.github.com/repos/php-fig/log/zipball/446d54b4cb6bf489fc9d75f55843658e6f25d801",
|
||||
"reference": "446d54b4cb6bf489fc9d75f55843658e6f25d801",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -745,7 +761,7 @@
|
|||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "1.0.x-dev"
|
||||
"dev-master": "1.1.x-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
|
@ -770,20 +786,20 @@
|
|||
"psr",
|
||||
"psr-3"
|
||||
],
|
||||
"time": "2018-11-20T15:27:04+00:00"
|
||||
"time": "2019-11-01T11:05:21+00:00"
|
||||
},
|
||||
{
|
||||
"name": "swiftmailer/swiftmailer",
|
||||
"version": "v6.2.1",
|
||||
"version": "v6.2.3",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/swiftmailer/swiftmailer.git",
|
||||
"reference": "5397cd05b0a0f7937c47b0adcb4c60e5ab936b6a"
|
||||
"reference": "149cfdf118b169f7840bbe3ef0d4bc795d1780c9"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/swiftmailer/swiftmailer/zipball/5397cd05b0a0f7937c47b0adcb4c60e5ab936b6a",
|
||||
"reference": "5397cd05b0a0f7937c47b0adcb4c60e5ab936b6a",
|
||||
"url": "https://api.github.com/repos/swiftmailer/swiftmailer/zipball/149cfdf118b169f7840bbe3ef0d4bc795d1780c9",
|
||||
"reference": "149cfdf118b169f7840bbe3ef0d4bc795d1780c9",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -832,20 +848,20 @@
|
|||
"mail",
|
||||
"mailer"
|
||||
],
|
||||
"time": "2019-04-21T09:21:45+00:00"
|
||||
"time": "2019-11-12T09:31:26+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/polyfill-ctype",
|
||||
"version": "v1.11.0",
|
||||
"version": "v1.13.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/polyfill-ctype.git",
|
||||
"reference": "82ebae02209c21113908c229e9883c419720738a"
|
||||
"reference": "f8f0b461be3385e56d6de3dbb5a0df24c0c275e3"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/82ebae02209c21113908c229e9883c419720738a",
|
||||
"reference": "82ebae02209c21113908c229e9883c419720738a",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/f8f0b461be3385e56d6de3dbb5a0df24c0c275e3",
|
||||
"reference": "f8f0b461be3385e56d6de3dbb5a0df24c0c275e3",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -857,7 +873,7 @@
|
|||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "1.11-dev"
|
||||
"dev-master": "1.13-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
|
@ -874,12 +890,12 @@
|
|||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Symfony Community",
|
||||
"homepage": "https://symfony.com/contributors"
|
||||
"name": "Gert de Pagter",
|
||||
"email": "BackEndTea@gmail.com"
|
||||
},
|
||||
{
|
||||
"name": "Gert de Pagter",
|
||||
"email": "backendtea@gmail.com"
|
||||
"name": "Symfony Community",
|
||||
"homepage": "https://symfony.com/contributors"
|
||||
}
|
||||
],
|
||||
"description": "Symfony polyfill for ctype functions",
|
||||
|
@ -890,20 +906,20 @@
|
|||
"polyfill",
|
||||
"portable"
|
||||
],
|
||||
"time": "2019-02-06T07:57:58+00:00"
|
||||
"time": "2019-11-27T13:56:44+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/polyfill-iconv",
|
||||
"version": "v1.11.0",
|
||||
"version": "v1.13.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/polyfill-iconv.git",
|
||||
"reference": "f037ea22acfaee983e271dd9c3b8bb4150bd8ad7"
|
||||
"reference": "a019efccc03f1a335af6b4f20c30f5ea8060be36"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-iconv/zipball/f037ea22acfaee983e271dd9c3b8bb4150bd8ad7",
|
||||
"reference": "f037ea22acfaee983e271dd9c3b8bb4150bd8ad7",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-iconv/zipball/a019efccc03f1a335af6b4f20c30f5ea8060be36",
|
||||
"reference": "a019efccc03f1a335af6b4f20c30f5ea8060be36",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -915,7 +931,7 @@
|
|||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "1.11-dev"
|
||||
"dev-master": "1.13-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
|
@ -949,20 +965,20 @@
|
|||
"portable",
|
||||
"shim"
|
||||
],
|
||||
"time": "2019-02-06T07:57:58+00:00"
|
||||
"time": "2019-11-27T13:56:44+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/polyfill-intl-idn",
|
||||
"version": "v1.11.0",
|
||||
"version": "v1.13.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/polyfill-intl-idn.git",
|
||||
"reference": "c766e95bec706cdd89903b1eda8afab7d7a6b7af"
|
||||
"reference": "6f9c239e61e1b0c9229a28ff89a812dc449c3d46"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-intl-idn/zipball/c766e95bec706cdd89903b1eda8afab7d7a6b7af",
|
||||
"reference": "c766e95bec706cdd89903b1eda8afab7d7a6b7af",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-intl-idn/zipball/6f9c239e61e1b0c9229a28ff89a812dc449c3d46",
|
||||
"reference": "6f9c239e61e1b0c9229a28ff89a812dc449c3d46",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -976,7 +992,7 @@
|
|||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "1.9-dev"
|
||||
"dev-master": "1.13-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
|
@ -992,13 +1008,13 @@
|
|||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Symfony Community",
|
||||
"homepage": "https://symfony.com/contributors"
|
||||
},
|
||||
{
|
||||
"name": "Laurent Bassin",
|
||||
"email": "laurent@bassin.info"
|
||||
},
|
||||
{
|
||||
"name": "Symfony Community",
|
||||
"homepage": "https://symfony.com/contributors"
|
||||
}
|
||||
],
|
||||
"description": "Symfony polyfill for intl's idn_to_ascii and idn_to_utf8 functions",
|
||||
|
@ -1011,20 +1027,20 @@
|
|||
"portable",
|
||||
"shim"
|
||||
],
|
||||
"time": "2019-03-04T13:44:35+00:00"
|
||||
"time": "2019-11-27T13:56:44+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/polyfill-mbstring",
|
||||
"version": "v1.11.0",
|
||||
"version": "v1.13.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/polyfill-mbstring.git",
|
||||
"reference": "fe5e94c604826c35a32fa832f35bd036b6799609"
|
||||
"reference": "7b4aab9743c30be783b73de055d24a39cf4b954f"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/fe5e94c604826c35a32fa832f35bd036b6799609",
|
||||
"reference": "fe5e94c604826c35a32fa832f35bd036b6799609",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/7b4aab9743c30be783b73de055d24a39cf4b954f",
|
||||
"reference": "7b4aab9743c30be783b73de055d24a39cf4b954f",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -1036,7 +1052,7 @@
|
|||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "1.11-dev"
|
||||
"dev-master": "1.13-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
|
@ -1070,20 +1086,20 @@
|
|||
"portable",
|
||||
"shim"
|
||||
],
|
||||
"time": "2019-02-06T07:57:58+00:00"
|
||||
"time": "2019-11-27T14:18:11+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/polyfill-php72",
|
||||
"version": "v1.11.0",
|
||||
"version": "v1.13.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/polyfill-php72.git",
|
||||
"reference": "ab50dcf166d5f577978419edd37aa2bb8eabce0c"
|
||||
"reference": "66fea50f6cb37a35eea048d75a7d99a45b586038"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-php72/zipball/ab50dcf166d5f577978419edd37aa2bb8eabce0c",
|
||||
"reference": "ab50dcf166d5f577978419edd37aa2bb8eabce0c",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-php72/zipball/66fea50f6cb37a35eea048d75a7d99a45b586038",
|
||||
"reference": "66fea50f6cb37a35eea048d75a7d99a45b586038",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -1092,7 +1108,7 @@
|
|||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "1.11-dev"
|
||||
"dev-master": "1.13-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
|
@ -1125,7 +1141,7 @@
|
|||
"portable",
|
||||
"shim"
|
||||
],
|
||||
"time": "2019-02-06T07:57:58+00:00"
|
||||
"time": "2019-11-27T13:56:44+00:00"
|
||||
},
|
||||
{
|
||||
"name": "twig/extensions",
|
||||
|
@ -1184,16 +1200,16 @@
|
|||
},
|
||||
{
|
||||
"name": "twig/twig",
|
||||
"version": "v2.9.0",
|
||||
"version": "v2.12.2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/twigphp/Twig.git",
|
||||
"reference": "82a1c055c8ed4c4705023bfd0405f3c74db6e3ae"
|
||||
"reference": "d761fd1f1c6b867ae09a7d8119a6d95d06dc44ed"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/twigphp/Twig/zipball/82a1c055c8ed4c4705023bfd0405f3c74db6e3ae",
|
||||
"reference": "82a1c055c8ed4c4705023bfd0405f3c74db6e3ae",
|
||||
"url": "https://api.github.com/repos/twigphp/Twig/zipball/d761fd1f1c6b867ae09a7d8119a6d95d06dc44ed",
|
||||
"reference": "d761fd1f1c6b867ae09a7d8119a6d95d06dc44ed",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -1203,13 +1219,13 @@
|
|||
},
|
||||
"require-dev": {
|
||||
"psr/container": "^1.0",
|
||||
"symfony/debug": "^2.7",
|
||||
"symfony/phpunit-bridge": "^3.4.19|^4.1.8"
|
||||
"symfony/debug": "^3.4|^4.2",
|
||||
"symfony/phpunit-bridge": "^4.4@dev|^5.0"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "2.9-dev"
|
||||
"dev-master": "2.12-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
|
@ -1231,15 +1247,15 @@
|
|||
"homepage": "http://fabien.potencier.org",
|
||||
"role": "Lead Developer"
|
||||
},
|
||||
{
|
||||
"name": "Armin Ronacher",
|
||||
"email": "armin.ronacher@active-4.com",
|
||||
"role": "Project Founder"
|
||||
},
|
||||
{
|
||||
"name": "Twig Team",
|
||||
"homepage": "https://twig.symfony.com/contributors",
|
||||
"role": "Contributors"
|
||||
},
|
||||
{
|
||||
"name": "Armin Ronacher",
|
||||
"email": "armin.ronacher@active-4.com",
|
||||
"role": "Project Founder"
|
||||
}
|
||||
],
|
||||
"description": "Twig, the flexible, fast, and secure template language for PHP",
|
||||
|
@ -1247,7 +1263,7 @@
|
|||
"keywords": [
|
||||
"templating"
|
||||
],
|
||||
"time": "2019-04-28T06:57:38+00:00"
|
||||
"time": "2019-11-11T16:52:09+00:00"
|
||||
}
|
||||
],
|
||||
"packages-dev": [],
|
||||
|
|
197
database/2019_10_01_181738_profile_fields_in_database.php
Normal file
197
database/2019_10_01_181738_profile_fields_in_database.php
Normal file
|
@ -0,0 +1,197 @@
|
|||
<?php
|
||||
namespace Misuzu\DatabaseMigrations\ProfileFieldsInDatabase;
|
||||
|
||||
use PDO;
|
||||
|
||||
function migrate_up(PDO $conn): void {
|
||||
$conn->exec("
|
||||
CREATE TABLE `msz_profile_fields` (
|
||||
`field_id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||
`field_order` INT(11) NOT NULL DEFAULT 0,
|
||||
`field_key` VARCHAR(50) NOT NULL COLLATE 'utf8mb4_general_ci',
|
||||
`field_title` VARCHAR(50) NOT NULL COLLATE 'utf8mb4_bin',
|
||||
`field_regex` VARCHAR(255) NOT NULL COLLATE 'utf8mb4_bin',
|
||||
PRIMARY KEY (`field_id`),
|
||||
UNIQUE INDEX `profile_fields_key_unique` (`field_key`),
|
||||
INDEX `profile_fields_order_key` (`field_order`)
|
||||
) COLLATE='utf8mb4_bin' ENGINE=InnoDB;
|
||||
");
|
||||
|
||||
$conn->exec("
|
||||
CREATE TABLE `msz_profile_fields_formats` (
|
||||
`format_id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||
`field_id` INT(10) UNSIGNED NOT NULL DEFAULT 0,
|
||||
`format_regex` VARCHAR(255) NULL DEFAULT NULL COLLATE 'utf8mb4_bin',
|
||||
`format_link` VARCHAR(255) NULL DEFAULT NULL COLLATE 'utf8mb4_bin',
|
||||
`format_display` VARCHAR(255) NOT NULL DEFAULT '%s' COLLATE 'utf8mb4_bin',
|
||||
PRIMARY KEY (`format_id`),
|
||||
INDEX `profile_field_format_field_foreign` (`field_id`),
|
||||
CONSTRAINT `profile_field_format_field_foreign`
|
||||
FOREIGN KEY (`field_id`)
|
||||
REFERENCES `msz_profile_fields` (`field_id`)
|
||||
ON UPDATE CASCADE
|
||||
ON DELETE CASCADE
|
||||
) COLLATE='utf8mb4_bin' ENGINE=InnoDB;
|
||||
");
|
||||
|
||||
$conn->exec("
|
||||
CREATE TABLE `msz_profile_fields_values` (
|
||||
`field_id` INT(10) UNSIGNED NOT NULL,
|
||||
`user_id` INT(10) UNSIGNED NOT NULL,
|
||||
`format_id` INT(10) UNSIGNED NOT NULL,
|
||||
`field_value` VARCHAR(255) NOT NULL COLLATE 'utf8mb4_bin',
|
||||
PRIMARY KEY (`field_id`, `user_id`),
|
||||
INDEX `profile_fields_values_format_foreign` (`format_id`),
|
||||
INDEX `profile_fields_values_user_foreign` (`user_id`),
|
||||
INDEX `profile_fields_values_value_key` (`field_value`),
|
||||
CONSTRAINT `profile_fields_values_field_foreign`
|
||||
FOREIGN KEY (`field_id`)
|
||||
REFERENCES `msz_profile_fields` (`field_id`)
|
||||
ON UPDATE CASCADE
|
||||
ON DELETE CASCADE,
|
||||
CONSTRAINT `profile_fields_values_format_foreign`
|
||||
FOREIGN KEY (`format_id`)
|
||||
REFERENCES `msz_profile_fields_formats` (`format_id`)
|
||||
ON UPDATE CASCADE
|
||||
ON DELETE CASCADE,
|
||||
CONSTRAINT `profile_fields_values_user_foreign`
|
||||
FOREIGN KEY (`user_id`)
|
||||
REFERENCES `msz_users` (`user_id`)
|
||||
ON UPDATE CASCADE
|
||||
ON DELETE CASCADE
|
||||
) COLLATE='utf8mb4_bin' ENGINE=InnoDB;
|
||||
");
|
||||
|
||||
$fieldIds = [];
|
||||
$fields = [
|
||||
['order' => 10, 'key' => 'website', 'title' => 'Website', 'regex' => '#^((?:https?)://.{1,240})$#u'],
|
||||
['order' => 20, 'key' => 'youtube', 'title' => 'Youtube', 'regex' => '#^(?:https?://(?:www.)?youtube.com/(?:(?:user|c|channel)/)?)?(UC[a-zA-Z0-9-_]{1,22}|[a-zA-Z0-9-_%]{1,100})/?$#u'],
|
||||
['order' => 30, 'key' => 'twitter', 'title' => 'Twitter', 'regex' => '#^(?:https?://(?:www\.)?twitter.com/(?:\#!\/)?)?@?([A-Za-z0-9_]{1,20})/?$#u'],
|
||||
['order' => 40, 'key' => 'ninswitch', 'title' => 'Nintendo Switch', 'regex' => '#^(?:SW-)?([0-9]{4}-[0-9]{4}-[0-9]{4})$#u'],
|
||||
['order' => 50, 'key' => 'twitchtv', 'title' => 'Twitch.tv', 'regex' => '#^(?:https?://(?:www.)?twitch.tv/)?([0-9A-Za-z_]{3,25})/?$#u'],
|
||||
['order' => 60, 'key' => 'steam', 'title' => 'Steam', 'regex' => '#^(?:https?://(?:www.)?steamcommunity.com/(?:id|profiles)/)?([a-zA-Z0-9_-]{2,100})/?$#u'],
|
||||
['order' => 70, 'key' => 'osu', 'title' => 'osu!', 'regex' => '#^(?:https?://osu.ppy.sh/u(?:sers)?/)?([a-zA-Z0-9-\[\]_ ]{1,20})/?$#u'],
|
||||
['order' => 80, 'key' => 'lastfm', 'title' => 'Last.fm', 'regex' => '#^(?:https?://(?:www.)?last.fm/user/)?([a-zA-Z]{1}[a-zA-Z0-9_-]{1,14})/?$#u'],
|
||||
['order' => 90, 'key' => 'github', 'title' => 'Github', 'regex' => '#^(?:https?://(?:www.)?github.com/?)?([a-zA-Z0-9](?:[a-zA-Z0-9]|-(?=[a-zA-Z0-9])){0,38})/?$#u'],
|
||||
['order' => 100, 'key' => 'skype', 'title' => 'Skype', 'regex' => '#^((?:live:)?[a-zA-Z][\w\.,\-_@]{1,100})$#u'],
|
||||
['order' => 110, 'key' => 'discord', 'title' => 'Discord', 'regex' => '#^(.{1,32}\#[0-9]{4})$#u'],
|
||||
];
|
||||
$formats = [
|
||||
['field' => 'website', 'regex' => null, 'display' => '%s', 'link' => '%s'],
|
||||
['field' => 'youtube', 'regex' => null, 'display' => '%s', 'link' => 'https://youtube.com/%s'],
|
||||
['field' => 'youtube', 'regex' => '^UC[a-zA-Z0-9-_]{1,22}$', 'display' => 'Go to Channel', 'link' => 'https://youtube.com/channel/%s'],
|
||||
['field' => 'twitter', 'regex' => null, 'display' => '@%s', 'link' => 'https://twitter.com/%s'],
|
||||
['field' => 'ninswitch', 'regex' => null, 'display' => 'SW-%s', 'link' => null],
|
||||
['field' => 'twitchtv', 'regex' => null, 'display' => '%s', 'link' => 'https://twitch.tv/%s'],
|
||||
['field' => 'steam', 'regex' => null, 'display' => '%s', 'link' => 'https://steamcommunity.com/id/%s'],
|
||||
['field' => 'osu', 'regex' => null, 'display' => '%s', 'link' => 'https://osu.ppy.sh/users/%s'],
|
||||
['field' => 'lastfm', 'regex' => null, 'display' => '%s', 'link' => 'https://www.last.fm/user/%s'],
|
||||
['field' => 'github', 'regex' => null, 'display' => '%s', 'link' => 'https://github.com/%s'],
|
||||
['field' => 'skype', 'regex' => null, 'display' => '%s', 'link' => 'skype:%s?userinfo'],
|
||||
['field' => 'discord', 'regex' => null, 'display' => '%s', 'link' => null],
|
||||
];
|
||||
|
||||
$insertField = $conn->prepare("INSERT INTO `msz_profile_fields` (`field_order`, `field_key`, `field_title`, `field_regex`) VALUES (:order, :key, :title, :regex)");
|
||||
$insertFormat = $conn->prepare("INSERT INTO `msz_profile_fields_formats` (`field_id`, `format_regex`, `format_link`, `format_display`) VALUES (:field, :regex, :link, :display)");
|
||||
$insertValue = $conn->prepare("INSERT INTO `msz_profile_fields_values` (`field_id`, `user_id`, `format_id`, `field_value`) VALUES (:field, :user, :format, :value)");
|
||||
|
||||
for($i = 0; $i < count($fields); $i++) {
|
||||
$insertField->execute($fields[$i]);
|
||||
$fields[$i]['id'] = $fieldIds[$fields[$i]['key']] = (int)$conn->lastInsertId();
|
||||
}
|
||||
|
||||
for($i = 0; $i < count($formats); $i++) {
|
||||
$formats[$i]['field'] = $fieldIds[$formats[$i]['field']];
|
||||
$insertFormat->execute($formats[$i]);
|
||||
$formats[$i]['id'] = (int)$conn->lastInsertId();
|
||||
}
|
||||
|
||||
$users = $conn->query("
|
||||
SELECT `user_id`, `user_website`, `user_twitter`, `user_github`, `user_skype`, `user_discord`,
|
||||
`user_youtube`, `user_steam`, `user_ninswitch`, `user_twitchtv`, `user_osu`, `user_lastfm`
|
||||
FROM `msz_users`
|
||||
")->fetchAll(PDO::FETCH_ASSOC);
|
||||
|
||||
foreach($users as $user) {
|
||||
foreach($fields as $field) {
|
||||
$source = 'user_' . $field['key'];
|
||||
$formatId = 0;
|
||||
|
||||
if(empty($user[$source]))
|
||||
continue;
|
||||
|
||||
foreach($formats as $format) {
|
||||
if($format['field'] != $field['id'])
|
||||
continue;
|
||||
|
||||
if(empty($format['regex']) && $formatId < 1) {
|
||||
$formatId = $format['id'];
|
||||
continue;
|
||||
}
|
||||
|
||||
if(preg_match("#{$format['regex']}#", $user[$source])) {
|
||||
$formatId = $format['id'];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
$insertValue->execute([
|
||||
'field' => $field['id'],
|
||||
'user' => $user['user_id'],
|
||||
'format' => $formatId,
|
||||
'value' => $user[$source],
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
$conn->exec("
|
||||
ALTER TABLE `msz_users`
|
||||
DROP COLUMN `user_website`,
|
||||
DROP COLUMN `user_twitter`,
|
||||
DROP COLUMN `user_github`,
|
||||
DROP COLUMN `user_skype`,
|
||||
DROP COLUMN `user_discord`,
|
||||
DROP COLUMN `user_youtube`,
|
||||
DROP COLUMN `user_steam`,
|
||||
DROP COLUMN `user_ninswitch`,
|
||||
DROP COLUMN `user_twitchtv`,
|
||||
DROP COLUMN `user_osu`,
|
||||
DROP COLUMN `user_lastfm`;
|
||||
");
|
||||
}
|
||||
|
||||
function migrate_down(PDO $conn): void {
|
||||
$conn->exec("
|
||||
ALTER TABLE `msz_users`
|
||||
ADD COLUMN `user_website` VARCHAR(255) NOT NULL DEFAULT '' COLLATE 'utf8mb4_bin' AFTER `user_background_settings`,
|
||||
ADD COLUMN `user_twitter` VARCHAR(20) NOT NULL DEFAULT '' COLLATE 'utf8mb4_bin' AFTER `user_website`,
|
||||
ADD COLUMN `user_github` VARCHAR(40) NOT NULL DEFAULT '' COLLATE 'utf8mb4_bin' AFTER `user_twitter`,
|
||||
ADD COLUMN `user_skype` VARCHAR(60) NOT NULL DEFAULT '' COLLATE 'utf8mb4_bin' AFTER `user_github`,
|
||||
ADD COLUMN `user_discord` VARCHAR(40) NOT NULL DEFAULT '' COLLATE 'utf8mb4_bin' AFTER `user_skype`,
|
||||
ADD COLUMN `user_youtube` VARCHAR(255) NOT NULL DEFAULT '' COLLATE 'utf8mb4_bin' AFTER `user_discord`,
|
||||
ADD COLUMN `user_steam` VARCHAR(255) NOT NULL DEFAULT '' COLLATE 'utf8mb4_bin' AFTER `user_youtube`,
|
||||
ADD COLUMN `user_ninswitch` VARCHAR(14) NOT NULL DEFAULT '' COLLATE 'utf8mb4_bin' AFTER `user_steam`,
|
||||
ADD COLUMN `user_twitchtv` VARCHAR(30) NOT NULL DEFAULT '' COLLATE 'utf8mb4_bin' AFTER `user_ninswitch`,
|
||||
ADD COLUMN `user_osu` VARCHAR(20) NOT NULL DEFAULT '' COLLATE 'utf8mb4_bin' AFTER `user_twitchtv`,
|
||||
ADD COLUMN `user_lastfm` VARCHAR(20) NOT NULL DEFAULT '' COLLATE 'utf8mb4_bin' AFTER `user_osu`;
|
||||
");
|
||||
|
||||
$existingFields = $conn->query("
|
||||
SELECT pfv.`user_id`, pf.`field_key`, pfv.`field_value`
|
||||
FROM `msz_profile_fields_values` AS pfv
|
||||
LEFT JOIN `msz_profile_fields` AS pf
|
||||
ON pf.`field_id` = pfv.`field_id`
|
||||
");
|
||||
|
||||
$updatePreps = [];
|
||||
foreach($existingFields as $field) {
|
||||
($updatePreps[$field['field_key']] ?? ($updatePreps[$field['field_key']] = $conn->prepare("UPDATE `msz_users` SET `user_{$field['field_key']}` = :value WHERE `user_id` = :user_id")))->execute([
|
||||
'value' => $field['field_value'],
|
||||
'user_id' => $field['user_id'],
|
||||
]);
|
||||
}
|
||||
|
||||
$conn->exec("DROP TABLE `msz_profile_fields_values`");
|
||||
$conn->exec("DROP TABLE `msz_profile_fields_formats`");
|
||||
$conn->exec("DROP TABLE `msz_profile_fields`");
|
||||
}
|
|
@ -72,7 +72,6 @@ require_once 'src/Users/avatar.php';
|
|||
require_once 'src/Users/background.php';
|
||||
require_once 'src/Users/login_attempt.php';
|
||||
require_once 'src/Users/object.php';
|
||||
require_once 'src/Users/profile.php';
|
||||
require_once 'src/Users/recovery.php';
|
||||
require_once 'src/Users/relations.php';
|
||||
require_once 'src/Users/role.php';
|
||||
|
@ -287,10 +286,8 @@ if(PHP_SAPI === 'cli') {
|
|||
});
|
||||
|
||||
if($doRollback) {
|
||||
echo "Rolling back last migrations..." . PHP_EOL;
|
||||
$migrationManager->rollback();
|
||||
} else {
|
||||
echo "Running migrations..." . PHP_EOL;
|
||||
$migrationManager->migrate();
|
||||
}
|
||||
|
||||
|
|
|
@ -241,7 +241,6 @@ $roles = $getRoles->fetchAll();
|
|||
|
||||
echo tpl_render('manage.users.user', [
|
||||
'manage_user' => $manageUser,
|
||||
'profile_fields' => user_profile_fields_get(),
|
||||
'manage_notices' => $notices,
|
||||
'manage_roles' => $roles,
|
||||
'can_edit_user' => $canEdit,
|
||||
|
|
|
@ -1,15 +1,17 @@
|
|||
<?php
|
||||
namespace Misuzu;
|
||||
|
||||
use Misuzu\Users\User;
|
||||
|
||||
require_once '../misuzu.php';
|
||||
|
||||
$userId = !empty($_GET['u']) && is_string($_GET['u']) ? (int)$_GET['u'] : 0;
|
||||
$userId = !empty($_GET['u']) && is_string($_GET['u']) ? $_GET['u'] : 0;
|
||||
$profileMode = !empty($_GET['m']) && is_string($_GET['m']) ? (string)$_GET['m'] : '';
|
||||
$isEditing = !empty($_GET['edit']) && is_string($_GET['edit']) ? (bool)$_GET['edit'] : !empty($_POST) && is_array($_POST);
|
||||
|
||||
$userId = user_find_for_profile($userId);
|
||||
$profileUser = User::findForProfile($userId);
|
||||
|
||||
if($userId < 1) {
|
||||
if(empty($profileUser)) {
|
||||
http_response_code(404);
|
||||
echo tpl_render('profile.index');
|
||||
return;
|
||||
|
@ -19,9 +21,9 @@ $notices = [];
|
|||
|
||||
$currentUserId = user_session_current('user_id', 0);
|
||||
$viewingAsGuest = $currentUserId === 0;
|
||||
$viewingOwnProfile = $currentUserId === $userId;
|
||||
$viewingOwnProfile = $currentUserId === $profileUser->user_id;
|
||||
|
||||
$isBanned = user_warning_check_restriction($userId);
|
||||
$isBanned = user_warning_check_restriction($profileUser->user_id);
|
||||
$userPerms = perms_get_user($currentUserId)[MSZ_PERMS_USER];
|
||||
$canManageWarnings = perms_check($userPerms, MSZ_PERM_USER_MANAGE_WARNINGS);
|
||||
$canEdit = !$isBanned
|
||||
|
@ -31,7 +33,7 @@ $canEdit = !$isBanned
|
|||
|| user_check_super($currentUserId)
|
||||
|| (
|
||||
perms_check($userPerms, MSZ_PERM_USER_MANAGE_USERS)
|
||||
&& user_check_authority($currentUserId, $userId)
|
||||
&& user_check_authority($currentUserId, $profileUser->user_id)
|
||||
)
|
||||
);
|
||||
|
||||
|
@ -67,15 +69,11 @@ if($isEditing) {
|
|||
if(!$perms['edit_profile']) {
|
||||
$notices[] = MSZ_TMP_USER_ERROR_STRINGS['profile']['not-allowed'];
|
||||
} else {
|
||||
$setUserFieldErrors = user_profile_fields_set($userId, $_POST['profile']);
|
||||
$profileFields = $profileUser->profileFields(false);
|
||||
|
||||
if(count($setUserFieldErrors) > 0) {
|
||||
foreach($setUserFieldErrors as $name => $error) {
|
||||
$notices[] = sprintf(
|
||||
MSZ_TMP_USER_ERROR_STRINGS['profile'][$error] ?? MSZ_TMP_USER_ERROR_STRINGS['profile']['_'],
|
||||
$name,
|
||||
user_profile_field_get_display_name($name)
|
||||
);
|
||||
foreach($profileFields as $profileField) {
|
||||
if(isset($_POST['profile'][$profileField->field_key]) && !$profileField->setFieldValue($_POST['profile'][$profileField->field_key])) {
|
||||
$notices[] = sprintf(MSZ_TMP_USER_ERROR_STRINGS['profile']['invalid'], $profileField->field_title);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -86,7 +84,7 @@ if($isEditing) {
|
|||
$notices[] = MSZ_TMP_USER_ERROR_STRINGS['about']['not-allowed'];
|
||||
} else {
|
||||
$setAboutError = user_set_about_page(
|
||||
$userId,
|
||||
$profileUser->user_id,
|
||||
$_POST['about']['text'] ?? '',
|
||||
(int)($_POST['about']['parser'] ?? MSZ_PARSER_PLAIN)
|
||||
);
|
||||
|
@ -105,7 +103,7 @@ if($isEditing) {
|
|||
$notices[] = MSZ_TMP_USER_ERROR_STRINGS['signature']['not-allowed'];
|
||||
} else {
|
||||
$setSignatureError = user_set_signature(
|
||||
$userId,
|
||||
$profileUser->user_id,
|
||||
$_POST['signature']['text'] ?? '',
|
||||
(int)($_POST['signature']['parser'] ?? MSZ_PARSER_PLAIN)
|
||||
);
|
||||
|
@ -124,7 +122,7 @@ if($isEditing) {
|
|||
$notices[] = "You aren't allow to change your birthdate.";
|
||||
} else {
|
||||
$setBirthdate = user_set_birthdate(
|
||||
$userId,
|
||||
$profileUser->user_id,
|
||||
(int)($_POST['birthdate']['day'] ?? 0),
|
||||
(int)($_POST['birthdate']['month'] ?? 0),
|
||||
(int)($_POST['birthdate']['year'] ?? 0)
|
||||
|
@ -153,7 +151,7 @@ if($isEditing) {
|
|||
|
||||
if(!empty($_FILES['avatar'])) {
|
||||
if(!empty($_POST['avatar']['delete'])) {
|
||||
user_avatar_delete($userId);
|
||||
user_avatar_delete($profileUser->user_id);
|
||||
} else {
|
||||
if(!$perms['edit_avatar']) {
|
||||
$notices[] = MSZ_TMP_USER_ERROR_STRINGS['avatar']['not-allowed'];
|
||||
|
@ -171,7 +169,7 @@ if($isEditing) {
|
|||
);
|
||||
} else {
|
||||
$setAvatar = user_avatar_set_from_path(
|
||||
$userId,
|
||||
$profileUser->user_id,
|
||||
$_FILES['avatar']['tmp_name']['file'],
|
||||
$avatarProps
|
||||
);
|
||||
|
@ -193,8 +191,8 @@ if($isEditing) {
|
|||
|
||||
if(!empty($_FILES['background'])) {
|
||||
if((int)($_POST['background']['attach'] ?? -1) === 0) {
|
||||
user_background_delete($userId);
|
||||
user_background_set_settings($userId, MSZ_USER_BACKGROUND_ATTACHMENT_NONE);
|
||||
user_background_delete($profileUser->user_id);
|
||||
user_background_set_settings($profileUser->user_id, MSZ_USER_BACKGROUND_ATTACHMENT_NONE);
|
||||
} else {
|
||||
if(!$perms['edit_background']) {
|
||||
$notices[] = MSZ_TMP_USER_ERROR_STRINGS['background']['not-allowed'];
|
||||
|
@ -212,7 +210,7 @@ if($isEditing) {
|
|||
);
|
||||
} else {
|
||||
$setBackground = user_background_set_from_path(
|
||||
$userId,
|
||||
$profileUser->user_id,
|
||||
$_FILES['background']['tmp_name']['file'],
|
||||
$backgroundProps
|
||||
);
|
||||
|
@ -242,7 +240,7 @@ if($isEditing) {
|
|||
$backgroundSettings |= MSZ_USER_BACKGROUND_ATTRIBUTE_SLIDE;
|
||||
}
|
||||
|
||||
user_background_set_settings($userId, $backgroundSettings);
|
||||
user_background_set_settings($profileUser->user_id, $backgroundSettings);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -255,22 +253,61 @@ if($isEditing) {
|
|||
}
|
||||
}
|
||||
|
||||
$profile = user_profile_get($userId);
|
||||
$profileStats = DB::prepare(sprintf('
|
||||
SELECT (
|
||||
SELECT COUNT(`topic_id`)
|
||||
FROM `msz_forum_topics`
|
||||
WHERE `user_id` = u.`user_id`
|
||||
AND `topic_deleted` IS NULL
|
||||
) AS `forum_topic_count`,
|
||||
(
|
||||
SELECT COUNT(`post_id`)
|
||||
FROM `msz_forum_posts`
|
||||
WHERE `user_id` = u.`user_id`
|
||||
AND `post_deleted` IS NULL
|
||||
) AS `forum_post_count`,
|
||||
(
|
||||
SELECT COUNT(`change_id`)
|
||||
FROM `msz_changelog_changes`
|
||||
WHERE `user_id` = u.`user_id`
|
||||
) AS `changelog_count`,
|
||||
(
|
||||
SELECT COUNT(`comment_id`)
|
||||
FROM `msz_comments_posts`
|
||||
WHERE `user_id` = u.`user_id`
|
||||
AND `comment_deleted` IS NULL
|
||||
) AS `comments_count`,
|
||||
(
|
||||
SELECT COUNT(`user_id`)
|
||||
FROM `msz_user_relations`
|
||||
WHERE `subject_id` = u.`user_id`
|
||||
AND `relation_type` = %1$d
|
||||
) AS `followers_count`,
|
||||
(
|
||||
SELECT COUNT(`subject_id`)
|
||||
FROM `msz_user_relations`
|
||||
WHERE `user_id` = u.`user_id`
|
||||
AND `relation_type` = %1$d
|
||||
) AS `following_count`
|
||||
FROM `msz_users` AS u
|
||||
WHERE `user_id` = :user_id
|
||||
', MSZ_USER_RELATION_FOLLOW))->bind('user_id', $profileUser->user_id)->fetch();
|
||||
|
||||
$relationInfo = user_session_active()
|
||||
? user_relation_info($currentUserId, $profile['user_id'])
|
||||
? user_relation_info($currentUserId, $profileUser->user_id)
|
||||
: [];
|
||||
|
||||
$backgroundPath = sprintf('%s/backgrounds/original/%d.msz', MSZ_STORAGE, $profile['user_id']);
|
||||
$backgroundPath = sprintf('%s/backgrounds/original/%d.msz', MSZ_STORAGE, $profileUser->user_id);
|
||||
|
||||
if(is_file($backgroundPath)) {
|
||||
$backgroundInfo = getimagesize($backgroundPath);
|
||||
|
||||
if($backgroundInfo) {
|
||||
tpl_var('site_background', [
|
||||
'url' => url('user-background', ['user' => $profile['user_id']]),
|
||||
'url' => url('user-background', ['user' => $profileUser->user_id]),
|
||||
'width' => $backgroundInfo[0],
|
||||
'height' => $backgroundInfo[1],
|
||||
'settings' => $profile['user_background_settings'],
|
||||
'settings' => $profileUser->user_background_settings,
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
@ -282,7 +319,7 @@ switch($profileMode) {
|
|||
|
||||
case 'following':
|
||||
$template = 'profile.relations';
|
||||
$followingCount = user_relation_count_from($userId, MSZ_USER_RELATION_FOLLOW);
|
||||
$followingCount = user_relation_count_from($profileUser->user_id, MSZ_USER_RELATION_FOLLOW);
|
||||
$followingPagination = pagination_create($followingCount, MSZ_USER_RELATION_FOLLOW_PER_PAGE);
|
||||
$followingOffset = pagination_offset($followingPagination, pagination_param());
|
||||
|
||||
|
@ -291,11 +328,14 @@ switch($profileMode) {
|
|||
return;
|
||||
}
|
||||
|
||||
$following = user_relation_users_from($userId, MSZ_USER_RELATION_FOLLOW, $followingPagination['range'], $followingOffset, $currentUserId);
|
||||
$following = user_relation_users_from(
|
||||
$profileUser->user_id, MSZ_USER_RELATION_FOLLOW, $followingPagination['range'],
|
||||
$followingOffset, $currentUserId
|
||||
);
|
||||
|
||||
tpl_vars([
|
||||
'title' => $profile['username'] . ' / following',
|
||||
'canonical_url' => url('user-profile-following', ['user' => $userId]),
|
||||
'canonical_url' => url('user-profile-following', ['user' => $profileUser->user_id]),
|
||||
'profile_users' => $following,
|
||||
'profile_relation_pagination' => $followingPagination,
|
||||
]);
|
||||
|
@ -303,7 +343,7 @@ switch($profileMode) {
|
|||
|
||||
case 'followers':
|
||||
$template = 'profile.relations';
|
||||
$followerCount = user_relation_count_to($userId, MSZ_USER_RELATION_FOLLOW);
|
||||
$followerCount = user_relation_count_to($profileUser->user_id, MSZ_USER_RELATION_FOLLOW);
|
||||
$followerPagination = pagination_create($followerCount, MSZ_USER_RELATION_FOLLOW_PER_PAGE);
|
||||
$followerOffset = pagination_offset($followerPagination, pagination_param());
|
||||
|
||||
|
@ -312,11 +352,11 @@ switch($profileMode) {
|
|||
return;
|
||||
}
|
||||
|
||||
$followers = user_relation_users_to($userId, MSZ_USER_RELATION_FOLLOW, $followerPagination['range'], $followerOffset, $currentUserId);
|
||||
$followers = user_relation_users_to($profileUser->user_id, MSZ_USER_RELATION_FOLLOW, $followerPagination['range'], $followerOffset, $currentUserId);
|
||||
|
||||
tpl_vars([
|
||||
'title' => $profile['username'] . ' / followers',
|
||||
'canonical_url' => url('user-profile-followers', ['user' => $userId]),
|
||||
'canonical_url' => url('user-profile-followers', ['user' => $profileUser->user_id]),
|
||||
'profile_users' => $followers,
|
||||
'profile_relation_pagination' => $followerPagination,
|
||||
]);
|
||||
|
@ -324,7 +364,7 @@ switch($profileMode) {
|
|||
|
||||
case 'forum-topics':
|
||||
$template = 'profile.topics';
|
||||
$topicsCount = forum_topic_count_user($userId, $currentUserId);
|
||||
$topicsCount = forum_topic_count_user($profileUser->user_id, $currentUserId);
|
||||
$topicsPagination = pagination_create($topicsCount, 20);
|
||||
$topicsOffset = pagination_offset($topicsPagination, pagination_param());
|
||||
|
||||
|
@ -333,11 +373,11 @@ switch($profileMode) {
|
|||
return;
|
||||
}
|
||||
|
||||
$topics = forum_topic_listing_user($userId, $currentUserId, $topicsOffset, $topicsPagination['range']);
|
||||
$topics = forum_topic_listing_user($profileUser->user_id, $currentUserId, $topicsOffset, $topicsPagination['range']);
|
||||
|
||||
tpl_vars([
|
||||
'title' => $profile['username'] . ' / topics',
|
||||
'canonical_url' => url('user-profile-forum-topics', ['user' => $userId, 'page' => pagination_param()]),
|
||||
'canonical_url' => url('user-profile-forum-topics', ['user' => $profileUser->user_id, 'page' => pagination_param()]),
|
||||
'profile_topics' => $topics,
|
||||
'profile_topics_pagination' => $topicsPagination,
|
||||
]);
|
||||
|
@ -345,7 +385,7 @@ switch($profileMode) {
|
|||
|
||||
case 'forum-posts':
|
||||
$template = 'profile.posts';
|
||||
$postsCount = forum_post_count_user($userId);
|
||||
$postsCount = forum_post_count_user($profileUser->user_id);
|
||||
$postsPagination = pagination_create($postsCount, 20);
|
||||
$postsOffset = pagination_offset($postsPagination, pagination_param());
|
||||
|
||||
|
@ -354,11 +394,11 @@ switch($profileMode) {
|
|||
return;
|
||||
}
|
||||
|
||||
$posts = forum_post_listing($userId, $postsOffset, $postsPagination['range'], false, true);
|
||||
$posts = forum_post_listing($profileUser->user_id, $postsOffset, $postsPagination['range'], false, true);
|
||||
|
||||
tpl_vars([
|
||||
'title' => $profile['username'] . ' / posts',
|
||||
'canonical_url' => url('user-profile-forum-posts', ['user' => $userId, 'page' => pagination_param()]),
|
||||
'canonical_url' => url('user-profile-forum-posts', ['user' => $profileUser->user_id, 'page' => pagination_param()]),
|
||||
'profile_posts' => $posts,
|
||||
'profile_posts_pagination' => $postsPagination,
|
||||
]);
|
||||
|
@ -369,7 +409,7 @@ switch($profileMode) {
|
|||
$warnings = $viewingAsGuest
|
||||
? []
|
||||
: user_warning_fetch(
|
||||
$userId,
|
||||
$profileUser->user_id,
|
||||
90,
|
||||
$canManageWarnings
|
||||
? MSZ_WARN_TYPES_VISIBLE_TO_STAFF
|
||||
|
@ -384,14 +424,14 @@ switch($profileMode) {
|
|||
'profile_warnings' => $warnings,
|
||||
'profile_warnings_view_private' => $viewingOwnProfile,
|
||||
'profile_warnings_can_manage' => $canManageWarnings,
|
||||
'profile_fields' => user_session_active() ? user_profile_fields_display($profile, !$isEditing) : [],
|
||||
]);
|
||||
break;
|
||||
}
|
||||
|
||||
if(!empty($template)) {
|
||||
echo tpl_render($template, [
|
||||
'profile' => $profile,
|
||||
'profile_user' => $profileUser,
|
||||
'profile_stats' => $profileStats,
|
||||
'profile_mode' => $profileMode,
|
||||
'profile_notices' => $notices,
|
||||
'profile_can_edit' => $canEdit,
|
||||
|
|
|
@ -57,7 +57,7 @@ class DatabaseStatement {
|
|||
$objects = [];
|
||||
|
||||
if($this->isQuery || $this->execute()) {
|
||||
while(($object = $this->stmt->fetchObject($className, $args)) !== false) {
|
||||
while(($object = ($args === null ? $this->stmt->fetchObject($className) : $this->stmt->fetchObject($className, $args))) !== false) {
|
||||
$objects[] = $object;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -130,7 +130,6 @@ function ip_blacklist_add_raw(string $subnet, ?int $mask = null): bool {
|
|||
return false;
|
||||
}
|
||||
|
||||
// TODO: don't use REPLACE INTO
|
||||
$addBlacklist = \Misuzu\DB::prepare('
|
||||
REPLACE INTO `msz_ip_blacklist`
|
||||
(`ip_subnet`, `ip_mask`)
|
||||
|
|
151
src/Users/ProfileField.php
Normal file
151
src/Users/ProfileField.php
Normal file
|
@ -0,0 +1,151 @@
|
|||
<?php
|
||||
namespace Misuzu\Users;
|
||||
|
||||
use Misuzu\DB;
|
||||
|
||||
class ProfileField {
|
||||
public static function createField(
|
||||
string $fieldKey,
|
||||
string $fieldTitle,
|
||||
string $fieldRegex,
|
||||
int $fieldOrder
|
||||
): ?ProfileField {
|
||||
$createField = DB::prepare('
|
||||
INSERT INTO `msz_profile_fields` (
|
||||
`field_order`, `field_key`, `field_title`, `field_regex`
|
||||
) VALUES (:order, :key, :title, :regex)
|
||||
')->bind('order', $fieldOrder)->bind('key', $fieldKey)
|
||||
->bind('title', $fieldTitle)->bind('regex', $fieldRegex)
|
||||
->executeGetId();
|
||||
|
||||
if($createField < 1)
|
||||
return null;
|
||||
|
||||
return static::get($createField);
|
||||
}
|
||||
public static function createFormat(
|
||||
int $fieldId,
|
||||
string $formatDisplay = '%s',
|
||||
?string $formatLink = null,
|
||||
?string $formatRegex = null
|
||||
): ?ProfileField {
|
||||
$createFormat = DB::prepare('
|
||||
INSERT INTO `msz_profile_fields_formats` (
|
||||
`field_id`, `format_regex`, `format_link`, `format_display`
|
||||
) VALUES (:field, :regex, :link, :display)
|
||||
')->bind('field', $fieldId) ->bind('regex', $formatRegex)
|
||||
->bind('link', $formatLink)->bind('display', $formatDisplay)
|
||||
->executeGetId();
|
||||
|
||||
if($createFormat < 1)
|
||||
return null;
|
||||
|
||||
return static::get($createFormat);
|
||||
}
|
||||
|
||||
public static function get(int $fieldId): ?ProfileField {
|
||||
return DB::prepare(
|
||||
'SELECT `field_id`, `field_order`, `field_key`, `field_title`, `field_regex`'
|
||||
. ' FROM `msz_profile_fields`'
|
||||
. ' WHERE `field_id` = :field_id'
|
||||
)->bind('field_id', $fieldId)->fetchObject(ProfileField::class);
|
||||
}
|
||||
|
||||
public static function user(int $userId, bool $filterEmpty = true): array {
|
||||
$fields = DB::prepare(
|
||||
'SELECT pf.`field_id`, pf.`field_order`, pf.`field_key`, pf.`field_title`, pf.`field_regex`'
|
||||
. ', pff.`format_id`, pff.`format_regex`, pff.`format_link`, pff.`format_display`'
|
||||
. ', COALESCE(pfv.`user_id`, :user2) AS `user_id`, pfv.`field_value`'
|
||||
. ' FROM `msz_profile_fields` AS pf'
|
||||
. ' LEFT JOIN `msz_profile_fields_values` AS pfv ON pfv.`field_id` = pf.`field_id` AND pfv.`user_id` = :user1'
|
||||
. ' LEFT JOIN `msz_profile_fields_formats` AS pff ON pff.`field_id` = pf.`field_id` AND pff.`format_id` = pfv.`format_id`'
|
||||
. ' ORDER BY pf.`field_order`'
|
||||
)->bind('user1', $userId)->bind('user2', $userId)->fetchObjects(ProfileField::class);
|
||||
|
||||
if($filterEmpty) {
|
||||
$newFields = [];
|
||||
|
||||
foreach($fields as $field) {
|
||||
if(!empty($field->field_value))
|
||||
$newFields[] = $field;
|
||||
}
|
||||
|
||||
$fields = $newFields;
|
||||
}
|
||||
|
||||
return $fields;
|
||||
}
|
||||
|
||||
public function findDisplayFormat(string $value): int {
|
||||
if(!isset($this->field_id))
|
||||
return 0;
|
||||
|
||||
$format = DB::prepare('
|
||||
SELECT `format_id`
|
||||
FROM `msz_profile_fields_formats`
|
||||
WHERE `field_id` = :field
|
||||
AND `format_regex` IS NOT NULL
|
||||
AND :value REGEXP `format_regex`
|
||||
')->bind('field', $this->field_id)
|
||||
->bind('value', $value)
|
||||
->fetchColumn();
|
||||
|
||||
if($format < 1) {
|
||||
$format = DB::prepare('
|
||||
SELECT `format_id`
|
||||
FROM `msz_profile_fields_formats`
|
||||
WHERE `field_id` = :field
|
||||
AND `format_regex` IS NULL
|
||||
')->bind('field', $this->field_id)
|
||||
->fetchColumn(0, 0);
|
||||
}
|
||||
|
||||
return $format;
|
||||
}
|
||||
|
||||
// todo: use exceptions
|
||||
public function setFieldValue(string $value): bool {
|
||||
if(!isset($this->user_id, $this->field_id, $this->field_regex))
|
||||
return false;
|
||||
|
||||
if(empty($value)) {
|
||||
DB::prepare('
|
||||
DELETE FROM `msz_profile_fields_values`
|
||||
WHERE `user_id` = :user
|
||||
AND `field_id` = :field
|
||||
')->bind('user', $this->user_id)
|
||||
->bind('field', $this->field_id)
|
||||
->execute();
|
||||
$this->field_value = '';
|
||||
return true;
|
||||
}
|
||||
|
||||
if(preg_match($this->field_regex, $value, $matches)) {
|
||||
$value = $matches[1];
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
$displayFormat = $this->findDisplayFormat($value);
|
||||
|
||||
if($displayFormat < 1)
|
||||
return false;
|
||||
|
||||
$updateField = DB::prepare('
|
||||
REPLACE INTO `msz_profile_fields_values`
|
||||
(`field_id`, `user_id`, `format_id`, `field_value`)
|
||||
VALUES
|
||||
(:field, :user, :format, :value)
|
||||
')->bind('field', $this->field_id)
|
||||
->bind('user', $this->user_id)
|
||||
->bind('format', $displayFormat)
|
||||
->bind('value', $value)
|
||||
->execute();
|
||||
|
||||
if(!$updateField)
|
||||
return false;
|
||||
|
||||
$this->field_value = $value;
|
||||
return true;
|
||||
}
|
||||
}
|
|
@ -5,20 +5,20 @@ use Misuzu\DB;
|
|||
|
||||
class User {
|
||||
private const USER_SELECT = '
|
||||
SELECT `user_id`, `username`, `password`, `email`, `user_super`, `user_title`,
|
||||
`user_country`, `user_colour`, `display_role`, `user_totp_key`,
|
||||
`user_about_content`, `user_about_parser`,
|
||||
`user_signature_content`, `user_signature_parser`,
|
||||
`user_birthdate`, `user_background_settings`,
|
||||
INET6_NTOA(`register_ip`) AS `register_ip`,
|
||||
INET6_NTOA(`last_ip`) AS `last_ip`,
|
||||
UNIX_TIMESTAMP(`user_created`) AS `user_created`,
|
||||
UNIX_TIMESTAMP(`user_active`) AS `user_active`,
|
||||
UNIX_TIMESTAMP(`user_deleted`) AS `user_deleted`,
|
||||
`user_website`, `user_twitter`, `user_github`, `user_skype`,
|
||||
`user_discord`, `user_youtube`, `user_steam`, `user_ninswitch`,
|
||||
`user_twitchtv`, `user_osu`, `user_lastfm`
|
||||
FROM `msz_users`
|
||||
SELECT u.`user_id`, u.`username`, u.`password`, u.`email`, u.`user_super`, u.`user_title`,
|
||||
u.`user_country`, u.`user_colour`, u.`display_role`, u.`user_totp_key`,
|
||||
u.`user_about_content`, u.`user_about_parser`,
|
||||
u.`user_signature_content`, u.`user_signature_parser`,
|
||||
u.`user_birthdate`, u.`user_background_settings`,
|
||||
INET6_NTOA(u.`register_ip`) AS `register_ip`, INET6_NTOA(u.`last_ip`) AS `last_ip`,
|
||||
UNIX_TIMESTAMP(u.`user_created`) AS `user_created`, UNIX_TIMESTAMP(u.`user_active`) AS `user_active`,
|
||||
UNIX_TIMESTAMP(u.`user_deleted`) AS `user_deleted`,
|
||||
COALESCE(u.`user_title`, r.`role_title`) AS `user_title`,
|
||||
COALESCE(u.`user_colour`, r.`role_colour`) AS `user_colour`,
|
||||
TIMESTAMPDIFF(YEAR, IF(u.`user_birthdate` < \'0001-01-01\', NULL, u.`user_birthdate`), NOW()) AS `user_age`
|
||||
FROM `msz_users` AS u
|
||||
LEFT JOIN `msz_roles` AS r
|
||||
ON r.`role_id` = u.`display_role`
|
||||
';
|
||||
|
||||
public function __construct() {
|
||||
|
@ -63,6 +63,12 @@ class User {
|
|||
->bind('username', $usernameOrEmail)
|
||||
->fetchObject(User::class);
|
||||
}
|
||||
public static function findForProfile($userId): ?User {
|
||||
return DB::prepare(self::USER_SELECT . 'WHERE `user_id` = :user_id OR LOWER(`username`) = LOWER(:username)')
|
||||
->bind('user_id', (int)$userId)
|
||||
->bind('username', (string)$userId)
|
||||
->fetchObject(User::class);
|
||||
}
|
||||
|
||||
public function hasUserId(): bool {
|
||||
return isset($this->user_id) && $this->user_id > 0;
|
||||
|
@ -94,4 +100,21 @@ class User {
|
|||
public function hasTOTP(): bool {
|
||||
return !empty($this->user_totp_key);
|
||||
}
|
||||
|
||||
public function getBackgroundAttachment(): int {
|
||||
return $this->user_background_settings & 0x0F;
|
||||
}
|
||||
public function getBackgroundBlend(): bool {
|
||||
return ($this->user_background_settings & MSZ_USER_BACKGROUND_ATTRIBUTE_BLEND) > 0;
|
||||
}
|
||||
public function getBackgroundSlide(): bool {
|
||||
return ($this->user_background_settings & MSZ_USER_BACKGROUND_ATTRIBUTE_SLIDE) > 0;
|
||||
}
|
||||
|
||||
public function profileFields(bool $filterEmpty = true): array {
|
||||
if(!$this->hasUserId())
|
||||
return [];
|
||||
|
||||
return ProfileField::user($this->user_id, $filterEmpty);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,264 +0,0 @@
|
|||
<?php
|
||||
define('MSZ_USER_PROFILE_SET_ERROR', '_err');
|
||||
define('MSZ_USER_PROFILE_INVALID_FIELD', 1);
|
||||
define('MSZ_USER_PROFILE_FILTER_FAILED', 2);
|
||||
define('MSZ_USER_PROFILE_UPDATE_FAILED', 3);
|
||||
define('MSZ_USER_PROFILE_FIELD_SET_ERRORS', [
|
||||
MSZ_USER_PROFILE_INVALID_FIELD,
|
||||
MSZ_USER_PROFILE_FILTER_FAILED,
|
||||
MSZ_USER_PROFILE_UPDATE_FAILED,
|
||||
]);
|
||||
|
||||
define('MSZ_USER_PROFILE_FIELD_FORMAT', 'user_%s');
|
||||
define('MSZ_USER_PROFILE_FIELDS', [
|
||||
'website' => [
|
||||
'name' => 'Website',
|
||||
'type' => 'url',
|
||||
'regex' => '#^((?:https?)://.{1,240})$#u',
|
||||
'link' => '%s',
|
||||
'tooltip' => '%s',
|
||||
],
|
||||
'youtube' => [
|
||||
'name' => 'Youtube',
|
||||
'regex' => '#^(?:https?://(?:www.)?youtube.com/(?:(?:user|c|channel)/)?)?(UC[a-zA-Z0-9-_]{1,22}|[a-zA-Z0-9-_%]{1,100})/?$#u',
|
||||
'link' => [
|
||||
'_' => 'https://youtube.com/%s',
|
||||
'UC[a-zA-Z0-9-_]{1,22}' => 'https://youtube.com/channel/%s',
|
||||
],
|
||||
'format' => [
|
||||
'_' => '%s',
|
||||
'UC[a-zA-Z0-9-_]{1,22}' => 'Go to Channel',
|
||||
],
|
||||
],
|
||||
'twitter' => [
|
||||
'name' => 'Twitter',
|
||||
'regex' => '#^(?:https?://(?:www\.)?twitter.com/(?:\#!\/)?)?@?([A-Za-z0-9_]{1,20})/?$#u',
|
||||
'link' => 'https://twitter.com/%s',
|
||||
'format' => '@%s',
|
||||
],
|
||||
'ninswitch' => [
|
||||
'name' => 'Nintendo Switch',
|
||||
'regex' => '#^(?:SW-)?([0-9]{4}-[0-9]{4}-[0-9]{4})$#u',
|
||||
'format' => 'SW-%s',
|
||||
],
|
||||
'twitchtv' => [
|
||||
'name' => 'Twitch.tv',
|
||||
'regex' => '#^(?:https?://(?:www.)?twitch.tv/)?([0-9A-Za-z_]{3,25})/?$#u',
|
||||
'link' => 'https://twitch.tv/%s',
|
||||
],
|
||||
'steam' => [
|
||||
'name' => 'Steam',
|
||||
'regex' => '#^(?:https?://(?:www.)?steamcommunity.com/(?:id|profiles)/)?([a-zA-Z0-9_-]{2,100})/?$#u',
|
||||
'link' => 'https://steamcommunity.com/id/%s',
|
||||
],
|
||||
'osu' => [
|
||||
'name' => 'osu!',
|
||||
'regex' => '#^(?:https?://osu.ppy.sh/u(?:sers)?/)?([a-zA-Z0-9-\[\]_ ]{1,20})/?$#u',
|
||||
'link' => 'https://osu.ppy.sh/users/%s',
|
||||
],
|
||||
'lastfm' => [
|
||||
'name' => 'Last.fm',
|
||||
'regex' => '#^(?:https?://(?:www.)?last.fm/user/)?([a-zA-Z]{1}[a-zA-Z0-9_-]{1,14})/?$#u',
|
||||
'link' => 'https://www.last.fm/user/%s',
|
||||
],
|
||||
'github' => [
|
||||
'name' => 'Github',
|
||||
'regex' => '#^(?:https?://(?:www.)?github.com/?)?([a-zA-Z0-9](?:[a-zA-Z0-9]|-(?=[a-zA-Z0-9])){0,38})/?$#u',
|
||||
'link' => 'https://github.com/%s',
|
||||
],
|
||||
'skype' => [
|
||||
'name' => 'Skype',
|
||||
'regex' => '#^((?:live:)?[a-zA-Z][\w\.,\-_@]{1,100})$#u',
|
||||
'link' => 'skype:%s?userinfo',
|
||||
],
|
||||
'discord' => [
|
||||
'name' => 'Discord',
|
||||
'regex' => '#^(.{1,32}\#[0-9]{4})$#u',
|
||||
],
|
||||
]);
|
||||
|
||||
function user_profile_field_is_valid(string $name): bool {
|
||||
return array_key_exists($name, MSZ_USER_PROFILE_FIELDS);
|
||||
}
|
||||
|
||||
function user_profile_field_get_display_name(string $name): string {
|
||||
return MSZ_USER_PROFILE_FIELDS[$name]['name'] ?? '';
|
||||
}
|
||||
|
||||
function user_profile_field_get_database_name(string $name): string {
|
||||
return sprintf(MSZ_USER_PROFILE_FIELD_FORMAT, $name);
|
||||
}
|
||||
|
||||
function user_profile_fields_get(): array {
|
||||
return MSZ_USER_PROFILE_FIELDS;
|
||||
}
|
||||
|
||||
function user_profile_field_get_regex(string $name): string {
|
||||
return MSZ_USER_PROFILE_FIELDS[$name]['regex'] ?? '';
|
||||
}
|
||||
|
||||
// === NULL if field is invalid
|
||||
function user_profile_field_filter(string $name, string $value): ?string {
|
||||
if(!user_profile_field_is_valid($name)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$regex = user_profile_field_get_regex($name);
|
||||
|
||||
if(empty($regex) || empty($value)) {
|
||||
return $value;
|
||||
}
|
||||
|
||||
$checkRegex = preg_match($regex, $value, $matches);
|
||||
|
||||
if(!$checkRegex || empty($matches[1])) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $matches[1];
|
||||
}
|
||||
|
||||
function user_profile_fields_set(int $userId, array $fields): array {
|
||||
if(count($fields) < 1) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$errors = [];
|
||||
$values = [];
|
||||
|
||||
foreach($fields as $name => $value) {
|
||||
// should these just be ignored?
|
||||
if(!user_profile_field_is_valid($name)) {
|
||||
$errors[$name] = MSZ_USER_PROFILE_INVALID_FIELD;
|
||||
continue;
|
||||
}
|
||||
|
||||
$value = user_profile_field_filter($name, $value);
|
||||
|
||||
if($value === null) {
|
||||
$errors[$name] = MSZ_USER_PROFILE_FILTER_FAILED;
|
||||
continue;
|
||||
}
|
||||
|
||||
$values[user_profile_field_get_database_name($name)] = $value;
|
||||
}
|
||||
|
||||
if(count($values) > 0) {
|
||||
$updateFields = \Misuzu\DB::prepare('
|
||||
UPDATE `msz_users`
|
||||
SET ' . pdo_prepare_array_update($values, true) . '
|
||||
WHERE `user_id` = :user_id
|
||||
');
|
||||
$values['user_id'] = $userId;
|
||||
|
||||
if(!$updateFields->execute($values)) {
|
||||
$errors[MSZ_USER_PROFILE_SET_ERROR] = MSZ_USER_PROFILE_UPDATE_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
return $errors;
|
||||
}
|
||||
|
||||
function user_profile_fields_display(array $user, bool $hideEmpty = true): array {
|
||||
$output = [];
|
||||
|
||||
foreach(MSZ_USER_PROFILE_FIELDS as $name => $field) {
|
||||
$dbn = user_profile_field_get_database_name($name);
|
||||
|
||||
if($hideEmpty && (!array_key_exists($dbn, $user) || empty($user[$dbn]))) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$value = $user[$dbn] ?? '';
|
||||
$output[$name] = $field;
|
||||
$output[$name]['value'] = htmlentities($value);
|
||||
|
||||
foreach(['link', 'format'] as $multipath) {
|
||||
if(empty($output[$name][$multipath]) || !is_array($output[$name][$multipath])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
foreach(array_reverse($output[$name][$multipath], true) as $regex => $string) {
|
||||
if($regex === '_' || !preg_match("#{$regex}#", $value)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$output[$name][$multipath] = $string;
|
||||
break;
|
||||
}
|
||||
|
||||
if(is_array($output[$name][$multipath])) {
|
||||
$output[$name][$multipath] = $output[$name][$multipath]['_'];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $output;
|
||||
}
|
||||
|
||||
function user_profile_get(int $userId): array {
|
||||
$getProfile = \Misuzu\DB::prepare(
|
||||
sprintf(
|
||||
'
|
||||
SELECT
|
||||
u.`user_id`, u.`username`, u.`user_country`, u.`user_birthdate`,
|
||||
u.`user_created`, u.`user_active`, u.`user_background_settings`,
|
||||
u.`user_about_parser`, u.`user_about_content`,
|
||||
u.`user_signature_parser`, u.`user_signature_content`,
|
||||
%1$s,
|
||||
TIMESTAMPDIFF(YEAR, IF(u.`user_birthdate` < \'0001-01-01\', NULL, u.`user_birthdate`), NOW()) AS `user_age`,
|
||||
COALESCE(u.`user_title`, r.`role_title`) AS `user_title`,
|
||||
COALESCE(u.`user_colour`, r.`role_colour`) AS `user_colour`,
|
||||
`user_background_settings` & 0x0F AS `user_background_attachment`,
|
||||
(`user_background_settings` & %2$d) > 0 AS `user_background_blend`,
|
||||
(`user_background_settings` & %3$d) > 0 AS `user_background_slide`,
|
||||
(
|
||||
SELECT COUNT(`topic_id`)
|
||||
FROM `msz_forum_topics`
|
||||
WHERE `user_id` = u.`user_id`
|
||||
AND `topic_deleted` IS NULL
|
||||
) AS `forum_topic_count`,
|
||||
(
|
||||
SELECT COUNT(`post_id`)
|
||||
FROM `msz_forum_posts`
|
||||
WHERE `user_id` = u.`user_id`
|
||||
AND `post_deleted` IS NULL
|
||||
) AS `forum_post_count`,
|
||||
(
|
||||
SELECT COUNT(`change_id`)
|
||||
FROM `msz_changelog_changes`
|
||||
WHERE `user_id` = u.`user_id`
|
||||
) AS `changelog_count`,
|
||||
(
|
||||
SELECT COUNT(`comment_id`)
|
||||
FROM `msz_comments_posts`
|
||||
WHERE `user_id` = u.`user_id`
|
||||
AND `comment_deleted` IS NULL
|
||||
) AS `comments_count`,
|
||||
(
|
||||
SELECT COUNT(`user_id`)
|
||||
FROM `msz_user_relations`
|
||||
WHERE `subject_id` = u.`user_id`
|
||||
AND `relation_type` = %4$d
|
||||
) AS `followers_count`,
|
||||
(
|
||||
SELECT COUNT(`subject_id`)
|
||||
FROM `msz_user_relations`
|
||||
WHERE `user_id` = u.`user_id`
|
||||
AND `relation_type` = %4$d
|
||||
) AS `following_count`
|
||||
FROM `msz_users` AS u
|
||||
LEFT JOIN `msz_roles` AS r
|
||||
ON r.`role_id` = u.`display_role`
|
||||
WHERE `user_id` = :user_id
|
||||
LIMIT 1
|
||||
',
|
||||
pdo_prepare_array(user_profile_fields_get(), true, 'u.`user_%s`'),
|
||||
MSZ_USER_BACKGROUND_ATTRIBUTE_BLEND,
|
||||
MSZ_USER_BACKGROUND_ATTRIBUTE_SLIDE,
|
||||
MSZ_USER_RELATION_FOLLOW
|
||||
)
|
||||
);
|
||||
$getProfile->bind('user_id', $userId);
|
||||
return $getProfile->fetch();
|
||||
}
|
|
@ -22,7 +22,6 @@ function user_relation_set(int $userId, int $subjectId, int $type = MSZ_USER_REL
|
|||
return false;
|
||||
}
|
||||
|
||||
// TODO: don't use REPLACE INTO
|
||||
$addRelation = \Misuzu\DB::prepare('
|
||||
REPLACE INTO `msz_user_relations`
|
||||
(`user_id`, `subject_id`, `relation_type`)
|
||||
|
|
|
@ -39,22 +39,6 @@ function user_find_for_reset(string $email): array {
|
|||
return $getUser->fetch();
|
||||
}
|
||||
|
||||
function user_find_for_profile(string $idOrUsername): int {
|
||||
$getUserId = \Misuzu\DB::prepare('
|
||||
SELECT
|
||||
:user_id as `input_id`,
|
||||
(
|
||||
SELECT `user_id`
|
||||
FROM `msz_users`
|
||||
WHERE `user_id` = `input_id`
|
||||
OR LOWER(`username`) = LOWER(`input_id`)
|
||||
LIMIT 1
|
||||
) as `user_id`
|
||||
');
|
||||
$getUserId->bind('user_id', $idOrUsername);
|
||||
return (int)$getUserId->fetchColumn(1, 0);
|
||||
}
|
||||
|
||||
function user_password_hash(string $password): string {
|
||||
return password_hash($password, MSZ_USERS_PASSWORD_HASH_ALGO);
|
||||
}
|
||||
|
@ -444,9 +428,7 @@ define('MSZ_TMP_USER_ERROR_STRINGS', [
|
|||
'profile' => [
|
||||
'_' => 'An unexpected error occurred, contact an administator.',
|
||||
'not-allowed' => "You're not allowed to edit your profile.",
|
||||
MSZ_USER_PROFILE_INVALID_FIELD => "Field '%1\$s' does not exist!",
|
||||
MSZ_USER_PROFILE_FILTER_FAILED => '%2$s field was invalid!',
|
||||
MSZ_USER_PROFILE_UPDATE_FAILED => 'Failed to update profile, contact an administator.',
|
||||
'invalid' => '%s was formatted incorrectly!',
|
||||
],
|
||||
'about' => [
|
||||
'_' => 'An unexpected error occurred, contact an administator.',
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
<div class="profile__header__avatar">
|
||||
{% if profile_is_editing and perms.edit_avatar %}
|
||||
<label class="profile__header__avatar__image profile__header__avatar__image--edit" for="avatar-selection">
|
||||
{{ avatar(profile.user_id, 120, profile.username, {'id': 'avatar-preview'}) }}
|
||||
{{ avatar(profile_user.user_id, 120, profile_user.username, {'id': 'avatar-preview'}) }}
|
||||
</label>
|
||||
|
||||
<div class="profile__header__avatar__options">
|
||||
|
@ -24,27 +24,27 @@
|
|||
</div>
|
||||
{% else %}
|
||||
<div class="profile__header__avatar__image">
|
||||
{{ avatar(profile.user_id|default(0), 120, profile.username|default('')) }}
|
||||
{{ avatar(profile_user.user_id|default(0), 120, profile_user.username|default('')) }}
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<div class="profile__header__details__content">
|
||||
{% if profile is defined %}
|
||||
<div class="profile__header__username" style="{{ profile.user_colour|html_colour }}">
|
||||
{{ profile.username }}
|
||||
{% if profile_user is defined %}
|
||||
<div class="profile__header__username" style="{{ profile_user.user_colour|html_colour }}">
|
||||
{{ profile_user.username }}
|
||||
</div>
|
||||
|
||||
{% if profile.user_title is not empty %}
|
||||
{% if profile_user.user_title is not empty %}
|
||||
<div class="profile__header__title">
|
||||
{{ profile.user_title }}
|
||||
{{ profile_user.user_title }}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<div class="profile__header__country">
|
||||
<div class="flag flag--{{ profile.user_country|lower }}"></div>
|
||||
<div class="flag flag--{{ profile_user.user_country|lower }}"></div>
|
||||
<div class="profile__header__country__name">
|
||||
{{ profile.user_country|country_name }}{% if profile.user_age > 0 %}, {{ profile.user_age }} year{{ profile.user_age != 's' ? 's' : '' }} old{% endif %}
|
||||
{{ profile_user.user_country|country_name }}{% if profile_user.user_age > 0 %}, {{ profile_user.user_age }} year{{ profile_user.user_age != 's' ? 's' : '' }} old{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
{% else %}
|
||||
|
@ -57,7 +57,7 @@
|
|||
{% endif %}
|
||||
</div>
|
||||
|
||||
{% if profile is defined and profile_relation_info|length > 0 and (profile_relation_info.subject_relation is not null or profile_relation_info.user_relation is not null) %}
|
||||
{% if profile_user is defined and profile_relation_info|length > 0 and (profile_relation_info.subject_relation is not null or profile_relation_info.user_relation is not null) %}
|
||||
<div class="profile__header__details__relation" title="Since {{ profile_relation_info.relation_created|date('r') }}">
|
||||
{% if profile_relation_info.subject_relation and profile_relation_info.user_relation %}
|
||||
Mutual Friends
|
||||
|
@ -71,26 +71,26 @@
|
|||
</div>
|
||||
|
||||
<div class="profile__header__options">
|
||||
{% if profile is defined %}
|
||||
{% if profile_user is defined %}
|
||||
<div class="profile__header__actions">
|
||||
{% if profile_mode is empty %}
|
||||
{% if profile_is_editing %}
|
||||
<button class="input__button input__button--save profile__header__action">Save</button>
|
||||
<a href="{{ url('user-profile', {'user': profile.user_id}) }}" class="input__button input__button--destroy profile__header__action">Discard</a>
|
||||
<a href="{{ url('user-profile', {'user': profile_user.user_id}) }}" class="input__button input__button--destroy profile__header__action">Discard</a>
|
||||
<a href="{{ url('settings-index') }}" class="input__button profile__header__action">Settings</a>
|
||||
{% elseif profile_can_edit %}
|
||||
<a href="{{ url('user-profile-edit', {'user': profile.user_id}) }}" class="input__button profile__header__action">Edit Profile</a>
|
||||
<a href="{{ url('user-profile-edit', {'user': profile_user.user_id}) }}" class="input__button profile__header__action">Edit Profile</a>
|
||||
{% endif %}
|
||||
|
||||
{% if current_user is defined and current_user.user_id != profile.user_id and not profile_is_editing %}
|
||||
{% if current_user is defined and current_user.user_id != profile_user.user_id and not profile_is_editing %}
|
||||
{% if profile_relation_info.user_relation == constant('MSZ_USER_RELATION_FOLLOW') %}
|
||||
<a href="{{ url('user-relation-none', {'user': profile.user_id}) }}" class="input__button input__button--destroy profile__header__action js-user-relation-action" data-relation-user="{{ profile.user_id }}" data-relation-type="{{ constant('MSZ_USER_RELATION_NONE') }}">Unfollow</a>
|
||||
<a href="{{ url('user-relation-none', {'user': profile_user.user_id}) }}" class="input__button input__button--destroy profile__header__action js-user-relation-action" data-relation-user="{{ profile_user.user_id }}" data-relation-type="{{ constant('MSZ_USER_RELATION_NONE') }}">Unfollow</a>
|
||||
{% else %}
|
||||
<a href="{{ url('user-relation-follow', {'user': profile.user_id}) }}" class="input__button profile__header__action js-user-relation-action" data-relation-user="{{ profile.user_id }}" data-relation-type="{{ constant('MSZ_USER_RELATION_FOLLOW') }}">Follow</a>
|
||||
<a href="{{ url('user-relation-follow', {'user': profile_user.user_id}) }}" class="input__button profile__header__action js-user-relation-action" data-relation-user="{{ profile_user.user_id }}" data-relation-type="{{ constant('MSZ_USER_RELATION_FOLLOW') }}">Follow</a>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% else %}
|
||||
<a href="{{ url('user-profile', {'user': profile.user_id}) }}" class="input__button profile__header__action">Return</a>
|
||||
<a href="{{ url('user-profile', {'user': profile_user.user_id}) }}" class="input__button profile__header__action">Return</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
|
|
@ -3,16 +3,16 @@
|
|||
{% from 'user/macros.twig' import user_profile_warning %}
|
||||
{% from '_layout/input.twig' import input_hidden, input_csrf, input_text, input_checkbox, input_file, input_file_raw, input_select %}
|
||||
|
||||
{% if profile is defined %}
|
||||
{% set canonical_url = url('user-profile', {'user': profile.user_id}) %}
|
||||
{% set title = profile.username %}
|
||||
{% if profile_user is defined %}
|
||||
{% set canonical_url = url('user-profile', {'user': profile_user.user_id}) %}
|
||||
{% set title = profile_user.username %}
|
||||
{% else %}
|
||||
{% set title = 'User not found!' %}
|
||||
{% endif %}
|
||||
|
||||
{% block content %}
|
||||
{% if profile_is_editing %}
|
||||
<form class="profile" method="post" action="{{ url('user-profile', {'user': profile.user_id}) }}" enctype="multipart/form-data">
|
||||
<form class="profile" method="post" action="{{ url('user-profile', {'user': profile_user.user_id}) }}" enctype="multipart/form-data">
|
||||
{{ input_csrf('profile') }}
|
||||
|
||||
{% if perms.edit_avatar %}
|
||||
|
@ -20,7 +20,7 @@
|
|||
|
||||
<script>
|
||||
function updateAvatarPreview(name, url, preview) {
|
||||
url = url || "{{ url('user-avatar', {'user': profile.user_id, 'res': 240})|raw }}";
|
||||
url = url || "{{ url('user-avatar', {'user': profile_user.user_id, 'res': 240})|raw }}";
|
||||
preview = preview || document.getElementById('avatar-preview');
|
||||
preview.src = url;
|
||||
preview.title = name;
|
||||
|
@ -70,13 +70,14 @@
|
|||
<div class="warning">
|
||||
<div class="warning__content">
|
||||
{% for notice in profile_notices %}
|
||||
{{ notice }}
|
||||
<p>{{ notice }}</p>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<div class="profile__content">
|
||||
{% set profile_fields = profile_user.profileFields(not (profile_is_editing and perms.edit_profile)) %}
|
||||
{% set show_profile_fields = profile_is_editing ? perms.edit_profile : profile_fields|default([])|length > 0 %}
|
||||
{% set show_background_settings = profile_is_editing and perms.edit_background %}
|
||||
{% set show_birthdate = profile_is_editing and perms.edit_birthdate %}
|
||||
|
@ -93,11 +94,11 @@
|
|||
|
||||
{{ input_checkbox('background[attach]', 'None', true, '', 0, true, {'onchange':'profileChangeBackgroundAttach(this.value)'}) }}
|
||||
{% for key, value in background_attachments %}
|
||||
{{ input_checkbox('background[attach]', value|capitalize, key == profile.user_background_attachment, '', key, true, {'onchange':'profileChangeBackgroundAttach(this.value)'}) }}
|
||||
{{ input_checkbox('background[attach]', value|capitalize, key == profile_user.backgroundAttachment, '', key, true, {'onchange':'profileChangeBackgroundAttach(this.value)'}) }}
|
||||
{% endfor %}
|
||||
|
||||
{{ input_checkbox('background[attr][blend]', 'Blend', profile.user_background_blend, '', '', false, {'onchange':'profileToggleBackgroundAttr(\'blend\', this.checked)'}) }}
|
||||
{{ input_checkbox('background[attr][slide]', 'Slide', profile.user_background_slide, '', '', false, {'onchange':'profileToggleBackgroundAttr(\'slide\', this.checked)'}) }}
|
||||
{{ input_checkbox('background[attr][blend]', 'Blend', profile_user.backgroundBlend, '', '', false, {'onchange':'profileToggleBackgroundAttr(\'blend\', this.checked)'}) }}
|
||||
{{ input_checkbox('background[attr][slide]', 'Slide', profile_user.backgroundSlide, '', '', false, {'onchange':'profileToggleBackgroundAttr(\'slide\', this.checked)'}) }}
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
@ -112,22 +113,21 @@
|
|||
{{ container_title('Elsewhere') }}
|
||||
|
||||
<div class="profile__accounts__content">
|
||||
{% for name, data in profile_fields %}
|
||||
{% for field in profile_fields %}
|
||||
<label class="profile__accounts__item">
|
||||
<div class="profile__accounts__title">
|
||||
{{ data.name }}
|
||||
{{ field.field_title }}
|
||||
</div>
|
||||
|
||||
{% if profile_is_editing %}
|
||||
{{ input_text('profile[' ~ name ~ ']', 'profile__accounts__input', profile['user_' ~ name], data.type|default('text')) }}
|
||||
{{ input_text('profile[' ~ field.field_key ~ ']', 'profile__accounts__input', field.field_value, data.type|default('text')) }}
|
||||
{% else %}
|
||||
<div class="profile__accounts__value"
|
||||
{% if data.tooltip is defined %}title="{{ data.tooltip|format(data.value)|raw }}"{% endif %}>
|
||||
{% set profile_field_value = (data.format is defined ? data.format : '%s')|format(data.value) %}
|
||||
{% if data.link is defined %}
|
||||
{{ data.link|format(data.value)|html_link(profile_field_value, 'profile__accounts__link')|raw }}
|
||||
{% else %}
|
||||
<div class="profile__accounts__value">
|
||||
{% set profile_field_value = field.format_display|format(field.field_value) %}
|
||||
{% if field.format_link is empty %}
|
||||
{{ profile_field_value }}
|
||||
{% else %}
|
||||
{{ field.format_link|format(field.field_value)|html_link(profile_field_value, 'profile__accounts__link')|raw }}
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
@ -140,7 +140,7 @@
|
|||
<div class="container profile__container profile__birthdate">
|
||||
{{ container_title('Birthdate') }}
|
||||
|
||||
{% set birthdate = profile.user_birthdate|split('-') %}
|
||||
{% set birthdate = profile_user.user_birthdate|split('-') %}
|
||||
|
||||
<div class="profile__birthdate__content">
|
||||
<div class="profile__birthdate__date">
|
||||
|
@ -173,37 +173,37 @@
|
|||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if profile is defined %}
|
||||
{% if profile_user is defined %}
|
||||
<div class="profile__content__main">
|
||||
{% if (profile_is_editing and perms.edit_about) or profile.user_about_content|length > 0 %}
|
||||
{% if (profile_is_editing and perms.edit_about) or profile_user.user_about_content|length > 0 %}
|
||||
<div class="container profile__container profile__about" id="about">
|
||||
{{ container_title('About ' ~ profile.username) }}
|
||||
{{ container_title('About ' ~ profile_user.username) }}
|
||||
|
||||
{% if profile_is_editing %}
|
||||
<div class="profile__signature__editor">
|
||||
{{ input_select('about[parser]', constant('MSZ_PARSERS_NAMES'), profile.user_about_parser, '', '', false, 'profile__about__select') }}
|
||||
<textarea name="about[text]" class="input__textarea profile__about__text" id="about-textarea">{{ profile.user_about_content|escape }}</textarea>
|
||||
{{ input_select('about[parser]', constant('MSZ_PARSERS_NAMES'), profile_user.user_about_parser, '', '', false, 'profile__about__select') }}
|
||||
<textarea name="about[text]" class="input__textarea profile__about__text" id="about-textarea">{{ profile_user.user_about_content|escape }}</textarea>
|
||||
</div>
|
||||
{% else %}
|
||||
<div class="profile__about__content{% if profile_is_editing %} profile__about__content--edit{% elseif profile.user_about_parser == constant('MSZ_PARSER_MARKDOWN') %} markdown{% endif %}">
|
||||
{{ profile.user_about_content|escape|parse_text(profile.user_about_parser)|raw }}
|
||||
<div class="profile__about__content{% if profile_is_editing %} profile__about__content--edit{% elseif profile_user.user_about_parser == constant('MSZ_PARSER_MARKDOWN') %} markdown{% endif %}">
|
||||
{{ profile_user.user_about_content|escape|parse_text(profile_user.user_about_parser)|raw }}
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if (profile_is_editing and perms.edit_signature) or profile.user_signature_content|length > 0 %}
|
||||
{% if (profile_is_editing and perms.edit_signature) or profile_user.user_signature_content|length > 0 %}
|
||||
<div class="container profile__container profile__signature" id="signature">
|
||||
{{ container_title('Signature') }}
|
||||
|
||||
{% if profile_is_editing %}
|
||||
<div class="profile__signature__editor">
|
||||
{{ input_select('signature[parser]', constant('MSZ_PARSERS_NAMES'), profile.user_signature_parser, '', '', false, 'profile__signature__select') }}
|
||||
<textarea name="signature[text]" class="input__textarea profile__signature__text" id="signature-textarea">{{ profile.user_signature_content|escape }}</textarea>
|
||||
{{ input_select('signature[parser]', constant('MSZ_PARSERS_NAMES'), profile_user.user_signature_parser, '', '', false, 'profile__signature__select') }}
|
||||
<textarea name="signature[text]" class="input__textarea profile__signature__text" id="signature-textarea">{{ profile_user.user_signature_content|escape }}</textarea>
|
||||
</div>
|
||||
{% else %}
|
||||
<div class="profile__signature__content{% if profile_is_editing %} profile__signature__content--edit{% elseif profile.user_signature_parser == constant('MSZ_PARSER_MARKDOWN') %} markdown{% endif %}">
|
||||
{{ profile.user_signature_content|escape|parse_text(profile.user_signature_parser)|raw }}
|
||||
<div class="profile__signature__content{% if profile_is_editing %} profile__signature__content--edit{% elseif profile_user.user_signature_parser == constant('MSZ_PARSER_MARKDOWN') %} markdown{% endif %}">
|
||||
{{ profile_user.user_signature_content|escape|parse_text(profile_user.user_signature_parser)|raw }}
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
@ -211,7 +211,7 @@
|
|||
|
||||
{% if profile_warnings|length > 0 or profile_warnings_can_manage %}
|
||||
<div class="container profile__container profile__warning__container" id="account-standing">
|
||||
{{ container_title('Account Standing', false, profile_warnings_can_manage ? url('manage-users-warnings', {'user': profile.user_id}) : '') }}
|
||||
{{ container_title('Account Standing', false, profile_warnings_can_manage ? url('manage-users-warnings', {'user': profile_user.user_id}) : '') }}
|
||||
|
||||
<div class="profile__warning">
|
||||
<div class="profile__warning__background"></div>
|
||||
|
|
|
@ -1,50 +1,50 @@
|
|||
{% extends 'master.twig' %}
|
||||
|
||||
{% if profile is defined %}
|
||||
{% set image = url('user-avatar', {'user': profile.user_id, 'res': 200}) %}
|
||||
{% set manage_link = url('manage-user', {'user': profile.user_id}) %}
|
||||
{% if profile_user is defined %}
|
||||
{% set image = url('user-avatar', {'user': profile_user.user_id, 'res': 200}) %}
|
||||
{% set manage_link = url('manage-user', {'user': profile_user.user_id}) %}
|
||||
{% set stats = [
|
||||
{
|
||||
'title': 'Joined',
|
||||
'is_date': true,
|
||||
'value': profile.user_created,
|
||||
'value': profile_user.user_created,
|
||||
},
|
||||
{
|
||||
'title': 'Last seen',
|
||||
'is_date': true,
|
||||
'value': profile.user_active,
|
||||
'value': profile_user.user_active,
|
||||
},
|
||||
{
|
||||
'title': 'Following',
|
||||
'value': profile.following_count,
|
||||
'url': url('user-profile-following', {'user': profile.user_id}),
|
||||
'value': profile_stats.following_count,
|
||||
'url': url('user-profile-following', {'user': profile_user.user_id}),
|
||||
'active': profile_mode == 'following',
|
||||
},
|
||||
{
|
||||
'title': 'Followers',
|
||||
'value': profile.followers_count,
|
||||
'url': url('user-profile-followers', {'user': profile.user_id}),
|
||||
'value': profile_stats.followers_count,
|
||||
'url': url('user-profile-followers', {'user': profile_user.user_id}),
|
||||
'active': profile_mode == 'followers',
|
||||
},
|
||||
{
|
||||
'title': 'Topics',
|
||||
'value': profile.forum_topic_count,
|
||||
'url': url('user-profile-forum-topics', {'user': profile.user_id}),
|
||||
'value': profile_stats.forum_topic_count,
|
||||
'url': url('user-profile-forum-topics', {'user': profile_user.user_id}),
|
||||
'active': profile_mode == 'forum-topics',
|
||||
},
|
||||
{
|
||||
'title': 'Posts',
|
||||
'value': profile.forum_post_count,
|
||||
'url': url('user-profile-forum-posts', {'user': profile.user_id}),
|
||||
'value': profile_stats.forum_post_count,
|
||||
'url': url('user-profile-forum-posts', {'user': profile_user.user_id}),
|
||||
'active': profile_mode == 'forum-posts',
|
||||
},
|
||||
{
|
||||
'title': 'Comments',
|
||||
'value': profile.comments_count,
|
||||
'value': profile_stats.comments_count,
|
||||
},
|
||||
{
|
||||
'title': 'Changes',
|
||||
'value': profile.changelog_count,
|
||||
'value': profile_stats.changelog_count,
|
||||
},
|
||||
] %}
|
||||
{% else %}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue