mirror of
https://github.com/openvk/openvk
synced 2025-03-15 14:05:36 +03:00
Merge branch 'master' into feature-reports
This commit is contained in:
commit
f86963dedd
88 changed files with 2756 additions and 312 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -5,7 +5,7 @@ update.pid.old
|
||||||
Web/static/js/node_modules
|
Web/static/js/node_modules
|
||||||
|
|
||||||
tmp/*
|
tmp/*
|
||||||
!tmp/.gitkeep
|
!tmp/api-storage
|
||||||
!tmp/themepack_artifacts/.gitkeep
|
!tmp/themepack_artifacts/.gitkeep
|
||||||
themepacks/*
|
themepacks/*
|
||||||
!themepacks/.gitkeep
|
!themepacks/.gitkeep
|
||||||
|
|
8
.idea/.gitignore
vendored
Normal file
8
.idea/.gitignore
vendored
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
# Default ignored files
|
||||||
|
/shelf/
|
||||||
|
/workspace.xml
|
||||||
|
# Editor-based HTTP Client requests
|
||||||
|
/httpRequests/
|
||||||
|
# Datasource local storage ignored files
|
||||||
|
/dataSources/
|
||||||
|
/dataSources.local.xml
|
46
.idea/intellij-latte/xmlSources/Latte.dtd
Normal file
46
.idea/intellij-latte/xmlSources/Latte.dtd
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
<?xml encoding="UTF-8"?>
|
||||||
|
|
||||||
|
<!ELEMENT latte (tags,filters,variables,functions)>
|
||||||
|
<!ATTLIST latte vendor #REQUIRED>
|
||||||
|
<!ATTLIST latte version #REQUIRED>
|
||||||
|
|
||||||
|
<!ELEMENT tags (tag)+>
|
||||||
|
|
||||||
|
<!ELEMENT tag (arguments)?>
|
||||||
|
<!ATTLIST tag name CDATA #REQUIRED>
|
||||||
|
<!ATTLIST tag type (PAIR|UNPAIRED|UNPAIRED_ATTR|ATTR_ONLY|AUTO_EMPTY) #REQUIRED>
|
||||||
|
<!ATTLIST tag allowedFilters (true|false) #IMPLIED>
|
||||||
|
<!ATTLIST tag arguments CDATA #IMPLIED>
|
||||||
|
<!ATTLIST tag deprecatedMessage CDATA #IMPLIED>
|
||||||
|
<!ATTLIST tag multiLine (true|false) #IMPLIED>
|
||||||
|
|
||||||
|
<!ELEMENT arguments (argument)+>
|
||||||
|
|
||||||
|
<!ELEMENT argument EMPTY>
|
||||||
|
<!ATTLIST argument name #REQUIRED>
|
||||||
|
<!ATTLIST argument types CDATA #REQUIRED>
|
||||||
|
<!ATTLIST argument repeatable (true|false) #IMPLIED>
|
||||||
|
<!ATTLIST argument required (true|false) #IMPLIED>
|
||||||
|
<!ATTLIST argument validType #IMPLIED>
|
||||||
|
|
||||||
|
<!ELEMENT filters (filter)+>
|
||||||
|
|
||||||
|
<!ELEMENT filter EMPTY>
|
||||||
|
<!ATTLIST filter name #REQUIRED>
|
||||||
|
<!ATTLIST filter description CDATA #IMPLIED>
|
||||||
|
<!ATTLIST filter arguments CDATA #IMPLIED>
|
||||||
|
<!ATTLIST filter insertColons #IMPLIED>
|
||||||
|
|
||||||
|
<!ELEMENT variables (variable)+>
|
||||||
|
|
||||||
|
<!ELEMENT variable EMPTY>
|
||||||
|
<!ATTLIST variable name #REQUIRED>
|
||||||
|
<!ATTLIST variable type CDATA #REQUIRED>
|
||||||
|
|
||||||
|
<!ELEMENT functions (function)+>
|
||||||
|
|
||||||
|
<!ELEMENT function EMPTY>
|
||||||
|
<!ATTLIST function name #REQUIRED>
|
||||||
|
<!ATTLIST function arguments CDATA #REQUIRED>
|
||||||
|
<!ATTLIST function returnType #REQUIRED>
|
||||||
|
<!ATTLIST function description CDATA #IMPLIED>
|
290
.idea/intellij-latte/xmlSources/Latte.xml
Normal file
290
.idea/intellij-latte/xmlSources/Latte.xml
Normal file
|
@ -0,0 +1,290 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE latte PUBLIC "-//LATTE//Latte plugin XML V0.0.1//EN" "Latte.dtd">
|
||||||
|
<latte vendor="latte" version="1">
|
||||||
|
<tags>
|
||||||
|
<tag name="_" type="AUTO_EMPTY" allowedFilters="true">
|
||||||
|
<arguments>
|
||||||
|
<argument name="expression" types="PHP_EXPRESSION" validType="string" required="true" />
|
||||||
|
</arguments>
|
||||||
|
</tag>
|
||||||
|
<tag name="=" type="UNPAIRED" allowedFilters="true">
|
||||||
|
<arguments>
|
||||||
|
<argument name="expression" types="PHP_EXPRESSION" validType="string" required="true" />
|
||||||
|
</arguments>
|
||||||
|
</tag>
|
||||||
|
<tag name="block" type="AUTO_EMPTY" allowedFilters="true" multiLine="true">
|
||||||
|
<arguments>
|
||||||
|
<argument name="name" types="PHP_IDENTIFIER,VARIABLE,PHP_EXPRESSION" validType="string" required="true" />
|
||||||
|
</arguments>
|
||||||
|
</tag>
|
||||||
|
<tag name="breakIf" type="UNPAIRED">
|
||||||
|
<arguments>
|
||||||
|
<argument name="condition" types="PHP_CONDITION" validType="bool" required="true" />
|
||||||
|
</arguments>
|
||||||
|
</tag>
|
||||||
|
<tag name="capture" type="PAIR" allowedFilters="true" multiLine="true">
|
||||||
|
<arguments>
|
||||||
|
<argument name="variable" types="VARIABLE_DEFINITION" required="true" />
|
||||||
|
</arguments>
|
||||||
|
</tag>
|
||||||
|
<tag name="case" type="UNPAIRED">
|
||||||
|
<arguments>
|
||||||
|
<argument name="condition" types="PHP_CONDITION" required="true" repeatable="true" />
|
||||||
|
</arguments>
|
||||||
|
</tag>
|
||||||
|
<tag name="catch" type="UNPAIRED">
|
||||||
|
<arguments>
|
||||||
|
<argument name="condition" types="PHP_CONDITION" validType="bool" required="true" />
|
||||||
|
</arguments>
|
||||||
|
</tag>
|
||||||
|
<tag name="contentType" type="UNPAIRED">
|
||||||
|
<arguments>
|
||||||
|
<argument name="content-type" types="CONTENT_TYPE" validType="string" required="true" />
|
||||||
|
</arguments>
|
||||||
|
</tag>
|
||||||
|
<tag name="continueIf" type="UNPAIRED">
|
||||||
|
<arguments>
|
||||||
|
<argument name="condition" types="PHP_CONDITION" validType="bool" required="true" />
|
||||||
|
</arguments>
|
||||||
|
</tag>
|
||||||
|
<tag name="debugbreak" type="UNPAIRED">
|
||||||
|
<arguments>
|
||||||
|
<argument name="expression" types="PHP_EXPRESSION" required="true" />
|
||||||
|
</arguments>
|
||||||
|
</tag>
|
||||||
|
<tag name="default" type="UNPAIRED">
|
||||||
|
<arguments>
|
||||||
|
<argument name="variable" types="VARIABLE_DEFINITION_EXPRESSION" required="true" repeatable="true" />
|
||||||
|
</arguments>
|
||||||
|
</tag>
|
||||||
|
<tag name="define" type="PAIR" multiLine="true">
|
||||||
|
<arguments>
|
||||||
|
<argument name="name" types="PHP_IDENTIFIER,VARIABLE,PHP_EXPRESSION" required="true" />
|
||||||
|
<argument name="variable" types="VARIABLE_DEFINITION_ITEM" repeatable="true" />
|
||||||
|
</arguments>
|
||||||
|
</tag>
|
||||||
|
<tag name="do" type="UNPAIRED">
|
||||||
|
<arguments>
|
||||||
|
<argument name="expression" types="PHP_EXPRESSION" required="true" />
|
||||||
|
</arguments>
|
||||||
|
</tag>
|
||||||
|
<tag name="dump" type="UNPAIRED">
|
||||||
|
<arguments>
|
||||||
|
<argument name="expression" types="PHP_EXPRESSION" required="true" />
|
||||||
|
</arguments>
|
||||||
|
</tag>
|
||||||
|
<tag name="else" type="UNPAIRED_ATTR" />
|
||||||
|
<tag name="elseif" type="UNPAIRED">
|
||||||
|
<arguments>
|
||||||
|
<argument name="condition" types="PHP_CONDITION" validType="bool" required="true" />
|
||||||
|
</arguments>
|
||||||
|
</tag>
|
||||||
|
<tag name="elseifset" type="UNPAIRED">
|
||||||
|
<arguments>
|
||||||
|
<argument name="var" types="VARIABLE,BLOCK" validType="string" required="true" />
|
||||||
|
</arguments>
|
||||||
|
</tag>
|
||||||
|
<tag name="extends" type="UNPAIRED">
|
||||||
|
<arguments>
|
||||||
|
<argument name="file" types="PHP_IDENTIFIER,VARIABLE,PHP_EXPRESSION,NONE" validType="string" required="true" />
|
||||||
|
</arguments>
|
||||||
|
</tag>
|
||||||
|
<tag name="first" type="PAIR">
|
||||||
|
<arguments>
|
||||||
|
<argument name="width" types="PHP_IDENTIFIER,PHP_EXPRESSION" validType="int" required="true" />
|
||||||
|
</arguments>
|
||||||
|
</tag>
|
||||||
|
<tag name="for" type="PAIR" arguments="initialization; condition; afterthought" multiLine="true" />
|
||||||
|
<tag name="foreach" type="PAIR" arguments="expression as [$key =>] $value" allowedFilters="true" multiLine="true" />
|
||||||
|
<tag name="if" type="PAIR">
|
||||||
|
<arguments>
|
||||||
|
<argument name="condition" types="PHP_CONDITION" validType="bool" required="true" />
|
||||||
|
</arguments>
|
||||||
|
</tag>
|
||||||
|
<tag name="ifset" type="PAIR">
|
||||||
|
<arguments>
|
||||||
|
<argument name="var" types="VARIABLE,BLOCK,PHP_EXPRESSION" validType="string" required="true" />
|
||||||
|
</arguments>
|
||||||
|
</tag>
|
||||||
|
<tag name="import" type="UNPAIRED">
|
||||||
|
<arguments>
|
||||||
|
<argument name="file" types="PHP_IDENTIFIER,VARIABLE,PHP_EXPRESSION" validType="string" required="true" />
|
||||||
|
</arguments>
|
||||||
|
</tag>
|
||||||
|
<tag name="include" type="UNPAIRED" allowedFilters="true">
|
||||||
|
<arguments>
|
||||||
|
<argument name="file" types="BLOCK,IDENTIFIER,PHP_EXPRESSION" validType="string" required="true" />
|
||||||
|
<argument name="arguments" types="KEY_VALUE" repeatable="true" />
|
||||||
|
</arguments>
|
||||||
|
</tag>
|
||||||
|
<tag name="includeblock" type="UNPAIRED">
|
||||||
|
<arguments>
|
||||||
|
<argument name="file" types="PHP_IDENTIFIER,VARIABLE,PHP_EXPRESSION" validType="string" required="true" />
|
||||||
|
</arguments>
|
||||||
|
</tag>
|
||||||
|
<tag name="l" type="UNPAIRED" />
|
||||||
|
<tag name="last" type="PAIR">
|
||||||
|
<arguments>
|
||||||
|
<argument name="width" types="PHP_IDENTIFIER,PHP_EXPRESSION" validType="int" required="true" />
|
||||||
|
</arguments>
|
||||||
|
</tag>
|
||||||
|
<tag name="layout" type="UNPAIRED">
|
||||||
|
<arguments>
|
||||||
|
<argument name="file" types="PHP_IDENTIFIER,VARIABLE,PHP_EXPRESSION,NONE" validType="string" required="true" />
|
||||||
|
</arguments>
|
||||||
|
</tag>
|
||||||
|
<tag name="class" type="ATTR_ONLY" arguments="class" />
|
||||||
|
<tag name="attr" type="ATTR_ONLY" arguments="attr" />
|
||||||
|
<tag name="ifcontent" type="ATTR_ONLY" />
|
||||||
|
<tag name="php" type="UNPAIRED">
|
||||||
|
<arguments>
|
||||||
|
<argument name="expression" types="PHP_EXPRESSION" required="true" />
|
||||||
|
</arguments>
|
||||||
|
</tag>
|
||||||
|
<tag name="r" type="UNPAIRED" />
|
||||||
|
<tag name="sandbox" type="UNPAIRED">
|
||||||
|
<arguments>
|
||||||
|
<argument name="file" types="BLOCK,PHP_IDENTIFIER,VARIABLE,PHP_EXPRESSION" validType="string" required="true" />
|
||||||
|
<argument name="key-value" types="KEY_VALUE" repeatable="true" />
|
||||||
|
</arguments>
|
||||||
|
</tag>
|
||||||
|
<tag name="sep" type="PAIR">
|
||||||
|
<arguments>
|
||||||
|
<argument name="width" types="PHP_IDENTIFIER,PHP_EXPRESSION" validType="int" />
|
||||||
|
</arguments>
|
||||||
|
</tag>
|
||||||
|
<tag name="snippet" type="PAIR" multiLine="true">
|
||||||
|
<arguments>
|
||||||
|
<argument name="name" types="PHP_IDENTIFIER,VARIABLE,PHP_EXPRESSION" validType="string" />
|
||||||
|
</arguments>
|
||||||
|
</tag>
|
||||||
|
<tag name="snippetArea" type="PAIR" multiLine="true">
|
||||||
|
<arguments>
|
||||||
|
<argument name="name" types="PHP_IDENTIFIER,PHP_EXPRESSION" validType="string" required="true" />
|
||||||
|
</arguments>
|
||||||
|
</tag>
|
||||||
|
<tag name="spaceless" type="PAIR" />
|
||||||
|
<tag name="switch" type="PAIR" multiLine="true">
|
||||||
|
<arguments>
|
||||||
|
<argument name="expression" types="PHP_EXPRESSION" />
|
||||||
|
</arguments>
|
||||||
|
</tag>
|
||||||
|
<tag name="syntax" type="PAIR" arguments="off | double | latte" multiLine="true" />
|
||||||
|
<tag name="templatePrint" type="UNPAIRED">
|
||||||
|
<arguments>
|
||||||
|
<argument name="class-name" types="PHP_CLASS_NAME" />
|
||||||
|
</arguments>
|
||||||
|
</tag>
|
||||||
|
<tag name="templateType" type="UNPAIRED">
|
||||||
|
<arguments>
|
||||||
|
<argument name="class-name" types="PHP_CLASS_NAME" required="true" />
|
||||||
|
</arguments>
|
||||||
|
</tag>
|
||||||
|
<tag name="try" type="PAIR" />
|
||||||
|
<tag name="rollback" type="UNPAIRED" />
|
||||||
|
<tag name="tag" type="ATTR_ONLY">
|
||||||
|
<arguments>
|
||||||
|
<argument name="expression" types="PHP_EXPRESSION" required="true" validType="string" repeatable="true" />
|
||||||
|
</arguments>
|
||||||
|
</tag>
|
||||||
|
<tag name="ifchanged" type="PAIR">
|
||||||
|
<arguments>
|
||||||
|
<argument name="expression" types="PHP_EXPRESSION" required="true" repeatable="true" />
|
||||||
|
</arguments>
|
||||||
|
</tag>
|
||||||
|
<tag name="skipIf" type="UNPAIRED">
|
||||||
|
<arguments>
|
||||||
|
<argument name="condition" types="PHP_CONDITION" validType="bool" required="true" />
|
||||||
|
</arguments>
|
||||||
|
</tag>
|
||||||
|
<tag name="var" type="UNPAIRED">
|
||||||
|
<arguments>
|
||||||
|
<argument name="variable" types="VARIABLE_DEFINITION_EXPRESSION" required="true" repeatable="true" />
|
||||||
|
</arguments>
|
||||||
|
</tag>
|
||||||
|
<tag name="trace" type="UNPAIRED" />
|
||||||
|
<tag name="varPrint" type="UNPAIRED" arguments="all" />
|
||||||
|
<tag name="varType" type="UNPAIRED">
|
||||||
|
<arguments>
|
||||||
|
<argument name="file" types="PHP_TYPE" required="true" />
|
||||||
|
<argument name="variable" types="VARIABLE_DEFINITION" required="true" />
|
||||||
|
</arguments>
|
||||||
|
</tag>
|
||||||
|
<tag name="while" type="PAIR" multiLine="true">
|
||||||
|
<arguments>
|
||||||
|
<argument name="condition" types="PHP_CONDITION" validType="bool" required="true" />
|
||||||
|
</arguments>
|
||||||
|
</tag>
|
||||||
|
<tag name="iterateWhile" type="PAIR" multiLine="true" />
|
||||||
|
<tag name="embed" type="PAIR" multiLine="true">
|
||||||
|
<arguments>
|
||||||
|
<argument name="file" types="BLOCK_USAGE,PHP_IDENTIFIER,VARIABLE,PHP_EXPRESSION" validType="string" required="true" />
|
||||||
|
<argument name="key-value" types="KEY_VALUE" repeatable="true" />
|
||||||
|
</arguments>
|
||||||
|
</tag>
|
||||||
|
<!-- @deprecated - latte -->
|
||||||
|
<tag name="assign" type="UNPAIRED" arguments="$variable = expr" />
|
||||||
|
<tag name="truncate" type="UNPAIRED" arguments="expression" deprecatedMessage="Tag {? ...} is deprecated in Latte 2.4. For variable definitions use {var ...} or {php ...} in other cases." />
|
||||||
|
</tags>
|
||||||
|
<filters>
|
||||||
|
<filter name="truncate" arguments=":($length, $append = '…')" description="shortens the length preserving whole words" insertColons=":" />
|
||||||
|
<filter name="substr" arguments=":($offset [, $length])" description="returns part of the string" insertColons=":" />
|
||||||
|
<filter name="trim" arguments=":($charset = mezery)" description="strips whitespace or other characters from the beginning and end of the string" />
|
||||||
|
<filter name="stripHtml" arguments="" description="removes HTML tags and converts HTML entities to text" />
|
||||||
|
<filter name="strip" arguments="" description="removes whitespace" />
|
||||||
|
<filter name="indent" arguments=":($level = 1, $char = '\t')" description="indents the text from left with number of tabs" />
|
||||||
|
<filter name="replace" arguments=":($search, $replace = '')" description="replaces all occurrences of the search string with the replacement" insertColons=":" />
|
||||||
|
<filter name="replaceRE" arguments=":($pattern, $replace = '')" description="replaces all occurrences according to regular expression" insertColons=":" />
|
||||||
|
<filter name="padLeft" arguments=":($length, $pad = ' ')" description="completes the string to given length from left" insertColons=":" />
|
||||||
|
<filter name="padRight" arguments=":($length, $pad = ' ')" description="completes the string to given length from right" insertColons=":" />
|
||||||
|
<filter name="repeat" arguments=":($count)" description="repeats the string" insertColons=":" />
|
||||||
|
<filter name="implode" arguments=":($glue = '')" description="joins an array to a string" />
|
||||||
|
<filter name="webalize" description="adjusts the UTF-8 string to the shape used in the URL" />
|
||||||
|
<filter name="breaklines" description="inserts HTML line breaks before all newlines" />
|
||||||
|
<filter name="reverse" description="reverse an UTF-8 string or array" />
|
||||||
|
<filter name="length" description="returns length of a string or array" />
|
||||||
|
<filter name="sort" description="simply sorts array" />
|
||||||
|
<filter name="reverse" description="array sorted in reverse order (used with |sort)" />
|
||||||
|
<filter name="batch" arguments=":($array, $length [, $item])" description="returns length of a string or array" insertColons="::" />
|
||||||
|
|
||||||
|
<filter name="clamp" description="returns value clamped to the inclusive range of min and max." insertColons="::" />
|
||||||
|
|
||||||
|
<filter name="lower" description="makes a string lower case" />
|
||||||
|
<filter name="upper" description="makes a string upper case" />
|
||||||
|
<filter name="firstUpper" description="makes the first letter upper case" />
|
||||||
|
<filter name="capitalize" description="lower case, the first letter of each word upper case" />
|
||||||
|
|
||||||
|
<filter name="date" arguments=":($format)" description="formats date" insertColons=":" />
|
||||||
|
<filter name="number" arguments=":($decimals = 0, $decPoint = '.', $thousandsSep = ',')" description="format number" />
|
||||||
|
<filter name="bytes" arguments=":($precision = 2)" description="formats size in bytes" />
|
||||||
|
<filter name="dataStream" arguments=":($mimetype = 'detect')" description="Data URI protocol conversion" />
|
||||||
|
|
||||||
|
<filter name="noescape" description="prints a variable without escaping" />
|
||||||
|
<filter name="escapeurl" description="escapes parameter in URL" />
|
||||||
|
|
||||||
|
<filter name="nocheck" description="prevents automatic URL sanitization" />
|
||||||
|
<filter name="checkurl" description="sanitizes string for use inside href attribute" />
|
||||||
|
|
||||||
|
<filter name="query" description="generates a query string in the URL" />
|
||||||
|
<filter name="ceil" arguments=":(int $precision = 0)" description="rounds a number up to a given precision" />
|
||||||
|
<filter name="explode" arguments=":(string $separator = '')" description="splits a string by the given delimiter" />
|
||||||
|
<filter name="first" description="returns first element of array or character of string" />
|
||||||
|
<filter name="floor" arguments=":(int $precision = 0)" description="rounds a number down to a given precision" />
|
||||||
|
<filter name="join" arguments=":(string $glue = '')" description="joins an array to a string" />
|
||||||
|
<filter name="last" description="returns last element of array or character of string" />
|
||||||
|
<filter name="random" description="returns random element of array or character of string" />
|
||||||
|
<filter name="round" arguments=":(int $precision = 0)" description="rounds a number to a given precision" />
|
||||||
|
<filter name="slice" arguments=":(int $start, int $length = null, bool $preserveKeys = false)" description="extracts a slice of an array or a string" insertColons=":" />
|
||||||
|
<filter name="spaceless" description="removes whitespace" />
|
||||||
|
<filter name="split" arguments=":(string $separator = '')" description="splits a string by the given delimiter" />
|
||||||
|
</filters>
|
||||||
|
<functions>
|
||||||
|
<function name="clamp" returnType="int|float" arguments="(int|float $value, int|float $min, int|float $max)" description="clamps value to the inclusive range of min and max" />
|
||||||
|
<function name="divisibleBy" returnType="bool" arguments="(int $value)" description="checks if a variable is divisible by a number" />
|
||||||
|
<function name="even" returnType="bool" arguments="(int $value)" description="checks if the given number is even" />
|
||||||
|
<function name="first" returnType="mixed" arguments="(string|array $value)" description="returns first element of array or character of string" />
|
||||||
|
<function name="last" returnType="mixed" arguments="(string|array $value)" description="returns last element of array or character of string" />
|
||||||
|
<function name="odd" returnType="bool" arguments="(int $value)" description="checks if the given number is odd" />
|
||||||
|
<function name="slice" returnType="string|array" arguments="(string|array $value, int $start, int $length = null, bool $preserveKeys = false)" description="extracts a slice of an array or a string" />
|
||||||
|
</functions>
|
||||||
|
</latte>
|
59
.idea/intellij-latte/xmlSources/NetteApplication.xml
Normal file
59
.idea/intellij-latte/xmlSources/NetteApplication.xml
Normal file
|
@ -0,0 +1,59 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE latte PUBLIC "-//LATTE//Latte plugin configuration XML V0.0.1//EN" "Latte.dtd">
|
||||||
|
<latte version="1" vendor="nette/application">
|
||||||
|
<tags>
|
||||||
|
<!-- nette/application tags -->
|
||||||
|
<tag name="cache" type="PAIR" arguments="if => expr, key, …">
|
||||||
|
<arguments>
|
||||||
|
<argument name="name[:part]" types="KEY_VALUE" validType="string" required="true" />
|
||||||
|
<argument name="arguments" types="PHP_EXPRESSION" repeatable="true" />
|
||||||
|
</arguments>
|
||||||
|
</tag>
|
||||||
|
<tag name="control" type="UNPAIRED">
|
||||||
|
<arguments>
|
||||||
|
<argument name="name[:part]" types="PHP_IDENTIFIER,PHP_EXPRESSION" validType="string" required="true" />
|
||||||
|
<argument name="arguments" types="PHP_EXPRESSION" repeatable="true" />
|
||||||
|
</arguments>
|
||||||
|
</tag>
|
||||||
|
<tag name="link" type="UNPAIRED">
|
||||||
|
<arguments>
|
||||||
|
<argument name="destination" types="LINK_DESTINATION,PHP_EXPRESSION" validType="string" required="true" />
|
||||||
|
<argument name="arguments" types="LINK_PARAMETERS" repeatable="true" />
|
||||||
|
</arguments>
|
||||||
|
</tag>
|
||||||
|
<tag name="href" type="ATTR_ONLY">
|
||||||
|
<arguments>
|
||||||
|
<argument name="destination" types="LINK_DESTINATION,PHP_EXPRESSION" validType="string" required="true" />
|
||||||
|
<argument name="arguments" types="LINK_PARAMETERS" repeatable="true" />
|
||||||
|
</arguments>
|
||||||
|
</tag>
|
||||||
|
<tag name="nonce" type="ATTR_ONLY" />
|
||||||
|
<tag name="plink" type="UNPAIRED">
|
||||||
|
<arguments>
|
||||||
|
<argument name="destination" types="LINK_DESTINATION,PHP_EXPRESSION" validType="string" required="true" />
|
||||||
|
<argument name="arguments" types="LINK_PARAMETERS" repeatable="true" />
|
||||||
|
</arguments>
|
||||||
|
</tag>
|
||||||
|
<!-- @deprecated - nette/application -->
|
||||||
|
<tag name="ifCurrent" type="PAIR" deprecatedMessage="Tag {ifCurrent} is deprecated in Latte 2.6. Use custom function isLinkCurrent() instead.">
|
||||||
|
<arguments>
|
||||||
|
<argument name="destination" types="LINK_DESTINATION,PHP_EXPRESSION" validType="string" required="true" />
|
||||||
|
<argument name="arguments" types="LINK_PARAMETERS" repeatable="true" />
|
||||||
|
</arguments>
|
||||||
|
</tag>
|
||||||
|
</tags>
|
||||||
|
<variables>
|
||||||
|
<variable name="control" type="\Nette\Application\UI\Control" />
|
||||||
|
<variable name="basePath" type="string" />
|
||||||
|
<variable name="baseUrl" type="string" />
|
||||||
|
<variable name="flashes" type="mixed[]" />
|
||||||
|
<variable name="presenter" type="\Nette\Application\UI\Presenter" />
|
||||||
|
<variable name="iterator" type="\Latte\Runtime\CachingIterator" />
|
||||||
|
<variable name="form" type="\Nette\Application\UI\Form" />
|
||||||
|
<variable name="user" type="\Nette\Security\User" />
|
||||||
|
</variables>
|
||||||
|
<functions>
|
||||||
|
<function name="isLinkCurrent" returnType="bool" arguments="(string $destination = null, $args = [])" />
|
||||||
|
<function name="isModuleCurrent" returnType="bool" arguments="(string $moduleName)" />
|
||||||
|
</functions>
|
||||||
|
</latte>
|
41
.idea/intellij-latte/xmlSources/NetteForms.xml
Normal file
41
.idea/intellij-latte/xmlSources/NetteForms.xml
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE latte PUBLIC "-//LATTE//Latte plugin configuration XML V0.0.1//EN" "Latte.dtd">
|
||||||
|
<latte version="1" vendor="nette/forms">
|
||||||
|
<tags>
|
||||||
|
<tag name="form" type="PAIR" multiLine="true">
|
||||||
|
<arguments>
|
||||||
|
<argument name="name" types="PHP_IDENTIFIER,VARIABLE,PHP_EXPRESSION" validType="string" required="true" />
|
||||||
|
</arguments>
|
||||||
|
</tag>
|
||||||
|
<tag name="formContainer" type="PAIR" multiLine="true">
|
||||||
|
<arguments>
|
||||||
|
<argument name="name" types="PHP_IDENTIFIER,VARIABLE,PHP_EXPRESSION" validType="string" required="true" />
|
||||||
|
</arguments>
|
||||||
|
</tag>
|
||||||
|
<tag name="formPrint" type="UNPAIRED">
|
||||||
|
<arguments>
|
||||||
|
<argument name="name" types="PHP_IDENTIFIER,VARIABLE,PHP_EXPRESSION" validType="string" required="true" />
|
||||||
|
</arguments>
|
||||||
|
</tag>
|
||||||
|
<tag name="input" type="UNPAIRED">
|
||||||
|
<arguments>
|
||||||
|
<argument name="name" types="PHP_IDENTIFIER,VARIABLE,CONTROL,PHP_EXPRESSION" validType="string" required="true" />
|
||||||
|
</arguments>
|
||||||
|
</tag>
|
||||||
|
<tag name="inputError" type="UNPAIRED">
|
||||||
|
<arguments>
|
||||||
|
<argument name="name" types="PHP_IDENTIFIER,VARIABLE,CONTROL,PHP_EXPRESSION" validType="string" required="true" />
|
||||||
|
</arguments>
|
||||||
|
</tag>
|
||||||
|
<tag name="label" type="AUTO_EMPTY">
|
||||||
|
<arguments>
|
||||||
|
<argument name="name" types="PHP_IDENTIFIER,VARIABLE,CONTROL,PHP_EXPRESSION" validType="string" required="true" />
|
||||||
|
</arguments>
|
||||||
|
</tag>
|
||||||
|
<tag name="name" type="ATTR_ONLY">
|
||||||
|
<arguments>
|
||||||
|
<argument name="name" types="PHP_IDENTIFIER,VARIABLE,CONTROL,PHP_EXPRESSION" validType="string" required="true" />
|
||||||
|
</arguments>
|
||||||
|
</tag>
|
||||||
|
</tags>
|
||||||
|
</latte>
|
6
.idea/misc.xml
Normal file
6
.idea/misc.xml
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="ProjectRootManager">
|
||||||
|
<output url="file://$PROJECT_DIR$/out" />
|
||||||
|
</component>
|
||||||
|
</project>
|
8
.idea/modules.xml
Normal file
8
.idea/modules.xml
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="ProjectModuleManager">
|
||||||
|
<modules>
|
||||||
|
<module fileurl="file://$PROJECT_DIR$/.idea/openvk.iml" filepath="$PROJECT_DIR$/.idea/openvk.iml" />
|
||||||
|
</modules>
|
||||||
|
</component>
|
||||||
|
</project>
|
45
.idea/openvk.iml
Normal file
45
.idea/openvk.iml
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<module type="JAVA_MODULE" version="4">
|
||||||
|
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
||||||
|
<exclude-output />
|
||||||
|
<content url="file://$MODULE_DIR$">
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/vendor/rybakit/msgpack" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/vendor/chillerlan/php-qrcode" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/vendor/psr/cache" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/vendor/chillerlan/php-settings-container" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/vendor/vearutop/php-obscene-censor-rus" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/vendor/psr/http-message" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/polyfill-php72" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/polyfill-intl-idn" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/polyfill-intl-normalizer" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/vendor/scssphp/scssphp" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/vendor/bhaktaraz/php-rss-generator" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/vendor/erusev/parsedown" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/vendor/ezyang/htmlpurifier" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/vendor/whichbrowser/parser" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/vendor/komeiji-satori/curl" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/vendor/composer" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/vendor/james-heinrich/getid3" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/vendor/guzzlehttp/promises" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/vendor/ralouphie/getallheaders" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/vendor/wapmorgan/binary-stream" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/vendor/guzzlehttp/psr7" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/vendor/al/emoji-detector" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/vendor/guzzlehttp/guzzle" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/vendor/lfkeitel/phptotp" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/vendor/zadarma/user-api-v1" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/polyfill-ctype" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/string" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/polyfill-intl-grapheme" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/deprecation-contracts" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/polyfill-php73" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/vendor/psr/container" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/polyfill-mbstring" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/console" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/polyfill-php80" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/service-contracts" />
|
||||||
|
</content>
|
||||||
|
<orderEntry type="inheritedJdk" />
|
||||||
|
<orderEntry type="sourceFolder" forTests="false" />
|
||||||
|
</component>
|
||||||
|
</module>
|
47
.idea/php.xml
Normal file
47
.idea/php.xml
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="PhpIncludePathManager">
|
||||||
|
<include_path>
|
||||||
|
<path value="$PROJECT_DIR$/vendor/rybakit/msgpack" />
|
||||||
|
<path value="$PROJECT_DIR$/vendor/chillerlan/php-qrcode" />
|
||||||
|
<path value="$PROJECT_DIR$/vendor/psr/cache" />
|
||||||
|
<path value="$PROJECT_DIR$/vendor/chillerlan/php-settings-container" />
|
||||||
|
<path value="$PROJECT_DIR$/vendor/vearutop/php-obscene-censor-rus" />
|
||||||
|
<path value="$PROJECT_DIR$/vendor/psr/http-message" />
|
||||||
|
<path value="$PROJECT_DIR$/vendor/symfony/polyfill-php72" />
|
||||||
|
<path value="$PROJECT_DIR$/vendor/symfony/polyfill-intl-idn" />
|
||||||
|
<path value="$PROJECT_DIR$/vendor/symfony/polyfill-intl-normalizer" />
|
||||||
|
<path value="$PROJECT_DIR$/vendor/scssphp/scssphp" />
|
||||||
|
<path value="$PROJECT_DIR$/vendor/bhaktaraz/php-rss-generator" />
|
||||||
|
<path value="$PROJECT_DIR$/vendor/erusev/parsedown" />
|
||||||
|
<path value="$PROJECT_DIR$/vendor/ezyang/htmlpurifier" />
|
||||||
|
<path value="$PROJECT_DIR$/vendor/whichbrowser/parser" />
|
||||||
|
<path value="$PROJECT_DIR$/vendor/komeiji-satori/curl" />
|
||||||
|
<path value="$PROJECT_DIR$/vendor/composer" />
|
||||||
|
<path value="$PROJECT_DIR$/vendor/james-heinrich/getid3" />
|
||||||
|
<path value="$PROJECT_DIR$/vendor/guzzlehttp/promises" />
|
||||||
|
<path value="$PROJECT_DIR$/vendor/ralouphie/getallheaders" />
|
||||||
|
<path value="$PROJECT_DIR$/vendor/wapmorgan/binary-stream" />
|
||||||
|
<path value="$PROJECT_DIR$/vendor/guzzlehttp/psr7" />
|
||||||
|
<path value="$PROJECT_DIR$/vendor/al/emoji-detector" />
|
||||||
|
<path value="$PROJECT_DIR$/vendor/guzzlehttp/guzzle" />
|
||||||
|
<path value="$PROJECT_DIR$/vendor/lfkeitel/phptotp" />
|
||||||
|
<path value="$PROJECT_DIR$/vendor/zadarma/user-api-v1" />
|
||||||
|
<path value="$PROJECT_DIR$/../../../chandler" />
|
||||||
|
<path value="$PROJECT_DIR$/../../../vendor" />
|
||||||
|
<path value="$PROJECT_DIR$/vendor/symfony/polyfill-ctype" />
|
||||||
|
<path value="$PROJECT_DIR$/vendor/symfony/string" />
|
||||||
|
<path value="$PROJECT_DIR$/vendor/symfony/polyfill-intl-grapheme" />
|
||||||
|
<path value="$PROJECT_DIR$/vendor/symfony/deprecation-contracts" />
|
||||||
|
<path value="$PROJECT_DIR$/vendor/symfony/polyfill-php73" />
|
||||||
|
<path value="$PROJECT_DIR$/vendor/psr/container" />
|
||||||
|
<path value="$PROJECT_DIR$/vendor/symfony/polyfill-mbstring" />
|
||||||
|
<path value="$PROJECT_DIR$/vendor/symfony/console" />
|
||||||
|
<path value="$PROJECT_DIR$/vendor/symfony/polyfill-php80" />
|
||||||
|
<path value="$PROJECT_DIR$/vendor/symfony/service-contracts" />
|
||||||
|
</include_path>
|
||||||
|
</component>
|
||||||
|
<component name="PhpProjectSharedConfiguration" php_language_level="7.4">
|
||||||
|
<option name="suggestChangeDefaultLanguageLevel" value="false" />
|
||||||
|
</component>
|
||||||
|
</project>
|
10
.idea/runConfigurations.xml
Normal file
10
.idea/runConfigurations.xml
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="RunConfigurationProducerService">
|
||||||
|
<option name="ignoredProducers">
|
||||||
|
<set>
|
||||||
|
<option value="com.android.tools.idea.compose.preview.runconfiguration.ComposePreviewRunConfigurationProducer" />
|
||||||
|
</set>
|
||||||
|
</option>
|
||||||
|
</component>
|
||||||
|
</project>
|
6
.idea/vcs.xml
Normal file
6
.idea/vcs.xml
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="VcsDirectoryMappings">
|
||||||
|
<mapping directory="" vcs="Git" />
|
||||||
|
</component>
|
||||||
|
</project>
|
86
CLI/RebuildImagesCommand.php
Normal file
86
CLI/RebuildImagesCommand.php
Normal file
|
@ -0,0 +1,86 @@
|
||||||
|
<?php declare(strict_types=1);
|
||||||
|
namespace openvk\CLI;
|
||||||
|
use Chandler\Database\DatabaseConnection;
|
||||||
|
use openvk\Web\Models\Repositories\Photos;
|
||||||
|
use Symfony\Component\Console\Command\Command;
|
||||||
|
use Symfony\Component\Console\Input\InputInterface;
|
||||||
|
use Symfony\Component\Console\Input\InputOption;
|
||||||
|
use Symfony\Component\Console\Output\OutputInterface;
|
||||||
|
use Nette\Utils\ImageException;
|
||||||
|
|
||||||
|
class RebuildImagesCommand extends Command
|
||||||
|
{
|
||||||
|
private $images;
|
||||||
|
|
||||||
|
protected static $defaultName = "build-images";
|
||||||
|
|
||||||
|
function __construct()
|
||||||
|
{
|
||||||
|
$this->images = DatabaseConnection::i()->getContext()->table("photos");
|
||||||
|
|
||||||
|
parent::__construct();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function configure(): void
|
||||||
|
{
|
||||||
|
$this->setDescription("Create resized versions of images")
|
||||||
|
->setHelp("This command allows you to resize all your images after configuration change")
|
||||||
|
->addOption("upgrade-only", "U", InputOption::VALUE_NEGATABLE, "Only upgrade images which aren't resized?");
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function execute(InputInterface $input, OutputInterface $output): int
|
||||||
|
{
|
||||||
|
$header = $output->section();
|
||||||
|
$counter = $output->section();
|
||||||
|
|
||||||
|
$header->writeln([
|
||||||
|
"Image Rebuild Utility",
|
||||||
|
"=====================",
|
||||||
|
"",
|
||||||
|
]);
|
||||||
|
|
||||||
|
$filter = ["deleted" => false];
|
||||||
|
if($input->getOption("upgrade-only"))
|
||||||
|
$filter["sizes"] = NULL;
|
||||||
|
|
||||||
|
$selection = $this->images->select("id")->where($filter);
|
||||||
|
$totalPics = $selection->count();
|
||||||
|
$header->writeln([
|
||||||
|
"Total of $totalPics images found.",
|
||||||
|
"",
|
||||||
|
]);
|
||||||
|
|
||||||
|
$errors = 0;
|
||||||
|
$count = 0;
|
||||||
|
$avgTime = NULL;
|
||||||
|
$begin = new \DateTimeImmutable("now");
|
||||||
|
foreach($selection as $idHolder) {
|
||||||
|
$start = microtime(true);
|
||||||
|
|
||||||
|
try {
|
||||||
|
$photo = (new Photos)->get($idHolder->id);
|
||||||
|
$photo->getSizes(true, true);
|
||||||
|
$photo->getDimensions();
|
||||||
|
} catch(ImageException $ex) {
|
||||||
|
$errors++;
|
||||||
|
}
|
||||||
|
|
||||||
|
$timeConsumed = microtime(true) - $start;
|
||||||
|
if(!$avgTime)
|
||||||
|
$avgTime = $timeConsumed;
|
||||||
|
else
|
||||||
|
$avgTime = ($avgTime + $timeConsumed) / 2;
|
||||||
|
|
||||||
|
$eta = $begin->getTimestamp() + ceil($totalPics * $avgTime);
|
||||||
|
$int = (new \DateTimeImmutable("now"))->diff(new \DateTimeImmutable("@$eta"));
|
||||||
|
$int = $int->d . "d" . $int->h . "h" . $int->i . "m" . $int->s . "s";
|
||||||
|
$pct = floor(100 * ($count / $totalPics));
|
||||||
|
|
||||||
|
$counter->overwrite("Processed " . ++$count . " images... ($pct% $int left $errors/$count fail)");
|
||||||
|
}
|
||||||
|
|
||||||
|
$counter->overwrite("Processing finished :3");
|
||||||
|
|
||||||
|
return Command::SUCCESS;
|
||||||
|
}
|
||||||
|
}
|
35
README.md
35
README.md
|
@ -6,13 +6,13 @@ _[Русский](README_RU.md)_
|
||||||
|
|
||||||
VKontakte belongs to Pavel Durov and VK Group.
|
VKontakte belongs to Pavel Durov and VK Group.
|
||||||
|
|
||||||
To be honest, we don't even know whether it even works. However, this version is maintained and we will be happy to accept your bugreports [in our bug-tracker](https://github.com/openvk/openvk/projects/1). You should also be able to submit them using [ticketing system](https://openvk.su/support?act=new) (you will need an OVK account for this).
|
To be honest, we don't know whether it even works. However, this version is maintained and we will be happy to accept your bugreports [in our bug-tracker](https://github.com/openvk/openvk/projects/1). You should also be able to submit them using [ticketing system](https://openvk.su/support?act=new) (you will need an OVK account for this).
|
||||||
|
|
||||||
## When's the release?
|
## When's the release?
|
||||||
|
|
||||||
Please use the master branch, as it has the most changes.
|
We will release OpenVK as soon as it's ready. As for now you can:
|
||||||
|
* `git clone` this repo's master branch (use `git pull` to update)
|
||||||
Updating the source code is done with this command: `git pull`
|
* Grab a prebuilt OpenVK distro from [GitHub artifacts](https://github.com/openvk/archive/actions/workflows/nightly.yml)
|
||||||
|
|
||||||
## Instances
|
## Instances
|
||||||
|
|
||||||
|
@ -24,7 +24,7 @@ Updating the source code is done with this command: `git pull`
|
||||||
|
|
||||||
Yes! And you're very welcome to.
|
Yes! And you're very welcome to.
|
||||||
|
|
||||||
However, OVK makes use of Chandler Application Server. This software requires extensions, that may not be provided by your hosting provider (namely, sodium and yaml. this extensions are available on most of ISPManager hostings).
|
However, OVK makes use of Chandler Application Server. This software requires extensions, that may not be provided by your hosting provider (namely, sodium and yaml. these extensions are available on most of ISPManager hostings).
|
||||||
|
|
||||||
If you want, you can add your instance to the list above so that people can register there.
|
If you want, you can add your instance to the list above so that people can register there.
|
||||||
|
|
||||||
|
@ -32,7 +32,7 @@ If you want, you can add your instance to the list above so that people can regi
|
||||||
|
|
||||||
1. Install PHP 7.4, web-server, Composer, Node.js, Yarn and [Chandler](https://github.com/openvk/chandler)
|
1. Install PHP 7.4, web-server, Composer, Node.js, Yarn and [Chandler](https://github.com/openvk/chandler)
|
||||||
|
|
||||||
* PHP 8 has **not** yet been tested, so you should not expect it to work.
|
* PHP 8 has **not** yet been tested, so you should not expect it to work. (edit: it does not work).
|
||||||
|
|
||||||
2. Install [commitcaptcha](https://github.com/openvk/commitcaptcha) and OpenVK as Chandler extensions like this:
|
2. Install [commitcaptcha](https://github.com/openvk/commitcaptcha) and OpenVK as Chandler extensions like this:
|
||||||
|
|
||||||
|
@ -48,26 +48,25 @@ ln -s /path/to/chandler/extensions/available/commitcaptcha /path/to/chandler/ext
|
||||||
ln -s /path/to/chandler/extensions/available/openvk /path/to/chandler/extensions/enabled/
|
ln -s /path/to/chandler/extensions/available/openvk /path/to/chandler/extensions/enabled/
|
||||||
```
|
```
|
||||||
|
|
||||||
4. Import `install/init-static-db.sql` to **same database** you installed Chandler to and import all sqls from `install/sqls` to **same database**
|
4. Import `install/init-static-db.sql` to the **same database** you installed Chandler to and import all sqls from `install/sqls` to the **same database**
|
||||||
5. Import `install/init-event-db.sql` to **separate database**
|
5. Import `install/init-event-db.sql` to a **separate database** (Yandex.Clickhouse can also be used, higly recommended)
|
||||||
6. Copy `openvk-example.yml` to `openvk.yml` and change options
|
6. Copy `openvk-example.yml` to `openvk.yml` and change options to your liking
|
||||||
7. Run `composer install` in OpenVK directory
|
7. Run `composer install` in OpenVK directory
|
||||||
8. Move to `Web/static/js` and execute `yarn install`
|
8. Run `composer install` in commitcaptcha directory
|
||||||
9. Set `openvk` as your root app in `chandler.yml`
|
9. Move to `Web/static/js` and execute `yarn install`
|
||||||
|
10. Set `openvk` as your root app in `chandler.yml`
|
||||||
|
|
||||||
Once you are done, you can login as a system administrator on the network itself (no registration required):
|
Once you are done, you can login as a system administrator on the network itself (no registration required):
|
||||||
|
|
||||||
* **Login**: `admin@localhost.localdomain6`
|
* **Login**: `admin@localhost.localdomain6`
|
||||||
* **Password**: `admin`
|
* **Password**: `admin`
|
||||||
* It is recommended to change the password before using the built-in account.
|
* It is recommended to change the password of the built-in account or disable it.
|
||||||
|
|
||||||
Full example installation instruction for CentOS 8 is also available [here](https://docs.openvk.su/openvk_engine/centos8_installation/).
|
💡Confused? Full installation walkthrough is available [here](https://docs.openvk.su/openvk_engine/centos8_installation/) (CentOS 8 [and](https://almalinux.org/) [family](https://yum.oracle.com/oracle-linux-isos.html)).
|
||||||
|
|
||||||
### If my website uses OpenVK, should I publish it's sources?
|
### If my website uses OpenVK, should I release it's sources?
|
||||||
|
|
||||||
You are encouraged to do so. We don't enforce this though. You can keep your sources to yourself (unless you distribute your OpenVK distro to other people).
|
It depends. You can keep the sources to yourself if you do not plan to distribute your website binaries. If your website software must be distributed, it can stay non-OSS provided the OpenVK is not used as a primary application and is not modified. If you modified OpenVK for your needs or your work is based on it and you're planning to redistribute this, then you should license it under terms of any LGPL-compatible license (like OSL, GPL, LGPL etc).
|
||||||
|
|
||||||
You also not required to publish source texts of your themepacks and plugins.
|
|
||||||
|
|
||||||
## Where can I get assistance?
|
## Where can I get assistance?
|
||||||
|
|
||||||
|
@ -80,7 +79,7 @@ You may reach out to us via:
|
||||||
* [Discussions](https://github.com/openvk/openvk/discussions)
|
* [Discussions](https://github.com/openvk/openvk/discussions)
|
||||||
* Matrix chat: #openvk:matrix.org
|
* Matrix chat: #openvk:matrix.org
|
||||||
|
|
||||||
**Attention**: bug tracker, telegram and matrix chat are public places. And ticketing system is being served by volunteers. If you need to report something, that shouldn't be immediately disclosed to general public (for instance, vulnerability report), please use contact us directly at this email: **openvk [at] tutanota [dot] com**
|
**Attention**: bug tracker, board, telegram and matrix chat are public places. And ticketing system is being served by volunteers. If you need to report something, that shouldn't be immediately disclosed to general public (for instance, vulnerability report), please use contact us directly at this email: **openvk [at] tutanota [dot] com**
|
||||||
|
|
||||||
<a href="https://codeberg.org/OpenVK/openvk">
|
<a href="https://codeberg.org/OpenVK/openvk">
|
||||||
<img alt="Get it on Codeberg" src="https://codeberg.org/Codeberg/GetItOnCodeberg/media/branch/main/get-it-on-blue-on-white.png" height="60">
|
<img alt="Get it on Codeberg" src="https://codeberg.org/Codeberg/GetItOnCodeberg/media/branch/main/get-it-on-blue-on-white.png" height="60">
|
||||||
|
|
23
README_RU.md
23
README_RU.md
|
@ -10,9 +10,9 @@ _[English](README.md)_
|
||||||
|
|
||||||
## Когда релиз?
|
## Когда релиз?
|
||||||
|
|
||||||
Пожалуйста, используйте ветку master, так как в ней больше всего изменений.
|
Мы выпустим OpenVK, как только он будет готов. На данный момент Вы можете:
|
||||||
|
* Сделать `git clone` master ветки этой репозитории (используйте `git pull` для обновления)
|
||||||
Обновление исходного кода выполняется с помощью этой команды: `git pull`.
|
* Взять готовую сборку OpenVK из [GitHub Actions](https://github.com/openvk/archive/actions/workflows/nightly.yml)
|
||||||
|
|
||||||
## Инстанции
|
## Инстанции
|
||||||
|
|
||||||
|
@ -32,7 +32,7 @@ _[English](README.md)_
|
||||||
|
|
||||||
1. Установите PHP 7.4, веб-сервер, Composer, Node.js, Yarn и [Chandler](https://github.com/openvk/chandler)
|
1. Установите PHP 7.4, веб-сервер, Composer, Node.js, Yarn и [Chandler](https://github.com/openvk/chandler)
|
||||||
|
|
||||||
* PHP 8 еще **не** тестировался, поэтому не стоит ожидать, что он будет работать.
|
* PHP 8 еще **не** тестировался, поэтому не стоит ожидать, что он будет работать (обновление: он не работает).
|
||||||
|
|
||||||
2. Установите [commitcaptcha](https://github.com/openvk/commitcaptcha) и OpenVK в качестве расширений Chandler следующим образом:
|
2. Установите [commitcaptcha](https://github.com/openvk/commitcaptcha) и OpenVK в качестве расширений Chandler следующим образом:
|
||||||
|
|
||||||
|
@ -49,11 +49,12 @@ ln -s /path/to/chandler/extensions/available/openvk /path/to/chandler/extensions
|
||||||
```
|
```
|
||||||
|
|
||||||
4. Импортируйте `install/init-static-db.sql` в **ту же базу данных**, в которую вы установили Chandler, и импортируйте все SQL файлы из папки `install/sqls` в **ту же базу данных**
|
4. Импортируйте `install/init-static-db.sql` в **ту же базу данных**, в которую вы установили Chandler, и импортируйте все SQL файлы из папки `install/sqls` в **ту же базу данных**
|
||||||
5. Импортируйте `install/init-event-db.sql` в **отдельную базу данных**
|
5. Импортируйте `install/init-event-db.sql` в **отдельную базу данных** (Яндекс.Clickhouse также может быть использован, настоятельно рекомендуется)
|
||||||
6. Скопируйте `openvk-example.yml` в `openvk.yml` и измените параметры
|
6. Скопируйте `openvk-example.yml` в `openvk.yml` и измените параметры
|
||||||
7. Запустите `composer install` в директории OpenVK
|
7. Запустите `composer install` в директории OpenVK
|
||||||
8. Перейдите в `Web/static/js` и выполните `yarn install`
|
8. Запустите `composer install` в директории commitcaptcha
|
||||||
9. Установите `openvk` в качестве корневого приложения в файле `chandler.yml`
|
9. Перейдите в `Web/static/js` и выполните `yarn install`
|
||||||
|
10. Установите `openvk` в качестве корневого приложения в файле `chandler.yml`
|
||||||
|
|
||||||
После этого вы можете войти как системный администратор в саму сеть (регистрация не требуется):
|
После этого вы можете войти как системный администратор в саму сеть (регистрация не требуется):
|
||||||
|
|
||||||
|
@ -61,13 +62,11 @@ ln -s /path/to/chandler/extensions/available/openvk /path/to/chandler/extensions
|
||||||
* **Пароль**: `admin`
|
* **Пароль**: `admin`
|
||||||
* Перед использованием встроенной учетной записи рекомендуется сменить пароль.
|
* Перед использованием встроенной учетной записи рекомендуется сменить пароль.
|
||||||
|
|
||||||
Полный пример инструкции по установке CentOS 8 также доступен [здесь](https://docs.openvk.su/openvk_engine/centos8_installation/).
|
💡Запутались? Полное руководство по установке доступно [здесь](https://docs.openvk.su/openvk_engine/centos8_installation/) (CentOS 8 [и](https://almalinux.org/ru/) [семейство](https://yum.oracle.com/oracle-linux-isos.html)).
|
||||||
|
|
||||||
### Если мой сайт использует OpenVK, должен ли я публиковать его исходные тексты?
|
### Если мой сайт использует OpenVK, должен ли я публиковать его исходные тексты?
|
||||||
|
|
||||||
Вам рекомендуется это делать. Однако мы не следим за этим. Вы можете держать свои исходные тексты при себе (если только вы не распространяете свой дистрибутив OpenVK среди других людей).
|
Это зависит от обстоятельств. Вы можете оставить исходные тексты при себе, если не планируете распространять бинарники вашего сайта. Если программное обеспечение вашего сайта должно распространяться, оно может оставаться не-OSS при условии, что OpenVK не используется в качестве основного приложения и не модифицируется. Если вы модифицировали OpenVK для своих нужд или ваша работа основана на нем и вы планируете ее распространять, то вы должны лицензировать ее на условиях любой совместимой с LGPL лицензии (например, OSL, GPL, LGPL и т.д.).
|
||||||
|
|
||||||
Вы также не обязаны публиковать исходные тексты ваших тематических пакетов и плагинов.
|
|
||||||
|
|
||||||
## Где я могу получить помощь?
|
## Где я могу получить помощь?
|
||||||
|
|
||||||
|
@ -80,7 +79,7 @@ ln -s /path/to/chandler/extensions/available/openvk /path/to/chandler/extensions
|
||||||
* [Обсуждения](https://github.com/openvk/openvk/discussions)
|
* [Обсуждения](https://github.com/openvk/openvk/discussions)
|
||||||
* Чат в Matrix: #ovk:matrix.org
|
* Чат в Matrix: #ovk:matrix.org
|
||||||
|
|
||||||
**Внимание**: баг-трекер, телеграм- и matrix-чат являются публичными местами, и жалобы в OVK обслуживается волонтерами. Если вам нужно сообщить о чем-то, что не должно быть раскрыто широкой публике (например, сообщение об уязвимости), пожалуйста, свяжитесь с нами напрямую по этому адресу: **openvk [собака] tutanota [точка] com**.
|
**Внимание**: баг-трекер, форум, телеграм- и matrix-чат являются публичными местами, и жалобы в OVK обслуживается волонтерами. Если вам нужно сообщить о чем-то, что не должно быть раскрыто широкой публике (например, сообщение об уязвимости), пожалуйста, свяжитесь с нами напрямую по этому адресу: **openvk [собака] tutanota [точка] com**.
|
||||||
|
|
||||||
<a href="https://codeberg.org/OpenVK/openvk">
|
<a href="https://codeberg.org/OpenVK/openvk">
|
||||||
<img alt="Получить на Codeberg" src="https://codeberg.org/Codeberg/GetItOnCodeberg/media/branch/main/get-it-on-blue-on-white.png" height="60">
|
<img alt="Получить на Codeberg" src="https://codeberg.org/Codeberg/GetItOnCodeberg/media/branch/main/get-it-on-blue-on-white.png" height="60">
|
||||||
|
|
|
@ -60,7 +60,7 @@ final class Account extends VKAPIRequestHandler
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
function getAppPermissions(): object
|
function getAppPermissions(): int
|
||||||
{
|
{
|
||||||
return 9355263;
|
return 9355263;
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,7 +25,7 @@ final class Friends extends VKAPIRequestHandler
|
||||||
$usersApi = new Users($this->getUser());
|
$usersApi = new Users($this->getUser());
|
||||||
|
|
||||||
if (!is_null($fields)) {
|
if (!is_null($fields)) {
|
||||||
$response = $usersApi->get(implode(',', $friends), $fields, 0, $count, true); // FIXME
|
$response = $usersApi->get(implode(',', $friends), $fields, 0, $count); // FIXME
|
||||||
}
|
}
|
||||||
|
|
||||||
return (object) [
|
return (object) [
|
||||||
|
|
74
VKAPI/Handlers/Likes.php
Normal file
74
VKAPI/Handlers/Likes.php
Normal file
|
@ -0,0 +1,74 @@
|
||||||
|
<?php declare(strict_types=1);
|
||||||
|
namespace openvk\VKAPI\Handlers;
|
||||||
|
use openvk\Web\Models\Repositories\Users as UsersRepo;
|
||||||
|
use openvk\Web\Models\Repositories\Posts as PostsRepo;
|
||||||
|
|
||||||
|
final class Likes extends VKAPIRequestHandler
|
||||||
|
{
|
||||||
|
function add(string $type, int $owner_id, int $item_id): object
|
||||||
|
{
|
||||||
|
$this->requireUser();
|
||||||
|
|
||||||
|
switch ($type) {
|
||||||
|
case 'post':
|
||||||
|
$post = (new PostsRepo)->getPostById($owner_id, $item_id);
|
||||||
|
if (is_null($post)) $this->fail(100, 'One of the parameters specified was missing or invalid: object not found');
|
||||||
|
|
||||||
|
$post->setLike(true, $this->getUser());
|
||||||
|
return (object)[
|
||||||
|
"likes" => $post->getLikesCount()
|
||||||
|
];
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
$this->fail(100, 'One of the parameters specified was missing or invalid: incorrect type');
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function remove(string $type, int $owner_id, int $item_id): object
|
||||||
|
{
|
||||||
|
$this->requireUser();
|
||||||
|
|
||||||
|
switch ($type) {
|
||||||
|
case 'post':
|
||||||
|
$post = (new PostsRepo)->getPostById($owner_id, $item_id);
|
||||||
|
if (is_null($post)) $this->fail(100, 'One of the parameters specified was missing or invalid: object not found');
|
||||||
|
|
||||||
|
$post->setLike(false, $this->getUser());
|
||||||
|
return (object)[
|
||||||
|
"likes" => $post->getLikesCount()
|
||||||
|
];
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
$this->fail(100, 'One of the parameters specified was missing or invalid: incorrect type');
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function isLiked(int $user_id, string $type, int $owner_id, int $item_id): object
|
||||||
|
{
|
||||||
|
$this->requireUser();
|
||||||
|
|
||||||
|
switch ($type) {
|
||||||
|
case 'post':
|
||||||
|
$user = (new UsersRepo)->get($user_id);
|
||||||
|
if (is_null($user)) return (object)[
|
||||||
|
"liked" => 0,
|
||||||
|
"copied" => 0,
|
||||||
|
"sex" => 0
|
||||||
|
];
|
||||||
|
|
||||||
|
$post = (new PostsRepo)->getPostById($owner_id, $item_id);
|
||||||
|
if (is_null($post)) $this->fail(100, 'One of the parameters specified was missing or invalid: object not found');
|
||||||
|
|
||||||
|
return (object)[
|
||||||
|
"liked" => (int) $post->hasLikeFrom($user),
|
||||||
|
"copied" => 0 // TODO: handle this
|
||||||
|
];
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
$this->fail(100, 'One of the parameters specified was missing or invalid: incorrect type');
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -4,6 +4,7 @@ use openvk\Web\Events\NewMessageEvent;
|
||||||
use openvk\Web\Models\Entities\{Correspondence, Message};
|
use openvk\Web\Models\Entities\{Correspondence, Message};
|
||||||
use openvk\Web\Models\Repositories\{Messages as MSGRepo, Users as USRRepo};
|
use openvk\Web\Models\Repositories\{Messages as MSGRepo, Users as USRRepo};
|
||||||
use openvk\VKAPI\Structures\{Message as APIMsg, Conversation as APIConvo};
|
use openvk\VKAPI\Structures\{Message as APIMsg, Conversation as APIConvo};
|
||||||
|
use openvk\VKAPI\Handlers\Users as APIUsers;
|
||||||
use Chandler\Signaling\SignalManager;
|
use Chandler\Signaling\SignalManager;
|
||||||
|
|
||||||
final class Messages extends VKAPIRequestHandler
|
final class Messages extends VKAPIRequestHandler
|
||||||
|
@ -48,10 +49,12 @@ final class Messages extends VKAPIRequestHandler
|
||||||
$rMsg->read_state = 1;
|
$rMsg->read_state = 1;
|
||||||
$rMsg->out = (int) ($message->getSender()->getId() === $this->getUser()->getId());
|
$rMsg->out = (int) ($message->getSender()->getId() === $this->getUser()->getId());
|
||||||
$rMsg->body = $message->getText(false);
|
$rMsg->body = $message->getText(false);
|
||||||
|
$rMsg->text = $message->getText(false);
|
||||||
$rMsg->emoji = true;
|
$rMsg->emoji = true;
|
||||||
|
|
||||||
if($preview_length > 0)
|
if($preview_length > 0)
|
||||||
$rMsg->body = ovk_proc_strtr($rMsg->body, $preview_length);
|
$rMsg->body = ovk_proc_strtr($rMsg->body, $preview_length);
|
||||||
|
$rMsg->text = ovk_proc_strtr($rMsg->text, $preview_length);
|
||||||
|
|
||||||
$items[] = $rMsg;
|
$items[] = $rMsg;
|
||||||
}
|
}
|
||||||
|
@ -145,12 +148,14 @@ final class Messages extends VKAPIRequestHandler
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
function getConversations(int $offset = 0, int $count = 20, string $filter = "all", int $extended = 0): object
|
function getConversations(int $offset = 0, int $count = 20, string $filter = "all", int $extended = 0, string $fields = ""): object
|
||||||
{
|
{
|
||||||
$this->requireUser();
|
$this->requireUser();
|
||||||
|
|
||||||
$convos = (new MSGRepo)->getCorrespondencies($this->getUser(), -1, $count, $offset);
|
$convos = (new MSGRepo)->getCorrespondencies($this->getUser(), -1, $count, $offset);
|
||||||
$list = [];
|
$list = [];
|
||||||
|
|
||||||
|
$users = [];
|
||||||
foreach($convos as $convo) {
|
foreach($convos as $convo) {
|
||||||
$correspondents = $convo->getCorrespondents();
|
$correspondents = $convo->getCorrespondents();
|
||||||
if($correspondents[0]->getId() === $this->getUser()->getId())
|
if($correspondents[0]->getId() === $this->getUser()->getId())
|
||||||
|
@ -189,7 +194,13 @@ final class Messages extends VKAPIRequestHandler
|
||||||
$lastMessagePreview->read_state = 1;
|
$lastMessagePreview->read_state = 1;
|
||||||
$lastMessagePreview->out = (int) ($lastMessage->getSender()->getId() === $this->getUser()->getId());
|
$lastMessagePreview->out = (int) ($lastMessage->getSender()->getId() === $this->getUser()->getId());
|
||||||
$lastMessagePreview->body = $lastMessage->getText(false);
|
$lastMessagePreview->body = $lastMessage->getText(false);
|
||||||
|
$lastMessagePreview->text = $lastMessage->getText(false);
|
||||||
$lastMessagePreview->emoji = true;
|
$lastMessagePreview->emoji = true;
|
||||||
|
|
||||||
|
if($extended == 1) {
|
||||||
|
$users[] = $lastMessage->getSender()->getId();
|
||||||
|
$users[] = $author;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$list[] = [
|
$list[] = [
|
||||||
|
@ -198,10 +209,20 @@ final class Messages extends VKAPIRequestHandler
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if($extended == 0){
|
||||||
return (object) [
|
return (object) [
|
||||||
"count" => sizeof($list),
|
"count" => sizeof($list),
|
||||||
"items" => $list,
|
"items" => $list,
|
||||||
];
|
];
|
||||||
|
} else {
|
||||||
|
$users = array_unique($users);
|
||||||
|
|
||||||
|
return (object) [
|
||||||
|
"count" => sizeof($list),
|
||||||
|
"items" => $list,
|
||||||
|
"profiles" => (new APIUsers)->get(implode(',', $users), $fields, $offset, $count)
|
||||||
|
];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function getHistory(int $offset = 0, int $count = 20, int $user_id = -1, int $peer_id = -1, int $start_message_id = 0, int $rev = 0, int $extended = 0): object
|
function getHistory(int $offset = 0, int $count = 20, int $user_id = -1, int $peer_id = -1, int $start_message_id = 0, int $rev = 0, int $extended = 0): object
|
||||||
|
@ -230,6 +251,7 @@ final class Messages extends VKAPIRequestHandler
|
||||||
$rMsg->read_state = 1;
|
$rMsg->read_state = 1;
|
||||||
$rMsg->out = (int) ($msgU->sender_id === $this->getUser()->getId());
|
$rMsg->out = (int) ($msgU->sender_id === $this->getUser()->getId());
|
||||||
$rMsg->body = $message->getText(false);
|
$rMsg->body = $message->getText(false);
|
||||||
|
$rMsg->text = $message->getText(false);
|
||||||
$rMsg->emoji = true;
|
$rMsg->emoji = true;
|
||||||
|
|
||||||
$results[] = $rMsg;
|
$results[] = $rMsg;
|
||||||
|
|
230
VKAPI/Handlers/Photos.php
Normal file
230
VKAPI/Handlers/Photos.php
Normal file
|
@ -0,0 +1,230 @@
|
||||||
|
<?php declare(strict_types=1);
|
||||||
|
namespace openvk\VKAPI\Handlers;
|
||||||
|
|
||||||
|
use Nette\InvalidStateException;
|
||||||
|
use Nette\Utils\ImageException;
|
||||||
|
use openvk\Web\Models\Entities\Photo;
|
||||||
|
use openvk\Web\Models\Repositories\Albums;
|
||||||
|
use openvk\Web\Models\Repositories\Clubs;
|
||||||
|
|
||||||
|
final class Photos extends VKAPIRequestHandler
|
||||||
|
{
|
||||||
|
private function getPhotoUploadUrl(string $field, int $group = 0, bool $multifile = false): string
|
||||||
|
{
|
||||||
|
$secret = CHANDLER_ROOT_CONF["security"]["secret"];
|
||||||
|
$uploadInfo = [
|
||||||
|
1,
|
||||||
|
$field,
|
||||||
|
(int) $multifile,
|
||||||
|
0,
|
||||||
|
time(),
|
||||||
|
$this->getUser()->getId(),
|
||||||
|
$group,
|
||||||
|
0, # this is unused but stays here base64 reasons (X2 doesn't work, so there's dummy value for short)
|
||||||
|
];
|
||||||
|
$uploadInfo = pack("vZ10v2P3S", ...$uploadInfo);
|
||||||
|
$uploadInfo = base64_encode($uploadInfo);
|
||||||
|
$uploadHash = hash_hmac("sha3-224", $uploadInfo, $secret);
|
||||||
|
$uploadInfo = rawurlencode($uploadInfo);
|
||||||
|
|
||||||
|
return ovk_scheme(true) . $_SERVER["HTTP_HOST"] . "/upload/photo/$uploadHash?$uploadInfo";
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getImagePath(string $photo, string $hash, ?string& $up = NULL, ?string& $group = NULL): string
|
||||||
|
{
|
||||||
|
$secret = CHANDLER_ROOT_CONF["security"]["secret"];
|
||||||
|
if(!hash_equals(hash_hmac("sha3-224", $photo, $secret), $hash))
|
||||||
|
$this->fail(121, "Incorrect hash");
|
||||||
|
|
||||||
|
[$up, $image, $group] = explode("|", $photo);
|
||||||
|
|
||||||
|
$imagePath = __DIR__ . "/../../tmp/api-storage/photos/$up" . "_$image.oct";
|
||||||
|
if(!file_exists($imagePath))
|
||||||
|
$this->fail(10, "Invalid image");
|
||||||
|
|
||||||
|
return $imagePath;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getOwnerPhotoUploadServer(int $owner_id = 0): object
|
||||||
|
{
|
||||||
|
$this->requireUser();
|
||||||
|
|
||||||
|
if($owner_id < 0) {
|
||||||
|
$club = (new Clubs)->get(abs($owner_id));
|
||||||
|
if(!$club)
|
||||||
|
$this->fail(0404, "Club not found");
|
||||||
|
else if(!$club->canBeModifiedBy($this->getUser()))
|
||||||
|
$this->fail(200, "Access: Club can't be 'written' by user");
|
||||||
|
}
|
||||||
|
|
||||||
|
return (object) [
|
||||||
|
"upload_url" => $this->getPhotoUploadUrl("photo", isset($club) ? 0 : $club->getId()),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
function saveOwnerPhoto(string $photo, string $hash): object
|
||||||
|
{
|
||||||
|
$imagePath = $this->getImagePath($photo, $hash, $uploader, $group);
|
||||||
|
if($group == 0) {
|
||||||
|
$user = (new \openvk\Web\Models\Repositories\Users)->get((int) $uploader);
|
||||||
|
$album = (new Albums)->getUserAvatarAlbum($user);
|
||||||
|
} else {
|
||||||
|
$club = (new Clubs)->get((int) $group);
|
||||||
|
$album = (new Albums)->getClubAvatarAlbum($club);
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
$avatar = new Photo;
|
||||||
|
$avatar->setOwner((int) $uploader);
|
||||||
|
$avatar->setDescription("Profile photo");
|
||||||
|
$avatar->setCreated(time());
|
||||||
|
$avatar->setFile([
|
||||||
|
"tmp_name" => $imagePath,
|
||||||
|
"error" => 0,
|
||||||
|
]);
|
||||||
|
$avatar->save();
|
||||||
|
$album->addPhoto($avatar);
|
||||||
|
unlink($imagePath);
|
||||||
|
} catch(ImageException | InvalidStateException $e) {
|
||||||
|
unlink($imagePath);
|
||||||
|
$this->fail(129, "Invalid image file");
|
||||||
|
}
|
||||||
|
|
||||||
|
return (object) [
|
||||||
|
"photo_hash" => NULL,
|
||||||
|
"photo_src" => $avatar->getURL(),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
function getWallUploadServer(?int $group_id = NULL): object
|
||||||
|
{
|
||||||
|
$this->requireUser();
|
||||||
|
|
||||||
|
$album = NULL;
|
||||||
|
if(!is_null($group_id)) {
|
||||||
|
$club = (new Clubs)->get(abs($group_id));
|
||||||
|
if(!$club)
|
||||||
|
$this->fail(0404, "Club not found");
|
||||||
|
else if(!$club->canBeModifiedBy($this->getUser()))
|
||||||
|
$this->fail(200, "Access: Club can't be 'written' by user");
|
||||||
|
} else {
|
||||||
|
$album = (new Albums)->getUserWallAlbum($this->getUser());
|
||||||
|
}
|
||||||
|
|
||||||
|
return (object) [
|
||||||
|
"upload_url" => $this->getPhotoUploadUrl("photo", $group_id ?? 0),
|
||||||
|
"album_id" => $album,
|
||||||
|
"user_id" => $this->getUser()->getId(),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
function saveWallPhoto(string $photo, string $hash, int $group_id = 0, ?string $caption = NULL): array
|
||||||
|
{
|
||||||
|
$imagePath = $this->getImagePath($photo, $hash, $uploader, $group);
|
||||||
|
if($group_id != $group)
|
||||||
|
$this->fail(8, "group_id doesn't match");
|
||||||
|
|
||||||
|
$album = NULL;
|
||||||
|
if($group_id != 0) {
|
||||||
|
$uploader = (new \openvk\Web\Models\Repositories\Users)->get((int) $uploader);
|
||||||
|
$album = (new Albums)->getUserWallAlbum($uploader);
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
$photo = new Photo;
|
||||||
|
$photo->setOwner((int) $uploader);
|
||||||
|
$photo->setCreated(time());
|
||||||
|
$photo->setFile([
|
||||||
|
"tmp_name" => $imagePath,
|
||||||
|
"error" => 0,
|
||||||
|
]);
|
||||||
|
|
||||||
|
if (!is_null($caption))
|
||||||
|
$photo->setDescription($caption);
|
||||||
|
|
||||||
|
$photo->save();
|
||||||
|
unlink($imagePath);
|
||||||
|
} catch(ImageException | InvalidStateException $e) {
|
||||||
|
unlink($imagePath);
|
||||||
|
$this->fail(129, "Invalid image file");
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!is_null($album))
|
||||||
|
$album->addPhoto($photo);
|
||||||
|
|
||||||
|
return [
|
||||||
|
$photo->toVkApiStruct(),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
function getUploadServer(?int $album_id = NULL): object
|
||||||
|
{
|
||||||
|
$this->requireUser();
|
||||||
|
|
||||||
|
# Not checking rights to album because save() method will do so anyways
|
||||||
|
return (object) [
|
||||||
|
"upload_url" => $this->getPhotoUploadUrl("photo", 0, true),
|
||||||
|
"album_id" => $album_id,
|
||||||
|
"user_id" => $this->getUser()->getId(),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
function save(string $photos_list, string $hash, int $album_id = 0, ?string $caption = NULL): object
|
||||||
|
{
|
||||||
|
$this->requireUser();
|
||||||
|
|
||||||
|
$secret = CHANDLER_ROOT_CONF["security"]["secret"];
|
||||||
|
if(!hash_equals(hash_hmac("sha3-224", $photos_list, $secret), $hash))
|
||||||
|
$this->fail(121, "Incorrect hash");
|
||||||
|
|
||||||
|
$album = NULL;
|
||||||
|
if($album_id != 0) {
|
||||||
|
$album_ = (new Albums)->get($album_id);
|
||||||
|
if(!$album_)
|
||||||
|
$this->fail(0404, "Invalid album");
|
||||||
|
else if(!$album_->canBeModifiedBy($this->getUser()))
|
||||||
|
$this->fail(15, "Access: Album can't be 'written' by user");
|
||||||
|
|
||||||
|
$album = $album_;
|
||||||
|
}
|
||||||
|
|
||||||
|
$pList = json_decode($photos_list);
|
||||||
|
$imagePaths = [];
|
||||||
|
foreach($pList as $pDesc)
|
||||||
|
$imagePaths[] = __DIR__ . "/../../tmp/api-storage/photos/$pDesc->keyholder" . "_$pDesc->resource.oct";
|
||||||
|
|
||||||
|
$images = [];
|
||||||
|
try {
|
||||||
|
foreach($imagePaths as $imagePath) {
|
||||||
|
$photo = new Photo;
|
||||||
|
$photo->setOwner($this->getUser()->getId());
|
||||||
|
$photo->setCreated(time());
|
||||||
|
$photo->setFile([
|
||||||
|
"tmp_name" => $imagePath,
|
||||||
|
"error" => 0,
|
||||||
|
]);
|
||||||
|
|
||||||
|
if (!is_null($caption))
|
||||||
|
$photo->setDescription($caption);
|
||||||
|
|
||||||
|
$photo->save();
|
||||||
|
unlink($imagePath);
|
||||||
|
|
||||||
|
if(!is_null($album))
|
||||||
|
$album->addPhoto($photo);
|
||||||
|
|
||||||
|
$images[] = $photo->toVkApiStruct();
|
||||||
|
}
|
||||||
|
} catch(ImageException | InvalidStateException $e) {
|
||||||
|
foreach($imagePaths as $imagePath)
|
||||||
|
unlink($imagePath);
|
||||||
|
|
||||||
|
$this->fail(129, "Invalid image file");
|
||||||
|
}
|
||||||
|
|
||||||
|
return (object) [
|
||||||
|
"count" => sizeof($images),
|
||||||
|
"items" => $images,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
|
@ -5,13 +5,15 @@ use openvk\Web\Models\Repositories\Users as UsersRepo;
|
||||||
|
|
||||||
final class Users extends VKAPIRequestHandler
|
final class Users extends VKAPIRequestHandler
|
||||||
{
|
{
|
||||||
function get(string $user_ids = "0", string $fields = "", int $offset = 0, int $count = 100): array
|
function get(string $user_ids = "0", string $fields = "", int $offset = 0, int $count = 100, User $authuser = null /* костыль(( */): array
|
||||||
{
|
{
|
||||||
$this->requireUser();
|
// $this->requireUser();
|
||||||
|
|
||||||
|
if($authuser == null) $authuser = $this->getUser();
|
||||||
|
|
||||||
$users = new UsersRepo;
|
$users = new UsersRepo;
|
||||||
if($user_ids == "0")
|
if($user_ids == "0")
|
||||||
$user_ids = (string) $this->getUser()->getId();
|
$user_ids = (string) $authuser->getId();
|
||||||
|
|
||||||
$usrs = explode(',', $user_ids);
|
$usrs = explode(',', $user_ids);
|
||||||
$response;
|
$response;
|
||||||
|
@ -51,7 +53,7 @@ final class Users extends VKAPIRequestHandler
|
||||||
$response[$i]->verified = intval($usr->isVerified());
|
$response[$i]->verified = intval($usr->isVerified());
|
||||||
break;
|
break;
|
||||||
case 'sex':
|
case 'sex':
|
||||||
$response[$i]->sex = $this->getUser()->isFemale() ? 1 : 2;
|
$response[$i]->sex = $usr->isFemale() ? 1 : 2;
|
||||||
break;
|
break;
|
||||||
case 'has_photo':
|
case 'has_photo':
|
||||||
$response[$i]->has_photo = is_null($usr->getAvatarPhoto()) ? 0 : 1;
|
$response[$i]->has_photo = is_null($usr->getAvatarPhoto()) ? 0 : 1;
|
||||||
|
@ -71,10 +73,10 @@ final class Users extends VKAPIRequestHandler
|
||||||
$response[$i]->screen_name = $usr->getShortCode();
|
$response[$i]->screen_name = $usr->getShortCode();
|
||||||
break;
|
break;
|
||||||
case 'friend_status':
|
case 'friend_status':
|
||||||
switch($usr->getSubscriptionStatus($this->getUser())) {
|
switch($usr->getSubscriptionStatus($authuser)) {
|
||||||
case 3:
|
case 3:
|
||||||
case 0:
|
case 0:
|
||||||
$response[$i]->friend_status = $usr->getSubscriptionStatus($this->getUser());
|
$response[$i]->friend_status = $usr->getSubscriptionStatus($authuser);
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
$response[$i]->friend_status = 2;
|
$response[$i]->friend_status = 2;
|
||||||
|
@ -158,13 +160,14 @@ final class Users extends VKAPIRequestHandler
|
||||||
$users = new UsersRepo;
|
$users = new UsersRepo;
|
||||||
|
|
||||||
$array = [];
|
$array = [];
|
||||||
|
$find = $users->find($q);
|
||||||
|
|
||||||
foreach ($users->find($q) as $user) {
|
foreach ($find as $user) {
|
||||||
$array[] = $user->getId();
|
$array[] = $user->getId();
|
||||||
}
|
}
|
||||||
|
|
||||||
return (object)[
|
return (object)[
|
||||||
"count" => $users->getFoundCount($q),
|
"count" => $find->size(),
|
||||||
"items" => $this->get(implode(',', $array), $fields, $offset, $count)
|
"items" => $this->get(implode(',', $array), $fields, $offset, $count)
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,6 +22,32 @@ final class Wall extends VKAPIRequestHandler
|
||||||
|
|
||||||
foreach ($posts->getPostsFromUsersWall((int)$owner_id, 1, $count, $offset) as $post) {
|
foreach ($posts->getPostsFromUsersWall((int)$owner_id, 1, $count, $offset) as $post) {
|
||||||
$from_id = get_class($post->getOwner()) == "openvk\Web\Models\Entities\Club" ? $post->getOwner()->getId() * (-1) : $post->getOwner()->getId();
|
$from_id = get_class($post->getOwner()) == "openvk\Web\Models\Entities\Club" ? $post->getOwner()->getId() * (-1) : $post->getOwner()->getId();
|
||||||
|
|
||||||
|
$attachments;
|
||||||
|
foreach($post->getChildren() as $attachment)
|
||||||
|
{
|
||||||
|
if($attachment instanceof \openvk\Web\Models\Entities\Photo)
|
||||||
|
{
|
||||||
|
$attachments[] = [
|
||||||
|
"type" => "photo",
|
||||||
|
"photo" => [
|
||||||
|
"album_id" => $attachment->getAlbum() ? $attachment->getAlbum()->getId() : null,
|
||||||
|
"date" => $attachment->getPublicationTime()->timestamp(),
|
||||||
|
"id" => $attachment->getVirtualId(),
|
||||||
|
"owner_id" => $attachment->getOwner()->getId(),
|
||||||
|
"sizes" => array([
|
||||||
|
"height" => 500, // Для временного компросима оставляю статическое число. Если каждый раз обращаться к файлу за количеством пикселов, то наступает пuпuська полная с производительностью, так что пока так
|
||||||
|
"url" => $attachment->getURL(),
|
||||||
|
"type" => "m",
|
||||||
|
"width" => 500,
|
||||||
|
]),
|
||||||
|
"text" => "",
|
||||||
|
"has_tags" => false
|
||||||
|
]
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
$items[] = (object)[
|
$items[] = (object)[
|
||||||
"id" => $post->getVirtualId(),
|
"id" => $post->getVirtualId(),
|
||||||
"from_id" => $from_id,
|
"from_id" => $from_id,
|
||||||
|
@ -35,6 +61,7 @@ final class Wall extends VKAPIRequestHandler
|
||||||
"can_archive" => false, // TODO MAYBE
|
"can_archive" => false, // TODO MAYBE
|
||||||
"is_archived" => false,
|
"is_archived" => false,
|
||||||
"is_pinned" => $post->isPinned(),
|
"is_pinned" => $post->isPinned(),
|
||||||
|
"attachments" => $attachments,
|
||||||
"post_source" => (object)["type" => "vk"],
|
"post_source" => (object)["type" => "vk"],
|
||||||
"comments" => (object)[
|
"comments" => (object)[
|
||||||
"count" => $post->getCommentsCount(),
|
"count" => $post->getCommentsCount(),
|
||||||
|
@ -56,6 +83,8 @@ final class Wall extends VKAPIRequestHandler
|
||||||
$profiles[] = $from_id;
|
$profiles[] = $from_id;
|
||||||
else
|
else
|
||||||
$groups[] = $from_id * -1;
|
$groups[] = $from_id * -1;
|
||||||
|
|
||||||
|
$attachments = null; // free attachments so it will not clone everythingg
|
||||||
}
|
}
|
||||||
|
|
||||||
if($extended == 1)
|
if($extended == 1)
|
||||||
|
@ -127,6 +156,31 @@ final class Wall extends VKAPIRequestHandler
|
||||||
$post = (new PostsRepo)->getPostById(intval($id[0]), intval($id[1]));
|
$post = (new PostsRepo)->getPostById(intval($id[0]), intval($id[1]));
|
||||||
if($post) {
|
if($post) {
|
||||||
$from_id = get_class($post->getOwner()) == "openvk\Web\Models\Entities\Club" ? $post->getOwner()->getId() * (-1) : $post->getOwner()->getId();
|
$from_id = get_class($post->getOwner()) == "openvk\Web\Models\Entities\Club" ? $post->getOwner()->getId() * (-1) : $post->getOwner()->getId();
|
||||||
|
$attachments;
|
||||||
|
foreach($post->getChildren() as $attachment)
|
||||||
|
{
|
||||||
|
if($attachment instanceof \openvk\Web\Models\Entities\Photo)
|
||||||
|
{
|
||||||
|
$attachments[] = [
|
||||||
|
"type" => "photo",
|
||||||
|
"photo" => [
|
||||||
|
"album_id" => $attachment->getAlbum() ? $attachment->getAlbum()->getId() : null,
|
||||||
|
"date" => $attachment->getPublicationTime()->timestamp(),
|
||||||
|
"id" => $attachment->getVirtualId(),
|
||||||
|
"owner_id" => $attachment->getOwner()->getId(),
|
||||||
|
"sizes" => array([
|
||||||
|
"height" => 500, // я ещё я заебался вставлять одинаковый код в два разных места
|
||||||
|
"url" => $attachment->getURL(),
|
||||||
|
"type" => "m",
|
||||||
|
"width" => 500,
|
||||||
|
]),
|
||||||
|
"text" => "",
|
||||||
|
"has_tags" => false
|
||||||
|
]
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
$items[] = (object)[
|
$items[] = (object)[
|
||||||
"id" => $post->getVirtualId(),
|
"id" => $post->getVirtualId(),
|
||||||
"from_id" => $from_id,
|
"from_id" => $from_id,
|
||||||
|
@ -141,6 +195,7 @@ final class Wall extends VKAPIRequestHandler
|
||||||
"is_archived" => false,
|
"is_archived" => false,
|
||||||
"is_pinned" => $post->isPinned(),
|
"is_pinned" => $post->isPinned(),
|
||||||
"post_source" => (object)["type" => "vk"],
|
"post_source" => (object)["type" => "vk"],
|
||||||
|
"attachments" => $attachments,
|
||||||
"comments" => (object)[
|
"comments" => (object)[
|
||||||
"count" => $post->getCommentsCount(),
|
"count" => $post->getCommentsCount(),
|
||||||
"can_post" => 1
|
"can_post" => 1
|
||||||
|
@ -161,6 +216,8 @@ final class Wall extends VKAPIRequestHandler
|
||||||
$profiles[] = $from_id;
|
$profiles[] = $from_id;
|
||||||
else
|
else
|
||||||
$groups[] = $from_id * -1;
|
$groups[] = $from_id * -1;
|
||||||
|
|
||||||
|
$attachments = null; // free attachments so it will not clone everythingg
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,10 +11,11 @@ final class Message
|
||||||
public $out;
|
public $out;
|
||||||
public $title = "";
|
public $title = "";
|
||||||
public $body;
|
public $body;
|
||||||
|
public $text;
|
||||||
public $attachments = [];
|
public $attachments = [];
|
||||||
public $fwd_messages = [];
|
public $fwd_messages = [];
|
||||||
public $emoji;
|
public $emoji;
|
||||||
public $important = 1;
|
public $important = true;
|
||||||
public $deleted = 0;
|
public $deleted = 0;
|
||||||
public $random_id = NULL;
|
public $random_id = NULL;
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,12 +38,12 @@ class Club extends RowModel
|
||||||
return iterator_to_array($avPhotos)[0] ?? NULL;
|
return iterator_to_array($avPhotos)[0] ?? NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
function getAvatarUrl(): string
|
function getAvatarUrl(string $size = "miniscule"): string
|
||||||
{
|
{
|
||||||
$serverUrl = ovk_scheme(true) . $_SERVER["HTTP_HOST"];
|
$serverUrl = ovk_scheme(true) . $_SERVER["HTTP_HOST"];
|
||||||
$avPhoto = $this->getAvatarPhoto();
|
$avPhoto = $this->getAvatarPhoto();
|
||||||
|
|
||||||
return is_null($avPhoto) ? "$serverUrl/assets/packages/static/openvk/img/camera_200.png" : $avPhoto->getURL();
|
return is_null($avPhoto) ? "$serverUrl/assets/packages/static/openvk/img/camera_200.png" : $avPhoto->getURLBySizeId($size);
|
||||||
}
|
}
|
||||||
|
|
||||||
function getAvatarLink(): string
|
function getAvatarLink(): string
|
||||||
|
|
|
@ -1,5 +1,8 @@
|
||||||
<?php declare(strict_types=1);
|
<?php declare(strict_types=1);
|
||||||
namespace openvk\Web\Models\Entities;
|
namespace openvk\Web\Models\Entities;
|
||||||
|
use MessagePack\MessagePack;
|
||||||
|
use openvk\Web\Models\Entities\Album;
|
||||||
|
use openvk\Web\Models\Repositories\Albums;
|
||||||
use Chandler\Database\DatabaseConnection as DB;
|
use Chandler\Database\DatabaseConnection as DB;
|
||||||
use Nette\InvalidStateException as ISE;
|
use Nette\InvalidStateException as ISE;
|
||||||
use Nette\Utils\Image;
|
use Nette\Utils\Image;
|
||||||
|
@ -11,18 +14,80 @@ class Photo extends Media
|
||||||
|
|
||||||
const ALLOWED_SIDE_MULTIPLIER = 7;
|
const ALLOWED_SIDE_MULTIPLIER = 7;
|
||||||
|
|
||||||
|
private function resizeImage(string $filename, string $outputDir, \SimpleXMLElement $size): array
|
||||||
|
{
|
||||||
|
$res = [false];
|
||||||
|
$image = Image::fromFile($filename);
|
||||||
|
$requiresProportion = ((string) $size["requireProp"]) != "none";
|
||||||
|
if($requiresProportion) {
|
||||||
|
$props = explode(":", (string) $size["requireProp"]);
|
||||||
|
$px = (int) $props[0];
|
||||||
|
$py = (int) $props[1];
|
||||||
|
if(($image->getWidth() / $image->getHeight()) > ($px / $py)) {
|
||||||
|
# For some weird reason using resize with EXACT flag causes system to consume an unholy amount of RAM
|
||||||
|
$image->crop(0, 0, "100%", (int) ceil(($px * $image->getWidth()) / $py));
|
||||||
|
$res[0] = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(isset($size["maxSize"])) {
|
||||||
|
$maxSize = (int) $size["maxSize"];
|
||||||
|
$image->resize($maxSize, $maxSize, Image::SHRINK_ONLY | Image::FIT);
|
||||||
|
} else if(isset($size["maxResolution"])) {
|
||||||
|
$resolution = explode("x", (string) $size["maxResolution"]);
|
||||||
|
$image->resize((int) $resolution[0], (int) $resolution[1], Image::SHRINK_ONLY | Image::FIT);
|
||||||
|
} else {
|
||||||
|
throw new \RuntimeException("Malformed size description: " . (string) $size["id"]);
|
||||||
|
}
|
||||||
|
|
||||||
|
$res[1] = $image->getWidth();
|
||||||
|
$res[2] = $image->getHeight();
|
||||||
|
if($res[1] <= 300 || $res[2] <= 300)
|
||||||
|
$image->save("$outputDir/" . (string) $size["id"] . ".gif");
|
||||||
|
else
|
||||||
|
$image->save("$outputDir/" . (string) $size["id"] . ".jpeg");
|
||||||
|
|
||||||
|
imagedestroy($image->getImageResource());
|
||||||
|
unset($image);
|
||||||
|
|
||||||
|
return $res;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function saveImageResizedCopies(string $filename, string $hash): void
|
||||||
|
{
|
||||||
|
$dir = dirname($this->pathFromHash($hash));
|
||||||
|
$dir = "$dir/$hash" . "_cropped";
|
||||||
|
if(!is_dir($dir)) {
|
||||||
|
@unlink($dir); # Added to transparently bypass issues with dead pesudofolders summoned by buggy SWIFT impls (selectel)
|
||||||
|
mkdir($dir);
|
||||||
|
}
|
||||||
|
|
||||||
|
$sizes = simplexml_load_file(OPENVK_ROOT . "/data/photosizes.xml");
|
||||||
|
if(!$sizes)
|
||||||
|
throw new \RuntimeException("Could not load photosizes.xml!");
|
||||||
|
|
||||||
|
$sizesMeta = [];
|
||||||
|
foreach($sizes->Size as $size)
|
||||||
|
$sizesMeta[(string) $size["id"]] = $this->resizeImage($filename, $dir, $size);
|
||||||
|
|
||||||
|
$sizesMeta = MessagePack::pack($sizesMeta);
|
||||||
|
$this->stateChanges("sizes", $sizesMeta);
|
||||||
|
}
|
||||||
|
|
||||||
protected function saveFile(string $filename, string $hash): bool
|
protected function saveFile(string $filename, string $hash): bool
|
||||||
{
|
{
|
||||||
$image = Image::fromFile($filename);
|
$image = Image::fromFile($filename);
|
||||||
if(($image->height >= ($image->width * Photo::ALLOWED_SIDE_MULTIPLIER)) || ($image->width >= ($image->height * Photo::ALLOWED_SIDE_MULTIPLIER)))
|
if(($image->height >= ($image->width * Photo::ALLOWED_SIDE_MULTIPLIER)) || ($image->width >= ($image->height * Photo::ALLOWED_SIDE_MULTIPLIER)))
|
||||||
throw new ISE("Invalid layout: image is too wide/short");
|
throw new ISE("Invalid layout: image is too wide/short");
|
||||||
|
|
||||||
|
$image->resize(8192, 4320, Image::SHRINK_ONLY | Image::FIT);
|
||||||
$image->save($this->pathFromHash($hash), 92, Image::JPEG);
|
$image->save($this->pathFromHash($hash), 92, Image::JPEG);
|
||||||
|
$this->saveImageResizedCopies($filename, $hash);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
function crop(real $left, real $top, real $width, real $height): bool
|
function crop(real $left, real $top, real $width, real $height): void
|
||||||
{
|
{
|
||||||
if(isset($this->changes["hash"]))
|
if(isset($this->changes["hash"]))
|
||||||
$hash = $this->changes["hash"];
|
$hash = $this->changes["hash"];
|
||||||
|
@ -33,7 +98,7 @@ class Photo extends Media
|
||||||
|
|
||||||
$image = Image::fromFile($this->pathFromHash($hash));
|
$image = Image::fromFile($this->pathFromHash($hash));
|
||||||
$image->crop($left, $top, $width, $height);
|
$image->crop($left, $top, $width, $height);
|
||||||
return $image->save($this->pathFromHash($hash));
|
$image->save($this->pathFromHash($hash));
|
||||||
}
|
}
|
||||||
|
|
||||||
function isolate(): void
|
function isolate(): void
|
||||||
|
@ -44,6 +109,127 @@ class Photo extends Media
|
||||||
DB::i()->getContext()->table("album_relations")->where("media", $this->getRecord()->id)->delete();
|
DB::i()->getContext()->table("album_relations")->where("media", $this->getRecord()->id)->delete();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getSizes(bool $upgrade = false, bool $forceUpdate = false): ?array
|
||||||
|
{
|
||||||
|
$sizes = $this->getRecord()->sizes;
|
||||||
|
if(!$sizes || $forceUpdate) {
|
||||||
|
if($forceUpdate || $upgrade || OPENVK_ROOT_CONF["openvk"]["preferences"]["photos"]["upgradeStructure"]) {
|
||||||
|
$hash = $this->getRecord()->hash;
|
||||||
|
$this->saveImageResizedCopies($this->pathFromHash($hash), $hash);
|
||||||
|
$this->save();
|
||||||
|
|
||||||
|
return $this->getSizes();
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
$res = [];
|
||||||
|
$sizes = MessagePack::unpack($sizes);
|
||||||
|
foreach($sizes as $id => $meta) {
|
||||||
|
$url = $this->getURL();
|
||||||
|
$url = str_replace(".$this->fileExtension", "_cropped/$id.", $url);
|
||||||
|
$url .= ($meta[1] <= 300 || $meta[2] <= 300) ? "gif" : "jpeg";
|
||||||
|
|
||||||
|
$res[$id] = (object) [
|
||||||
|
"url" => $url,
|
||||||
|
"width" => $meta[1],
|
||||||
|
"height" => $meta[2],
|
||||||
|
"crop" => $meta[0]
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
[$x, $y] = $this->getDimensions();
|
||||||
|
$res["UPLOADED_MAXRES"] = (object) [
|
||||||
|
"url" => $this->getURL(),
|
||||||
|
"width" => $x,
|
||||||
|
"height" => $y,
|
||||||
|
"crop" => false
|
||||||
|
];
|
||||||
|
|
||||||
|
return $res;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getVkApiSizes(): ?array
|
||||||
|
{
|
||||||
|
$res = [];
|
||||||
|
$sizes = $this->getSizes();
|
||||||
|
if(!$sizes)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
$manifest = simplexml_load_file(OPENVK_ROOT . "/data/photosizes.xml");
|
||||||
|
if(!$manifest)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
$mappings = [];
|
||||||
|
foreach($manifest->Size as $size)
|
||||||
|
$mappings[(string) $size["id"]] = (string) $size["vkId"];
|
||||||
|
|
||||||
|
foreach($sizes as $id => $meta)
|
||||||
|
$res[$mappings[$id] ?? $id] = $meta;
|
||||||
|
|
||||||
|
return $res;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getURLBySizeId(string $size): string
|
||||||
|
{
|
||||||
|
$sizes = $this->getSizes();
|
||||||
|
if(!$sizes)
|
||||||
|
return $this->getURL();
|
||||||
|
|
||||||
|
$size = $sizes[$size];
|
||||||
|
if(!$size)
|
||||||
|
return $this->getURL();
|
||||||
|
|
||||||
|
return $size->url;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getDimensions(): array
|
||||||
|
{
|
||||||
|
$x = $this->getRecord()->width;
|
||||||
|
$y = $this->getRecord()->height;
|
||||||
|
if(!$x) { # no sizes in database
|
||||||
|
$hash = $this->getRecord()->hash;
|
||||||
|
$image = Image::fromFile($this->pathFromHash($hash));
|
||||||
|
|
||||||
|
$x = $image->getWidth();
|
||||||
|
$y = $image->getHeight();
|
||||||
|
$this->stateChanges("width", $x);
|
||||||
|
$this->stateChanges("height", $y);
|
||||||
|
$this->save();
|
||||||
|
}
|
||||||
|
|
||||||
|
return [$x, $y];
|
||||||
|
}
|
||||||
|
|
||||||
|
function getAlbum(): ?Album
|
||||||
|
{
|
||||||
|
return (new Albums)->getAlbumByPhotoId($this);
|
||||||
|
}
|
||||||
|
|
||||||
|
function toVkApiStruct(): object
|
||||||
|
{
|
||||||
|
$res = (object) [];
|
||||||
|
|
||||||
|
$res->id = $res->pid = $this->getId();
|
||||||
|
$res->owner_id = $res->user_id = $this->getOwner()->getId()->getId();
|
||||||
|
$res->aid = $res->album_id = NULL;
|
||||||
|
$res->width = $this->getDimensions()[0];
|
||||||
|
$res->height = $this->getDimensions()[1];
|
||||||
|
$res->date = $res->created = $this->getPublicationTime()->timestamp();
|
||||||
|
|
||||||
|
$res->sizes = $this->getVkApiSizes();
|
||||||
|
$res->src_small = $res->photo_75 = $this->getURLBySizeId("miniscule");
|
||||||
|
$res->src = $res->photo_130 = $this->getURLBySizeId("tiny");
|
||||||
|
$res->src_big = $res->photo_604 = $this->getURLBySizeId("normal");
|
||||||
|
$res->src_xbig = $res->photo_807 = $this->getURLBySizeId("large");
|
||||||
|
$res->src_xxbig = $res->photo_1280 = $this->getURLBySizeId("larger");
|
||||||
|
$res->src_xxxbig = $res->photo_2560 = $this->getURLBySizeId("original");
|
||||||
|
$res->src_original = $res->url = $this->getURLBySizeId("UPLOADED_MAXRES");
|
||||||
|
|
||||||
|
return $res;
|
||||||
|
}
|
||||||
|
|
||||||
static function fastMake(int $owner, string $description = "", array $file, ?Album $album = NULL, bool $anon = false): Photo
|
static function fastMake(int $owner, string $description = "", array $file, ?Album $album = NULL, bool $anon = false): Photo
|
||||||
{
|
{
|
||||||
$photo = new static;
|
$photo = new static;
|
||||||
|
|
|
@ -31,11 +31,11 @@ class User extends RowModel
|
||||||
const NSFW_TOLERANT = 1;
|
const NSFW_TOLERANT = 1;
|
||||||
const NSFW_FULL_TOLERANT = 2;
|
const NSFW_FULL_TOLERANT = 2;
|
||||||
|
|
||||||
protected function _abstractRelationGenerator(string $filename, int $page = 1): \Traversable
|
protected function _abstractRelationGenerator(string $filename, int $page = 1, int $limit = 6): \Traversable
|
||||||
{
|
{
|
||||||
$id = $this->getId();
|
$id = $this->getId();
|
||||||
$query = "SELECT id FROM\n" . file_get_contents(__DIR__ . "/../sql/$filename.tsql");
|
$query = "SELECT id FROM\n" . file_get_contents(__DIR__ . "/../sql/$filename.tsql");
|
||||||
$query .= "\n LIMIT 6 OFFSET " . ( ($page - 1) * 6 );
|
$query .= "\n LIMIT " . $limit . " OFFSET " . ( ($page - 1) * $limit );
|
||||||
|
|
||||||
$rels = DatabaseConnection::i()->getConnection()->query($query, $id, $id);
|
$rels = DatabaseConnection::i()->getConnection()->query($query, $id, $id);
|
||||||
foreach($rels as $rel) {
|
foreach($rels as $rel) {
|
||||||
|
@ -102,7 +102,7 @@ class User extends RowModel
|
||||||
return "/id" . $this->getId();
|
return "/id" . $this->getId();
|
||||||
}
|
}
|
||||||
|
|
||||||
function getAvatarUrl(): string
|
function getAvatarUrl(string $size = "miniscule"): string
|
||||||
{
|
{
|
||||||
$serverUrl = ovk_scheme(true) . $_SERVER["HTTP_HOST"];
|
$serverUrl = ovk_scheme(true) . $_SERVER["HTTP_HOST"];
|
||||||
|
|
||||||
|
@ -115,7 +115,7 @@ class User extends RowModel
|
||||||
if(is_null($avPhoto))
|
if(is_null($avPhoto))
|
||||||
return "$serverUrl/assets/packages/static/openvk/img/camera_200.png";
|
return "$serverUrl/assets/packages/static/openvk/img/camera_200.png";
|
||||||
else
|
else
|
||||||
return $avPhoto->getURL();
|
return $avPhoto->getURLBySizeId($size);
|
||||||
}
|
}
|
||||||
|
|
||||||
function getAvatarLink(): string
|
function getAvatarLink(): string
|
||||||
|
@ -215,6 +215,11 @@ class User extends RowModel
|
||||||
return $this->getRecord()->block_reason;
|
return $this->getRecord()->block_reason;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getBanInSupportReason(): ?string
|
||||||
|
{
|
||||||
|
return $this->getRecord()->block_in_support_reason;
|
||||||
|
}
|
||||||
|
|
||||||
function getType(): int
|
function getType(): int
|
||||||
{
|
{
|
||||||
return $this->getRecord()->type;
|
return $this->getRecord()->type;
|
||||||
|
@ -438,9 +443,9 @@ class User extends RowModel
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
function getFriends(int $page = 1): \Traversable
|
function getFriends(int $page = 1, int $limit = 6): \Traversable
|
||||||
{
|
{
|
||||||
return $this->_abstractRelationGenerator("get-friends", $page);
|
return $this->_abstractRelationGenerator("get-friends", $page, $limit);
|
||||||
}
|
}
|
||||||
|
|
||||||
function getFriendsCount(): int
|
function getFriendsCount(): int
|
||||||
|
@ -448,9 +453,9 @@ class User extends RowModel
|
||||||
return $this->_abstractRelationCount("get-friends");
|
return $this->_abstractRelationCount("get-friends");
|
||||||
}
|
}
|
||||||
|
|
||||||
function getFollowers(int $page = 1): \Traversable
|
function getFollowers(int $page = 1, int $limit = 6): \Traversable
|
||||||
{
|
{
|
||||||
return $this->_abstractRelationGenerator("get-followers", $page);
|
return $this->_abstractRelationGenerator("get-followers", $page, $limit);
|
||||||
}
|
}
|
||||||
|
|
||||||
function getFollowersCount(): int
|
function getFollowersCount(): int
|
||||||
|
@ -458,9 +463,9 @@ class User extends RowModel
|
||||||
return $this->_abstractRelationCount("get-followers");
|
return $this->_abstractRelationCount("get-followers");
|
||||||
}
|
}
|
||||||
|
|
||||||
function getSubscriptions(int $page = 1): \Traversable
|
function getSubscriptions(int $page = 1, int $limit = 6): \Traversable
|
||||||
{
|
{
|
||||||
return $this->_abstractRelationGenerator("get-subscriptions-user", $page);
|
return $this->_abstractRelationGenerator("get-subscriptions-user", $page, $limit);
|
||||||
}
|
}
|
||||||
|
|
||||||
function getSubscriptionsCount(): int
|
function getSubscriptionsCount(): int
|
||||||
|
@ -674,6 +679,11 @@ class User extends RowModel
|
||||||
return !is_null($this->getBanReason());
|
return !is_null($this->getBanReason());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function isBannedInSupport(): bool
|
||||||
|
{
|
||||||
|
return !is_null($this->getBanInSupportReason());
|
||||||
|
}
|
||||||
|
|
||||||
function isOnline(): bool
|
function isOnline(): bool
|
||||||
{
|
{
|
||||||
return time() - $this->getRecord()->online <= 300;
|
return time() - $this->getRecord()->online <= 300;
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
<?php declare(strict_types=1);
|
<?php declare(strict_types=1);
|
||||||
namespace openvk\Web\Models\Repositories;
|
namespace openvk\Web\Models\Repositories;
|
||||||
use openvk\Web\Models\Entities\Album;
|
use openvk\Web\Models\Entities\Album;
|
||||||
|
use openvk\Web\Models\Entities\Photo;
|
||||||
use openvk\Web\Models\Entities\Club;
|
use openvk\Web\Models\Entities\Club;
|
||||||
use openvk\Web\Models\Entities\User;
|
use openvk\Web\Models\Entities\User;
|
||||||
use Nette\Database\Table\ActiveRow;
|
use Nette\Database\Table\ActiveRow;
|
||||||
|
@ -115,4 +116,11 @@ class Albums
|
||||||
|
|
||||||
return new Album($album);
|
return new Album($album);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getAlbumByPhotoId(Photo $photo): ?Album
|
||||||
|
{
|
||||||
|
$dbalbum = $this->context->table("album_relations")->where(["media" => $photo->getId()])->fetch();
|
||||||
|
|
||||||
|
return $dbalbum->collection ? $this->get($dbalbum->collection) : null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -94,7 +94,6 @@ class Posts
|
||||||
{
|
{
|
||||||
$post = $this->posts->where(['wall' => $wall, 'virtual_id' => $post])->fetch();
|
$post = $this->posts->where(['wall' => $wall, 'virtual_id' => $post])->fetch();
|
||||||
if(!is_null($post))
|
if(!is_null($post))
|
||||||
|
|
||||||
return new Post($post);
|
return new Post($post);
|
||||||
else
|
else
|
||||||
return null;
|
return null;
|
||||||
|
|
|
@ -39,7 +39,7 @@ class Users
|
||||||
function find(string $query): Util\EntityStream
|
function find(string $query): Util\EntityStream
|
||||||
{
|
{
|
||||||
$query = "%$query%";
|
$query = "%$query%";
|
||||||
$result = $this->users->where("CONCAT_WS(' ', first_name, last_name, pseudo) LIKE ?", $query)->where("deleted", 0);
|
$result = $this->users->where("CONCAT_WS(' ', first_name, last_name, pseudo, shortcode) LIKE ?", $query)->where("deleted", 0);
|
||||||
|
|
||||||
return new Util\EntityStream("User", $result);
|
return new Util\EntityStream("User", $result);
|
||||||
}
|
}
|
||||||
|
|
|
@ -346,7 +346,20 @@ final class AdminPresenter extends OpenVKPresenter
|
||||||
exit(json_encode([ "error" => "User does not exist" ]));
|
exit(json_encode([ "error" => "User does not exist" ]));
|
||||||
|
|
||||||
$user->ban($this->queryParam("reason"));
|
$user->ban($this->queryParam("reason"));
|
||||||
exit(json_encode([ "reason" => $this->queryParam("reason") ]));
|
exit(json_encode([ "success" => true, "reason" => $this->queryParam("reason") ]));
|
||||||
|
}
|
||||||
|
|
||||||
|
function renderQuickUnban(int $id): void
|
||||||
|
{
|
||||||
|
$this->assertNoCSRF();
|
||||||
|
|
||||||
|
$user = $this->users->get($id);
|
||||||
|
if(!$user)
|
||||||
|
exit(json_encode([ "error" => "User does not exist" ]));
|
||||||
|
|
||||||
|
$user->setBlock_Reason(null);
|
||||||
|
$user->save();
|
||||||
|
exit(json_encode([ "success" => true ]));
|
||||||
}
|
}
|
||||||
|
|
||||||
function renderQuickWarn(int $id): void
|
function renderQuickWarn(int $id): void
|
||||||
|
|
|
@ -4,6 +4,7 @@ use openvk\Web\Models\Entities\IP;
|
||||||
use openvk\Web\Models\Entities\User;
|
use openvk\Web\Models\Entities\User;
|
||||||
use openvk\Web\Models\Entities\PasswordReset;
|
use openvk\Web\Models\Entities\PasswordReset;
|
||||||
use openvk\Web\Models\Entities\EmailVerification;
|
use openvk\Web\Models\Entities\EmailVerification;
|
||||||
|
use openvk\Web\Models\Exceptions\InvalidUserNameException;
|
||||||
use openvk\Web\Models\Repositories\IPs;
|
use openvk\Web\Models\Repositories\IPs;
|
||||||
use openvk\Web\Models\Repositories\Users;
|
use openvk\Web\Models\Repositories\Users;
|
||||||
use openvk\Web\Models\Repositories\Restores;
|
use openvk\Web\Models\Repositories\Restores;
|
||||||
|
@ -88,12 +89,8 @@ final class AuthPresenter extends OpenVKPresenter
|
||||||
if (strtotime($this->postParam("birthday")) > time())
|
if (strtotime($this->postParam("birthday")) > time())
|
||||||
$this->flashFail("err", tr("invalid_birth_date"), tr("invalid_birth_date_comment"));
|
$this->flashFail("err", tr("invalid_birth_date"), tr("invalid_birth_date_comment"));
|
||||||
|
|
||||||
$chUser = ChandlerUser::create($this->postParam("email"), $this->postParam("password"));
|
try {
|
||||||
if(!$chUser)
|
|
||||||
$this->flashFail("err", tr("failed_to_register"), tr("user_already_exists"));
|
|
||||||
|
|
||||||
$user = new User;
|
$user = new User;
|
||||||
$user->setUser($chUser->getId());
|
|
||||||
$user->setFirst_Name($this->postParam("first_name"));
|
$user->setFirst_Name($this->postParam("first_name"));
|
||||||
$user->setLast_Name($this->postParam("last_name"));
|
$user->setLast_Name($this->postParam("last_name"));
|
||||||
$user->setSex((int)($this->postParam("sex") === "female"));
|
$user->setSex((int)($this->postParam("sex") === "female"));
|
||||||
|
@ -102,6 +99,15 @@ final class AuthPresenter extends OpenVKPresenter
|
||||||
$user->setRegistering_Ip(CONNECTING_IP);
|
$user->setRegistering_Ip(CONNECTING_IP);
|
||||||
$user->setBirthday(strtotime($this->postParam("birthday")));
|
$user->setBirthday(strtotime($this->postParam("birthday")));
|
||||||
$user->setActivated((int)!OPENVK_ROOT_CONF['openvk']['preferences']['security']['requireEmail']);
|
$user->setActivated((int)!OPENVK_ROOT_CONF['openvk']['preferences']['security']['requireEmail']);
|
||||||
|
} catch(InvalidUserNameException $ex) {
|
||||||
|
$this->flashFail("err", tr("error"), tr("invalid_real_name"));
|
||||||
|
}
|
||||||
|
|
||||||
|
$chUser = ChandlerUser::create($this->postParam("email"), $this->postParam("password"));
|
||||||
|
if(!$chUser)
|
||||||
|
$this->flashFail("err", tr("failed_to_register"), tr("user_already_exists"));
|
||||||
|
|
||||||
|
$user->setUser($chUser->getId());
|
||||||
$user->save();
|
$user->save();
|
||||||
|
|
||||||
if(!is_null($referer)) {
|
if(!is_null($referer)) {
|
||||||
|
|
|
@ -204,6 +204,8 @@ abstract class OpenVKPresenter extends SimplePresenter
|
||||||
$this->template->isXmas = intval(date('d')) >= 1 && date('m') == 12 || intval(date('d')) <= 15 && date('m') == 1 ? true : false;
|
$this->template->isXmas = intval(date('d')) >= 1 && date('m') == 12 || intval(date('d')) <= 15 && date('m') == 1 ? true : false;
|
||||||
$this->template->isTimezoned = Session::i()->get("_timezoneOffset");
|
$this->template->isTimezoned = Session::i()->get("_timezoneOffset");
|
||||||
|
|
||||||
|
$userValidated = 0;
|
||||||
|
$cacheTime = OPENVK_ROOT_CONF["openvk"]["preferences"]["nginxCacheTime"] ?? 0;
|
||||||
if(!is_null($user)) {
|
if(!is_null($user)) {
|
||||||
$this->user = (object) [];
|
$this->user = (object) [];
|
||||||
$this->user->raw = $user;
|
$this->user->raw = $user;
|
||||||
|
@ -261,6 +263,8 @@ abstract class OpenVKPresenter extends SimplePresenter
|
||||||
exit;
|
exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$userValidated = 1;
|
||||||
|
$cacheTime = 0; # Force no cache
|
||||||
if ($this->user->identity->onlineStatus() == 0) {
|
if ($this->user->identity->onlineStatus() == 0) {
|
||||||
$this->user->identity->setOnline(time());
|
$this->user->identity->setOnline(time());
|
||||||
$this->user->identity->save();
|
$this->user->identity->save();
|
||||||
|
@ -273,6 +277,8 @@ abstract class OpenVKPresenter extends SimplePresenter
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
header("X-OpenVK-User-Validated: $userValidated");
|
||||||
|
header("X-Accel-Expires: $cacheTime");
|
||||||
setlocale(LC_TIME, ...(explode(";", tr("__locale"))));
|
setlocale(LC_TIME, ...(explode(";", tr("__locale"))));
|
||||||
|
|
||||||
parent::onStartup();
|
parent::onStartup();
|
||||||
|
|
|
@ -276,6 +276,8 @@ final class PhotosPresenter extends OpenVKPresenter
|
||||||
|
|
||||||
$photo->isolate();
|
$photo->isolate();
|
||||||
$photo->delete();
|
$photo->delete();
|
||||||
exit("Фотография успешно удалена!");
|
|
||||||
|
$this->flash("succ", "Фотография удалена", "Эта фотография была успешно удалена.");
|
||||||
|
$this->redirect("/id0", static::REDIRECT_TEMPORARY);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,6 +25,10 @@ final class SearchPresenter extends OpenVKPresenter
|
||||||
$type = $this->queryParam("type") ?? "users";
|
$type = $this->queryParam("type") ?? "users";
|
||||||
$page = (int) ($this->queryParam("p") ?? 1);
|
$page = (int) ($this->queryParam("p") ?? 1);
|
||||||
|
|
||||||
|
$this->willExecuteWriteAction();
|
||||||
|
if($query != "")
|
||||||
|
$this->assertUserLoggedIn();
|
||||||
|
|
||||||
// https://youtu.be/pSAWM5YuXx8
|
// https://youtu.be/pSAWM5YuXx8
|
||||||
|
|
||||||
$repos = [ "groups" => "clubs", "users" => "users" ];
|
$repos = [ "groups" => "clubs", "users" => "users" ];
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<?php declare(strict_types=1);
|
<?php declare(strict_types=1);
|
||||||
namespace openvk\Web\Presenters;
|
namespace openvk\Web\Presenters;
|
||||||
use openvk\Web\Models\Entities\Ticket;
|
use openvk\Web\Models\Entities\Ticket;
|
||||||
use openvk\Web\Models\Repositories\Tickets;
|
use openvk\Web\Models\Repositories\{Tickets, Users};
|
||||||
use openvk\Web\Models\Entities\TicketComment;
|
use openvk\Web\Models\Entities\TicketComment;
|
||||||
use openvk\Web\Models\Repositories\TicketComments;
|
use openvk\Web\Models\Repositories\TicketComments;
|
||||||
use openvk\Web\Util\Telegram;
|
use openvk\Web\Util\Telegram;
|
||||||
|
@ -34,7 +34,13 @@ final class SupportPresenter extends OpenVKPresenter
|
||||||
$this->template->tickets = $this->tickets->getTicketsByUserId($this->user->id, $this->template->page);
|
$this->template->tickets = $this->tickets->getTicketsByUserId($this->user->id, $this->template->page);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if($this->template->mode === "new")
|
||||||
|
$this->template->banReason = $this->user->identity->getBanInSupportReason();
|
||||||
|
|
||||||
if($_SERVER["REQUEST_METHOD"] === "POST") {
|
if($_SERVER["REQUEST_METHOD"] === "POST") {
|
||||||
|
if($this->user->identity->isBannedInSupport())
|
||||||
|
$this->flashFail("err", tr("not_enough_permissions"), tr("not_enough_permissions_comment"));
|
||||||
|
|
||||||
if(!empty($this->postParam("name")) && !empty($this->postParam("text"))) {
|
if(!empty($this->postParam("name")) && !empty($this->postParam("text"))) {
|
||||||
$this->willExecuteWriteAction();
|
$this->willExecuteWriteAction();
|
||||||
|
|
||||||
|
@ -268,4 +274,32 @@ final class SupportPresenter extends OpenVKPresenter
|
||||||
|
|
||||||
exit(header("HTTP/1.1 200 OK"));
|
exit(header("HTTP/1.1 200 OK"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function renderQuickBanInSupport(int $id): void
|
||||||
|
{
|
||||||
|
$this->assertPermission("openvk\Web\Models\Entities\TicketReply", "write", 0);
|
||||||
|
$this->assertNoCSRF();
|
||||||
|
|
||||||
|
$user = (new Users)->get($id);
|
||||||
|
if(!$user)
|
||||||
|
exit(json_encode([ "error" => "User does not exist" ]));
|
||||||
|
|
||||||
|
$user->setBlock_In_Support_Reason($this->queryParam("reason"));
|
||||||
|
$user->save();
|
||||||
|
$this->returnJson([ "success" => true, "reason" => $this->queryParam("reason") ]);
|
||||||
|
}
|
||||||
|
|
||||||
|
function renderQuickUnbanInSupport(int $id): void
|
||||||
|
{
|
||||||
|
$this->assertPermission("openvk\Web\Models\Entities\TicketReply", "write", 0);
|
||||||
|
$this->assertNoCSRF();
|
||||||
|
|
||||||
|
$user = (new Users)->get($id);
|
||||||
|
if(!$user)
|
||||||
|
exit(json_encode([ "error" => "User does not exist" ]));
|
||||||
|
|
||||||
|
$user->setBlock_In_Support_Reason(null);
|
||||||
|
$user->save();
|
||||||
|
$this->returnJson([ "success" => true ]);
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -285,7 +285,6 @@ final class UserPresenter extends OpenVKPresenter
|
||||||
$photo->setCreated(time());
|
$photo->setCreated(time());
|
||||||
$photo->save();
|
$photo->save();
|
||||||
} catch(ISE $ex) {
|
} catch(ISE $ex) {
|
||||||
$name = $album->getName();
|
|
||||||
$this->flashFail("err", tr("error"), tr("error_upload_failed"));
|
$this->flashFail("err", tr("error"), tr("error_upload_failed"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -78,6 +78,92 @@ final class VKAPIPresenter extends OpenVKPresenter
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function renderPhotoUpload(string $signature): void
|
||||||
|
{
|
||||||
|
$secret = CHANDLER_ROOT_CONF["security"]["secret"];
|
||||||
|
$computedSignature = hash_hmac("sha3-224", $_SERVER["QUERY_STRING"], $secret);
|
||||||
|
if(!(strlen($signature) == 56 && sodium_memcmp($signature, $computedSignature) == 0)) {
|
||||||
|
header("HTTP/1.1 422 Unprocessable Entity");
|
||||||
|
exit("Try harder <3");
|
||||||
|
}
|
||||||
|
|
||||||
|
$data = unpack("vDOMAIN/Z10FIELD/vMF/vMP/PTIME/PUSER/PGROUP", base64_decode($_SERVER["QUERY_STRING"]));
|
||||||
|
if((time() - $data["TIME"]) > 600) {
|
||||||
|
header("HTTP/1.1 422 Unprocessable Entity");
|
||||||
|
exit("Expired");
|
||||||
|
}
|
||||||
|
|
||||||
|
$folder = __DIR__ . "../../tmp/api-storage/photos";
|
||||||
|
$maxSize = OPENVK_ROOT_CONF["openvk"]["preferences"]["uploads"]["api"]["maxFileSize"];
|
||||||
|
$maxFiles = OPENVK_ROOT_CONF["openvk"]["preferences"]["uploads"]["api"]["maxFilesPerDomain"];
|
||||||
|
$usrFiles = sizeof(glob("$folder/$data[USER]_*.oct"));
|
||||||
|
if($usrFiles >= $maxFiles) {
|
||||||
|
header("HTTP/1.1 507 Insufficient Storage");
|
||||||
|
exit("There are $maxFiles pending already. Please save them before uploading more :3");
|
||||||
|
}
|
||||||
|
|
||||||
|
# Not multifile
|
||||||
|
if($data["MF"] === 0) {
|
||||||
|
$file = $_FILES[$data["FIELD"]];
|
||||||
|
if(!$file) {
|
||||||
|
header("HTTP/1.0 400");
|
||||||
|
exit("No file");
|
||||||
|
} else if($file["error"] != UPLOAD_ERR_OK) {
|
||||||
|
header("HTTP/1.0 500");
|
||||||
|
exit("File could not be consumed");
|
||||||
|
} else if($file["size"] > $maxSize) {
|
||||||
|
header("HTTP/1.0 507 Insufficient Storage");
|
||||||
|
exit("File is too big");
|
||||||
|
}
|
||||||
|
|
||||||
|
move_uploaded_file($file["tmp_name"], "$folder/$data[USER]_" . ($usrFiles + 1) . ".oct");
|
||||||
|
header("HTTP/1.0 202 Accepted");
|
||||||
|
|
||||||
|
$photo = $data["USER"] . "|" . ($usrFiles + 1) . "|" . $data["GROUP"];
|
||||||
|
exit(json_encode([
|
||||||
|
"server" => "ephemeral",
|
||||||
|
"photo" => $photo,
|
||||||
|
"hash" => hash_hmac("sha3-224", $photo, $secret),
|
||||||
|
]));
|
||||||
|
}
|
||||||
|
|
||||||
|
$files = [];
|
||||||
|
for($i = 1; $i <= 5; $i++) {
|
||||||
|
$file = $_FILES[$data["FIELD"] . $i] ?? NULL;
|
||||||
|
if (!$file || $file["error"] != UPLOAD_ERR_OK || $file["size"] > $maxSize) {
|
||||||
|
continue;
|
||||||
|
} else if((sizeof($files) + $usrFiles) > $maxFiles) {
|
||||||
|
# Clear uploaded files since they can't be saved anyway
|
||||||
|
foreach($files as $f)
|
||||||
|
unlink($f);
|
||||||
|
|
||||||
|
header("HTTP/1.1 507 Insufficient Storage");
|
||||||
|
exit("There are $maxFiles pending already. Please save them before uploading more :3");
|
||||||
|
}
|
||||||
|
|
||||||
|
$files[++$usrFiles] = move_uploaded_file($file["tmp_name"], "$folder/$data[USER]_$usrFiles.oct");
|
||||||
|
}
|
||||||
|
|
||||||
|
if(sizeof($files) === 0) {
|
||||||
|
header("HTTP/1.0 400");
|
||||||
|
exit("No file");
|
||||||
|
}
|
||||||
|
|
||||||
|
$filesManifest = [];
|
||||||
|
foreach($files as $id => $file)
|
||||||
|
$filesManifest[] = ["keyholder" => $data["USER"], "resource" => $id, "club" => $data["GROUP"]];
|
||||||
|
|
||||||
|
$filesManifest = json_encode($filesManifest);
|
||||||
|
$manifestHash = hash_hmac("sha3-224", $filesManifest, $secret);
|
||||||
|
header("HTTP/1.0 202 Accepted");
|
||||||
|
exit(json_encode([
|
||||||
|
"server" => "ephemeral",
|
||||||
|
"photos_list" => $filesManifest,
|
||||||
|
"album_id" => "undefined",
|
||||||
|
"hash" => $manifestHash,
|
||||||
|
]));
|
||||||
|
}
|
||||||
|
|
||||||
function renderRoute(string $object, string $method): void
|
function renderRoute(string $object, string $method): void
|
||||||
{
|
{
|
||||||
$authMechanism = $this->queryParam("auth_mechanism") ?? "token";
|
$authMechanism = $this->queryParam("auth_mechanism") ?? "token";
|
||||||
|
|
|
@ -103,7 +103,7 @@
|
||||||
<div n:if="isset($thisUser) ? (!$thisUser->isBanned() XOR !$thisUser->isActivated()) : true" class="header_navigation">
|
<div n:if="isset($thisUser) ? (!$thisUser->isBanned() XOR !$thisUser->isActivated()) : true" class="header_navigation">
|
||||||
{ifset $thisUser}
|
{ifset $thisUser}
|
||||||
<div class="link">
|
<div class="link">
|
||||||
<a href="/">{_header_home}</a>
|
<a href="/" title="[Alt+Shift+,]" accesskey=",">{_header_home}</a>
|
||||||
</div>
|
</div>
|
||||||
<div class="link">
|
<div class="link">
|
||||||
<a href="/search?type=groups">{_header_groups}</a>
|
<a href="/search?type=groups">{_header_groups}</a>
|
||||||
|
@ -122,7 +122,7 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="link">
|
<div class="link">
|
||||||
<form action="/search" method="get">
|
<form action="/search" method="get">
|
||||||
<input type="search" name="query" placeholder="{_header_search}" style="height: 20px;background: url('/assets/packages/static/openvk/img/search_icon.png') no-repeat 3px 4px; background-color: #fff; padding-left: 18px;width: 120px;" />
|
<input type="search" name="query" placeholder="{_header_search}" style="height: 20px;background: url('/assets/packages/static/openvk/img/search_icon.png') no-repeat 3px 4px; background-color: #fff; padding-left: 18px;width: 120px;" title="{_header_search} [Alt+Shift+F]" accesskey="f" />
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
{else}
|
{else}
|
||||||
|
@ -144,7 +144,7 @@
|
||||||
{ifset $thisUser}
|
{ifset $thisUser}
|
||||||
{if !$thisUser->isBanned() XOR !$thisUser->isActivated()}
|
{if !$thisUser->isBanned() XOR !$thisUser->isActivated()}
|
||||||
<a href="/edit" class="link edit-button">{_edit_button}</a>
|
<a href="/edit" class="link edit-button">{_edit_button}</a>
|
||||||
<a href="{$thisUser->getURL()}" class="link">{_my_page}</a>
|
<a href="{$thisUser->getURL()}" class="link" title="{_my_page} [Alt+Shift+.]" accesskey=".">{_my_page}</a>
|
||||||
<a href="/friends{$thisUser->getId()}" class="link">{_my_friends}
|
<a href="/friends{$thisUser->getId()}" class="link">{_my_friends}
|
||||||
<object type="internal/link" n:if="$thisUser->getFollowersCount() > 0">
|
<object type="internal/link" n:if="$thisUser->getFollowersCount() > 0">
|
||||||
<a href="/friends{$thisUser->getId()}?act=incoming">
|
<a href="/friends{$thisUser->getId()}?act=incoming">
|
||||||
|
@ -161,8 +161,8 @@
|
||||||
</a>
|
</a>
|
||||||
<a n:if="$thisUser->getLeftMenuItemStatus('notes')" href="/notes{$thisUser->getId()}" class="link">{_my_notes}</a>
|
<a n:if="$thisUser->getLeftMenuItemStatus('notes')" href="/notes{$thisUser->getId()}" class="link">{_my_notes}</a>
|
||||||
<a n:if="$thisUser->getLeftMenuItemStatus('groups')" href="/groups{$thisUser->getId()}" class="link">{_my_groups}</a>
|
<a n:if="$thisUser->getLeftMenuItemStatus('groups')" href="/groups{$thisUser->getId()}" class="link">{_my_groups}</a>
|
||||||
<a n:if="$thisUser->getLeftMenuItemStatus('news')" href="/feed" class="link">{_my_feed}</a>
|
<a n:if="$thisUser->getLeftMenuItemStatus('news')" href="/feed" class="link" title="{_my_feed} [Alt+Shift+W]" accesskey="w">{_my_feed}</a>
|
||||||
<a href="/notifications" class="link">{_my_feedback}
|
<a href="/notifications" class="link" title="{_my_feedback} [Alt+Shift+N]" accesskey="n">{_my_feedback}
|
||||||
{if $thisUser->getNotificationsCount() > 0}
|
{if $thisUser->getNotificationsCount() > 0}
|
||||||
(<b>{$thisUser->getNotificationsCount()}</b>)
|
(<b>{$thisUser->getNotificationsCount()}</b>)
|
||||||
{/if}
|
{/if}
|
||||||
|
@ -173,7 +173,7 @@
|
||||||
{var canAccessHelpdesk = $thisUser->getChandlerUser()->can("write")->model('openvk\Web\Models\Entities\TicketReply')->whichBelongsTo(0)}
|
{var canAccessHelpdesk = $thisUser->getChandlerUser()->can("write")->model('openvk\Web\Models\Entities\TicketReply')->whichBelongsTo(0)}
|
||||||
{var menuLinksAvaiable = sizeof(OPENVK_ROOT_CONF['openvk']['preferences']['menu']['links']) > 0 && $thisUser->getLeftMenuItemStatus('links')}
|
{var menuLinksAvaiable = sizeof(OPENVK_ROOT_CONF['openvk']['preferences']['menu']['links']) > 0 && $thisUser->getLeftMenuItemStatus('links')}
|
||||||
<div n:if="$canAccessAdminPanel || $canAccessHelpdesk || $menuLinksAvaiable" class="menu_divider"></div>
|
<div n:if="$canAccessAdminPanel || $canAccessHelpdesk || $menuLinksAvaiable" class="menu_divider"></div>
|
||||||
<a href="/admin" class="link" n:if="$canAccessAdminPanel">Админ-панель</a>
|
<a href="/admin" class="link" n:if="$canAccessAdminPanel" title="Админ-панель [Alt+Shift+A]" accesskey="a">Админ-панель</a>
|
||||||
<a href="/support/tickets" class="link" n:if="$canAccessHelpdesk">Helpdesk
|
<a href="/support/tickets" class="link" n:if="$canAccessHelpdesk">Helpdesk
|
||||||
{if $helpdeskTicketNotAnsweredCount > 0}
|
{if $helpdeskTicketNotAnsweredCount > 0}
|
||||||
(<b>{$helpdeskTicketNotAnsweredCount}</b>)
|
(<b>{$helpdeskTicketNotAnsweredCount}</b>)
|
||||||
|
@ -294,6 +294,37 @@
|
||||||
|
|
||||||
<script n:if="OPENVK_ROOT_CONF['openvk']['telemetry']['plausible']['enable']" async defer data-domain="{php echo OPENVK_ROOT_CONF['openvk']['telemetry']['plausible']['domain']}" src="{php echo OPENVK_ROOT_CONF['openvk']['telemetry']['plausible']['server']}js/plausible.js"></script>
|
<script n:if="OPENVK_ROOT_CONF['openvk']['telemetry']['plausible']['enable']" async defer data-domain="{php echo OPENVK_ROOT_CONF['openvk']['telemetry']['plausible']['domain']}" src="{php echo OPENVK_ROOT_CONF['openvk']['telemetry']['plausible']['server']}js/plausible.js"></script>
|
||||||
|
|
||||||
|
<script n:if="OPENVK_ROOT_CONF['openvk']['telemetry']['piwik']['enable']">
|
||||||
|
{var $piwik = (object) OPENVK_ROOT_CONF['openvk']['telemetry']['piwik']}
|
||||||
|
|
||||||
|
//<![CDATA[
|
||||||
|
(function(window,document,dataLayerName,id){
|
||||||
|
window[dataLayerName]=window[dataLayerName]||[],window[dataLayerName].push({ start:(new Date).getTime(),event:"stg.start" });var scripts=document.getElementsByTagName('script')[0],tags=document.createElement('script');
|
||||||
|
function stgCreateCookie(a,b,c){ var d="";if(c){ var e=new Date;e.setTime(e.getTime()+24*c*60*60*1e3),d=";expires="+e.toUTCString() }document.cookie=a+"="+b+d+";path=/" }
|
||||||
|
var isStgDebug=(window.location.href.match("stg_debug")||document.cookie.match("stg_debug"))&&!window.location.href.match("stg_disable_debug");stgCreateCookie("stg_debug",isStgDebug?1:"",isStgDebug?14:-1);
|
||||||
|
var qP=[];dataLayerName!=="dataLayer"&&qP.push("data_layer_name="+dataLayerName),isStgDebug&&qP.push("stg_debug");var qPString=qP.length>0?("?"+qP.join("&")):"";
|
||||||
|
tags.async=!0,tags.src={$piwik->container . "/"}+id+".js"+qPString,scripts.parentNode.insertBefore(tags,scripts);
|
||||||
|
!function(a,n,i){ a[n]=a[n]||{ };for(var c=0;c<i.length;c++)!function(i){ a[n][i]=a[n][i]||{ },a[n][i].api=a[n][i].api||function(){ var a=[].slice.call(arguments,0);"string"==typeof a[0]&&window[dataLayerName].push({ event:n+"."+i+":"+a[0],parameters:[].slice.call(arguments,1) }) } }(i[c]) }(window,"ppms",["tm","cm"]);
|
||||||
|
})(window,document,{$piwik->layer}, {$piwik->site});
|
||||||
|
//]]>
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script n:if="OPENVK_ROOT_CONF['openvk']['telemetry']['matomo']['enable']">
|
||||||
|
{var $matomo = (object) OPENVK_ROOT_CONF['openvk']['telemetry']['matomo']}
|
||||||
|
//<![CDATA[
|
||||||
|
var _paq = window._paq = window._paq || [];
|
||||||
|
_paq.push(['trackPageView']);
|
||||||
|
_paq.push(['enableLinkTracking']);
|
||||||
|
(function() {
|
||||||
|
var u="//" + {$matomo->container} + "/";
|
||||||
|
_paq.push(['setTrackerUrl', u+'matomo.php']);
|
||||||
|
_paq.push(['setSiteId', {$matomo->site}]);
|
||||||
|
var d=document, g=d.createElement('script'), s=d.getElementsByTagName('script')[0];
|
||||||
|
g.type='text/javascript'; g.async=true; g.src=u+'matomo.js'; s.parentNode.insertBefore(g,s);
|
||||||
|
})();
|
||||||
|
//]]>
|
||||||
|
</script>
|
||||||
|
|
||||||
{ifset bodyScripts}
|
{ifset bodyScripts}
|
||||||
{include bodyScripts}
|
{include bodyScripts}
|
||||||
{/ifset}
|
{/ifset}
|
||||||
|
|
|
@ -38,7 +38,7 @@
|
||||||
</label>
|
</label>
|
||||||
<span id="avatar" class="aui-avatar aui-avatar-project aui-avatar-xlarge">
|
<span id="avatar" class="aui-avatar aui-avatar-project aui-avatar-xlarge">
|
||||||
<span class="aui-avatar-inner">
|
<span class="aui-avatar-inner">
|
||||||
<img src="{$club->getAvatarUrl()}" style="object-fit: cover;"></img>
|
<img src="{$club->getAvatarUrl('tiny')}" style="object-fit: cover;"></img>
|
||||||
</span>
|
</span>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
@ -155,7 +155,7 @@
|
||||||
<td>
|
<td>
|
||||||
<span class="aui-avatar aui-avatar-xsmall">
|
<span class="aui-avatar aui-avatar-xsmall">
|
||||||
<span class="aui-avatar-inner">
|
<span class="aui-avatar-inner">
|
||||||
<img src="{$follower->getAvatarUrl()}" alt="{$follower->getCanonicalName()}" role="presentation" />
|
<img src="{$follower->getAvatarUrl('miniscule')}" alt="{$follower->getCanonicalName()}" role="presentation" />
|
||||||
</span>
|
</span>
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
|
|
|
@ -32,7 +32,7 @@
|
||||||
<td>
|
<td>
|
||||||
<span class="aui-avatar aui-avatar-xsmall">
|
<span class="aui-avatar aui-avatar-xsmall">
|
||||||
<span class="aui-avatar-inner">
|
<span class="aui-avatar-inner">
|
||||||
<img src="{$club->getAvatarUrl()}" alt="{$club->getCanonicalName()}" style="object-fit: cover;" role="presentation" />
|
<img src="{$club->getAvatarUrl('miniscule')}" alt="{$club->getCanonicalName()}" style="object-fit: cover;" role="presentation" />
|
||||||
</span>
|
</span>
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
|
@ -43,7 +43,7 @@
|
||||||
|
|
||||||
<span class="aui-avatar aui-avatar-xsmall">
|
<span class="aui-avatar aui-avatar-xsmall">
|
||||||
<span class="aui-avatar-inner">
|
<span class="aui-avatar-inner">
|
||||||
<img src="{$user->getAvatarUrl()}" alt="{$user->getCanonicalName()}" role="presentation" />
|
<img src="{$user->getAvatarUrl('miniscule')}" alt="{$user->getCanonicalName()}" role="presentation" />
|
||||||
</span>
|
</span>
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
</label>
|
</label>
|
||||||
<span id="avatar" class="aui-avatar aui-avatar-project aui-avatar-xlarge">
|
<span id="avatar" class="aui-avatar aui-avatar-project aui-avatar-xlarge">
|
||||||
<span class="aui-avatar-inner">
|
<span class="aui-avatar-inner">
|
||||||
<img src="{$user->getAvatarUrl()}" style="object-fit: cover;"></img>
|
<img src="{$user->getAvatarUrl('tiny')}" style="object-fit: cover;"></img>
|
||||||
</span>
|
</span>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -32,7 +32,7 @@
|
||||||
<td>
|
<td>
|
||||||
<span class="aui-avatar aui-avatar-xsmall">
|
<span class="aui-avatar aui-avatar-xsmall">
|
||||||
<span class="aui-avatar-inner">
|
<span class="aui-avatar-inner">
|
||||||
<img src="{$user->getAvatarUrl()}" alt="{$user->getCanonicalName()}" style="object-fit: cover;" role="presentation" />
|
<img src="{$user->getAvatarUrl('miniscule')}" alt="{$user->getCanonicalName()}" style="object-fit: cover;" role="presentation" />
|
||||||
</span>
|
</span>
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
|
|
|
@ -74,7 +74,7 @@
|
||||||
<td>
|
<td>
|
||||||
<span class="aui-avatar aui-avatar-xsmall">
|
<span class="aui-avatar aui-avatar-xsmall">
|
||||||
<span class="aui-avatar-inner">
|
<span class="aui-avatar-inner">
|
||||||
<img src="{$user->getAvatarUrl()}" alt="{$user->getCanonicalName()}" role="presentation" />
|
<img src="{$user->getAvatarUrl('miniscule')}" alt="{$user->getCanonicalName()}" role="presentation" />
|
||||||
</span>
|
</span>
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
|
|
|
@ -18,7 +18,7 @@
|
||||||
<span>{_code}: </span>
|
<span>{_code}: </span>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<input type="text" name="code" required />
|
<input type="text" name="code" autocomplete="off" required />
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
|
|
|
@ -41,7 +41,7 @@
|
||||||
{/block}
|
{/block}
|
||||||
|
|
||||||
{block preview}
|
{block preview}
|
||||||
<img src="{$x instanceof $Manager ? $x->getUser()->getAvatarURL() : $x->getAvatarURL()}" alt="{$x instanceof $Manager ? $x->getUser()->getCanonicalName() : $x->getCanonicalName()}" width=75 />
|
<img src="{$x instanceof $Manager ? $x->getUser()->getAvatarURL() : $x->getAvatarURL('miniscule')}" alt="{$x instanceof $Manager ? $x->getUser()->getCanonicalName() : $x->getCanonicalName()}" width=75 />
|
||||||
{/block}
|
{/block}
|
||||||
|
|
||||||
{block name}
|
{block name}
|
||||||
|
|
|
@ -57,7 +57,7 @@
|
||||||
<div class="cl_element" n:foreach="$club->getFollowers(1) as $follower">
|
<div class="cl_element" n:foreach="$club->getFollowers(1) as $follower">
|
||||||
<div class="cl_avatar">
|
<div class="cl_avatar">
|
||||||
<a href="{$follower->getURL()}">
|
<a href="{$follower->getURL()}">
|
||||||
<img class="ava" src="{$follower->getAvatarUrl()}" />
|
<img class="ava" src="{$follower->getAvatarUrl('miniscule')}" />
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<a href="{$follower->getURL()}" class="cl_name">
|
<a href="{$follower->getURL()}" class="cl_name">
|
||||||
|
@ -94,7 +94,7 @@
|
||||||
{var avatarPhoto = $club->getAvatarPhoto()}
|
{var avatarPhoto = $club->getAvatarPhoto()}
|
||||||
{var avatarLink = ((is_null($avatarPhoto) ? FALSE : $avatarPhoto->isAnonymous()) ? "/photo" . ("s/" . base_convert((string) $avatarPhoto->getId(), 10, 32)) : $club->getAvatarLink())}
|
{var avatarLink = ((is_null($avatarPhoto) ? FALSE : $avatarPhoto->isAnonymous()) ? "/photo" . ("s/" . base_convert((string) $avatarPhoto->getId(), 10, 32)) : $club->getAvatarLink())}
|
||||||
<a href="{$avatarLink|nocheck}">
|
<a href="{$avatarLink|nocheck}">
|
||||||
<img src="{$club->getAvatarUrl()}" style="width: 100%; image-rendering: -webkit-optimize-contrast;" />
|
<img src="{$club->getAvatarUrl('normal')}" style="width: 100%; image-rendering: -webkit-optimize-contrast;" />
|
||||||
</a>
|
</a>
|
||||||
<div n:ifset="$thisUser" id="profile_links">
|
<div n:ifset="$thisUser" id="profile_links">
|
||||||
{if $club->canBeModifiedBy($thisUser)}
|
{if $club->canBeModifiedBy($thisUser)}
|
||||||
|
|
|
@ -44,7 +44,7 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="messenger-app--input">
|
<div class="messenger-app--input">
|
||||||
{if $correspondent->getId() === $thisUser->getId() || $correspondent->getPrivacyPermission('messages.write', $thisUser)}
|
{if $correspondent->getId() === $thisUser->getId() || $correspondent->getPrivacyPermission('messages.write', $thisUser)}
|
||||||
<img class="ava" src="{$thisUser->getAvatarUrl()}" alt="{$thisUser->getCanonicalName()}" />
|
<img class="ava" src="{$thisUser->getAvatarUrl('miniscule')}" alt="{$thisUser->getCanonicalName()}" />
|
||||||
<div class="messenger-app--input---messagebox">
|
<div class="messenger-app--input---messagebox">
|
||||||
<textarea
|
<textarea
|
||||||
data-bind="value: messageContent, event: { keydown: onTextareaKeyPress }"
|
data-bind="value: messageContent, event: { keydown: onTextareaKeyPress }"
|
||||||
|
@ -52,7 +52,7 @@
|
||||||
placeholder="Введите сообщение"></textarea>
|
placeholder="Введите сообщение"></textarea>
|
||||||
<button class="button" data-bind="click: sendMessage">Отправить</button>
|
<button class="button" data-bind="click: sendMessage">Отправить</button>
|
||||||
</div>
|
</div>
|
||||||
<img class="ava" src="{$correspondent->getAvatarUrl()}" alt="{$correspondent->getCanonicalName()}" />
|
<img class="ava" src="{$correspondent->getAvatarUrl('miniscule')}" alt="{$correspondent->getCanonicalName()}" />
|
||||||
{else}
|
{else}
|
||||||
<div class="blocked" data-localized-text="Вы не можете писать сообщения {$correspondent->getCanonicalName()} из-за его настроек приватности."></div>
|
<div class="blocked" data-localized-text="Вы не можете писать сообщения {$correspondent->getCanonicalName()} из-за его настроек приватности."></div>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
|
@ -25,7 +25,7 @@
|
||||||
{var lastMsg = $coresp->getPreviewMessage()}
|
{var lastMsg = $coresp->getPreviewMessage()}
|
||||||
|
|
||||||
<div class="crp-entry--image">
|
<div class="crp-entry--image">
|
||||||
<img src="{$recipient->getAvatarURL()}"
|
<img src="{$recipient->getAvatarURL('miniscule')}"
|
||||||
alt="Фотография пользователя" />
|
alt="Фотография пользователя" />
|
||||||
</div>
|
</div>
|
||||||
<div class="crp-entry--info">
|
<div class="crp-entry--info">
|
||||||
|
@ -36,7 +36,7 @@
|
||||||
{var _author = $lastMsg->getSender()}
|
{var _author = $lastMsg->getSender()}
|
||||||
|
|
||||||
<div class="crp-entry--message---av" n:if="$_author->getId() === $thisUser->getId()">
|
<div class="crp-entry--message---av" n:if="$_author->getId() === $thisUser->getId()">
|
||||||
<img src="{$_author->getAvatarURL()}"
|
<img src="{$_author->getAvatarURL('miniscule')}"
|
||||||
alt="Фотография пользователя" />
|
alt="Фотография пользователя" />
|
||||||
</div>
|
</div>
|
||||||
<div class="crp-entry--message---text">
|
<div class="crp-entry--message---text">
|
||||||
|
|
|
@ -68,7 +68,7 @@
|
||||||
<div n:foreach="$data as $dat">
|
<div n:foreach="$data as $dat">
|
||||||
<div class="profile_thumb">
|
<div class="profile_thumb">
|
||||||
<a href="{$owner->getURL()}">
|
<a href="{$owner->getURL()}">
|
||||||
<img src="{$owner->getAvatarUrl()}" style="width: 50px;">
|
<img src="{$owner->getAvatarUrl('miniscule')}" style="width: 50px;">
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<article class="note_body" id="userContent" style="width: 540px; display: inline-block; margin-bottom: 35px;">
|
<article class="note_body" id="userContent" style="width: 540px; display: inline-block; margin-bottom: 35px;">
|
||||||
|
|
|
@ -26,7 +26,7 @@
|
||||||
{/block}
|
{/block}
|
||||||
|
|
||||||
{block preview}
|
{block preview}
|
||||||
<img src="{$x->getModel(1)->getAvatarUrl()}" width=64 />
|
<img src="{$x->getModel(1)->getAvatarUrl('miniscule')}" width=64 />
|
||||||
{/block}
|
{/block}
|
||||||
|
|
||||||
{block name}
|
{block name}
|
||||||
|
|
|
@ -23,9 +23,11 @@
|
||||||
{else}
|
{else}
|
||||||
{tr("albums", $count)}
|
{tr("albums", $count)}
|
||||||
{/if}
|
{/if}
|
||||||
<span n:if="isset($thisUser) && $thisUser->getId() == $owner->getId()">
|
|
||||||
|
<span n:if="$canEdit" style="float: right;">
|
||||||
|
|
|
|
||||||
<a href="/albums/create">{_create_album}</a>
|
{var isClub = ($owner instanceof \openvk\Web\Models\Entities\Club)}
|
||||||
|
<a href="/albums/create{$isClub ? '?gpid=' . $owner->getId() : ''}">{_create_album}</a>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -43,7 +45,7 @@
|
||||||
|
|
||||||
{block preview}
|
{block preview}
|
||||||
{var cover = $x->getCoverPhoto()}
|
{var cover = $x->getCoverPhoto()}
|
||||||
{var preview = is_null($cover) ? "/assets/packages/static/openvk/img/camera_200.png" : $cover->getURL()}
|
{var preview = is_null($cover) ? "/assets/packages/static/openvk/img/camera_200.png" : $cover->getURLBySizeId("normal")}
|
||||||
|
|
||||||
<a href="/album{$x->getPrettyId()}">
|
<a href="/album{$x->getPrettyId()}">
|
||||||
<img src="{$preview}" alt="{$x->getName()}" style="height: 130px; width: 170px; object-fit: cover" />
|
<img src="{$preview}" alt="{$x->getName()}" style="height: 130px; width: 170px; object-fit: cover" />
|
||||||
|
|
|
@ -21,7 +21,7 @@
|
||||||
|
|
||||||
{block content}
|
{block content}
|
||||||
<center style="margin-bottom: 8pt;">
|
<center style="margin-bottom: 8pt;">
|
||||||
<img src="{$photo->getURL()}" style="max-width: 80%; max-height: 60vh;" />
|
<img src="{$photo->getURLBySizeId('large')}" style="max-width: 80%; max-height: 60vh;" />
|
||||||
</center>
|
</center>
|
||||||
|
|
||||||
<hr/>
|
<hr/>
|
||||||
|
|
|
@ -50,7 +50,7 @@
|
||||||
{/block}
|
{/block}
|
||||||
|
|
||||||
{block preview}
|
{block preview}
|
||||||
<img src="{$x->getAvatarUrl()}" width="75" alt="{_"photo"}" />
|
<img src="{$x->getAvatarUrl('miniscule')}" width="75" alt="{_"photo"}" />
|
||||||
{/block}
|
{/block}
|
||||||
|
|
||||||
{block name}
|
{block name}
|
||||||
|
|
|
@ -47,7 +47,7 @@
|
||||||
<tr>
|
<tr>
|
||||||
{if $comment->getUType() === 0}
|
{if $comment->getUType() === 0}
|
||||||
<td width="54" valign="top">
|
<td width="54" valign="top">
|
||||||
<img src="{$comment->getUser()->getAvatarUrl()}" width="50" />
|
<img src="{$comment->getUser()->getAvatarUrl('miniscule')}" width="50" />
|
||||||
</td>
|
</td>
|
||||||
{else}
|
{else}
|
||||||
<td width="54" valign="top">
|
<td width="54" valign="top">
|
||||||
|
|
|
@ -26,6 +26,15 @@
|
||||||
<br />
|
<br />
|
||||||
|
|
||||||
{if $isNew}
|
{if $isNew}
|
||||||
|
{if !is_null($banReason)}
|
||||||
|
<center>
|
||||||
|
<img src="/assets/packages/static/openvk/img/oof.apng" alt="{_'banned_alt'}" style="width: 20%;" />
|
||||||
|
</center>
|
||||||
|
<p>
|
||||||
|
{tr("banned_in_support_1", htmlentities($thisUser->getCanonicalName()))|noescape}<br/>
|
||||||
|
{tr("banned_in_support_2", htmlentities($banReason))|noescape}
|
||||||
|
</p>
|
||||||
|
{else}
|
||||||
<div class="new">
|
<div class="new">
|
||||||
<form action="/support" method="post" style="margin:0;">
|
<form action="/support" method="post" style="margin:0;">
|
||||||
<center>
|
<center>
|
||||||
|
@ -38,6 +47,7 @@
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
{/if}
|
{/if}
|
||||||
|
{/if}
|
||||||
|
|
||||||
{if $isMain}
|
{if $isMain}
|
||||||
<h4>{_support_faq}</h4><br />
|
<h4>{_support_faq}</h4><br />
|
||||||
|
|
|
@ -60,7 +60,7 @@
|
||||||
<tr>
|
<tr>
|
||||||
{if $comment->getUType() === 0}
|
{if $comment->getUType() === 0}
|
||||||
<td width="54" valign="top">
|
<td width="54" valign="top">
|
||||||
<img src="{$comment->getUser()->getAvatarUrl()}" width="50" />
|
<img src="{$comment->getUser()->getAvatarUrl('miniscule')}" width="50" />
|
||||||
</td>
|
</td>
|
||||||
{else}
|
{else}
|
||||||
<td width="54" valign="top">
|
<td width="54" valign="top">
|
||||||
|
|
|
@ -85,7 +85,7 @@
|
||||||
{/block}
|
{/block}
|
||||||
|
|
||||||
{block preview}
|
{block preview}
|
||||||
<img src="{$x->getAvatarUrl()}" width="75" alt="Фотография группы" />
|
<img src="{$x->getAvatarUrl('miniscule')}" width="75" alt="Фотография пользователя" />
|
||||||
{/block}
|
{/block}
|
||||||
|
|
||||||
{block name}
|
{block name}
|
||||||
|
|
|
@ -48,7 +48,7 @@
|
||||||
{/block}
|
{/block}
|
||||||
|
|
||||||
{block preview}
|
{block preview}
|
||||||
<img src="{$x->getAvatarUrl()}" width="75" alt="Фотография группы" />
|
<img src="{$x->getAvatarUrl('miniscule')}" width="75" alt="Фотография группы" />
|
||||||
{/block}
|
{/block}
|
||||||
|
|
||||||
{block name}{/block}
|
{block name}{/block}
|
||||||
|
|
|
@ -347,16 +347,22 @@
|
||||||
<center>{tr("also_you_can_transfer_points", $thisUser->getCoins(), rawurlencode($csrfToken))|noescape}</center>
|
<center>{tr("also_you_can_transfer_points", $thisUser->getCoins(), rawurlencode($csrfToken))|noescape}</center>
|
||||||
</div>
|
</div>
|
||||||
<div style="width: 22%; float: right;">
|
<div style="width: 22%; float: right;">
|
||||||
<p style="margin: 0; font-size: medium; text-align: center;">
|
<div style="margin: 0; font-size: medium; text-align: center; font-weight: 900;">
|
||||||
<b>
|
{_on_your_account}
|
||||||
{_on_your_account}<br/>
|
<div style="width: 100%; height: 60px; font-weight: 100;" id="balance">{$thisUser->getCoins()}</div>
|
||||||
<span style="font-size: 50px;">{$thisUser->getCoins()}</span><br/>
|
{_points_count}<br/>
|
||||||
{_points_count}<br/><br/>
|
|
||||||
<small><a href="?act=finance.top-up">[{_have_voucher}?]</a></small>
|
<small><a href="?act=finance.top-up">[{_have_voucher}?]</a></small>
|
||||||
</b>
|
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{script "js/node_modules/textfit/textFit.min.js"}
|
||||||
|
<script>
|
||||||
|
let balance = document.querySelector("#balance");
|
||||||
|
|
||||||
|
balance.style.width = Math.ceil(balance.parentNode.getBoundingClientRect().width) + "px";
|
||||||
|
textFit(balance, { alignVert: true });
|
||||||
|
</script>
|
||||||
|
|
||||||
{elseif $isFinanceTU}
|
{elseif $isFinanceTU}
|
||||||
|
|
||||||
<p>{_voucher_explanation} {_voucher_explanation_ex}</p>
|
<p>{_voucher_explanation} {_voucher_explanation_ex}</p>
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
<!-- openGraph -->
|
<!-- openGraph -->
|
||||||
<meta property="og:title" content="{$user->getCanonicalName()}" />
|
<meta property="og:title" content="{$user->getCanonicalName()}" />
|
||||||
<meta property="og:url" content="http://{$_SERVER['HTTP_HOST']}{$user->getURL()}" />
|
<meta property="og:url" content="http://{$_SERVER['HTTP_HOST']}{$user->getURL()}" />
|
||||||
<meta property="og:image" content="{$user->getAvatarUrl()}" />
|
<meta property="og:image" content="{$user->getAvatarUrl('normal')}" />
|
||||||
<meta property="og:type" content="profile" />
|
<meta property="og:type" content="profile" />
|
||||||
<meta property="og:first_name" content="{$user->getFirstName()}" />
|
<meta property="og:first_name" content="{$user->getFirstName()}" />
|
||||||
<meta property="og:last_name" content="{$user->getLastName()}" />
|
<meta property="og:last_name" content="{$user->getLastName()}" />
|
||||||
|
@ -62,7 +62,7 @@
|
||||||
<div class="left_small_block">
|
<div class="left_small_block">
|
||||||
<div>
|
<div>
|
||||||
<a href="{$user->getAvatarLink()|nocheck}">
|
<a href="{$user->getAvatarLink()|nocheck}">
|
||||||
<img src="{$user->getAvatarUrl()}"
|
<img src="{$user->getAvatarUrl('normal')}"
|
||||||
alt="{$user->getCanonicalName()}"
|
alt="{$user->getCanonicalName()}"
|
||||||
style="width: 100%; image-rendering: -webkit-optimize-contrast;" />
|
style="width: 100%; image-rendering: -webkit-optimize-contrast;" />
|
||||||
</a>
|
</a>
|
||||||
|
@ -72,7 +72,7 @@
|
||||||
<div id="profile_link" style="width: 194px;">
|
<div id="profile_link" style="width: 194px;">
|
||||||
<a href="/edit" class="link">{_"edit_page"}</a>
|
<a href="/edit" class="link">{_"edit_page"}</a>
|
||||||
</div>
|
</div>
|
||||||
<div n:if="OPENVK_ROOT_CONF['openvk']['preferences']['commerce']" id="profile_link" style="width: 194px;">
|
<div n:if="OPENVK_ROOT_CONF['openvk']['preferences']['commerce'] && !$thisUser->prefersNotToSeeRating()" id="profile_link" style="width: 194px;">
|
||||||
<a onClick="showIncreaseRatingDialog({$thisUser->getCoins()}, {ltrim($thisUser->getUrl(), '/')}, {$csrfToken})" class="link">{_increase_rating}</a>
|
<a onClick="showIncreaseRatingDialog({$thisUser->getCoins()}, {ltrim($thisUser->getUrl(), '/')}, {$csrfToken})" class="link">{_increase_rating}</a>
|
||||||
</div>
|
</div>
|
||||||
{else}
|
{else}
|
||||||
|
@ -94,6 +94,16 @@
|
||||||
</a>
|
</a>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
|
{if $thisUser->getChandlerUser()->can('write')->model('openvk\Web\Models\Entities\TicketReply')->whichBelongsTo(0)}
|
||||||
|
<a href="javascript:toggleBanInSupport()" class="profile_link">
|
||||||
|
{if $user->isBannedInSupport()}
|
||||||
|
{_unban_in_support_user_action}
|
||||||
|
{else}
|
||||||
|
{_ban_in_support_user_action}
|
||||||
|
{/if}
|
||||||
|
</a>
|
||||||
|
{/if}
|
||||||
|
|
||||||
<a n:if="OPENVK_ROOT_CONF['openvk']['preferences']['commerce'] && $user->getGiftCount() == 0" href="/gifts?act=pick&user={$user->getId()}" class="profile_link">{_send_gift}</a>
|
<a n:if="OPENVK_ROOT_CONF['openvk']['preferences']['commerce'] && $user->getGiftCount() == 0" href="/gifts?act=pick&user={$user->getId()}" class="profile_link">{_send_gift}</a>
|
||||||
<a n:if="$user->getPrivacyPermission('messages.write', $thisUser)" href="/im?sel={$user->getId()}" class="profile_link">{_"send_message"}</a>
|
<a n:if="$user->getPrivacyPermission('messages.write', $thisUser)" href="/im?sel={$user->getId()}" class="profile_link">{_"send_message"}</a>
|
||||||
|
|
||||||
|
@ -180,7 +190,7 @@
|
||||||
<div class="cl_element" n:foreach="$user->getFriends(1) as $friend">
|
<div class="cl_element" n:foreach="$user->getFriends(1) as $friend">
|
||||||
<div class="cl_avatar">
|
<div class="cl_avatar">
|
||||||
<a href="{$friend->getURL()}">
|
<a href="{$friend->getURL()}">
|
||||||
<img class="ava" src="{$friend->getAvatarUrl()}" />
|
<img class="ava" src="{$friend->getAvatarUrl('miniscule')}" />
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<a href="{$friend->getURL()}" class="cl_name">
|
<a href="{$friend->getURL()}" class="cl_name">
|
||||||
|
@ -208,7 +218,7 @@
|
||||||
{var cover = $album->getCoverPhoto()}
|
{var cover = $album->getCoverPhoto()}
|
||||||
|
|
||||||
<img
|
<img
|
||||||
src="{is_null($cover)?'/assets/packages/static/openvk/img/camera_200.png':$cover->getURL()}"
|
src="{is_null($cover)?'/assets/packages/static/openvk/img/camera_200.png':$cover->getURLBySizeId('small')}"
|
||||||
style="max-width: 80px; max-height: 54pt;" />
|
style="max-width: 80px; max-height: 54pt;" />
|
||||||
</div>
|
</div>
|
||||||
<div style="overflow: hidden; overflow-wrap: break-word;">
|
<div style="overflow: hidden; overflow-wrap: break-word;">
|
||||||
|
@ -512,7 +522,7 @@
|
||||||
xhr = new XMLHttpRequest();
|
xhr = new XMLHttpRequest();
|
||||||
xhr.open("GET", "/admin/ban/" + {$user->getId()} + "?reason=" + res + "&hash=" + {rawurlencode($csrfToken)}, true);
|
xhr.open("GET", "/admin/ban/" + {$user->getId()} + "?reason=" + res + "&hash=" + {rawurlencode($csrfToken)}, true);
|
||||||
xhr.onload = (function() {
|
xhr.onload = (function() {
|
||||||
if(xhr.responseText.indexOf("reason") === -1)
|
if(xhr.responseText.indexOf("success") === -1)
|
||||||
MessageBox("Ошибка", "Не удалось забанить пользователя...", ["OK"], [Function.noop]);
|
MessageBox("Ошибка", "Не удалось забанить пользователя...", ["OK"], [Function.noop]);
|
||||||
else
|
else
|
||||||
MessageBox("Операция успешна", "Пользователь заблокирован", ["OK"], [Function.noop]);
|
MessageBox("Операция успешна", "Пользователь заблокирован", ["OK"], [Function.noop]);
|
||||||
|
@ -526,7 +536,7 @@
|
||||||
function warnUser() {
|
function warnUser() {
|
||||||
uBanMsgTxt = "Вы собираетесь предупредить пользователя " + {$user->getCanonicalName()} + ".";
|
uBanMsgTxt = "Вы собираетесь предупредить пользователя " + {$user->getCanonicalName()} + ".";
|
||||||
uBanMsgTxt += "<br/>Мы отправим уведомление пользователю в личные сообщения от имени аккаунта администратора.";
|
uBanMsgTxt += "<br/>Мы отправим уведомление пользователю в личные сообщения от имени аккаунта администратора.";
|
||||||
uBanMsgTxt += "<br/><br/><b>Текст предупреждения</b>: <input type='text' id='uWarnMsgInput' placeholder='придумайте что-нибудь крутое' />"
|
uBanMsgTxt += "<br/><br/><b>Текст предупреждения</b>: <input type='text' id='uWarnMsgInput' placeholder='придумайте что-нибудь крутое' />";
|
||||||
|
|
||||||
MessageBox("Выдать предупреждение " + {$user->getFirstName()}, uBanMsgTxt, ["Подтвердить", "Отмена"], [
|
MessageBox("Выдать предупреждение " + {$user->getFirstName()}, uBanMsgTxt, ["Подтвердить", "Отмена"], [
|
||||||
(function() {
|
(function() {
|
||||||
|
@ -546,6 +556,51 @@
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
<script n:if="isset($thisUser) && $thisUser->getChandlerUser()->can('write')->model('openvk\Web\Models\Entities\TicketReply')->whichBelongsTo(0)">
|
||||||
|
{if $user->isBannedInSupport()}
|
||||||
|
function toggleBanInSupport() {
|
||||||
|
uBanMsgTxt = "Вы собираетесь разблокировать в поддержке пользователя " + {$user->getCanonicalName()} + ".";
|
||||||
|
uBanMsgTxt += "<br/>Сейчас он заблокирован по причине <strong>" + {$user->getBanInSupportReason()} + "</strong>.";
|
||||||
|
|
||||||
|
MessageBox("Разблокировать в поддержке " + {$user->getFirstName()}, uBanMsgTxt, ["Подтвердить", "Отмена"], [
|
||||||
|
(function() {
|
||||||
|
xhr = new XMLHttpRequest();
|
||||||
|
xhr.open("GET", "/admin/support/unban/" + {$user->getId()} + "?hash=" + {rawurlencode($csrfToken)}, true);
|
||||||
|
xhr.onload = (function() {
|
||||||
|
if(xhr.responseText.indexOf("success") === -1)
|
||||||
|
MessageBox("Ошибка", "Не удалось разблокировать пользователя в поддержке...", ["OK"], [Function.noop]);
|
||||||
|
else
|
||||||
|
MessageBox("Операция успешна", "Пользователь разблокирован в поддержке", ["OK"], [Function.noop]);
|
||||||
|
});
|
||||||
|
xhr.send(null);
|
||||||
|
}),
|
||||||
|
Function.noop
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
{else}
|
||||||
|
function toggleBanInSupport() {
|
||||||
|
uBanMsgTxt = "Вы собираетесь заблокировать в поддержке пользователя " + {$user->getCanonicalName()} + ".";
|
||||||
|
uBanMsgTxt += "<br/><br/><b>Причина бана</b>: <input type='text' id='uBanMsgInput' placeholder='придумайте что-нибудь крутое' />";
|
||||||
|
|
||||||
|
MessageBox("Заблокировать в поддержке " + {$user->getFirstName()}, uBanMsgTxt, ["Подтвердить", "Отмена"], [
|
||||||
|
(function() {
|
||||||
|
res = document.querySelector("#uBanMsgInput").value;
|
||||||
|
xhr = new XMLHttpRequest();
|
||||||
|
xhr.open("GET", "/admin/support/ban/" + {$user->getId()} + "?reason=" + res + "&hash=" + {rawurlencode($csrfToken)}, true);
|
||||||
|
xhr.onload = (function() {
|
||||||
|
if(xhr.responseText.indexOf("success") === -1)
|
||||||
|
MessageBox("Ошибка", "Не удалось заблокировать пользователя в поддержке...", ["OK"], [Function.noop]);
|
||||||
|
else
|
||||||
|
MessageBox("Операция успешна", "Пользователь заблокирован в поддержке", ["OK"], [Function.noop]);
|
||||||
|
});
|
||||||
|
xhr.send(null);
|
||||||
|
}),
|
||||||
|
Function.noop
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
{/if}
|
||||||
|
</script>
|
||||||
|
|
||||||
<script n:if="isset($thisUser) && $user->getId() == $thisUser->getId()" n:syntax="off">
|
<script n:if="isset($thisUser) && $user->getId() == $thisUser->getId()" n:syntax="off">
|
||||||
function setStatusEditorShown(shown) {
|
function setStatusEditorShown(shown) {
|
||||||
document.getElementById("status_editor").style.display = shown ? "block" : "none";
|
document.getElementById("status_editor").style.display = shown ? "block" : "none";
|
||||||
|
|
|
@ -4,4 +4,82 @@
|
||||||
{tr("user_banned", htmlentities($user->getFirstName()))|noescape}<br/>
|
{tr("user_banned", htmlentities($user->getFirstName()))|noescape}<br/>
|
||||||
{_"user_banned_comment"} <b>{$user->getBanReason()}</b>.
|
{_"user_banned_comment"} <b>{$user->getBanReason()}</b>.
|
||||||
</p>
|
</p>
|
||||||
|
<p n:if="isset($thisUser) && $thisUser->getChandlerUser()->can('access')->model('admin')->whichBelongsTo(NULL) || $thisUser->getChandlerUser()->can('write')->model('openvk\Web\Models\Entities\TicketReply')->whichBelongsTo(0)">
|
||||||
|
<br />
|
||||||
|
<a n:if="$thisUser->getChandlerUser()->can('access')->model('admin')->whichBelongsTo(NULL)" href="javascript:unbanUser()" class="button">{_unban_user_action}</a>
|
||||||
|
<a n:if="$thisUser->getChandlerUser()->can('write')->model('openvk\Web\Models\Entities\TicketReply')->whichBelongsTo(0)" href="javascript:toggleBanInSupport()" class="button">
|
||||||
|
{if $user->isBannedInSupport()}
|
||||||
|
{_unban_in_support_user_action}
|
||||||
|
{else}
|
||||||
|
{_ban_in_support_user_action}
|
||||||
|
{/if}
|
||||||
|
</a>
|
||||||
|
</p>
|
||||||
</center>
|
</center>
|
||||||
|
|
||||||
|
<script n:if="isset($thisUser) && $thisUser->getChandlerUser()->can('access')->model('admin')->whichBelongsTo(NULL)">
|
||||||
|
function unbanUser() {
|
||||||
|
uUnbanMsgTxt = "Вы собираетесь разбанить пользователя " + {$user->getCanonicalName()} + ".";
|
||||||
|
uUnbanMsgTxt += "<br/>Сейчас он заблокирован по причине: <strong>" + {$user->getBanReason()} + "</strong>.";
|
||||||
|
|
||||||
|
MessageBox("Разбанить " + {$user->getFirstName()}, uUnbanMsgTxt, ["Подтвердить", "Отмена"], [
|
||||||
|
(function() {
|
||||||
|
xhr = new XMLHttpRequest();
|
||||||
|
xhr.open("GET", "/admin/unban/" + {$user->getId()} + "?hash=" + {rawurlencode($csrfToken)}, true);
|
||||||
|
xhr.onload = (function() {
|
||||||
|
if(xhr.responseText.indexOf("success") === -1)
|
||||||
|
MessageBox("Ошибка", "Не удалось разблокировать пользователя...", ["OK"], [Function.noop]);
|
||||||
|
else
|
||||||
|
MessageBox("Операция успешна", "Пользователь разблокирован", ["OK"], [Function.noop]);
|
||||||
|
});
|
||||||
|
xhr.send(null);
|
||||||
|
}),
|
||||||
|
Function.noop
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script n:if="isset($thisUser) && $thisUser->getChandlerUser()->can('write')->model('openvk\Web\Models\Entities\TicketReply')->whichBelongsTo(0)">
|
||||||
|
{if $user->isBannedInSupport()}
|
||||||
|
function toggleBanInSupport() {
|
||||||
|
uBanMsgTxt = "Вы собираетесь разблокировать в поддержке пользователя " + {$user->getCanonicalName()} + ".";
|
||||||
|
uBanMsgTxt += "<br/>Сейчас он заблокирован по причине <strong>" + {$user->getBanInSupportReason()} + "</strong>.";
|
||||||
|
|
||||||
|
MessageBox("Разблокировать в поддержке " + {$user->getFirstName()}, uBanMsgTxt, ["Подтвердить", "Отмена"], [
|
||||||
|
(function() {
|
||||||
|
xhr = new XMLHttpRequest();
|
||||||
|
xhr.open("GET", "/admin/support/unban/" + {$user->getId()} + "?hash=" + {rawurlencode($csrfToken)}, true);
|
||||||
|
xhr.onload = (function() {
|
||||||
|
if(xhr.responseText.indexOf("success") === -1)
|
||||||
|
MessageBox("Ошибка", "Не удалось разблокировать пользователя в поддержке...", ["OK"], [Function.noop]);
|
||||||
|
else
|
||||||
|
MessageBox("Операция успешна", "Пользователь разблокирован в поддержке", ["OK"], [Function.noop]);
|
||||||
|
});
|
||||||
|
xhr.send(null);
|
||||||
|
}),
|
||||||
|
Function.noop
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
{else}
|
||||||
|
function toggleBanInSupport() {
|
||||||
|
uBanMsgTxt = "Вы собираетесь заблокировать в поддержке пользователя " + {$user->getCanonicalName()} + ".";
|
||||||
|
uBanMsgTxt += "<br/><br/><b>Причина бана</b>: <input type='text' id='uBanMsgInput' placeholder='придумайте что-нибудь крутое' />";
|
||||||
|
|
||||||
|
MessageBox("Заблокировать в поддержке " + {$user->getFirstName()}, uBanMsgTxt, ["Подтвердить", "Отмена"], [
|
||||||
|
(function() {
|
||||||
|
res = document.querySelector("#uBanMsgInput").value;
|
||||||
|
xhr = new XMLHttpRequest();
|
||||||
|
xhr.open("GET", "/admin/support/ban/" + {$user->getId()} + "?reason=" + res + "&hash=" + {rawurlencode($csrfToken)}, true);
|
||||||
|
xhr.onload = (function() {
|
||||||
|
if(xhr.responseText.indexOf("success") === -1)
|
||||||
|
MessageBox("Ошибка", "Не удалось заблокировать пользователя в поддержке...", ["OK"], [Function.noop]);
|
||||||
|
else
|
||||||
|
MessageBox("Операция успешна", "Пользователь заблокирован в поддержке", ["OK"], [Function.noop]);
|
||||||
|
});
|
||||||
|
xhr.send(null);
|
||||||
|
}),
|
||||||
|
Function.noop
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
{/if}
|
||||||
|
</script>
|
||||||
|
|
|
@ -2,11 +2,11 @@
|
||||||
{if !$attachment->isDeleted()}
|
{if !$attachment->isDeleted()}
|
||||||
{var link = "/photo" . ($attachment->isAnonymous() ? ("s/" . base_convert((string) $attachment->getId(), 10, 32)) : $attachment->getPrettyId())}
|
{var link = "/photo" . ($attachment->isAnonymous() ? ("s/" . base_convert((string) $attachment->getId(), 10, 32)) : $attachment->getPrettyId())}
|
||||||
<a href="{$link}">
|
<a href="{$link}">
|
||||||
<img class="media" src="{$attachment->getURL()}" alt="{$attachment->getDescription()}" />
|
<img class="media" src="{$attachment->getURLBySizeId('normal')}" alt="{$attachment->getDescription()}" />
|
||||||
</a>
|
</a>
|
||||||
{else}
|
{else}
|
||||||
<a href="javascript:alert('{_"attach_no_longer_available"}');">
|
<a href="javascript:alert('{_attach_no_longer_available}');">
|
||||||
<img class="media" src="/assets/packages/static/openvk/img/camera_200.png" alt="{_"attach_no_longer_available"}" />
|
<img class="media" src="/assets/packages/static/openvk/img/camera_200.png" alt="{_attach_no_longer_available}" />
|
||||||
</a>
|
</a>
|
||||||
{/if}
|
{/if}
|
||||||
{elseif $attachment instanceof \openvk\Web\Models\Entities\Video}
|
{elseif $attachment instanceof \openvk\Web\Models\Entities\Video}
|
||||||
|
@ -14,12 +14,12 @@
|
||||||
{elseif $attachment instanceof \openvk\Web\Models\Entities\Post}
|
{elseif $attachment instanceof \openvk\Web\Models\Entities\Post}
|
||||||
{php $GLOBALS["_nesAttGloCou"] = (isset($GLOBALS["_nesAttGloCou"]) ? $GLOBALS["_nesAttGloCou"] : 0) + 1}
|
{php $GLOBALS["_nesAttGloCou"] = (isset($GLOBALS["_nesAttGloCou"]) ? $GLOBALS["_nesAttGloCou"] : 0) + 1}
|
||||||
{if $GLOBALS["_nesAttGloCou"] > 2}
|
{if $GLOBALS["_nesAttGloCou"] > 2}
|
||||||
<a href="/wall{$attachment->getPrettyId()}">{_"open_post"}</a>
|
<a href="/wall{$attachment->getPrettyId()}">{_open_post}</a>
|
||||||
{else}
|
{else}
|
||||||
{include "post.xml", post => $attachment, compact => true}
|
{include "post.xml", post => $attachment, compact => true}
|
||||||
{/if}
|
{/if}
|
||||||
{else}
|
{else}
|
||||||
<span style="color:red;">{_"version_incompatibility"}</span>
|
<span style="color:red;">{_version_incompatibility}</span>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
{php $GLOBALS["_nesAttGloCou"] = NULL}
|
{php $GLOBALS["_nesAttGloCou"] = NULL}
|
||||||
|
|
|
@ -8,10 +8,7 @@
|
||||||
<tr>
|
<tr>
|
||||||
<td width="30" valign="top">
|
<td width="30" valign="top">
|
||||||
<a href="{$author->getURL()}">
|
<a href="{$author->getURL()}">
|
||||||
<img
|
<img src="{$author->getAvatarURL('miniscule')}" width="30" class="cCompactAvatars" />
|
||||||
src="{$author->getAvatarURL()}"
|
|
||||||
width="30"
|
|
||||||
class="cCompactAvatars" />
|
|
||||||
</a>
|
</a>
|
||||||
</td>
|
</td>
|
||||||
<td width="100%" valign="top">
|
<td width="100%" valign="top">
|
||||||
|
@ -19,7 +16,7 @@
|
||||||
<a href="{$author->getURL()}"><b>
|
<a href="{$author->getURL()}"><b>
|
||||||
{$author->getCanonicalName()}
|
{$author->getCanonicalName()}
|
||||||
</b></a>
|
</b></a>
|
||||||
{if $author->isVerified()}<img class="name-checkmark" src="/assets/packages/static/openvk/img/checkmark.png">{/if}<br/>
|
<img n:if="$author->isVerified()" class="name-checkmark" src="/assets/packages/static/openvk/img/checkmark.png"><br/>
|
||||||
</div>
|
</div>
|
||||||
<div class="post-content" id="{$comment->getId()}">
|
<div class="post-content" id="{$comment->getId()}">
|
||||||
<div class="text" id="text{$comment->getId()}">
|
<div class="text" id="text{$comment->getId()}">
|
||||||
|
@ -34,9 +31,9 @@
|
||||||
<div n:if="isset($thisUser) &&! ($compact ?? false)" class="post-menu">
|
<div n:if="isset($thisUser) &&! ($compact ?? false)" class="post-menu">
|
||||||
<a href="#_comment{$comment->getId()}" class="date">{$comment->getPublicationTime()}</a> |
|
<a href="#_comment{$comment->getId()}" class="date">{$comment->getPublicationTime()}</a> |
|
||||||
{if $comment->canBeDeletedBy($thisUser)}
|
{if $comment->canBeDeletedBy($thisUser)}
|
||||||
<a href="/comment{$comment->getId()}/delete">{_"delete"}</a> |
|
<a href="/comment{$comment->getId()}/delete">{_delete}</a> |
|
||||||
{/if}
|
{/if}
|
||||||
<a class="comment-reply">{_"reply"}</a>
|
<a class="comment-reply">{_reply}</a>
|
||||||
<div style="float: right; font-size: .7rem;">
|
<div style="float: right; font-size: .7rem;">
|
||||||
<a class="post-like-button" href="/comment{$comment->getId()}/like?hash={rawurlencode($csrfToken)}">
|
<a class="post-like-button" href="/comment{$comment->getId()}/like?hash={rawurlencode($csrfToken)}">
|
||||||
<div class="heart" style="{if $comment->hasLikeFrom($thisUser)}opacity: 1;{else}opacity: 0.4;{/if}"></div>
|
<div class="heart" style="{if $comment->hasLikeFrom($thisUser)}opacity: 1;{else}opacity: 0.4;{/if}"></div>
|
||||||
|
@ -45,7 +42,6 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
<h4 n:if="$showTitle ?? true">{_"comments"} ({$count})</h4>
|
<h4 n:if="$showTitle ?? true">{_comments} ({$count})</h4>
|
||||||
|
|
||||||
<div n:ifset="$thisUser">
|
<div n:ifset="$thisUser">
|
||||||
{var commentsURL = "/al_comments/create/$model/" . $parent->getId()}
|
{var commentsURL = "/al_comments/create/$model/" . $parent->getId()}
|
||||||
|
@ -27,7 +27,7 @@
|
||||||
{else}
|
{else}
|
||||||
<p>Будьте первым кто оставит комментарий к этой дичи!</p>
|
<p>Будьте первым кто оставит комментарий к этой дичи!</p>
|
||||||
{/if} -->
|
{/if} -->
|
||||||
{_"comments_tip"}
|
{_comments_tip}
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
{script "js/al_comments.js"}
|
{script "js/al_comments.js"}
|
||||||
|
|
|
@ -3,16 +3,10 @@
|
||||||
|
|
||||||
<div n:if="!($conf->page === 1 && $conf->count <= $conf->perPage)" style="padding: 8px;">
|
<div n:if="!($conf->page === 1 && $conf->count <= $conf->perPage)" style="padding: 8px;">
|
||||||
<div n:class="paginator, ($conf->atBottom ?? false) ? paginator-at-bottom">
|
<div n:class="paginator, ($conf->atBottom ?? false) ? paginator-at-bottom">
|
||||||
{if $conf->page > $space}
|
<a n:if="$conf->page > $space" n:attr="class => ($conf->page === 1 ? 'active')" href="?{http_build_query(array_merge($_GET, ['p' => 1]), 'k', '&', PHP_QUERY_RFC3986)}">«</a>
|
||||||
<a n:attr="class => ($conf->page === 1 ? 'active')" href="?{http_build_query(array_merge($_GET, ['p' => 1]), 'k', '&', PHP_QUERY_RFC3986)}">«</a>
|
|
||||||
{/if}
|
|
||||||
{for $j = $conf->page - ($space-1); $j <= $conf->page + ($space-1); $j++}
|
{for $j = $conf->page - ($space-1); $j <= $conf->page + ($space-1); $j++}
|
||||||
{if $j > 0 && $j <= $pageCount}
|
<a n:if="$j > 0 && $j <= $pageCount" n:attr="class => ($conf->page === $j ? 'active')" href="?{http_build_query(array_merge($_GET, ['p' => $j]), 'k', '&', PHP_QUERY_RFC3986)}">{$j}</a>
|
||||||
<a n:attr="class => ($conf->page === $j ? 'active')" href="?{http_build_query(array_merge($_GET, ['p' => $j]), 'k', '&', PHP_QUERY_RFC3986)}">{$j}</a>
|
|
||||||
{/if}
|
|
||||||
{/for}
|
{/for}
|
||||||
{if $conf->page <= $pageCount-$space}
|
<a n:if="$conf->page <= $pageCount-$space" n:attr="class => ($conf->page === $pageCount ? 'active')" href="?{http_build_query(array_merge($_GET, ['p' => $pageCount]), 'k', '&', PHP_QUERY_RFC3986)}">»</a>
|
||||||
<a n:attr="class => ($conf->page === $pageCount ? 'active')" href="?{http_build_query(array_merge($_GET, ['p' => $pageCount]), 'k', '&', PHP_QUERY_RFC3986)}">»</a>
|
|
||||||
{/if}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,9 +1,4 @@
|
||||||
{var microblogEnabled = isset($thisUser) ? $thisUser->hasMicroblogEnabled() : false}
|
{var microblogEnabled = isset($thisUser) ? $thisUser->hasMicroblogEnabled() : false}
|
||||||
{if !$post->isPostedOnBehalfOfGroup()}
|
|
||||||
{var then = date_create("@" . $post->getOwner()->getOnline()->timestamp())}
|
|
||||||
{var now = date_create()}
|
|
||||||
{var diff = date_diff($now, $then)}
|
|
||||||
{/if}
|
|
||||||
|
|
||||||
{if $microblogEnabled}
|
{if $microblogEnabled}
|
||||||
{include "post/microblogpost.xml", post => $post, diff => $diff, commentSection => $commentSection}
|
{include "post/microblogpost.xml", post => $post, diff => $diff, commentSection => $commentSection}
|
||||||
|
|
|
@ -9,25 +9,14 @@
|
||||||
<tr>
|
<tr>
|
||||||
<td width="54" valign="top">
|
<td width="54" valign="top">
|
||||||
<a href="{$author->getURL()}">
|
<a href="{$author->getURL()}">
|
||||||
<img
|
<img src="{$author->getAvatarURL('miniscule')}" width="{ifset $compact}25{else}50{/ifset}" {ifset $compact}class="cCompactAvatars"{/ifset} />
|
||||||
src="{$author->getAvatarURL()}"
|
<span n:if="!$post->isPostedOnBehalfOfGroup() && !$compact && $author->isOnline()" class="post-online">{_online}</span>
|
||||||
width="{ifset $compact}25{else}50{/ifset}"
|
|
||||||
{ifset $compact}class="cCompactAvatars"{/ifset} />
|
|
||||||
{if !$post->isPostedOnBehalfOfGroup() && !$compact}
|
|
||||||
<span n:if="$author->isOnline()" class="post-online">
|
|
||||||
{_online}
|
|
||||||
</span>
|
|
||||||
{/if}
|
|
||||||
</a>
|
</a>
|
||||||
</td>
|
</td>
|
||||||
<td width="100%" valign="top">
|
<td width="100%" valign="top">
|
||||||
<div class="post-author">
|
<div class="post-author">
|
||||||
<a href="{$author->getURL()}">
|
<a href="{$author->getURL()}"><b>{$author->getCanonicalName()}</b></a>
|
||||||
<b>
|
<img n:if="$author->isVerified()" class="name-checkmark" src="/assets/packages/static/openvk/img/checkmark.png">
|
||||||
{$author->getCanonicalName()}
|
|
||||||
</b>
|
|
||||||
</a>
|
|
||||||
{if $author->isVerified()}<img class="name-checkmark" src="/assets/packages/static/openvk/img/checkmark.png">{/if}
|
|
||||||
{if ($onWallOf ?? false) &&!$post->isPostedOnBehalfOfGroup() && $post->getOwnerPost() !== $post->getTargetWall()}
|
{if ($onWallOf ?? false) &&!$post->isPostedOnBehalfOfGroup() && $post->getOwnerPost() !== $post->getTargetWall()}
|
||||||
{var wallId = $post->getTargetWall()}
|
{var wallId = $post->getTargetWall()}
|
||||||
{var wallURL = $wallId > -1 ? "/id$wallId" : "/club" . abs($wallId)}
|
{var wallURL = $wallId > -1 ? "/id$wallId" : "/club" . abs($wallId)}
|
||||||
|
@ -44,18 +33,17 @@
|
||||||
</b>
|
</b>
|
||||||
</a>
|
</a>
|
||||||
{/if}
|
{/if}
|
||||||
{ifset $compact}<br>
|
|
||||||
|
{ifset $compact}
|
||||||
|
<br>
|
||||||
<a href="/wall{$post->getPrettyId()}" class="date">
|
<a href="/wall{$post->getPrettyId()}" class="date">
|
||||||
{$post->getPublicationTime()}
|
{$post->getPublicationTime()}
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
{/ifset}
|
{/ifset}
|
||||||
{if $post->isPinned()}
|
|
||||||
<span class="nobold">{_pinned}</span>
|
<span n:if="$post->isPinned()" class="nobold">{_pinned}</span>
|
||||||
{/if}
|
|
||||||
{if $post->canBeDeletedBy($thisUser) && !($forceNoDeleteLink ?? false) && !isset($compact)}
|
<a n:if="$post->canBeDeletedBy($thisUser) && !($forceNoDeleteLink ?? false) && !isset($compact)" class="delete" href="/wall{$post->getPrettyId()}/delete"></a>
|
||||||
<a class="delete" href="/wall{$post->getPrettyId()}/delete"></a>
|
|
||||||
{/if}
|
|
||||||
|
|
||||||
{if $post->canBePinnedBy($thisUser) && !($forceNoPinLink ?? false) && !isset($compact)}
|
{if $post->canBePinnedBy($thisUser) && !($forceNoPinLink ?? false) && !isset($compact)}
|
||||||
{if $post->isPinned()}
|
{if $post->isPinned()}
|
||||||
|
@ -80,11 +68,11 @@
|
||||||
! Этот пост был размещён за взятку.
|
! Этот пост был размещён за взятку.
|
||||||
</div>
|
</div>
|
||||||
<div n:if="$post->isSigned()" class="post-signature">
|
<div n:if="$post->isSigned()" class="post-signature">
|
||||||
{var acutalAuthor = $post->getOwner(false)}
|
{var actualAuthor = $post->getOwner(false)}
|
||||||
<span>
|
<span>
|
||||||
Автор:
|
{_author}:
|
||||||
<a href="{$acutalAuthor->getURL()}">
|
<a href="{$actualAuthor->getURL()}">
|
||||||
{$acutalAuthor->getCanonicalName()}
|
{$actualAuthor->getCanonicalName()}
|
||||||
</a>
|
</a>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
@ -94,26 +82,17 @@
|
||||||
{if isset($thisUser)}
|
{if isset($thisUser)}
|
||||||
|
|
||||||
|
|
||||||
{if !($forceNoCommentsLink ?? false)}
|
<a n:if="!($forceNoCommentsLink ?? false) && $commentsCount == 0" href="javascript:expand_comment_textarea({$commentTextAreaId})">{_comment}</a>
|
||||||
<a n:if="$commentsCount == 0" href="javascript:expand_comment_textarea({$commentTextAreaId})">
|
|
||||||
{_"comment"}
|
|
||||||
</a>
|
|
||||||
{/if}
|
|
||||||
|
|
||||||
<div class="like_wrap">
|
<div class="like_wrap">
|
||||||
{if !($forceNoShareLink ?? false)}
|
<a n:if="!($forceNoShareLink ?? false)" class="post-share-button" href="javascript:repostPost('{$post->getPrettyId()}', '{rawurlencode($csrfToken)}')">
|
||||||
<a class="post-share-button" href="javascript:repostPost('{$post->getPrettyId()}', '{rawurlencode($csrfToken)}')">
|
|
||||||
<div class="repost-icon" style="opacity: 0.4;"></div>
|
<div class="repost-icon" style="opacity: 0.4;"></div>
|
||||||
<span class="likeCnt">{if $post->getRepostCount() > 0}{$post->getRepostCount()}{/if}</span>
|
<span class="likeCnt">{if $post->getRepostCount() > 0}{$post->getRepostCount()}{/if}</span>
|
||||||
</a>
|
</a>
|
||||||
{/if}
|
|
||||||
|
|
||||||
{if !($forceNoLike ?? false)}
|
{if !($forceNoLike ?? false)}
|
||||||
{var liked = $post->hasLikeFrom($thisUser)}
|
{var liked = $post->hasLikeFrom($thisUser)}
|
||||||
<a href="/wall{$post->getPrettyId()}/like?hash={rawurlencode($csrfToken)}"
|
<a href="/wall{$post->getPrettyId()}/like?hash={rawurlencode($csrfToken)}" class="post-like-button" data-liked="{(int) $liked}" data-likes="{$post->getLikesCount()}">
|
||||||
class="post-like-button"
|
|
||||||
data-liked="{(int) $liked}"
|
|
||||||
data-likes="{$post->getLikesCount()}">
|
|
||||||
<div class="heart" id="{if $liked}liked{/if}"></div>
|
<div class="heart" id="{if $liked}liked{/if}"></div>
|
||||||
<span class="likeCnt">{if $post->getLikesCount() > 0}{$post->getLikesCount()}{/if}</span>
|
<span class="likeCnt">{if $post->getLikesCount() > 0}{$post->getLikesCount()}{/if}</span>
|
||||||
</a>
|
</a>
|
||||||
|
@ -121,11 +100,8 @@
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
{if !($forceNoCommentsLink ?? false)}
|
<div n:if="!($forceNoCommentsLink ?? false) && $commentSection == true && $compact == false" class="post-menu-s">
|
||||||
<div n:if="$commentSection == true && $compact == false" class="post-menu-s">
|
<a n:if="$commentsCount > 3" href="/wall{$post->getPrettyId()}" class="expand_button">{_view_other_comments}</a>
|
||||||
{if $commentsCount > 3}
|
|
||||||
<a href="/wall{$post->getPrettyId()}" class="expand_button">{_view_other_comments}</a>
|
|
||||||
{/if}
|
|
||||||
{foreach $comments as $comment}
|
{foreach $comments as $comment}
|
||||||
{include "../comment.xml", comment => $comment, $compact => true}
|
{include "../comment.xml", comment => $comment, $compact => true}
|
||||||
{/foreach}
|
{/foreach}
|
||||||
|
@ -135,7 +111,6 @@
|
||||||
{include "../textArea.xml", route => $commentsURL, postOpts => false, graffiti => (bool) ovkGetQuirk("comments.allow-graffiti"), post => $post, club => $club}
|
{include "../textArea.xml", route => $commentsURL, postOpts => false, graffiti => (bool) ovkGetQuirk("comments.allow-graffiti"), post => $post, club => $club}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
|
|
|
@ -5,26 +5,15 @@
|
||||||
<tr>
|
<tr>
|
||||||
<td width="54" valign="top">
|
<td width="54" valign="top">
|
||||||
<a href="{$author->getURL()}">
|
<a href="{$author->getURL()}">
|
||||||
<img
|
<img src="{$author->getAvatarURL('miniscule')}" width="50" />
|
||||||
src="{$author->getAvatarURL()}"
|
<span n:if="!$post->isPostedOnBehalfOfGroup() && !($compact ?? false) && $author->isOnline()" class="post-online">{_online}</span>
|
||||||
width="50" />
|
|
||||||
</a>
|
</a>
|
||||||
{if !$post->isPostedOnBehalfOfGroup() && !($compact ?? false)}
|
|
||||||
<span n:if="$author->isOnline()" class="post-online">
|
|
||||||
{_online}
|
|
||||||
</span>
|
|
||||||
{/if}
|
|
||||||
|
|
||||||
</td>
|
</td>
|
||||||
<td width="100%" valign="top">
|
<td width="100%" valign="top">
|
||||||
<div class="post-author">
|
<div class="post-author">
|
||||||
<a href="{$author->getURL()}">
|
<a href="{$author->getURL()}"><b>{$author->getCanonicalName()}</b></a>
|
||||||
<b>
|
<img n:if="$author->isVerified()" class="name-checkmark" src="/assets/packages/static/openvk/img/checkmark.png">
|
||||||
{$author->getCanonicalName()}
|
{$post->isPostedOnBehalfOfGroup() ? tr("post_writes_g") : ($author->isFemale() ? tr("post_writes_f") : tr("post_writes_m"))}
|
||||||
</b>
|
|
||||||
</a>
|
|
||||||
{if $author->isVerified()}<img class="name-checkmark" src="/assets/packages/static/openvk/img/checkmark.png">{/if}
|
|
||||||
{$post->isPostedOnBehalfOfGroup() ? "опубликовали" : ($author->isFemale() ? tr("post_writes_f") : tr("post_writes_m"))}
|
|
||||||
{if ($onWallOf ?? false) &&!$post->isPostedOnBehalfOfGroup() && $post->getOwnerPost() !== $post->getTargetWall()}
|
{if ($onWallOf ?? false) &&!$post->isPostedOnBehalfOfGroup() && $post->getOwnerPost() !== $post->getTargetWall()}
|
||||||
{var wallId = $post->getTargetWall()}
|
{var wallId = $post->getTargetWall()}
|
||||||
{var wallURL = $wallId > -1 ? "/id$wallId" : "/club" . abs($wallId)}
|
{var wallURL = $wallId > -1 ? "/id$wallId" : "/club" . abs($wallId)}
|
||||||
|
@ -43,10 +32,7 @@
|
||||||
{/if}
|
{/if}
|
||||||
<br/>
|
<br/>
|
||||||
<a href="/wall{$post->getPrettyId()}" class="date">
|
<a href="/wall{$post->getPrettyId()}" class="date">
|
||||||
{$post->getPublicationTime()}
|
{$post->getPublicationTime()}{if $post->isPinned()}, {_pinned}{/if}
|
||||||
{if $post->isPinned()}
|
|
||||||
, {_pinned}
|
|
||||||
{/if}
|
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<div class="post-content" id="{$post->getPrettyId()}">
|
<div class="post-content" id="{$post->getPrettyId()}">
|
||||||
|
@ -64,68 +50,54 @@
|
||||||
! Этот пост был размещён за взятку.
|
! Этот пост был размещён за взятку.
|
||||||
</div>
|
</div>
|
||||||
<div n:if="$post->isSigned()" class="post-signature">
|
<div n:if="$post->isSigned()" class="post-signature">
|
||||||
{var acutalAuthor = $post->getOwner(false)}
|
{var actualAuthor = $post->getOwner(false)}
|
||||||
<span>
|
<span>
|
||||||
Автор:
|
{_author}:
|
||||||
<a href="{$acutalAuthor->getURL()}">
|
<a href="{$actualAuthor->getURL()}">
|
||||||
{$acutalAuthor->getCanonicalName()}
|
{$actualAuthor->getCanonicalName()}
|
||||||
</a>
|
</a>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div n:if="isset($thisUser) &&! ($compact ?? false)" class="post-menu">
|
<div n:if="isset($thisUser) &&! ($compact ?? false)" class="post-menu">
|
||||||
{if $post->canBeDeletedBy($thisUser) && !($forceNoDeleteLink ?? false)}
|
{if $post->canBeDeletedBy($thisUser) && !($forceNoDeleteLink ?? false)}
|
||||||
<a href="/wall{$post->getPrettyId()}/delete">{_"delete"}</a> |
|
<a href="/wall{$post->getPrettyId()}/delete">{_delete}</a> |
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
{if $post->canBePinnedBy($thisUser) && !($forceNoPinLink ?? false)}
|
{if $post->canBePinnedBy($thisUser) && !($forceNoPinLink ?? false)}
|
||||||
{if $post->isPinned()}
|
{if $post->isPinned()}
|
||||||
<a href="/wall{$post->getPrettyId()}/pin?act=unpin&hash={rawurlencode($csrfToken)}">{_unpin}</a> |
|
<a href="/wall{$post->getPrettyId()}/pin?act=unpin&hash={rawurlencode($csrfToken)}">{_unpin}</a>
|
||||||
{else}
|
{else}
|
||||||
<a href="/wall{$post->getPrettyId()}/pin?act=pin&hash={rawurlencode($csrfToken)}">{_pin}</a> |
|
<a href="/wall{$post->getPrettyId()}/pin?act=pin&hash={rawurlencode($csrfToken)}">{_pin}</a>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
{if !($forceNoCommentsLink ?? false)}
|
<a n:if="!($forceNoCommentsLink ?? false)" href="/wall{$post->getPrettyId()}#comments">
|
||||||
<a href="/wall{$post->getPrettyId()}#comments">
|
{_comments}
|
||||||
{if $post->getCommentsCount() > 0}
|
{if $post->getCommentsCount() > 0}
|
||||||
{_"comments"} (<b>{$post->getCommentsCount()}</b>)
|
(<b>{$post->getCommentsCount()}</b>)
|
||||||
{else}
|
|
||||||
{_"comments"}
|
|
||||||
{/if}
|
{/if}
|
||||||
</a>
|
</a>
|
||||||
{/if}
|
|
||||||
|
|
||||||
{if !($forceNoCommentsLink ?? false) && !($forceNoShareLink ?? false)}
|
{if !($forceNoCommentsLink ?? false) && !($forceNoShareLink ?? false)}
|
||||||
|
|
|
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
{if !($forceNoShareLink ?? false)}
|
<a n:if="!($forceNoShareLink ?? false)" class="post-share-button" href="javascript:repostPost('{$post->getPrettyId()}', '{rawurlencode($csrfToken)}')">
|
||||||
<a class="post-share-button" href="javascript:repostPost('{$post->getPrettyId()}', '{rawurlencode($csrfToken)}')">
|
{_share}
|
||||||
{if $post->getRepostCount() > 0}
|
{if $post->getRepostCount() > 0}
|
||||||
{_"share"}
|
|
||||||
(<b>{$post->getRepostCount()}</b>)
|
(<b>{$post->getRepostCount()}</b>)
|
||||||
{else}
|
|
||||||
{_"share"}
|
|
||||||
{/if}
|
{/if}
|
||||||
</a>
|
</a>
|
||||||
{/if}
|
|
||||||
|
|
||||||
{if !($forceNoLike ?? false)}
|
<div n:if="!($forceNoLike ?? false)" class="like_wrap">
|
||||||
<div class="like_wrap">
|
|
||||||
{var liked = $post->hasLikeFrom($thisUser)}
|
{var liked = $post->hasLikeFrom($thisUser)}
|
||||||
<a href="/wall{$post->getPrettyId()}/like?hash={rawurlencode($csrfToken)}"
|
<a href="/wall{$post->getPrettyId()}/like?hash={rawurlencode($csrfToken)}" class="post-like-button" data-liked="{(int) $liked}" data-likes="{$post->getLikesCount()}">
|
||||||
class="post-like-button"
|
|
||||||
data-liked="{(int) $liked}"
|
|
||||||
data-likes="{$post->getLikesCount()}">
|
|
||||||
<div class="heart" id="{if $liked}liked{/if}"></div>
|
<div class="heart" id="{if $liked}liked{/if}"></div>
|
||||||
<span class="likeCnt">{if $post->getLikesCount() > 0}{$post->getLikesCount()}{/if}</span>
|
<span class="likeCnt">{if $post->getLikesCount() > 0}{$post->getLikesCount()}{/if}</span>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
|
||||||
</div>
|
|
||||||
<div n:if="isset($thisUser) &&! ($compact ?? false)" class="post-menu-s">
|
|
||||||
<!-- kosfurler -->
|
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
|
@ -27,25 +27,25 @@
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<label>
|
<label>
|
||||||
<input type="checkbox" name="as_group" onchange="onWallAsGroupClick(this)" /> {_"post_as_group"}
|
<input type="checkbox" name="as_group" onchange="onWallAsGroupClick(this)" /> {_post_as_group}
|
||||||
</label>
|
</label>
|
||||||
<label id="forceSignOpt" style="display: none;">
|
<label id="forceSignOpt" style="display: none;">
|
||||||
<input type="checkbox" name="force_sign" /> {_"add_signature"}
|
<input type="checkbox" name="force_sign" /> {_add_signature}
|
||||||
</label>
|
</label>
|
||||||
{/if}
|
{/if}
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
<label n:if="$anonEnabled" id="octoberAnonOpt">
|
<label n:if="$anonEnabled" id="octoberAnonOpt">
|
||||||
<input type="checkbox" name="anon" /> {_"as_anonymous"}
|
<input type="checkbox" name="anon" /> {_as_anonymous}
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
<label>
|
<label>
|
||||||
<input type="checkbox" name="nsfw" /> {_"contains_nsfw"}
|
<input type="checkbox" name="nsfw" /> {_contains_nsfw}
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
<div n:if="!($postOpts ?? true) && !is_null($thisUser) && !is_null($club ?? NULL) && $club->canBeModifiedBy($thisUser)" class="post-opts">
|
<div n:if="!($postOpts ?? true) && !is_null($thisUser) && !is_null($club ?? NULL) && $club->canBeModifiedBy($thisUser)" class="post-opts">
|
||||||
<label>
|
<label>
|
||||||
<input type="checkbox" name="as_group" /> {_"comment_as_group"}
|
<input type="checkbox" name="as_group" /> {_comment_as_group}
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
<input type="file" class="postFileSel" id="postFilePic" name="_pic_attachment" accept="image/*" style="display:none;" />
|
<input type="file" class="postFileSel" id="postFilePic" name="_pic_attachment" accept="image/*" style="display:none;" />
|
||||||
|
@ -53,7 +53,7 @@
|
||||||
<input type="hidden" name="type" value="1" />
|
<input type="hidden" name="type" value="1" />
|
||||||
<input type="hidden" name="hash" value="{$csrfToken}" />
|
<input type="hidden" name="hash" value="{$csrfToken}" />
|
||||||
<br/>
|
<br/>
|
||||||
<input type="submit" value="{_'write'}" class="button" />
|
<input type="submit" value="{_write}" class="button" />
|
||||||
<div style="float: right; display: flex; flex-direction: column;">
|
<div style="float: right; display: flex; flex-direction: column;">
|
||||||
<a href="javascript:void(u('#post-buttons{$textAreaId} #wallAttachmentMenu').toggleClass('hidden'));">
|
<a href="javascript:void(u('#post-buttons{$textAreaId} #wallAttachmentMenu').toggleClass('hidden'));">
|
||||||
{_attach}
|
{_attach}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
<div class="content_divider">
|
<div class="content_divider">
|
||||||
<div class="content_title_expanded" onclick="hidePanel(this);">
|
<div class="content_title_expanded" onclick="hidePanel(this);">
|
||||||
{_"wall"}
|
{_wall}
|
||||||
<nobold>
|
<nobold>
|
||||||
{tr("wall", $count)}
|
{tr("wall", $count)}
|
||||||
<a href="/wall{$owner}" class="float-right lowercase">{_all_title}</a>
|
<a href="/wall{$owner}" class="float-right lowercase">{_all_title}</a>
|
||||||
|
|
|
@ -271,16 +271,24 @@ routes:
|
||||||
handler: "Admin->gifts"
|
handler: "Admin->gifts"
|
||||||
- url: "/admin/ban/{num}"
|
- url: "/admin/ban/{num}"
|
||||||
handler: "Admin->quickBan"
|
handler: "Admin->quickBan"
|
||||||
|
- url: "/admin/unban/{num}"
|
||||||
|
handler: "Admin->quickUnban"
|
||||||
- url: "/admin/warn/{num}"
|
- url: "/admin/warn/{num}"
|
||||||
handler: "Admin->quickWarn"
|
handler: "Admin->quickWarn"
|
||||||
- url: "/support/reports"
|
- url: "/admin/support/ban/{num}"
|
||||||
|
handler: "Support->quickBanInSupport"
|
||||||
|
- url: "/admin/support/unban/{num}"
|
||||||
|
handler: "Support->quickUnbanInSupport"
|
||||||
|
- url: "/admin/support/reports"
|
||||||
handler: "Report->list"
|
handler: "Report->list"
|
||||||
- url: "/support/report{num}"
|
- url: "/admin/support/report{num}"
|
||||||
handler: "Report->view"
|
handler: "Report->view"
|
||||||
- url: "/support/reportAction{num}"
|
- url: "/admin/support/reportAction{num}"
|
||||||
handler: "Report->action"
|
handler: "Report->action"
|
||||||
- url: "/report/{num}"
|
- url: "/report/{num}"
|
||||||
handler: "Report->create"
|
handler: "Report->create"
|
||||||
|
- url: "/upload/photo/{text}"
|
||||||
|
handler: "VKAPI->photoUpload"
|
||||||
- url: "/method/{text}.{text}"
|
- url: "/method/{text}.{text}"
|
||||||
handler: "VKAPI->route"
|
handler: "VKAPI->route"
|
||||||
- url: "/token"
|
- url: "/token"
|
||||||
|
|
|
@ -360,7 +360,7 @@ p {
|
||||||
}
|
}
|
||||||
|
|
||||||
.page_footer {
|
.page_footer {
|
||||||
margin-left: 95px;
|
margin-left: 130px;
|
||||||
padding-top: 5px;
|
padding-top: 5px;
|
||||||
clear: both;
|
clear: both;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
@ -1334,6 +1334,15 @@ body.scrolled .toTop:hover {
|
||||||
font-size: 15px;
|
font-size: 15px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#test-label {
|
||||||
|
padding: 8pt;
|
||||||
|
margin: 4pt;
|
||||||
|
border: 1px solid #9a205e;
|
||||||
|
background-color: #f5e9ec;
|
||||||
|
position: fixed;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
.post-upload {
|
.post-upload {
|
||||||
margin-top: 11px;
|
margin-top: 11px;
|
||||||
margin-left: 3px;
|
margin-left: 3px;
|
||||||
|
@ -1912,6 +1921,7 @@ table td[width="120"] {
|
||||||
width: 50px;
|
width: 50px;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
vertical-align: top;
|
vertical-align: top;
|
||||||
|
box-sizing: border-box;
|
||||||
}
|
}
|
||||||
|
|
||||||
.mb_tabs {
|
.mb_tabs {
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
"react-dom-factories": "^1.0.2",
|
"react-dom-factories": "^1.0.2",
|
||||||
"requirejs": "^2.3.6",
|
"requirejs": "^2.3.6",
|
||||||
"soundjs": "^1.0.1",
|
"soundjs": "^1.0.1",
|
||||||
|
"textfit": "^2.4.0",
|
||||||
"umbrellajs": "^3.1.0"
|
"umbrellajs": "^3.1.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -271,6 +271,11 @@ soundjs@^1.0.1:
|
||||||
resolved "https://registry.yarnpkg.com/soundjs/-/soundjs-1.0.1.tgz#99970542d28d0df2a1ebd061ae75c961a98c8180"
|
resolved "https://registry.yarnpkg.com/soundjs/-/soundjs-1.0.1.tgz#99970542d28d0df2a1ebd061ae75c961a98c8180"
|
||||||
integrity sha512-MgFPvmKYfpcNiE3X5XybNvScie3DMQlZgmNzUn4puBcpw64f4LqjH/fhM8Sb/eTJ8hK57Crr7mWy0bfJOqPj6Q==
|
integrity sha512-MgFPvmKYfpcNiE3X5XybNvScie3DMQlZgmNzUn4puBcpw64f4LqjH/fhM8Sb/eTJ8hK57Crr7mWy0bfJOqPj6Q==
|
||||||
|
|
||||||
|
textfit@^2.4.0:
|
||||||
|
version "2.4.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/textfit/-/textfit-2.4.0.tgz#80cba8006bfb9c3d9d552739257957bdda95c79c"
|
||||||
|
integrity sha512-/x4aoY5+/tJmu+iwpBH1yw75TFp86M6X15SvaaY/Eep7YySQYtqdOifEtfvVyMwzl7SZ+G4RQw00FD9g5R6i1Q==
|
||||||
|
|
||||||
trim-extra-html-whitespace@1.3.0:
|
trim-extra-html-whitespace@1.3.0:
|
||||||
version "1.3.0"
|
version "1.3.0"
|
||||||
resolved "https://registry.yarnpkg.com/trim-extra-html-whitespace/-/trim-extra-html-whitespace-1.3.0.tgz#b47efb0d1a5f2a56a85cc45cea525651e93404cf"
|
resolved "https://registry.yarnpkg.com/trim-extra-html-whitespace/-/trim-extra-html-whitespace-1.3.0.tgz#b47efb0d1a5f2a56a85cc45cea525651e93404cf"
|
||||||
|
|
|
@ -14,7 +14,9 @@
|
||||||
"chillerlan/php-qrcode": "dev-main",
|
"chillerlan/php-qrcode": "dev-main",
|
||||||
"vearutop/php-obscene-censor-rus": "dev-master",
|
"vearutop/php-obscene-censor-rus": "dev-master",
|
||||||
"erusev/parsedown": "dev-master",
|
"erusev/parsedown": "dev-master",
|
||||||
"bhaktaraz/php-rss-generator": "dev-master"
|
"bhaktaraz/php-rss-generator": "dev-master",
|
||||||
|
"ext-simplexml": "*",
|
||||||
|
"symfony/console": "5.4.x-dev"
|
||||||
},
|
},
|
||||||
"minimum-stability": "dev"
|
"minimum-stability": "dev"
|
||||||
}
|
}
|
||||||
|
|
804
composer.lock
generated
804
composer.lock
generated
|
@ -4,7 +4,7 @@
|
||||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||||
"This file is @generated automatically"
|
"This file is @generated automatically"
|
||||||
],
|
],
|
||||||
"content-hash": "2c94032cae911ca438bbcfc46c346961",
|
"content-hash": "878bd996183ccbb15637a7399ba03ab9",
|
||||||
"packages": [
|
"packages": [
|
||||||
{
|
{
|
||||||
"name": "al/emoji-detector",
|
"name": "al/emoji-detector",
|
||||||
|
@ -852,6 +852,54 @@
|
||||||
},
|
},
|
||||||
"time": "2016-08-06T20:24:11+00:00"
|
"time": "2016-08-06T20:24:11+00:00"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "psr/container",
|
||||||
|
"version": "1.x-dev",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/php-fig/container.git",
|
||||||
|
"reference": "513e0666f7216c7459170d56df27dfcefe1689ea"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/php-fig/container/zipball/513e0666f7216c7459170d56df27dfcefe1689ea",
|
||||||
|
"reference": "513e0666f7216c7459170d56df27dfcefe1689ea",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"php": ">=7.4.0"
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"Psr\\Container\\": "src/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"MIT"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "PHP-FIG",
|
||||||
|
"homepage": "https://www.php-fig.org/"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "Common Container Interface (PHP FIG PSR-11)",
|
||||||
|
"homepage": "https://github.com/php-fig/container",
|
||||||
|
"keywords": [
|
||||||
|
"PSR-11",
|
||||||
|
"container",
|
||||||
|
"container-interface",
|
||||||
|
"container-interop",
|
||||||
|
"psr"
|
||||||
|
],
|
||||||
|
"support": {
|
||||||
|
"issues": "https://github.com/php-fig/container/issues",
|
||||||
|
"source": "https://github.com/php-fig/container/tree/1.1.2"
|
||||||
|
},
|
||||||
|
"time": "2021-11-05T16:50:12+00:00"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "psr/http-message",
|
"name": "psr/http-message",
|
||||||
"version": "dev-master",
|
"version": "dev-master",
|
||||||
|
@ -1085,6 +1133,336 @@
|
||||||
},
|
},
|
||||||
"time": "2022-01-06T19:41:32+00:00"
|
"time": "2022-01-06T19:41:32+00:00"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "symfony/console",
|
||||||
|
"version": "5.4.x-dev",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/symfony/console.git",
|
||||||
|
"reference": "900275254f0a1a2afff1ab0e11abd5587a10e1d6"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/symfony/console/zipball/900275254f0a1a2afff1ab0e11abd5587a10e1d6",
|
||||||
|
"reference": "900275254f0a1a2afff1ab0e11abd5587a10e1d6",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"php": ">=7.2.5",
|
||||||
|
"symfony/deprecation-contracts": "^2.1|^3",
|
||||||
|
"symfony/polyfill-mbstring": "~1.0",
|
||||||
|
"symfony/polyfill-php73": "^1.9",
|
||||||
|
"symfony/polyfill-php80": "^1.16",
|
||||||
|
"symfony/service-contracts": "^1.1|^2|^3",
|
||||||
|
"symfony/string": "^5.1|^6.0"
|
||||||
|
},
|
||||||
|
"conflict": {
|
||||||
|
"psr/log": ">=3",
|
||||||
|
"symfony/dependency-injection": "<4.4",
|
||||||
|
"symfony/dotenv": "<5.1",
|
||||||
|
"symfony/event-dispatcher": "<4.4",
|
||||||
|
"symfony/lock": "<4.4",
|
||||||
|
"symfony/process": "<4.4"
|
||||||
|
},
|
||||||
|
"provide": {
|
||||||
|
"psr/log-implementation": "1.0|2.0"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"psr/log": "^1|^2",
|
||||||
|
"symfony/config": "^4.4|^5.0|^6.0",
|
||||||
|
"symfony/dependency-injection": "^4.4|^5.0|^6.0",
|
||||||
|
"symfony/event-dispatcher": "^4.4|^5.0|^6.0",
|
||||||
|
"symfony/lock": "^4.4|^5.0|^6.0",
|
||||||
|
"symfony/process": "^4.4|^5.0|^6.0",
|
||||||
|
"symfony/var-dumper": "^4.4|^5.0|^6.0"
|
||||||
|
},
|
||||||
|
"suggest": {
|
||||||
|
"psr/log": "For using the console logger",
|
||||||
|
"symfony/event-dispatcher": "",
|
||||||
|
"symfony/lock": "",
|
||||||
|
"symfony/process": ""
|
||||||
|
},
|
||||||
|
"default-branch": true,
|
||||||
|
"type": "library",
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"Symfony\\Component\\Console\\": ""
|
||||||
|
},
|
||||||
|
"exclude-from-classmap": [
|
||||||
|
"/Tests/"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"MIT"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Fabien Potencier",
|
||||||
|
"email": "fabien@symfony.com"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Symfony Community",
|
||||||
|
"homepage": "https://symfony.com/contributors"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "Eases the creation of beautiful and testable command line interfaces",
|
||||||
|
"homepage": "https://symfony.com",
|
||||||
|
"keywords": [
|
||||||
|
"cli",
|
||||||
|
"command line",
|
||||||
|
"console",
|
||||||
|
"terminal"
|
||||||
|
],
|
||||||
|
"support": {
|
||||||
|
"source": "https://github.com/symfony/console/tree/v5.4.7"
|
||||||
|
},
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"url": "https://symfony.com/sponsor",
|
||||||
|
"type": "custom"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://github.com/fabpot",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
|
||||||
|
"type": "tidelift"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"time": "2022-03-31T17:09:19+00:00"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "symfony/deprecation-contracts",
|
||||||
|
"version": "2.5.x-dev",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/symfony/deprecation-contracts.git",
|
||||||
|
"reference": "e8b495ea28c1d97b5e0c121748d6f9b53d075c66"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/e8b495ea28c1d97b5e0c121748d6f9b53d075c66",
|
||||||
|
"reference": "e8b495ea28c1d97b5e0c121748d6f9b53d075c66",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"php": ">=7.1"
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"extra": {
|
||||||
|
"branch-alias": {
|
||||||
|
"dev-main": "2.5-dev"
|
||||||
|
},
|
||||||
|
"thanks": {
|
||||||
|
"name": "symfony/contracts",
|
||||||
|
"url": "https://github.com/symfony/contracts"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"autoload": {
|
||||||
|
"files": [
|
||||||
|
"function.php"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"MIT"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Nicolas Grekas",
|
||||||
|
"email": "p@tchwork.com"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Symfony Community",
|
||||||
|
"homepage": "https://symfony.com/contributors"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "A generic function and convention to trigger deprecation notices",
|
||||||
|
"homepage": "https://symfony.com",
|
||||||
|
"support": {
|
||||||
|
"source": "https://github.com/symfony/deprecation-contracts/tree/2.5"
|
||||||
|
},
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"url": "https://symfony.com/sponsor",
|
||||||
|
"type": "custom"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://github.com/fabpot",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
|
||||||
|
"type": "tidelift"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"time": "2022-01-02T09:53:40+00:00"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "symfony/polyfill-ctype",
|
||||||
|
"version": "v1.25.0",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/symfony/polyfill-ctype.git",
|
||||||
|
"reference": "30885182c981ab175d4d034db0f6f469898070ab"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/30885182c981ab175d4d034db0f6f469898070ab",
|
||||||
|
"reference": "30885182c981ab175d4d034db0f6f469898070ab",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"php": ">=7.1"
|
||||||
|
},
|
||||||
|
"provide": {
|
||||||
|
"ext-ctype": "*"
|
||||||
|
},
|
||||||
|
"suggest": {
|
||||||
|
"ext-ctype": "For best performance"
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"extra": {
|
||||||
|
"branch-alias": {
|
||||||
|
"dev-main": "1.23-dev"
|
||||||
|
},
|
||||||
|
"thanks": {
|
||||||
|
"name": "symfony/polyfill",
|
||||||
|
"url": "https://github.com/symfony/polyfill"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"autoload": {
|
||||||
|
"files": [
|
||||||
|
"bootstrap.php"
|
||||||
|
],
|
||||||
|
"psr-4": {
|
||||||
|
"Symfony\\Polyfill\\Ctype\\": ""
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"MIT"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Gert de Pagter",
|
||||||
|
"email": "BackEndTea@gmail.com"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Symfony Community",
|
||||||
|
"homepage": "https://symfony.com/contributors"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "Symfony polyfill for ctype functions",
|
||||||
|
"homepage": "https://symfony.com",
|
||||||
|
"keywords": [
|
||||||
|
"compatibility",
|
||||||
|
"ctype",
|
||||||
|
"polyfill",
|
||||||
|
"portable"
|
||||||
|
],
|
||||||
|
"support": {
|
||||||
|
"source": "https://github.com/symfony/polyfill-ctype/tree/v1.25.0"
|
||||||
|
},
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"url": "https://symfony.com/sponsor",
|
||||||
|
"type": "custom"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://github.com/fabpot",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
|
||||||
|
"type": "tidelift"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"time": "2021-10-20T20:35:02+00:00"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "symfony/polyfill-intl-grapheme",
|
||||||
|
"version": "v1.25.0",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/symfony/polyfill-intl-grapheme.git",
|
||||||
|
"reference": "81b86b50cf841a64252b439e738e97f4a34e2783"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/81b86b50cf841a64252b439e738e97f4a34e2783",
|
||||||
|
"reference": "81b86b50cf841a64252b439e738e97f4a34e2783",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"php": ">=7.1"
|
||||||
|
},
|
||||||
|
"suggest": {
|
||||||
|
"ext-intl": "For best performance"
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"extra": {
|
||||||
|
"branch-alias": {
|
||||||
|
"dev-main": "1.23-dev"
|
||||||
|
},
|
||||||
|
"thanks": {
|
||||||
|
"name": "symfony/polyfill",
|
||||||
|
"url": "https://github.com/symfony/polyfill"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"autoload": {
|
||||||
|
"files": [
|
||||||
|
"bootstrap.php"
|
||||||
|
],
|
||||||
|
"psr-4": {
|
||||||
|
"Symfony\\Polyfill\\Intl\\Grapheme\\": ""
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"MIT"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Nicolas Grekas",
|
||||||
|
"email": "p@tchwork.com"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Symfony Community",
|
||||||
|
"homepage": "https://symfony.com/contributors"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "Symfony polyfill for intl's grapheme_* functions",
|
||||||
|
"homepage": "https://symfony.com",
|
||||||
|
"keywords": [
|
||||||
|
"compatibility",
|
||||||
|
"grapheme",
|
||||||
|
"intl",
|
||||||
|
"polyfill",
|
||||||
|
"portable",
|
||||||
|
"shim"
|
||||||
|
],
|
||||||
|
"support": {
|
||||||
|
"source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.25.0"
|
||||||
|
},
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"url": "https://symfony.com/sponsor",
|
||||||
|
"type": "custom"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://github.com/fabpot",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
|
||||||
|
"type": "tidelift"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"time": "2021-11-23T21:10:46+00:00"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/polyfill-intl-idn",
|
"name": "symfony/polyfill-intl-idn",
|
||||||
"version": "v1.24.0",
|
"version": "v1.24.0",
|
||||||
|
@ -1256,6 +1634,89 @@
|
||||||
],
|
],
|
||||||
"time": "2021-02-19T12:13:01+00:00"
|
"time": "2021-02-19T12:13:01+00:00"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "symfony/polyfill-mbstring",
|
||||||
|
"version": "v1.25.0",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/symfony/polyfill-mbstring.git",
|
||||||
|
"reference": "0abb51d2f102e00a4eefcf46ba7fec406d245825"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/0abb51d2f102e00a4eefcf46ba7fec406d245825",
|
||||||
|
"reference": "0abb51d2f102e00a4eefcf46ba7fec406d245825",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"php": ">=7.1"
|
||||||
|
},
|
||||||
|
"provide": {
|
||||||
|
"ext-mbstring": "*"
|
||||||
|
},
|
||||||
|
"suggest": {
|
||||||
|
"ext-mbstring": "For best performance"
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"extra": {
|
||||||
|
"branch-alias": {
|
||||||
|
"dev-main": "1.23-dev"
|
||||||
|
},
|
||||||
|
"thanks": {
|
||||||
|
"name": "symfony/polyfill",
|
||||||
|
"url": "https://github.com/symfony/polyfill"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"autoload": {
|
||||||
|
"files": [
|
||||||
|
"bootstrap.php"
|
||||||
|
],
|
||||||
|
"psr-4": {
|
||||||
|
"Symfony\\Polyfill\\Mbstring\\": ""
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"MIT"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Nicolas Grekas",
|
||||||
|
"email": "p@tchwork.com"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Symfony Community",
|
||||||
|
"homepage": "https://symfony.com/contributors"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "Symfony polyfill for the Mbstring extension",
|
||||||
|
"homepage": "https://symfony.com",
|
||||||
|
"keywords": [
|
||||||
|
"compatibility",
|
||||||
|
"mbstring",
|
||||||
|
"polyfill",
|
||||||
|
"portable",
|
||||||
|
"shim"
|
||||||
|
],
|
||||||
|
"support": {
|
||||||
|
"source": "https://github.com/symfony/polyfill-mbstring/tree/v1.25.0"
|
||||||
|
},
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"url": "https://symfony.com/sponsor",
|
||||||
|
"type": "custom"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://github.com/fabpot",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
|
||||||
|
"type": "tidelift"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"time": "2021-11-30T18:21:41+00:00"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/polyfill-php72",
|
"name": "symfony/polyfill-php72",
|
||||||
"version": "v1.24.0",
|
"version": "v1.24.0",
|
||||||
|
@ -1332,6 +1793,338 @@
|
||||||
],
|
],
|
||||||
"time": "2021-05-27T09:17:38+00:00"
|
"time": "2021-05-27T09:17:38+00:00"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "symfony/polyfill-php73",
|
||||||
|
"version": "v1.25.0",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/symfony/polyfill-php73.git",
|
||||||
|
"reference": "cc5db0e22b3cb4111010e48785a97f670b350ca5"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/symfony/polyfill-php73/zipball/cc5db0e22b3cb4111010e48785a97f670b350ca5",
|
||||||
|
"reference": "cc5db0e22b3cb4111010e48785a97f670b350ca5",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"php": ">=7.1"
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"extra": {
|
||||||
|
"branch-alias": {
|
||||||
|
"dev-main": "1.23-dev"
|
||||||
|
},
|
||||||
|
"thanks": {
|
||||||
|
"name": "symfony/polyfill",
|
||||||
|
"url": "https://github.com/symfony/polyfill"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"autoload": {
|
||||||
|
"files": [
|
||||||
|
"bootstrap.php"
|
||||||
|
],
|
||||||
|
"psr-4": {
|
||||||
|
"Symfony\\Polyfill\\Php73\\": ""
|
||||||
|
},
|
||||||
|
"classmap": [
|
||||||
|
"Resources/stubs"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"MIT"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Nicolas Grekas",
|
||||||
|
"email": "p@tchwork.com"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Symfony Community",
|
||||||
|
"homepage": "https://symfony.com/contributors"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "Symfony polyfill backporting some PHP 7.3+ features to lower PHP versions",
|
||||||
|
"homepage": "https://symfony.com",
|
||||||
|
"keywords": [
|
||||||
|
"compatibility",
|
||||||
|
"polyfill",
|
||||||
|
"portable",
|
||||||
|
"shim"
|
||||||
|
],
|
||||||
|
"support": {
|
||||||
|
"source": "https://github.com/symfony/polyfill-php73/tree/v1.25.0"
|
||||||
|
},
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"url": "https://symfony.com/sponsor",
|
||||||
|
"type": "custom"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://github.com/fabpot",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
|
||||||
|
"type": "tidelift"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"time": "2021-06-05T21:20:04+00:00"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "symfony/polyfill-php80",
|
||||||
|
"version": "v1.25.0",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/symfony/polyfill-php80.git",
|
||||||
|
"reference": "4407588e0d3f1f52efb65fbe92babe41f37fe50c"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/4407588e0d3f1f52efb65fbe92babe41f37fe50c",
|
||||||
|
"reference": "4407588e0d3f1f52efb65fbe92babe41f37fe50c",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"php": ">=7.1"
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"extra": {
|
||||||
|
"branch-alias": {
|
||||||
|
"dev-main": "1.23-dev"
|
||||||
|
},
|
||||||
|
"thanks": {
|
||||||
|
"name": "symfony/polyfill",
|
||||||
|
"url": "https://github.com/symfony/polyfill"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"autoload": {
|
||||||
|
"files": [
|
||||||
|
"bootstrap.php"
|
||||||
|
],
|
||||||
|
"psr-4": {
|
||||||
|
"Symfony\\Polyfill\\Php80\\": ""
|
||||||
|
},
|
||||||
|
"classmap": [
|
||||||
|
"Resources/stubs"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"MIT"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Ion Bazan",
|
||||||
|
"email": "ion.bazan@gmail.com"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Nicolas Grekas",
|
||||||
|
"email": "p@tchwork.com"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Symfony Community",
|
||||||
|
"homepage": "https://symfony.com/contributors"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "Symfony polyfill backporting some PHP 8.0+ features to lower PHP versions",
|
||||||
|
"homepage": "https://symfony.com",
|
||||||
|
"keywords": [
|
||||||
|
"compatibility",
|
||||||
|
"polyfill",
|
||||||
|
"portable",
|
||||||
|
"shim"
|
||||||
|
],
|
||||||
|
"support": {
|
||||||
|
"source": "https://github.com/symfony/polyfill-php80/tree/v1.25.0"
|
||||||
|
},
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"url": "https://symfony.com/sponsor",
|
||||||
|
"type": "custom"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://github.com/fabpot",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
|
||||||
|
"type": "tidelift"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"time": "2022-03-04T08:16:47+00:00"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "symfony/service-contracts",
|
||||||
|
"version": "2.5.x-dev",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/symfony/service-contracts.git",
|
||||||
|
"reference": "24d9dc654b83e91aa59f9d167b131bc3b5bea24c"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/symfony/service-contracts/zipball/24d9dc654b83e91aa59f9d167b131bc3b5bea24c",
|
||||||
|
"reference": "24d9dc654b83e91aa59f9d167b131bc3b5bea24c",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"php": ">=7.2.5",
|
||||||
|
"psr/container": "^1.1",
|
||||||
|
"symfony/deprecation-contracts": "^2.1|^3"
|
||||||
|
},
|
||||||
|
"conflict": {
|
||||||
|
"ext-psr": "<1.1|>=2"
|
||||||
|
},
|
||||||
|
"suggest": {
|
||||||
|
"symfony/service-implementation": ""
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"extra": {
|
||||||
|
"branch-alias": {
|
||||||
|
"dev-main": "2.5-dev"
|
||||||
|
},
|
||||||
|
"thanks": {
|
||||||
|
"name": "symfony/contracts",
|
||||||
|
"url": "https://github.com/symfony/contracts"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"Symfony\\Contracts\\Service\\": ""
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"MIT"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Nicolas Grekas",
|
||||||
|
"email": "p@tchwork.com"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Symfony Community",
|
||||||
|
"homepage": "https://symfony.com/contributors"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "Generic abstractions related to writing services",
|
||||||
|
"homepage": "https://symfony.com",
|
||||||
|
"keywords": [
|
||||||
|
"abstractions",
|
||||||
|
"contracts",
|
||||||
|
"decoupling",
|
||||||
|
"interfaces",
|
||||||
|
"interoperability",
|
||||||
|
"standards"
|
||||||
|
],
|
||||||
|
"support": {
|
||||||
|
"source": "https://github.com/symfony/service-contracts/tree/2.5"
|
||||||
|
},
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"url": "https://symfony.com/sponsor",
|
||||||
|
"type": "custom"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://github.com/fabpot",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
|
||||||
|
"type": "tidelift"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"time": "2022-03-13T20:07:29+00:00"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "symfony/string",
|
||||||
|
"version": "5.4.x-dev",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/symfony/string.git",
|
||||||
|
"reference": "92043b7d8383e48104e411bc9434b260dbeb5a10"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/symfony/string/zipball/92043b7d8383e48104e411bc9434b260dbeb5a10",
|
||||||
|
"reference": "92043b7d8383e48104e411bc9434b260dbeb5a10",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"php": ">=7.2.5",
|
||||||
|
"symfony/polyfill-ctype": "~1.8",
|
||||||
|
"symfony/polyfill-intl-grapheme": "~1.0",
|
||||||
|
"symfony/polyfill-intl-normalizer": "~1.0",
|
||||||
|
"symfony/polyfill-mbstring": "~1.0",
|
||||||
|
"symfony/polyfill-php80": "~1.15"
|
||||||
|
},
|
||||||
|
"conflict": {
|
||||||
|
"symfony/translation-contracts": ">=3.0"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"symfony/error-handler": "^4.4|^5.0|^6.0",
|
||||||
|
"symfony/http-client": "^4.4|^5.0|^6.0",
|
||||||
|
"symfony/translation-contracts": "^1.1|^2",
|
||||||
|
"symfony/var-exporter": "^4.4|^5.0|^6.0"
|
||||||
|
},
|
||||||
|
"default-branch": true,
|
||||||
|
"type": "library",
|
||||||
|
"autoload": {
|
||||||
|
"files": [
|
||||||
|
"Resources/functions.php"
|
||||||
|
],
|
||||||
|
"psr-4": {
|
||||||
|
"Symfony\\Component\\String\\": ""
|
||||||
|
},
|
||||||
|
"exclude-from-classmap": [
|
||||||
|
"/Tests/"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"MIT"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Nicolas Grekas",
|
||||||
|
"email": "p@tchwork.com"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Symfony Community",
|
||||||
|
"homepage": "https://symfony.com/contributors"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "Provides an object-oriented API to strings and deals with bytes, UTF-8 code points and grapheme clusters in a unified way",
|
||||||
|
"homepage": "https://symfony.com",
|
||||||
|
"keywords": [
|
||||||
|
"grapheme",
|
||||||
|
"i18n",
|
||||||
|
"string",
|
||||||
|
"unicode",
|
||||||
|
"utf-8",
|
||||||
|
"utf8"
|
||||||
|
],
|
||||||
|
"support": {
|
||||||
|
"source": "https://github.com/symfony/string/tree/v5.4.3"
|
||||||
|
},
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"url": "https://symfony.com/sponsor",
|
||||||
|
"type": "custom"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://github.com/fabpot",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
|
||||||
|
"type": "tidelift"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"time": "2022-01-02T09:53:40+00:00"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "vearutop/php-obscene-censor-rus",
|
"name": "vearutop/php-obscene-censor-rus",
|
||||||
"version": "dev-master",
|
"version": "dev-master",
|
||||||
|
@ -1562,11 +2355,14 @@
|
||||||
"chillerlan/php-qrcode": 20,
|
"chillerlan/php-qrcode": 20,
|
||||||
"vearutop/php-obscene-censor-rus": 20,
|
"vearutop/php-obscene-censor-rus": 20,
|
||||||
"erusev/parsedown": 20,
|
"erusev/parsedown": 20,
|
||||||
"bhaktaraz/php-rss-generator": 20
|
"bhaktaraz/php-rss-generator": 20,
|
||||||
|
"symfony/console": 20
|
||||||
},
|
},
|
||||||
"prefer-stable": false,
|
"prefer-stable": false,
|
||||||
"prefer-lowest": false,
|
"prefer-lowest": false,
|
||||||
"platform": [],
|
"platform": {
|
||||||
|
"ext-simplexml": "*"
|
||||||
|
},
|
||||||
"platform-dev": [],
|
"platform-dev": [],
|
||||||
"plugin-api-version": "2.0.0"
|
"plugin-api-version": "2.1.0"
|
||||||
}
|
}
|
||||||
|
|
13
data/photosizes.xml
Normal file
13
data/photosizes.xml
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<PhotoSizes name="standard">
|
||||||
|
<Size id="miniscule" vkId="s" maxSize="75" requireProp="none" />
|
||||||
|
<Size id="tiny" vkId="m" maxSize="130" requireProp="none" />
|
||||||
|
<Size id="tinier" vkId="o" maxSize="130" requireProp="3:2" />
|
||||||
|
<Size id="xsmall" vkId="p" maxSize="200" requireProp="3:2" />
|
||||||
|
<Size id="small" vkId="q" maxSize="320" requireProp="3:2" />
|
||||||
|
<Size id="medium" vkId="r" maxSize="510" requireProp="3:2" />
|
||||||
|
<Size id="normal" vkId="x" maxSize="604" requireProp="none" />
|
||||||
|
<Size id="large" vkId="y" maxSize="807" requireProp="none" />
|
||||||
|
<Size id="larger" vkId="z" maxResolution="1080x1024" requireProp="none" />
|
||||||
|
<Size id="original" vkId="w" maxResolution="2560x2048" requireProp="none" />
|
||||||
|
</PhotoSizes>
|
1
install/sqls/00019-block-in-support.sql
Normal file
1
install/sqls/00019-block-in-support.sql
Normal file
|
@ -0,0 +1 @@
|
||||||
|
ALTER TABLE `profiles` ADD COLUMN `block_in_support_reason` text COLLATE utf8mb4_unicode_520_ci DEFAULT NULL AFTER `block_reason`;
|
3
install/sqls/00020-image-sizes.sql
Normal file
3
install/sqls/00020-image-sizes.sql
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
ALTER TABLE `photos` ROW_FORMAT=COMPRESSED;
|
||||||
|
ALTER TABLE `photos` ADD COLUMN `sizes` VARBINARY(486) NULL DEFAULT NULL AFTER `hash`;
|
||||||
|
ALTER TABLE `photos` ADD COLUMN `width` SMALLINT UNSIGNED NULL DEFAULT NULL AFTER `sizes`, ADD COLUMN `height` SMALLINT UNSIGNED NULL DEFAULT NULL AFTER `sizes`;
|
|
@ -693,6 +693,9 @@
|
||||||
"ticket_changed" = "Ticket changed";
|
"ticket_changed" = "Ticket changed";
|
||||||
"ticket_changed_comment" = "The changes will take effect in a few seconds.";
|
"ticket_changed_comment" = "The changes will take effect in a few seconds.";
|
||||||
|
|
||||||
|
"banned_in_support_1" = "Sorry, <b>$1</b>, but now you can't create tickets.";
|
||||||
|
"banned_in_support_2" = "And the reason for this is simple: <b>$1</b>. Unfortunately, this time we had to take away this opportunity from you forever.";
|
||||||
|
|
||||||
/* Invite */
|
/* Invite */
|
||||||
|
|
||||||
"invite" = "Invite";
|
"invite" = "Invite";
|
||||||
|
@ -836,7 +839,10 @@
|
||||||
"manage_user_action" = "Manage user";
|
"manage_user_action" = "Manage user";
|
||||||
"manage_group_action" = "Manage group";
|
"manage_group_action" = "Manage group";
|
||||||
"ban_user_action" = "Ban user";
|
"ban_user_action" = "Ban user";
|
||||||
|
"unban_user_action" = "Unban user";
|
||||||
"warn_user_action" = "Warn user";
|
"warn_user_action" = "Warn user";
|
||||||
|
"ban_in_support_user_action" = "Ban in support";
|
||||||
|
"unban_in_support_user_action" = "Unban in support";
|
||||||
|
|
||||||
/* Paginator (deprecated) */
|
/* Paginator (deprecated) */
|
||||||
|
|
||||||
|
|
|
@ -398,7 +398,7 @@
|
||||||
|
|
||||||
"default" = "әдепкі";
|
"default" = "әдепкі";
|
||||||
|
|
||||||
"arbitrary_avatars" = "Ерікті"
|
"arbitrary_avatars" = "Ерікті";
|
||||||
"cut" = "Шаршы";
|
"cut" = "Шаршы";
|
||||||
"round_avatars" = "Дөңгелек";
|
"round_avatars" = "Дөңгелек";
|
||||||
|
|
||||||
|
|
|
@ -730,6 +730,9 @@
|
||||||
"ticket_changed" = "Тикет изменён";
|
"ticket_changed" = "Тикет изменён";
|
||||||
"ticket_changed_comment" = "Изменения вступят силу через несколько секунд.";
|
"ticket_changed_comment" = "Изменения вступят силу через несколько секунд.";
|
||||||
|
|
||||||
|
"banned_in_support_1" = "Извините, <b>$1</b>, но теперь вам нельзя создавать обращения.";
|
||||||
|
"banned_in_support_2" = "А причина этому проста: <b>$1</b>. К сожалению, на этот раз нам пришлось отобрать у вас эту возможность навсегда.";
|
||||||
|
|
||||||
/* Invite */
|
/* Invite */
|
||||||
|
|
||||||
"invite" = "Пригласить";
|
"invite" = "Пригласить";
|
||||||
|
@ -879,7 +882,10 @@
|
||||||
"manage_user_action" = "Управление пользователем";
|
"manage_user_action" = "Управление пользователем";
|
||||||
"manage_group_action" = "Управление группой";
|
"manage_group_action" = "Управление группой";
|
||||||
"ban_user_action" = "Заблокировать пользователя";
|
"ban_user_action" = "Заблокировать пользователя";
|
||||||
|
"unban_user_action" = "Разблокировать пользователя";
|
||||||
"warn_user_action" = "Предупредить пользователя";
|
"warn_user_action" = "Предупредить пользователя";
|
||||||
|
"ban_in_support_user_action" = "Заблокировать в поддержке";
|
||||||
|
"unban_in_support_user_action" = "Разблокировать в поддержке";
|
||||||
|
|
||||||
/* Paginator (deprecated) */
|
/* Paginator (deprecated) */
|
||||||
|
|
||||||
|
|
|
@ -255,6 +255,7 @@
|
||||||
"hidden_yes" = "Скрыт: Да";
|
"hidden_yes" = "Скрыт: Да";
|
||||||
"hidden_no" = "Скрыт: Нет";
|
"hidden_no" = "Скрыт: Нет";
|
||||||
"group_allow_post_for_everyone" = "Разрешить публиковать записи всем";
|
"group_allow_post_for_everyone" = "Разрешить публиковать записи всем";
|
||||||
|
"group_hide_from_global_feed" = "Не отображать записи в публичной доске";
|
||||||
"statistics" = "Статистика";
|
"statistics" = "Статистика";
|
||||||
"group_administrators_list" = "Список админов";
|
"group_administrators_list" = "Список админов";
|
||||||
"group_display_only_creator" = "Отображать только создателя группы";
|
"group_display_only_creator" = "Отображать только создателя группы";
|
||||||
|
@ -430,7 +431,7 @@
|
||||||
"ui_settings_rating_hide" = "Скрывать";
|
"ui_settings_rating_hide" = "Скрывать";
|
||||||
|
|
||||||
"additional_links" = "Дополнительные ссылки";
|
"additional_links" = "Дополнительные ссылки";
|
||||||
|
"ad_poster" = "Рекламный плакат";
|
||||||
/* Two-factor authentication */
|
/* Two-factor authentication */
|
||||||
|
|
||||||
"two_factor_authentication" = "Двухфакторная аутентификация";
|
"two_factor_authentication" = "Двухфакторная аутентификация";
|
||||||
|
@ -609,6 +610,21 @@
|
||||||
|
|
||||||
/* Support */
|
/* Support */
|
||||||
|
|
||||||
|
"increase_rating" = "Увеличить рейтинг";
|
||||||
|
"increase_rating_button" = "Увеличить";
|
||||||
|
"to_whom" = "Кому";
|
||||||
|
"increase_by" = "Увеличить на";
|
||||||
|
"price" = "Ценник";
|
||||||
|
|
||||||
|
"you_have_unused_votes" = "У Вас $1 неиспользованных рубля на кошельке.";
|
||||||
|
"apply_voucher" = "Применить купон";
|
||||||
|
|
||||||
|
"failed_to_increase_rating" = "Не удалось увеличить рейтинг";
|
||||||
|
"rating_increase_successful" = "Вы успешно увеличили рейтинг <b><a href=\"$1\">$2</a></b> на <b>$3%</b>.";
|
||||||
|
"negative_rating_value" = "Орган не может украсть баллы рейтинга у другого гражданина, так не положено.";
|
||||||
|
|
||||||
|
"increased_your_rating_by" = "увеличил ваш рейтинг на";
|
||||||
|
|
||||||
"support_opened" = "Открытые";
|
"support_opened" = "Открытые";
|
||||||
"support_answered" = "С ответом";
|
"support_answered" = "С ответом";
|
||||||
"support_closed" = "Закрытые";
|
"support_closed" = "Закрытые";
|
||||||
|
@ -759,7 +775,7 @@
|
||||||
"token_manipulation_error" = "Ошибка манипулирования токеном";
|
"token_manipulation_error" = "Ошибка манипулирования токеном";
|
||||||
"token_manipulation_error_comment" = "Токен недействителен или истёк";
|
"token_manipulation_error_comment" = "Токен недействителен или истёк";
|
||||||
|
|
||||||
"profile_changed" = "Досье изменёно";
|
"profile_changed" = "Досье изменено";
|
||||||
"profile_changed_comment" = "Товарищ, орган одобрил изменение вашего досье.";
|
"profile_changed_comment" = "Товарищ, орган одобрил изменение вашего досье.";
|
||||||
"profile_not_found" = "Гражданин не найден.";
|
"profile_not_found" = "Гражданин не найден.";
|
||||||
|
|
||||||
|
@ -795,6 +811,36 @@
|
||||||
/* About */
|
/* About */
|
||||||
|
|
||||||
"about_openvk" = "Об органе OpenVK";
|
"about_openvk" = "Об органе OpenVK";
|
||||||
|
"footer_about_instance" = "о стране";
|
||||||
|
"about_this_instance" = "Об этой стране";
|
||||||
|
"rules" = "Правила";
|
||||||
|
"most_popular_groups" = "Самые популярные клубы";
|
||||||
|
"on_this_instance_are" = "На этой стране";
|
||||||
|
|
||||||
|
"about_users_one" = "<b>1</b> гражданин";
|
||||||
|
"about_users_few" = "<b>$1</b> гражданина";
|
||||||
|
"about_users_many" = "<b>$1</b> гражданинов";
|
||||||
|
"about_users_other" = "<b>$1</b> гражданинов";
|
||||||
|
|
||||||
|
"about_online_users_one" = "<b>1</b> пользователь в сети";
|
||||||
|
"about_online_users_few" = "<b>$1</b> пользователя в сети";
|
||||||
|
"about_online_users_many" = "<b>$1</b> гражданинов в сети";
|
||||||
|
"about_online_users_other" = "<b>$1</b> гражданинов в сети";
|
||||||
|
|
||||||
|
"about_active_users_one" = "<b>1</b> активный пользователь";
|
||||||
|
"about_active_users_few" = "<b>$1</b> активных пользователя";
|
||||||
|
"about_active_users_many" = "<b>$1</b> активных гражданинов";
|
||||||
|
"about_active_users_other" = "<b>$1</b> активных гражданинов";
|
||||||
|
|
||||||
|
"about_groups_one" = "<b>1</b> клуб";
|
||||||
|
"about_groups_few" = "<b>$1</b> клубы";
|
||||||
|
"about_groups_many" = "<b>$1</b> клубов";
|
||||||
|
"about_groups_other" = "<b>$1</b> клубов";
|
||||||
|
|
||||||
|
"about_wall_posts_one" = "<b>1</b> заметка на досках";
|
||||||
|
"about_wall_posts_few" = "<b>$1</b> заметки на досках";
|
||||||
|
"about_wall_posts_many" = "<b>$1</b> заметки на досках";
|
||||||
|
"about_wall_posts_other" = "<b>$1</b> заметки на досках";
|
||||||
|
|
||||||
/* Dialogs */
|
/* Dialogs */
|
||||||
|
|
||||||
|
@ -810,5 +856,20 @@
|
||||||
"question_confirm" = "Товарищ, будьте внимательны с выбором. Вы согласны с вашим выбором? Отменить не представляется возможным.";
|
"question_confirm" = "Товарищ, будьте внимательны с выбором. Вы согласны с вашим выбором? Отменить не представляется возможным.";
|
||||||
|
|
||||||
/* User alerts */
|
/* User alerts */
|
||||||
|
"apply_style_for_this_device" = "Применить стиль только для этой ЭВМ";
|
||||||
|
|
||||||
"user_alert_scam" = "Органу управления было дозволено, что данный гражданин обманывает товарищей на денежные средства. Будьте осторожны при разговоре с ним.";
|
"user_alert_scam" = "Органу управления было дозволено, что данный гражданин обманывает товарищей на денежные средства. Будьте осторожны при разговоре с ним.";
|
||||||
|
|
||||||
|
|
||||||
|
"ec_header" = "Подтверждение регистрации прописки";
|
||||||
|
"ec_title" = "Спасибо!";
|
||||||
|
"ec_1" = "<b>$1</b>, на ваш почтовый ящик должно придти письмо с подтверждением регистрации.";
|
||||||
|
"ec_2" = "Если по каким-то причинам вам не пришло письмо, то проверьте мусорный бак. Если письма не окажется и там, то вы можете переотправить письмо.";
|
||||||
|
"ec_resend" = "Переотправить письмо";
|
||||||
|
|
||||||
|
"email_sent" = "Письмо было успешно отправлено.";
|
||||||
|
"email_sent_desc" = "Если ваш почтовый ящик существует, вы получите письмо.";
|
||||||
|
"email_error" = "Непредвиденная ошибка при отправке письма.";
|
||||||
|
"email_rate_limit_error" = "Нельзя делать это так часто, извините.";
|
||||||
|
|
||||||
|
"email_verify_success" = "Ваша регистрация была подтверждена. Приятного времяпрепровождения!";
|
|
@ -6,13 +6,19 @@ openvk:
|
||||||
|
|
||||||
preferences:
|
preferences:
|
||||||
femaleGenderPriority: true
|
femaleGenderPriority: true
|
||||||
|
nginxCacheTime: null
|
||||||
uploads:
|
uploads:
|
||||||
disableLargeUploads: false
|
disableLargeUploads: false
|
||||||
mode: "basic"
|
mode: "basic"
|
||||||
|
api:
|
||||||
|
maxFilesPerDomain: 10
|
||||||
|
maxFileSize: 25000000
|
||||||
shortcodes:
|
shortcodes:
|
||||||
minLength: 3 # won't affect existing short urls or the ones set via admin panel
|
minLength: 3 # won't affect existing short urls or the ones set via admin panel
|
||||||
forbiddenNames:
|
forbiddenNames:
|
||||||
- "index.php"
|
- "index.php"
|
||||||
|
photos:
|
||||||
|
upgradeStructure: true
|
||||||
security:
|
security:
|
||||||
requireEmail: false
|
requireEmail: false
|
||||||
requirePhone: false
|
requirePhone: false
|
||||||
|
@ -66,6 +72,15 @@ openvk:
|
||||||
enable: false
|
enable: false
|
||||||
domain: ""
|
domain: ""
|
||||||
server: ""
|
server: ""
|
||||||
|
piwik:
|
||||||
|
enable: false
|
||||||
|
container: ""
|
||||||
|
site: ""
|
||||||
|
layer: "dataLayer"
|
||||||
|
matomo:
|
||||||
|
enable: false
|
||||||
|
container: ""
|
||||||
|
site: ""
|
||||||
|
|
||||||
credentials:
|
credentials:
|
||||||
smsc:
|
smsc:
|
||||||
|
|
13
openvkctl
Executable file
13
openvkctl
Executable file
|
@ -0,0 +1,13 @@
|
||||||
|
#!/usr/bin/env php
|
||||||
|
<?php declare(strict_types=1);
|
||||||
|
namespace openvk;
|
||||||
|
use Symfony\Component\Console\Application;
|
||||||
|
|
||||||
|
$_SERVER["HTTP_ACCEPT_LANGUAGE"] = false;
|
||||||
|
$bootstrap = require(__DIR__ . "/../../../chandler/Bootstrap.php");
|
||||||
|
$bootstrap->ignite(true);
|
||||||
|
|
||||||
|
$application = new Application();
|
||||||
|
$application->add(new CLI\RebuildImagesCommand);
|
||||||
|
|
||||||
|
$application->run();
|
0
tmp/api-storage/photos/.gitkeep
Normal file
0
tmp/api-storage/photos/.gitkeep
Normal file
0
tmp/api-storage/videos/.gitkeep
Normal file
0
tmp/api-storage/videos/.gitkeep
Normal file
Loading…
Reference in a new issue