diff --git a/Web/Models/Entities/GeodbCity.php b/Web/Models/Entities/GeodbCity.php
new file mode 100644
index 000000000..fc9d95a29
--- /dev/null
+++ b/Web/Models/Entities/GeodbCity.php
@@ -0,0 +1,67 @@
+getRecord()->id;
+ }
+
+ function getCountry(): GeodbCountry
+ {
+ return (new GeodbCountries)->get($this->getRecord()->country);
+ }
+
+ function getName(): string
+ {
+ return $this->getRecord()->name;
+ }
+
+ function getNativeName(): ?string
+ {
+ return $this->getRecord()->native_name;
+ }
+
+ function getCanonicalName(): string
+ {
+ return $this->getNativeName() ?? $this->getName();
+ }
+
+ function getSimplified(): array
+ {
+ return [
+ "id" => $this->getId(),
+ "name" => $this->getName(),
+ "native_name" => $this->getNativeName()
+ ];
+ }
+
+ function getRequestSender(): ?User
+ {
+ return (new Users)->get((int) $this->getRecord()->is_request);
+ }
+
+ function save(User $user, $table): void
+ {
+ if(is_null($this->record)) {
+ $this->record = $table->insert($this->changes);
+ (new GeodbLogs)->create($user, $this->tableName, 0, $this->getRecord()->toArray(), $this->changes);
+ } else if($this->deleted) {
+ (new GeodbLogs)->create($user, $this->tableName, 2, $this, $this->changes);
+ $this->record = $table->insert((array) $this->record);
+ } else {
+ (new GeodbLogs)->create($user, $this->tableName, 1, $this, $this->changes);
+ $table->get($this->record->id)->update($this->changes);
+ $this->record = $table->get($this->record->id);
+ }
+
+ $this->changes = [];
+ }
+}
diff --git a/Web/Models/Entities/GeodbCountry.php b/Web/Models/Entities/GeodbCountry.php
new file mode 100644
index 000000000..ca6f29c1f
--- /dev/null
+++ b/Web/Models/Entities/GeodbCountry.php
@@ -0,0 +1,114 @@
+getRecord()->id;
+ }
+
+ function getCode(): string
+ {
+ return $this->getRecord()->code;
+ }
+
+ function getFlagURL(): string
+ {
+ return "/assets/packages/static/openvk/img/flags/" . $this->getRecord()->flag . ".gif";
+ }
+
+ function getName(): string
+ {
+ return $this->getRecord()->name;
+ }
+
+ function getNativeName(): ?string
+ {
+ return $this->getRecord()->native_name;
+ }
+
+ function getCanonicalName(): string
+ {
+ return $this->getNativeName() ?? $this->getName();
+ }
+
+ function getEditors(): \Traversable
+ {
+ return (new GeodbRights)->getList(NULL, $this->getId());
+ }
+
+ function getUserRights(int $user_id): ?GeodbEditor
+ {
+ return (new GeodbRights)->getCountryPermission($user_id, $this->getId());
+ }
+
+ function isUserCanEditEducation(int $user_id): bool
+ {
+ $rights = $this->getUserRights($user_id);
+ if (!$rights) return false;
+
+ return $rights->canEditEducation();
+ }
+
+ function isUserCanEditCities(int $user_id): bool
+ {
+ $rights = $this->getUserRights($user_id);
+ if (!$rights) return false;
+
+ return $rights->canEditCities();
+ }
+
+ function getSimplified(): array
+ {
+ return [
+ "id" => $this->getId(),
+ "name" => $this->getName(),
+ "native_name" => $this->getNativeName()
+ ];
+ }
+
+ function getCitiesCount(): int
+ {
+ return count(iterator_to_array((new GeodbCities)->getList($this->getId())));
+ }
+
+ function getSchoolsCount(): int
+ {
+ return count(iterator_to_array((new GeodbEducation)->getSchools($this->getId())));
+ }
+
+ function getUniversitiesCount(): int
+ {
+ return count(iterator_to_array((new GeodbEducation)->getUniversities($this->getId())));
+ }
+
+ function getFlagCode(): string
+ {
+ return $this->getRecord()->flag;
+ }
+
+ function save(User $user, $table, ?bool $new = false): void
+ {
+ if(is_null($this->record)) {
+ $this->record = $table->insert($this->changes);
+ (new GeodbLogs)->create($user, $this->tableName, 0, $this->getRecord()->toArray(), $this->changes);
+ } else if($this->deleted) {
+ (new GeodbLogs)->create($user, $this->tableName, 2, $this, $this->changes, $new);
+ $this->record = $table->insert((array) $this->record);
+ } else {
+ (new GeodbLogs)->create($user, $this->tableName, 1, $this, $this->changes, $new);
+ $table->get($this->record->id)->update($this->changes);
+ $this->record = $table->get($this->record->id);
+ }
+
+ $this->changes = [];
+ }
+}
diff --git a/Web/Models/Entities/GeodbEditor.php b/Web/Models/Entities/GeodbEditor.php
new file mode 100644
index 000000000..f9bccbae1
--- /dev/null
+++ b/Web/Models/Entities/GeodbEditor.php
@@ -0,0 +1,58 @@
+getRecord()->id;
+ }
+
+ function getUser(): User
+ {
+ return (new Users)->get((int) $this->getRecord()->uid);
+ }
+
+ function getCountry(): ?GeodbCountry
+ {
+ return (new GeodbCountries)->get((int) $this->getRecord()->country);
+ }
+
+ function canEditEducation(): bool
+ {
+ return (bool) $this->getRecord()->edu;
+ }
+
+ function canEditCities(): bool
+ {
+ return (bool) $this->getRecord()->cities;
+ }
+
+ function save(User $user, $table): void
+ {
+ if(is_null($this->record)) {
+ $this->record = $table->insert($this->changes);
+ (new GeodbLogs)->create($user, $this->tableName, 0, $this->getRecord()->toArray(), $this->changes);
+ } else if($this->deleted) {
+ (new GeodbLogs)->create($user, $this->tableName, 2, $this, $this->changes);
+ $this->record = $table->insert((array) $this->record);
+ } else {
+ (new GeodbLogs)->create($user, $this->tableName, 1, $this, $this->changes);
+ $table->get($this->record->id)->update($this->changes);
+ $this->record = $table->get($this->record->id);
+ }
+
+ $this->changes = [];
+ }
+
+ function getName(): string
+ {
+ return $this->getUser()->getCanonicalName() . " (" . ($this->getCountry()->getCanonicalName()) . ")";
+ }
+}
diff --git a/Web/Models/Entities/GeodbFaculty.php b/Web/Models/Entities/GeodbFaculty.php
new file mode 100644
index 000000000..9b1942b7f
--- /dev/null
+++ b/Web/Models/Entities/GeodbFaculty.php
@@ -0,0 +1,74 @@
+getRecord()->id;
+ }
+
+ function getUniversity(): GeodbUniversity
+ {
+ return (new GeodbEducation)->getUniversity((int) $this->getRecord()->university);
+ }
+
+ function getName(): string
+ {
+ return $this->getRecord()->name;
+ }
+
+ function getSimplified(): array
+ {
+ return [
+ "id" => $this->getId(),
+ "name" => $this->getName()
+ ];
+ }
+
+ function getSpecializations(?bool $needDeleted = false, ?bool $simplified = false): \Traversable
+ {
+ return (new GeodbSpecializations)->getList($this->getId(), $needDeleted, $simplified);
+ }
+
+ function getRequestSender(): ?User
+ {
+ return (new Users)->get((int) $this->getRecord()->is_request);
+ }
+
+ function getCountry(): ?GeodbCountry
+ {
+ return $this->getUniversity()->getCountry();
+ }
+
+ function getCity(): ?GeodbCity
+ {
+ return $this->getUniversity()->getCity();
+ }
+
+ function save(User $user, $table): void
+ {
+ if(is_null($this->record)) {
+ $this->record = $table->insert($this->changes);
+ (new GeodbLogs)->create($user, $this->tableName, 0, $this->getRecord()->toArray(), $this->changes);
+ } else if($this->deleted) {
+ (new GeodbLogs)->create($user, $this->tableName, 2, $this, $this->changes);
+ $this->record = $table->insert((array) $this->record);
+ } else {
+ (new GeodbLogs)->create($user, $this->tableName, 1, $this, $this->changes);
+ $table->get($this->record->id)->update($this->changes);
+ $this->record = $table->get($this->record->id);
+ }
+
+ $this->changes = [];
+ }
+}
diff --git a/Web/Models/Entities/GeodbLog.php b/Web/Models/Entities/GeodbLog.php
new file mode 100644
index 000000000..67204c6c2
--- /dev/null
+++ b/Web/Models/Entities/GeodbLog.php
@@ -0,0 +1,81 @@
+getRecord()->id;
+ }
+
+ function getUser(): ?User
+ {
+ return (new Users)->get((int) $this->getRecord()->user);
+ }
+
+ function getObjectTable(): string
+ {
+ return $this->getRecord()->object_table;
+ }
+
+ function getObjectId(): int
+ {
+ return $this->getRecord()->object_id;
+ }
+
+ function getObject()
+ {
+ $model = $this->getRecord()->object_model;
+ return new $model(DatabaseConnection::i()->getContext()->table($this->getObjectTable())->get($this->getObjectId()));
+ }
+
+ function getType(): string
+ {
+ return ["добавил", "отредактировал", "удалил", "восстановил"][$this->getRecord()->type];
+ }
+
+ function getObjectType(): string
+ {
+ return [
+ "geodb_countries" => "страну",
+ "geodb_cities" => "город",
+ "geodb_schools" => "школу",
+ "geodb_universities" => "университет",
+ "geodb_faculties" => "факультет",
+ "geodb_specializations" => "специальность",
+ "geodb_editors" => "редактора базы",
+ ][$this->getRecord()->object_table];
+ }
+
+ function getObjectName(): string
+ {
+ return in_array($this->getObjectTable(), ["geodb_cities", "geodb_countries"]) ? $this->getObject()->getNativeName() : $this->getObject()->getName();
+ }
+
+ function getLogsText(): string
+ {
+ return $this->getRecord()->logs_text;
+ }
+
+ function getObjectURL(): string
+ {
+ switch ($this->getObjectTable()) {
+ case "geodb_countries": return "/editdb?act=country&id=" . $this->getObjectId();
+ case "geodb_cities": return "/editdb?act=city&id=" . $this->getObjectId();
+ case "geodb_schools": return "/editdb?act=school&id=" . $this->getObjectId();
+ case "geodb_universities": return "/editdb?act=university&id=" . $this->getObjectId();
+ case "geodb_editors": return $this->getObject()->getUser()->getURL();
+ case "geodb_faculties" || "geodb_specializations": return "/editdb?act=university&id=" . $this->getObject()->getUniversity()->getId();
+ default: return "/err404.php?id=" . $this->getObjectId();
+ }
+ }
+}
diff --git a/Web/Models/Entities/GeodbSchool.php b/Web/Models/Entities/GeodbSchool.php
new file mode 100644
index 000000000..5963afaa6
--- /dev/null
+++ b/Web/Models/Entities/GeodbSchool.php
@@ -0,0 +1,62 @@
+getRecord()->id;
+ }
+
+ function getCountry(): GeodbCountry
+ {
+ return (new GeodbCountries)->get($this->getRecord()->country);
+ }
+
+ function getCity(): GeodbCity
+ {
+ return (new GeodbCities)->get($this->getRecord()->city);
+ }
+
+ function getName(): string
+ {
+ return $this->getRecord()->name;
+ }
+
+ function getSimplified(): array
+ {
+ return [
+ "id" => $this->getId(),
+ "name" => $this->getName()
+ ];
+ }
+
+ function getRequestSender(): ?User
+ {
+ return (new Users)->get((int) $this->getRecord()->is_request);
+ }
+
+ function save(User $user, $table): void
+ {
+ if(is_null($this->record)) {
+ $this->record = $table->insert($this->changes);
+ (new GeodbLogs)->create($user, $this->tableName, 0, $this->getRecord()->toArray(), $this->changes);
+ } else if($this->deleted) {
+ (new GeodbLogs)->create($user, $this->tableName, 2, $this, $this->changes);
+ $this->record = $table->insert((array) $this->record);
+ } else {
+ (new GeodbLogs)->create($user, $this->tableName, 1, $this, $this->changes);
+ $table->get($this->record->id)->update($this->changes);
+ $this->record = $table->get($this->record->id);
+ }
+
+ $this->changes = [];
+ }
+}
diff --git a/Web/Models/Entities/GeodbSpecialization.php b/Web/Models/Entities/GeodbSpecialization.php
new file mode 100644
index 000000000..d7cd07ca7
--- /dev/null
+++ b/Web/Models/Entities/GeodbSpecialization.php
@@ -0,0 +1,71 @@
+getRecord()->id;
+ }
+
+ function getName(): string
+ {
+ return $this->getRecord()->name;
+ }
+
+ function getFaculty(): GeodbFaculty
+ {
+ return (new GeodbFaculties)->get((int) $this->getRecord()->faculty);
+ }
+
+ function getUniversity(): GeodbUniversity
+ {
+ return $this->getFaculty()->getUniversity();
+ }
+
+ function getRequestSender(): ?User
+ {
+ return (new Users)->get((int) $this->getRecord()->is_request);
+ }
+
+ function getCity(): ?GeodbCity
+ {
+ return $this->getUniversity()->getCity();
+ }
+
+ function getCountry(): ?GeodbCountry
+ {
+ return $this->getUniversity()->getCountry();
+ }
+
+ function getSimplified(): array
+ {
+ return [ "id" => $this->getId(), "name" => $this->getName() ];
+ }
+
+ function save(User $user, $table): void
+ {
+ if(is_null($this->record)) {
+ $this->record = $table->insert($this->changes);
+ (new GeodbLogs)->create($user, $this->tableName, 0, $this->getRecord()->toArray(), $this->changes);
+ } else if($this->deleted) {
+ (new GeodbLogs)->create($user, $this->tableName, 2, $this, $this->changes);
+ $this->record = $table->insert((array) $this->record);
+ } else {
+ (new GeodbLogs)->create($user, $this->tableName, 1, $this, $this->changes);
+ $table->get($this->record->id)->update($this->changes);
+ $this->record = $table->get($this->record->id);
+ }
+
+ $this->changes = [];
+ }
+}
diff --git a/Web/Models/Entities/GeodbUniversity.php b/Web/Models/Entities/GeodbUniversity.php
new file mode 100644
index 000000000..ce9af8a13
--- /dev/null
+++ b/Web/Models/Entities/GeodbUniversity.php
@@ -0,0 +1,18 @@
+getList($this->getId(), $need_deleted);
+ foreach ($faculties as $faculty) {
+ $response = $faculty;
+ if ($simplified) $response = $response->getSimplified();
+ yield $response;
+ }
+ }
+}
diff --git a/Web/Models/Entities/User.php b/Web/Models/Entities/User.php
index 348631e42..aa0e9675c 100644
--- a/Web/Models/Entities/User.php
+++ b/Web/Models/Entities/User.php
@@ -5,7 +5,18 @@
use openvk\Web\Util\DateTime;
use openvk\Web\Models\RowModel;
use openvk\Web\Models\Entities\{Photo, Message, Correspondence, Gift};
-use openvk\Web\Models\Repositories\{Photos, Users, Clubs, Albums, Gifts, Notifications};
+use openvk\Web\Models\Repositories\{GeodbCities,
+ GeodbCountries,
+ GeodbEducation,
+ GeodbFaculties,
+ GeodbRights,
+ GeodbSpecializations,
+ Photos,
+ Users,
+ Clubs,
+ Albums,
+ Gifts,
+ Notifications};
use openvk\Web\Models\Exceptions\InvalidUserNameException;
use Nette\Database\Table\ActiveRow;
use Chandler\Database\DatabaseConnection;
@@ -349,9 +360,31 @@ function getFavoriteQuote(): ?string
return $this->getRecord()->fav_quote;
}
- function getCity(): ?string
+ function getCity(?bool $for_option = false)
{
- return $this->getRecord()->city;
+ $id = (int) $this->getRecord()->city_id;
+ $city = (new GeodbCities)->get($id);
+
+ if ($for_option) {
+ if (!$city) return null;
+ return ["id" => $city->getId(), "name" => $city->getName(), "native_name" => $city->getNativeName()];
+ } else {
+ if ($city && !$city->isDeleted()) return $city->getCanonicalName();
+ else return "DELETED";
+ }
+ }
+
+ function getCountry(?bool $for_option = false)
+ {
+ $id = (int) $this->getRecord()->country_id;
+ $country = (new GeodbCountries)->get($id);
+ if (!$country) return null;
+
+ if ($for_option) {
+ return ["id" => $country->getId(), "name" => $country->getName(), "native_name" => $country->getNativeName()];
+ } else {
+ return ($country->getCanonicalName() ?? "DELETED");
+ }
}
function getPhysicalAddress(): ?string
@@ -1031,7 +1064,7 @@ function changeEmail(string $email): void
function adminNotify(string $message): bool
{
- $admId = OPENVK_ROOT_CONF["openvk"]["preferences"]["support"]["adminAccount"];
+ $admId = (int) OPENVK_ROOT_CONF["openvk"]["preferences"]["support"]["adminAccount"];
if(!$admId)
return false;
else if(is_null($admin = (new Users)->get($admId)))
@@ -1126,6 +1159,50 @@ function toVkApiStruct(): object
return $res;
}
+
+ function canEditGeodb(): bool
+ {
+ return sizeof((new GeodbRights)->getList($this->getId())) > 0 || $this->getChandlerUser()->can("write")->model("openvk\Web\Models\Entities\GeodbCountry")->whichBelongsTo(0);
+ }
+
+ function getSchool(): ?GeodbSchool
+ {
+ return (new GeodbEducation)->getSchool((int) $this->getRecord()->school_id);
+ }
+
+ function getSchoolYears(): array
+ {
+ if (!$this->getRecord()->school_years) return [NULL, NULL, NULL];
+
+ return explode("**", $this->getRecord()->school_years);
+ }
+
+ function getSchoolSpecialization(): ?string
+ {
+ return $this->getRecord()->school_specialization;
+ }
+
+ function getUniversityYears(): array
+ {
+ if (!$this->getRecord()->university_years) return [NULL, NULL, NULL];
+
+ return explode("**", $this->getRecord()->university_years);
+ }
+
+ function getUniversitySpecialization(): ?GeodbSpecialization
+ {
+ return (new GeodbSpecializations)->get((int) $this->getRecord()->university_specialization);
+ }
+
+ function getUniversity(): ?GeodbUniversity
+ {
+ return (new GeodbEducation)->getUniversity((int) $this->getRecord()->university);
+ }
+
+ function getUniversityFaculty(): ?GeodbFaculty
+ {
+ return (new GeodbFaculties)->get($this->getRecord()->university_faculty);
+ }
use Traits\TBackDrops;
use Traits\TSubscribable;
diff --git a/Web/Models/Repositories/GeodbCities.php b/Web/Models/Repositories/GeodbCities.php
new file mode 100644
index 000000000..2edbf6be0
--- /dev/null
+++ b/Web/Models/Repositories/GeodbCities.php
@@ -0,0 +1,58 @@
+context = DatabaseConnection::i()->getContext();
+ $this->cities = $this->context->table("geodb_cities");
+ }
+
+ private function toGeodbCity(?ActiveRow $ar): ?GeodbCity
+ {
+ return is_null($ar) ? NULL : new GeodbCity($ar);
+ }
+
+ function get(int $id): ?GeodbCity
+ {
+ return $this->toGeodbCity($this->cities->get($id));
+ }
+
+ function getList(int $cid, ?bool $needDeleted = false, ?bool $simplified = false, ?bool $needRequests = false): \Traversable
+ {
+ $filter = ["country" => $cid];
+ $filter["deleted"] = $needDeleted;
+
+ foreach ($this->cities->where($filter) as $city) {
+ $response = new GeodbCity($city);
+ if ($needRequests && (!$response->getRequestSender())) continue;
+ if (!$needRequests && ($response->getRequestSender())) continue;
+ if ($simplified) $response = $response->getSimplified();
+
+ yield $response;
+ }
+ }
+
+ function find($q): ?GeodbCity
+ {
+ return $this->toGeodbCity($this->context->table("geodb_cities")->where("deleted = 0 AND is_request = 0 AND (id LIKE ? OR name LIKE ? OR native_name LIKE ?)", $q, $q, $q)->fetch());
+ }
+
+ function getRequestsCount(): int
+ {
+ return $this->cities->where("is_request != 0 && deleted = 0")->count();
+ }
+
+ function getTable()
+ {
+ return $this->cities;
+ }
+}
diff --git a/Web/Models/Repositories/GeodbCountries.php b/Web/Models/Repositories/GeodbCountries.php
new file mode 100644
index 000000000..01637f561
--- /dev/null
+++ b/Web/Models/Repositories/GeodbCountries.php
@@ -0,0 +1,54 @@
+context = DatabaseConnection::i()->getContext();
+ $this->countries = $this->context->table("geodb_countries");
+ }
+
+ private function toGeodbCountry(?ActiveRow $ar): ?GeodbCountry
+ {
+ return is_null($ar) ? NULL : new GeodbCountry($ar);
+ }
+
+ function get(int $id): ?GeodbCountry
+ {
+ return $this->toGeodbCountry($this->countries->get($id));
+ }
+
+ function getList(?bool $simplified = false, ?bool $needDeleted = false): \Traversable
+ {
+ foreach ($this->countries as $country) {
+ $response = new GeodbCountry($country);
+ if (!$needDeleted && $response->isDeleted()) continue;
+ if ($needDeleted && !$response->isDeleted()) continue;
+ if ($simplified) $response = $response->getSimplified();
+
+ yield $response;
+ }
+ }
+
+ function getByCode($code): ?GeodbCountry
+ {
+ return $this->toGeodbCountry($this->countries->where("code", $code)->fetch());
+ }
+
+ function find($q): ?GeodbCountry
+ {
+ return $this->toGeodbCountry($this->context->table("geodb_countries")->where("deleted = 0 AND is_request = 0 AND (id LIKE ? OR name LIKE ? OR native_name LIKE ?)", $q, $q, $q)->fetch());
+ }
+
+ function getTable()
+ {
+ return $this->countries;
+ }
+}
diff --git a/Web/Models/Repositories/GeodbEducation.php b/Web/Models/Repositories/GeodbEducation.php
new file mode 100644
index 000000000..567e3f001
--- /dev/null
+++ b/Web/Models/Repositories/GeodbEducation.php
@@ -0,0 +1,88 @@
+context = DatabaseConnection::i()->getContext();
+ $this->schools = $this->context->table("geodb_schools");
+ $this->universities = $this->context->table("geodb_universities");
+ }
+
+ private function toGeodbSchool(?ActiveRow $ar): ?GeodbSchool
+ {
+ return is_null($ar) ? NULL : new GeodbSchool($ar);
+ }
+
+ private function toGeodbUniversity(?ActiveRow $ar): ?GeodbUniversity
+ {
+ return is_null($ar) ? NULL : new GeodbUniversity($ar);
+ }
+
+ function getSchool(int $id): ?GeodbSchool
+ {
+ return $this->toGeodbSchool($this->schools->get($id));
+ }
+
+ function getUniversity(int $id): ?GeodbUniversity
+ {
+ return $this->toGeodbUniversity($this->universities->get($id));
+ }
+
+ function getSchools(int $country_id, ?int $city_id = NULL, ?bool $needDeleted = false, ?bool $simplified = false, ?bool $needRequests = false): \Traversable
+ {
+ $filter = ["country" => $country_id];
+ if ($city_id) $filter["city"] = $city_id;
+ $filter["deleted"] = $needDeleted;
+
+ foreach ($this->schools->where($filter) as $school) {
+ $response = new GeodbSchool($school);
+ if ($needRequests && (!$response->getRequestSender())) continue;
+ if (!$needRequests && ($response->getRequestSender())) continue;
+ if ($simplified) $response = $response->getSimplified();
+
+ yield $response;
+ }
+ }
+
+
+ function getUniversities(int $country_id, ?int $city_id = NULL, ?bool $needDeleted = false, ?bool $simplified = false, ?bool $needRequests = false): \Traversable
+ {
+ $filter = ["country" => $country_id];
+ if ($city_id) $filter["city"] = $city_id;
+ $filter["deleted"] = $needDeleted;
+
+ foreach ($this->universities->where($filter) as $university) {
+ $response = new GeodbUniversity($university);
+ if ($needRequests && (!$response->getRequestSender())) continue;
+ if (!$needRequests && ($response->getRequestSender())) continue;
+ if ($simplified) $response = $response->getSimplified();
+
+ yield $response;
+ }
+ }
+
+ function getSchoolsRequestsCount(): int
+ {
+ return $this->schools->where("is_request != 0 && deleted = 0")->count();
+ }
+
+ function getUniversitiesRequestsCount(): int
+ {
+ return $this->universities->where("is_request != 0 && deleted = 0")->count();
+ }
+
+ function getTable(string $view) {
+ return ($view === "universities") ? $this->universities : $this->schools;
+ }
+}
diff --git a/Web/Models/Repositories/GeodbFaculties.php b/Web/Models/Repositories/GeodbFaculties.php
new file mode 100644
index 000000000..1ac447bb9
--- /dev/null
+++ b/Web/Models/Repositories/GeodbFaculties.php
@@ -0,0 +1,54 @@
+context = DatabaseConnection::i()->getContext();
+ $this->faculties = $this->context->table("geodb_faculties");
+ }
+
+ private function toGeodbFaculty(?ActiveRow $ar): ?GeodbFaculty
+ {
+ return is_null($ar) ? NULL : new GeodbFaculty($ar);
+ }
+
+ function get(int $id): ?GeodbFaculty
+ {
+ return $this->toGeodbFaculty($this->faculties->get($id));
+ }
+
+ function getList(int $uid, ?bool $needDeleted = false, ?bool $simplified = false, ?bool $needRequests = false): \Traversable
+ {
+ $filter = ["university" => $uid];
+ $filter["deleted"] = $needDeleted;
+
+ foreach ($this->faculties->where($filter) as $city) {
+ $response = new GeodbFaculty($city);
+ if ($needRequests && (!$response->getRequestSender())) continue;
+ if (!$needRequests && ($response->getRequestSender())) continue;
+ if ($simplified) $response = $response->getSimplified();
+
+ yield $response;
+ }
+ }
+
+ function getRequestsCount(): int
+ {
+ return $this->faculties->where("is_request != 0 && deleted = 0")->count();
+ }
+
+ function getTable()
+ {
+ return $this->faculties;
+ }
+}
diff --git a/Web/Models/Repositories/GeodbLogs.php b/Web/Models/Repositories/GeodbLogs.php
new file mode 100644
index 000000000..f21147380
--- /dev/null
+++ b/Web/Models/Repositories/GeodbLogs.php
@@ -0,0 +1,90 @@
+context = DatabaseConnection::i()->getContext();
+ $this->logs = $this->context->table("geodb_logs");
+ }
+
+ private function toGeodbLog(?ActiveRow $ar): ?GeodbLog
+ {
+ return is_null($ar) ? NULL : new GeodbLog($ar);
+ }
+
+ function get(int $id): ?GeodbLog
+ {
+ return $this->toGeodbLog($this->logs->get($id));
+ }
+
+ function getList(int $uid): \Traversable
+ {
+ $filter = [];
+ if ($uid) $filter["user"] = $uid;
+
+ foreach ($this->logs->where($filter)->order("id DESC") as $log)
+ yield new GeodbLog($log);
+ }
+
+ function create(User $user, string $table, int $type, $object, $changes): void
+ {
+ $model = "openvk\\Web\\Models\\Entities\\" . [
+ "geodb_countries" => "GeodbCountry",
+ "geodb_cities" => "GeodbCity",
+ "geodb_schools" => "GeodbSchool",
+ "geodb_universities" => "GeodbUniversity",
+ "geodb_faculties" => "GeodbFaculty",
+ "geodb_specializations" => "GeodbSpecialization",
+ "geodb_editors" => "GeodbEditor",
+ ][$table];
+ $fields = [
+ "name" => "Название",
+ "native_name" => "Родное название",
+ "code" => "Код",
+ "flag" => "Флаг",
+ "country" => "Страна",
+ "city" => "Город",
+ "university" => "Университет",
+ "faculty" => "Факультет",
+ "deleted" => "Удалено",
+ "uid" => "ID пользователя",
+ "edu" => "Образование",
+ "cities" => "Города"
+ ];
+
+ $fobject = (is_array($object) ? $object : $object->unwrap());
+
+ $text = "";
+ foreach ($fobject as $field => $value) {
+ if ($changes[$field] === NULL) continue;
+ if (in_array($field, ["id", "is_log"])) continue;
+ if ($changes[$field] == $value && !is_array($object)) continue;
+
+ if (is_array($object)) {
+ $text .= "" . ($fields[$field] ?? $field) . ": $value
";
+ } else {
+ $text .= "" . ($fields[$field] ?? $field) . ": $value → $changes[$field]
";
+ }
+ }
+
+ $log = new GeodbLog;
+ $log->setUser($user->getId());
+ $log->setType($type);
+ $log->setObject_Table($table);
+ $log->setObject_Model($model);
+ $log->setObject_Id(is_array($object) ? $object["id"] : $object->getId());
+ $log->setLogs_Text($text);
+ $log->save();
+ }
+}
diff --git a/Web/Models/Repositories/GeodbRights.php b/Web/Models/Repositories/GeodbRights.php
new file mode 100644
index 000000000..d8de64200
--- /dev/null
+++ b/Web/Models/Repositories/GeodbRights.php
@@ -0,0 +1,140 @@
+context = DatabaseConnection::i()->getContext();
+ $this->editors = $this->context->table("geodb_editors");
+ }
+
+ private function toGeodbRight(?ActiveRow $ar): ?GeodbEditor
+ {
+ return is_null($ar) ? NULL : new GeodbEditor($ar);
+ }
+
+ function get(int $id): ?GeodbEditor
+ {
+ return $this->toGeodbRight($this->editors->get($id));
+ }
+
+ function getList(?int $uid = NULL, ?int $cid = NULL, ?string $q = NULL): array
+ {
+ $filter = ["deleted" => 0];
+ if ($uid) $filter["uid"] = $uid;
+ if ($cid) $filter["country"] = $cid;
+
+ if ($uid && $cid) {
+ $editor = $this->toGeodbRight($this->context->table("geodb_editors")->where($filter)->fetch());
+ if (!$editor) return [];
+
+ return [$editor, $editor->getCountry()];
+ }
+
+ $users = [];
+ $editors = [];
+
+ $rights = $this->context->table("geodb_editors")->where($filter);
+
+ foreach ($rights as $editor) {
+ $editor = $this->toGeodbRight($editor);
+ if (in_array($editor->getUser()->getId(), $users)) {
+ foreach ($editors as $key => $value) {
+ if ($value[0]->getUser()->getId() === $editor->getUser()->getId()) {
+ $editors[$key][1][] = $editor->getCountry();
+ }
+ }
+ } else {
+ if ($q) {
+ $_editors = $editors;
+ foreach ($_editors as $key => $value) {
+ $name = trim(mb_strtolower($value[0]->getUser()->getCanonicalName()));
+ $name_matches = [];
+ preg_match('/' . $q . '/i', $name, $name_matches);
+
+ if (!str_contains($name, trim(mb_strtolower($q))) && count($name_matches) === 0)
+ continue;
+
+ $editors[] = [$editor, [$editor->getCountry()]];
+ $users[] = $editor->getUser()->getId();
+ }
+ } else {
+ $editors[] = [$editor, [$editor->getCountry()]];
+ $users[] = $editor->getUser()->getId();
+ }
+ }
+ }
+
+ return $editors;
+ }
+
+ function getUserCountriesCount(int $user): int
+ {
+ return $this->context->table("geodb_editors")->where(["uid" => $user, "deleted" => 0])->count();
+ }
+
+ function getUserCountries(int $user): \Traversable
+ {
+ foreach ($this->context->table("geodb_editors")->where(["uid" => $user, "deleted" => 0]) as $editor) {
+ $editor = new GeodbEditor($editor);
+ if (!$editor->getCountry()->isDeleted()) {
+ yield $editor->getCountry();
+ }
+ }
+ }
+
+ function getCountryPermission(int $user, int $country): ?GeodbEditor
+ {
+ return $this->toGeodbRight($this->context->table("geodb_editors")->where(["uid" => $user, "country" => $country, "deleted" => 0])->fetch());
+ }
+
+ function search(string $q): array
+ {
+ $ids = [];
+ $r = [];
+
+ foreach ($this->editors->where("deleted", 0) as $_editor) {
+ $e = (new GeodbEditor($_editor));
+ $u = $e->getUser();
+ if (in_array($u->getId(), $ids)) {
+ foreach ($r as $key => $value) {
+ if ($value[0]->getUser()->getId() === $u->getId()) {
+ $r[$key][1][] = $e->getCountry();
+ }
+ }
+ } else {
+ $name = trim(mb_strtolower($u->getCanonicalName()));
+ $name_matches = [];
+ preg_match('/' . $q . '/i', $name, $name_matches);
+
+ if (!str_contains($name, trim(mb_strtolower($q))) && count($name_matches) === 0) continue;
+ $ids[] = $u->getId();
+ $r[] = [$e, [$e->getCountry()]];
+ }
+ }
+
+ return $r;
+ }
+
+ function getRequestsCount(): int
+ {
+ return (new GeodbCities)->getRequestsCount()
+ + (new GeodbEducation)->getSchoolsRequestsCount()
+ + (new GeodbEducation)->getUniversitiesRequestsCount()
+ + (new GeodbFaculties)->getRequestsCount()
+ + (new GeodbSpecializations)->getRequestsCount();
+ }
+
+ function getTable()
+ {
+ return $this->editors;
+ }
+}
diff --git a/Web/Models/Repositories/GeodbSpecializations.php b/Web/Models/Repositories/GeodbSpecializations.php
new file mode 100644
index 000000000..1a16078ef
--- /dev/null
+++ b/Web/Models/Repositories/GeodbSpecializations.php
@@ -0,0 +1,55 @@
+context = DatabaseConnection::i()->getContext();
+ $this->specializations = $this->context->table("geodb_specializations");
+ }
+
+ private function toGeodbSpecialization(?ActiveRow $ar): ?GeodbSpecialization
+ {
+ return is_null($ar) ? NULL : new GeodbSpecialization($ar);
+ }
+
+ function get(int $id): ?GeodbSpecialization
+ {
+ return $this->toGeodbSpecialization($this->specializations->get($id));
+ }
+
+ function getList(?int $fid = NULL, ?bool $needDeleted = false, ?bool $simplified = false, ?bool $needRequests = false): \Traversable
+ {
+ $filter[($fid < 0 ? "country" : "faculty")] = ($fid < 0 ? ($fid * -1) : $fid);
+ $filter["deleted"] = $needDeleted;
+
+ foreach ($this->specializations->where($filter) as $specialization) {
+ $response = new GeodbSpecialization($specialization);
+ if ($needRequests && (!$response->getRequestSender())) continue;
+ if (!$needRequests && ($response->getRequestSender())) continue;
+ if ($simplified) $response = $response->getSimplified();
+
+ yield $response;
+ }
+ }
+
+ function getRequestsCount(): int
+ {
+ return $this->specializations->where("is_request != 0 && deleted = 0")->count();
+ }
+
+ function getTable()
+ {
+ return $this->specializations;
+ }
+}
diff --git a/Web/Models/Repositories/Users.php b/Web/Models/Repositories/Users.php
index 6c165aa37..08a8b36b8 100644
--- a/Web/Models/Repositories/Users.php
+++ b/Web/Models/Repositories/Users.php
@@ -71,8 +71,13 @@ function find(string $query, array $pars = [], string $sort = "id DESC"): Util\E
case "hometown":
$result->where("hometown LIKE ?", $paramValue);
break;
+ case "country":
+ $country = (new GeodbCountries)->find($paramValue);
+ if ($country) $result->where("country_id LIKE ?", $country->getId());
+ break;
case "city":
- $result->where("city LIKE ?", $paramValue);
+ $country = (new GeodbCities)->find($paramValue);
+ if ($country) $result->where("city_id LIKE ?", $country->getId());
break;
case "maritalstatus":
$result->where("marital_status ?", $paramValue);
diff --git a/Web/Presenters/GeodbPresenter.php b/Web/Presenters/GeodbPresenter.php
new file mode 100644
index 000000000..fab644b66
--- /dev/null
+++ b/Web/Presenters/GeodbPresenter.php
@@ -0,0 +1,1081 @@
+context = DatabaseConnection::i()->getContext();
+ $this->editors = $geodbRights;
+ $this->countries = $geodbCountries;
+ $this->cities = $geodbCities;
+ $this->logs = $geodbLogs;
+ $this->education = $geodbEducation;
+ $this->faculties = $geodbFaculties;
+ $this->specializations = $geodbSpecializations;
+ }
+
+ function renderIndex(): void
+ {
+ if (!$this->user->identity->canEditGeodb())
+ $this->notFound();
+
+ $mode = in_array($this->queryParam("act"), [
+ "countries", "editors", "requests", "add_country", "editor", "country", "city", "add_city", "add_edu",
+ "school", "university", "add_faculty", "faculty", "specializations", "specialization", "add_specialization", "logs"
+ ]) ? $this->queryParam("act") : "countries";
+ $isGeodbAdmin = $this->user->identity->getChandlerUser()->can("write")->model("openvk\\Web\\Models\\Entities\\GeodbCountry")->whichBelongsTo(0);
+
+ if (in_array($mode, ["add_country", "editors", "editor"]))
+ $this->assertPermission("openvk\\Web\\Models\\Entities\\GeodbCountry", "write", 0);
+
+ if ($_SERVER["REQUEST_METHOD"] === "POST") {
+ $this->assertNoCSRF();
+
+ $payload = [];
+
+ switch ($mode) {
+ case "add_country":
+ if (!$this->postParam("code") || !$this->postParam("flag") || !$this->postParam("name"))
+ $this->flashFail("err", tr("error"), "Заполнены не все обязательные поля");
+
+ if (!$isGeodbAdmin) $this->notFound();
+
+ if ((int)$this->queryParam("id")) {
+ $country = $this->countries->get((int)$this->queryParam("id"));
+ } else {
+ $country = new GeodbCountry;
+ }
+
+ $country->setCode($this->postParam("code"));
+ $country->setFlag($this->postParam("flag"));
+ $country->setName($this->postParam("name"));
+ $country->setNative_Name($this->postParam("native_name"));
+ $country->save($this->user->identity, $this->countries->getTable(), true);
+
+ $this->flashFail("succ", "Страна добавлена");
+ break;
+
+ case "editors":
+ if (!$isGeodbAdmin) $this->notFound();
+
+ if ($this->postParam("q")) {
+ $editors = [];
+ $_editors = $this->editors->search($this->postParam("q"));
+
+ foreach ($_editors as $editor) {
+ $u = $editor[0]->getUser();
+ $r = [[
+ "id" => $u->getId(),
+ "name" => $u->getCanonicalName(),
+ "avatar" => $u->getAvatarURL("normal"),
+ "url" => $u->getURL(),
+ ],
+ []
+ ];
+
+ foreach ($editor[1] as $country) {
+ $r[1][] = [
+ "id" => $country->getId(),
+ "code" => $country->getCode(),
+ "flag" => $country->getFlagURL(),
+ "name" => $country->getCanonicalName(),
+ "edu" => $country->isUserCanEditEducation($u->getId()),
+ "cities" => $country->isUserCanEditCities($u->getId()),
+ ];
+ }
+
+ $editors[] = $r;
+ }
+
+ $this->returnJson(["editors" => $editors]);
+ } else {
+ if (!$this->postParam("link") || !$this->postParam("country"))
+ $this->flashFail("err", tr("error"), "Заполнены не все обязательные поля");
+
+ if (
+ (empty($this->postParam("can_access_edu")) && empty($this->postParam("can_access_cities")))
+ ||
+ ($this->postParam("can_access_edu") === 0 && $this->postParam("can_access_cities") === 0)
+ )
+ $this->returnJson(["success" => false, "error" => "Вы не можете добавить сотрудника без прав :("]);
+
+ $country = $this->countries->getByCode($this->postParam("country"));
+ if (!$country || $country->isDeleted())
+ $this->returnJson(["success" => false, "error" => "Страна не найдена"]);
+
+ $users_getter = is_numeric($this->postParam("link")) ? "get" : "getByAddress";
+ $user = (new Users)->$users_getter((int)$this->postParam("link") ?? $this->postParam("link"));
+
+ if (!$user)
+ $this->returnJson(["sucecss" => false, "error" => "Пользователь не найден"]);
+
+ $rights = $this->editors->getList($user->getId());
+ $_countries = [];
+ foreach ($rights as $right) {
+ foreach ($right[1] as $_country) {
+ if ($_country->getId() === $country->getId()) {
+ $this->returnJson(["success" => false, "error" => "Пользователь уже добавлен в эту страну. Редактируйте существующую запись для изменения прав."]);
+ } else {
+ $_countries[] = $_country;
+ }
+ }
+ }
+
+ $editor = new GeodbEditor;
+ $editor->setUid($user->getId());
+ $editor->setCountry($country->getId());
+ $editor->setEdu($this->postParam("can_access_edu") == "1");
+ $editor->setCities($this->postParam("can_access_cities") == "1");
+ $editor->save($this->user->identity, $this->editors->getTable());
+
+ $this->returnJson(["success" => true, "payload" => [
+ "id" => $country->getId(),
+ "user" => $user->getId(),
+ "name" => $country->getCanonicalName(),
+ "user_name" => $user->getCanonicalName(),
+ "code" => $country->getCode(),
+ "flag" => $country->getFlagURL(),
+ "edu" => $country->isUserCanEditEducation($user->getId()),
+ "cities" => $country->isUserCanEditCities($user->getId()),
+ "link" => $user->getURL(),
+ "avatar" => $user->getAvatarURL("normal"),
+ "user_exists" => (sizeof($_countries) > 0)
+ ]]);
+ }
+ break;
+
+ case "editor":
+ if (!$isGeodbAdmin) $this->notFound();
+
+ if (!$this->queryParam("id"))
+ $this->returnJson(["success" => false, "error" => "ID пользователя не передан."]);
+
+ if (!$this->postParam("country"))
+ $this->returnJson(["success" => false, "error" => "Код страны не передан"]);
+
+ if (
+ (
+ (empty($this->postParam("can_access_edu")) && empty($this->postParam("can_access_cities")))
+ ||
+ ($this->postParam("can_access_edu") === 0 && $this->postParam("can_access_cities") === 0)
+ )
+ &&
+ !$this->queryParam("delete")
+ )
+ $this->returnJson(["success" => false, "error" => "Права не выбраны"]);
+
+ $country = $this->countries->getByCode($this->postParam("country"));
+
+ if (!$country || $country->isDeleted())
+ $this->returnJson(["success" => false, "error" => "Страна не найдена"]);
+
+ $user = (new Users)->get((int)$this->queryParam("id"));
+ if (!$user)
+ $this->returnJson(["success" => false, "error" => "Пользователь не найден"]);
+
+ if ($this->queryParam("delete")) {
+ $editor = $this->editors->getList($user->getId(), $country->getId());
+ if (!$editor)
+ $this->returnJson(["success" => false, "error" => "Пользователь не редактирует эту страну"]);
+
+ $this->logs->create($this->user->identity, "geodb_editors", 2, $editor[0], ["deleted" => 1]);
+ $editor[0]->delete();
+
+ if ($this->editors->getUserCountriesCount($user->getId()) === 0)
+ $payload["delete_user"] = 1;
+ } else if ($this->queryParam("edit")) {
+ $editor = $this->editors->getList($user->getId(), $country->getId());
+ if (!$editor)
+ $this->returnJson(["success" => false, "error" => "Пользователь не редактирует эту страну"]);
+
+ $edu = $this->postParam("can_access_edu") == 1;
+ $cities = $this->postParam("can_access_cities") == 1;
+
+ $editor = $this->editors->get($editor[0]->getId());
+ $editor->setEdu($edu);
+ $editor->setCities($cities);
+ $editor->save($this->user->identity, $this->editors->getTable());
+
+ $this->returnJson(["success" => true, "payload" => [
+ "edu" => $edu,
+ "cities" => $cities
+ ]]);
+ } else {
+ $rights = $this->editors->getList($user->getId());
+ foreach ($rights as $right) {
+ foreach ($right[1] as $_country) {
+ if ($_country->getId() === $country->getId()) {
+ $this->returnJson(["success" => false, "error" => "Пользователь уже добавлен в эту страну. Редактируйте существующую запись для изменения прав."]);
+ }
+ }
+ }
+
+ $editor = new GeodbEditor;
+ $editor->setUid($user->getId());
+ $editor->setCountry($country->getId());
+ $editor->setEdu($this->postParam("can_access_edu") == 1);
+ $editor->setCities($this->postParam("can_access_cities") == 1);
+ $editor->save($this->user->identity, $this->editors->getTable());
+
+ $payload = [
+ "id" => $country->getId(),
+ "user" => $user->getId(),
+ "name" => $country->getCanonicalName(),
+ "user_name" => $user->getCanonicalName(),
+ "code" => $country->getCode(),
+ "flag" => $country->getFlagURL(),
+ "edu" => $country->isUserCanEditEducation($user->getId()),
+ "cities" => $country->isUserCanEditCities($user->getId()),
+ ];
+ }
+
+ $this->returnJson(["success" => true, "payload" => $payload]);
+ break;
+
+ case "city":
+ if ($this->queryParam("delete") || $this->queryParam("restore")) {
+ if (!$isGeodbAdmin && $this->queryParam("restore")) $this->notFound();
+ $city = $this->cities->get((int)$this->queryParam("id"));
+ if (!$city)
+ $this->returnJson(["success" => false, "error" => "Город не найден"]);
+
+ $city->setDeleted($this->queryParam("delete") ? 1 : 0);
+ $city->save($this->user->identity, $this->cities->getTable());
+ $this->returnJson(["success" => true]);
+ } else {
+ $city = $this->cities->get((int)$this->queryParam("id"));
+ if (!$city)
+ $this->notFound();
+
+ if (!$this->postParam("name") || !$this->postParam("native_name"))
+ $this->flashFail("err", tr("error"), "Заполнены не все обязательные поля");
+
+ $city->setName($this->postParam("name"));
+ $city->setNative_Name($this->postParam("native_name"));
+ $city->save($this->user->identity, $this->cities->getTable());
+
+ $this->flashFail("succ", "Город сохранен");
+ }
+ break;
+
+ case "add_city":
+ $country = $this->countries->get((int)$this->queryParam("id"));
+
+ if (!$country || $country->isDeleted())
+ $this->redirect("/editdb?act=countries");
+
+ if (!$this->postParam("name") || !$this->postParam("native_name"))
+ $this->flashFail("err", tr("error"), "Заполнены не все обязательные поля");
+
+ $city = new GeodbCity;
+ $city->setCountry($country->getId());
+ $city->setName($this->postParam("name"));
+ $city->setNative_Name($this->postParam("native_name"));
+ $city->save($this->user->identity, $this->cities->getTable());
+
+ $this->flashFail("succ", "Город добавлен");
+ break;
+
+ case "add_edu":
+ $country = $this->countries->get((int)$this->queryParam("id"));
+
+ if (!$country || $country->isDeleted())
+ $this->redirect("/editdb?act=countries");
+
+ $city = $this->cities->get((int)$this->postParam("city-id"));
+ if (!$city || ($city && $city->getCountry()->getId() !== $country->getId()))
+ $this->redirect("/editdb?act=country&id=" . $country->getId());
+
+ $view = in_array($this->queryParam("view"), ["schools", "universities"]) ? $this->queryParam("view") : "schools";
+
+ if (!$this->postParam("name"))
+ $this->flashFail("err", tr("error"), "Заполнены не все обязательные поля");
+
+ $item = ($view === "schools") ? new GeodbSchool : new GeodbUniversity;
+ $item->setCountry($country->getId());
+ $item->setCity($city->getId());
+ $item->setName($this->postParam("name"));
+ $item->save($this->user->identity, $this->education->getTable($view));
+
+ $this->flashFail("succ", ($view === "schools" ? "Школа добавлена" : "Университет добавлен"));
+ break;
+
+ case "country":
+ if (!$isGeodbAdmin) $this->notFound();
+
+ $country = $this->countries->get((int)$this->queryParam("id"));
+ if (!$country || ($country->isDeleted() && !$this->queryParam("restore")))
+ $this->returnJson(["success" => false, "error" => "Страна не найдена"]);
+
+ if ($this->queryParam("delete") || $this->queryParam("restore")) {
+ if (!$isGeodbAdmin) $this->notFound();
+
+ $country->setDeleted($this->queryParam("delete") ? 1 : 0);
+ $country->save($this->user->identity, $this->countries->getTable());
+ $this->returnJson(["success" => true, "payload" => $country->getId()]);
+ } else {
+ $city_id = NULL;
+ if ($this->queryParam("city")) {
+ $city = $this->cities->get((int)$this->queryParam("city"));
+ if ($city && ($city->getCountry()->getId() === $country->getId())) {
+ $city_id = $city->getId();
+ }
+ }
+
+ if ($this->queryParam("edu")) {
+ $view = in_array($this->queryParam("view"), ["schools", "universities"]) ? $this->queryParam("view") : "schools";
+ if ($view === "schools") {
+ $schools = $this->education->getSchools($country->getId(), $city_id);
+ $response = [];
+ foreach ($schools as $school) {
+ $response[] = $school->getSimplified();
+ }
+ } else {
+ $universities = $this->education->getUniversities($country->getId(), $city_id);
+ $response = [];
+
+ if ($this->queryParam("uid") && $this->queryParam("n") === "faculties") {
+ foreach ($universities as $university) {
+ if ($university->getId() === (int)$this->queryParam("uid")) {
+ $_faculties = $university->getFaculties();
+ foreach ($_faculties as $faculty) {
+ $_faculty = $faculty->getSimplified();
+ $specializations = $faculty->getSpecializations(false, true);
+ $_faculty["specializations"] = [];
+ foreach ($specializations as $specialization) {
+ $_faculty["specializations"][] = $specialization;
+ }
+ $response[] = $_faculty;
+ }
+ }
+ }
+ } else if ($this->queryParam("fid") && $this->queryParam("n") === "specializations") {
+ $faculty = $this->faculties->get((int)$this->queryParam("fid"));
+ $response = iterator_to_array($faculty->getSpecializations(false, true));
+ } else {
+ foreach ($universities as $university) {
+ $_university = $university->getSimplified();
+ $_faculties = $university->getFaculties();
+ $_university["faculties"] = [];
+ foreach ($_faculties as $key => $value) {
+ $_faculty = $value->getSimplified();
+ $specializations = $value->getSpecializations(false, true);
+ $_faculty["specializations"] = [];
+ foreach ($specializations as $specialization) {
+ $_faculty["specializations"][] = $specialization;
+ }
+ $_university["faculties"][$key] = $_faculty;
+ }
+
+ $response[] = $_university;
+ }
+ }
+ }
+
+ $response = ["success" => true, "list" => $response];
+ if ($city_id) $response["city"] = $city->getNativeName();
+ $this->returnJson($response);
+ }
+ }
+ break;
+
+ case "school":
+ $id = ((int)$this->postParam("id") ?: (int)$this->queryParam("id"));
+ $school = $this->education->getSchool($id);
+ if (!$school)
+ $this->returnJson(["success" => false, "error" => "Школа не найдена"]);
+
+ if ($this->queryParam("delete") || $this->queryParam("restore")) {
+ if (!$isGeodbAdmin && $this->queryParam("restore")) $this->notFound();
+ $school->setDeleted($this->queryParam("delete") ? 1 : 0);
+ } else {
+ if ((int)$this->postParam("city-id") !== $school->getCity()->getId()) {
+ $city = $this->cities->get((int)$this->postParam("city-id"));
+ if ($city) {
+ $school->setCity($city->getId());
+ }
+ }
+
+ $school->setName($this->postParam("name"));
+ }
+
+ $school->save($this->user->identity, $this->education->getTable("schools"));
+ if ($this->postParam("id"))
+ $this->returnJson(["success" => true, "payload" => $school->getId()]);
+ else
+ $this->flashFail("succ", "Изменения сохранены");
+ break;
+
+ case "university":
+ $id = ((int)$this->postParam("id") ?: (int)$this->queryParam("id"));
+ $university = $this->education->getUniversity($id);
+ if (!$university)
+ $this->returnJson(["success" => false, "error" => "Университет не найден"]);
+
+ if ($this->queryParam("delete") || $this->queryParam("restore")) {
+ if (!$isGeodbAdmin && $this->queryParam("restore")) $this->notFound();
+ $university->setDeleted($this->queryParam("delete") ? 1 : 0);
+ } else {
+ if ((int)$this->postParam("city-id") !== $university->getCity()->getId()) {
+ $city = $this->cities->get((int)$this->postParam("city-id"));
+ if ($city) {
+ $university->setCity($city->getId());
+ }
+ }
+
+ $university->setName($this->postParam("name"));
+ }
+
+ $university->save($this->user->identity, $this->education->getTable("universities"));
+ if ($this->postParam("id"))
+ $this->returnJson(["success" => true, "payload" => $university->getId()]);
+ else
+ $this->flashFail("succ", "Изменения сохранены");
+ break;
+
+ case "add_faculty":
+ $university = $this->education->getUniversity((int)$this->queryParam("uid"));
+
+ if (!$university || $university->isDeleted())
+ $this->redirect("/editdb?act=countries");
+
+ if (!$this->postParam("name"))
+ $this->returnJson(["success" => false, "error" => "Заполнены не все поля"]);
+
+ $faculty = new GeodbFaculty;
+ $faculty->setUniversity($university->getId());
+ $faculty->setName($this->postParam("name"));
+ $faculty->save($this->user->identity, $this->faculties->getTable());
+
+ $this->returnJson([
+ "success" => true,
+ "payload" => $faculty->getSimplified(),
+ "reload" => count(iterator_to_array($university->getFaculties())) === 1,
+ ]);
+ break;
+
+ case "faculty":
+ $deleted = ($isGeodbAdmin && !$this->queryParam("delete"));
+ if ($this->queryParam("delete") || $this->queryParam("restore")) {
+ if (!$isGeodbAdmin && $this->queryParam("restore")) $this->notFound();
+
+ $faculty = $this->faculties->get((int)$this->postParam("id"));
+ if (!$faculty || (!$deleted && $faculty->isDeleted()))
+ $this->returnJson(["success" => false, "error" => "Факультет не найден"]);
+
+ $faculty->setDeleted($this->queryParam("delete") ? 1 : 0);
+ $faculty->save($this->user->identity, $this->faculties->getTable());
+
+ $this->returnJson([
+ "success" => true,
+ "reload" => count(iterator_to_array($faculty->getUniversity()->getFaculties($deleted))) <= 0,
+ "payload" => $faculty->getId()
+ ]);
+ } else {
+ $faculty = $this->faculties->get((int)$this->queryParam("id"));
+ if (!$faculty)
+ $this->notFound();
+
+ if (!$this->postParam("name"))
+ $this->returnJson(["success" => false, "error" => "Заполнены не все обязательные поля"]);
+
+ $faculty->setName($this->postParam("name"));
+ $faculty->save($this->user->identity, $this->faculties->getTable());
+
+ $this->returnJson(["success" => true, "payload" => $faculty->getId()]);
+ }
+ break;
+
+ case "specializations":
+ $faculty = $this->faculties->get((int)$this->postParam("fid"));
+ if (!$faculty || $faculty->isDeleted())
+ $this->returnJson(["success" => false, "error" => "Факультет не найден"]);
+
+ $this->returnJson([
+ "success" => true,
+ "list" => iterator_to_array($this->specializations->getList($faculty->getId(), ($isGeodbAdmin && $this->queryParam("deleted")), true))
+ ]);
+ break;
+
+ case "specialization":
+ $deleted = ($isGeodbAdmin && !$this->queryParam("delete"));
+ if ($this->queryParam("delete") || $this->queryParam("restore")) {
+ if (!$isGeodbAdmin && $this->queryParam("restore")) $this->notFound();
+
+ $specialization = $this->specializations->get((int)$this->postParam("id"));
+ if (!$specialization || (!$deleted && $specialization->isDeleted()))
+ $this->returnJson(["success" => false, "error" => "Факультет не найден"]);
+
+ $specialization->setDeleted($this->queryParam("delete") ? 1 : 0);
+ $specialization->save($this->user->identity, $this->specializations->getTable());
+
+ $this->returnJson([
+ "success" => true,
+ "payload" => $specialization->getSimplified()
+ ]);
+ } else {
+ $specialization = $this->specializations->get((int)$this->queryParam("id"));
+ if (!$specialization)
+ $this->notFound();
+
+ if (!$this->postParam("name"))
+ $this->returnJson(["success" => false, "error" => "Заполнены не все обязательные поля"]);
+
+ $specialization->setName($this->postParam("name"));
+ $specialization->save($this->user->identity, $this->specializations->getTable());
+
+ $this->returnJson(["success" => true, "payload" => $specialization->getId()]);
+ }
+ break;
+
+ case "add_specialization":
+ $faculty = $this->faculties->get((int)$this->queryParam("fid"));
+
+ if (!$faculty || $faculty->isDeleted())
+ $this->returnJson(["success" => false, "error" => "Факультет не найден"]);
+
+ if (!$this->postParam("name"))
+ $this->returnJson(["success" => false, "error" => "Заполнены не все поля"]);
+
+ $specialization = new GeodbSpecialization;
+ $specialization->setFaculty($faculty->getId());
+ $specialization->setName($this->postParam("name"));
+ $specialization->save($this->user->identity, $this->specializations->getTable());
+
+ $this->returnJson([
+ "success" => true,
+ "payload" => $specialization->getSimplified(),
+ ]);
+ break;
+
+ case "requests":
+ $rid = (int)$this->postParam("rid");
+ $view = in_array($this->queryParam("tab"), ["cities", "schools", "universities", "faculties", "specializations"]) ? $this->queryParam("tab") : ($this->template->can_view_cities ? "cities" : "schools");
+ $item = NULL;
+ if (!in_array($view, ["schools", "universities"])) {
+ $repo = [
+ "cities" => "openvk\\Web\\Models\\Repositories\\GeodbCities",
+ "faculties" => "openvk\\Web\\Models\\Repositories\\GeodbFaculties",
+ "specializations" => "openvk\\Web\\Models\\Repositories\\GeodbSpecializations"
+ ][$view];
+ $item = (new $repo)->get($rid);
+ } else {
+ $repo = "openvk\\Web\\Models\\Repositories\\GeodbEducation";
+ if ($view === "schools") {
+ $item = $this->education->getSchool($rid);
+ } else {
+ $item = $this->education->getUniversity($rid);
+ }
+ }
+
+ if (!$item)
+ $this->returnJson(["success" => false, "error" => "Заявка не найдена"]);
+
+ $names = [
+ "cities" => "Вашем городе",
+ "schools" => "Вашей школе",
+ "universities" => "Вашем вузе",
+ "faculties" => "Вашем факультете",
+ "specializations" => "Вашей специализации"
+ ];
+
+ if ($this->queryParam("edit")) {
+ $item->setName($this->postParam("name"));
+ if ($view === "cities") {
+ $item->setNative_Name($this->postParam("native_name"));
+ }
+ $item->save($this->user->identity, (new $repo)->getTable($view));
+
+ $this->returnJson(["success" => true, "payload" => [$item->getName(), ($view === "cities" ? $item->getNativeName() : "")]]);
+ } else if ($this->queryParam("decline")) {
+ $user = $item->getRequestSender();
+ $user->adminNotify(($user->isFemale() ? "Дорогая " : "Дорогой ") . $user->getFirstName() . "!\n\nМы рассмотрели Вашу заявку. К сожалению, мы не смогли найти информацию о " . $names[$view] . " (" . $item->getName() . "). Пожалуйста, уточните данные и подайте заявку ещё раз.\n\nЭто сообщение отправлено автоматически. Пожалуйста, не отвечайте на него. Если у Вас есть вопросы, напишите нам здесь: https://$_SERVER[HTTP_HOST]/support?act=new.");
+ $item->delete();
+ $this->returnJson(["success" => true, "payload" => $rid]);
+ } else if ($this->queryParam("accept")) {
+ $user = $item->getRequestSender();
+ $item->setIs_Request(0);
+ $item->save($this->user->identity, (new $repo)->getTable($view));
+ $user->adminNotify(($user->isFemale() ? "Дорогая " : "Дорогой ") . $user->getFirstName() . "!\n\nМы рассмотрели Вашу заявку и добавили информацию о " . $names[$view] . " (" . $item->getName() . ") в базу.\n\nЭто сообщение отправлено автоматически. Пожалуйста, не отвечайте на него. Если у Вас есть вопросы, напишите нам здесь: https://$_SERVER[HTTP_HOST]/support?act=new.");
+ $this->returnJson(["success" => true, "payload" => $item->getId()]);
+ } else {
+ $this->returnJson(["success" => false, "error" => "Заявка не найдена"]);
+ }
+ break;
+
+ default:
+ $this->notFound();
+ break;
+ }
+ } else {
+ $this->template->mode = $mode;
+ $this->template->countries = $isGeodbAdmin
+ ? iterator_to_array($this->countries->getList(false, ($this->queryParam("deleted") && $mode === "countries")))
+ : iterator_to_array($this->editors->getUserCountries($this->user->identity->getId()));
+
+ $this->template->isGeodbAdmin = $isGeodbAdmin;
+
+ switch ($mode) {
+ case "countries":
+ $this->template->_template = "Geodb/Countries.xml";
+ $this->template->title = "Страны";
+ $this->template->can_add_country = $isGeodbAdmin;
+ $this->template->can_view_deleted = $isGeodbAdmin;
+ $this->template->is_deleted = ($isGeodbAdmin && $this->queryParam("deleted"));
+
+ if (count($this->template->countries) <= 0) {
+ if ($this->template->is_deleted) {
+ $this->redirect("/editdb?act=countries");
+ } else {
+ $this->flashFail("err", "Страны не найдены", ($isGeodbAdmin ? "Если Вы впервые редактируете геодб, сначала создайте страну здесь" : ""));
+ }
+ }
+ break;
+
+ case "add_country":
+ $this->template->_template = "Geodb/AddCountry.xml";
+ $this->template->country = $this->countries->get((int)$this->queryParam("id"));
+ break;
+
+ case "editors":
+ $this->template->_template = "Geodb/Editors.xml";
+ $this->template->title = "Редакторы базы";
+ $this->template->editors = $this->editors->getList(NULL, NULL, $this->queryParam("q"));
+ break;
+
+ case "editor":
+ $this->template->title = "Редакторы базы";
+ $this->template->mode = "editors";
+ break;
+
+ case "country":
+ $this->template->_template = "Geodb/Country.xml";
+ $country = $this->countries->get((int)$this->queryParam("id"));
+ $is_edu = $this->queryParam("edu") == 1;
+
+ if (!$country || $country->isDeleted())
+ $this->redirect("/editdb?act=countries");
+
+ $this->template->can_edit_edu = ($isGeodbAdmin || $country->isUserCanEditEducation($this->user->identity->getId()));
+ $this->template->can_edit_cities = ($isGeodbAdmin || $country->isUserCanEditCities($this->user->identity->getId()));
+
+ $this->template->country = $country;
+ $this->template->is_edu = $is_edu;
+
+ if (!$is_edu) {
+ if (!$this->template->can_edit_cities)
+ if ($this->template->can_edit_edu)
+ $this->redirect("/editdb?act=country&id=" . $country->getId() . "&edu=1");
+ else
+ $this->notFound();
+
+ $this->template->cities = iterator_to_array($this->cities->getList($country->getId(), ($isGeodbAdmin && $this->queryParam("deleted"))));
+ } else {
+ if (!$this->template->can_edit_edu)
+ $this->notFound();
+
+ $view = in_array($this->queryParam("view"), ["schools", "universities"]) ? $this->queryParam("view") : "schools";
+ $this->template->view = $view;
+
+ $city_id = NULL;
+ if ($this->queryParam("city")) {
+ $city = $this->cities->get((int)$this->queryParam("city"));
+ if ($city && ($city->getCountry()->getId() === $country->getId())) {
+ $this->template->city = $city;
+ $city_id = $city->getId();
+ }
+ }
+
+ if ($view === "schools") {
+ $this->template->schools = iterator_to_array($this->education->getSchools($country->getId(), $city_id, ($isGeodbAdmin && $this->queryParam("deleted"))));
+ } else {
+ $this->template->universities = iterator_to_array($this->education->getUniversities($country->getId(), $city_id, ($isGeodbAdmin && $this->queryParam("deleted"))));
+ }
+ }
+ $this->template->can_view_deleted = $isGeodbAdmin;
+ $this->template->is_deleted = ($isGeodbAdmin && $this->queryParam("deleted"));
+
+ $this->template->title = $is_edu ? "Образование" : "Города";
+ break;
+
+ case "add_city":
+ $this->template->_template = "Geodb/AddCity.xml";
+ $country = $this->countries->get((int)$this->queryParam("id"));
+
+ if (!$country || $country->isDeleted())
+ $this->redirect("/editdb?act=countries");
+
+ $this->template->country = $country;
+ $this->template->title = "Добавить город";
+ break;
+
+ case "city":
+ $this->template->_template = "Geodb/City.xml";
+ $city = $this->cities->get((int)$this->queryParam("id"));
+ if (!$city)
+ $this->notFound();
+
+ $country = $city->getCountry();
+
+ $this->template->country = $country;
+ $this->template->city = $city;
+ $this->template->title = "Город";
+ break;
+
+ case "university":
+ $this->template->_template = "Geodb/School.xml";
+ $university = $this->education->getUniversity((int)$this->queryParam("id"));
+ if (!$university)
+ $this->notFound();
+
+ $country = $university->getCountry();
+
+ $this->template->country = $country;
+ $this->template->school = $university;
+ $this->template->title = "Университет";
+ $this->template->can_view_deleted = $isGeodbAdmin;
+ $this->template->is_deleted = ($isGeodbAdmin && $this->queryParam("deleted"));
+ $this->template->faculties = iterator_to_array($university->getFaculties($this->template->is_deleted));
+ break;
+
+ case "add_edu":
+ $this->template->_template = "Geodb/AddEdu.xml";
+ $country = $this->countries->get((int)$this->queryParam("id"));
+
+ if (!$country || $country->isDeleted())
+ $this->redirect("/editdb?act=countries");
+
+ $this->template->country = $country;
+ $view = in_array($this->queryParam("view"), ["schools", "universities"]) ? $this->queryParam("view") : "schools";
+ $this->template->view = $view;
+ $titles = [
+ "schools" => "школу",
+ "universities" => "университет"
+ ];
+ $this->template->title = "Добавить " . $titles[$this->queryParam("view")];
+ break;
+
+ case "school":
+ $this->template->_template = "Geodb/School.xml";
+ $school = $this->education->getSchool((int)$this->queryParam("id"));
+ if (!$school)
+ $this->notFound();
+
+ $country = $school->getCountry();
+
+ $this->template->country = $country;
+ $this->template->school = $school;
+ $this->template->title = "Школа";
+ break;
+
+ case "requests":
+ $this->template->_template = "Geodb/Requests.xml";
+
+ if ($this->queryParam("cid")) {
+ $country = $this->countries->get((int)$this->queryParam("cid"));
+ if (!$country || $country->isDeleted())
+ $this->flashFail("err", "Страна не найдена", ($isGeodbAdmin ? "Если Вы впервые редактируете геодб, сначала создайте страну здесь" : ""));
+
+ $this->template->current_country = $country;
+
+ $this->template->can_view_cities = ($isGeodbAdmin || $country->isUserCanEditCities($this->user->identity->getId()));
+ $this->template->can_view_education = ($isGeodbAdmin || $country->isUserCanEditEducation($this->user->identity->getId()));
+
+ if (!$this->template->can_view_cities && !$this->template->can_view_education)
+ $this->notFound();
+
+ $view = in_array($this->queryParam("tab"), ["cities", "schools", "universities", "faculties", "specializations"]) ? $this->queryParam("tab") : ($this->template->can_view_cities ? "cities" : "schools");
+ $this->template->mode = $view;
+
+ $requests = [];
+ $_requests = [];
+
+ if (!in_array($view, ["schools", "universities"])) {
+ $repo = [
+ "cities" => "openvk\\Web\\Models\\Repositories\\GeodbCities",
+ "faculties" => "openvk\\Web\\Models\\Repositories\\GeodbFaculties",
+ "specializations" => "openvk\\Web\\Models\\Repositories\\GeodbSpecializations"
+ ][$view];
+ $cid = $country->getId();
+ if (in_array($view, ["specializations"])) $cid = $cid * -1;
+ $_requests = (new $repo)->getList($cid, false, false, true);
+ } else {
+ if ($view === "schools") {
+ $_requests = $this->education->getSchools($country->getId(), NULL, false, false, true);
+ } else {
+ $_requests = $this->education->getUniversities($country->getId(), NULL, false, false, true);
+ }
+ }
+
+ foreach ($_requests as $_item) {
+ $requests[] = [$_item, $_item->getRequestSender()];
+ }
+
+ $this->template->requests = $requests;
+ $this->template->type = ["cities" => "город", "schools" => "школу", "universities" => "университет", "faculties" => "факультет", "specialization" => "специализацию"][$view];
+ } else {
+ $this->redirect("/editdb?act=requests&cid=1");
+ }
+ break;
+
+ case "logs":
+ $this->template->_template = "Geodb/Logs.xml";
+
+ if (!$isGeodbAdmin)
+ $this->notFound();
+
+ $logs = $this->logs->getList((int)$this->queryParam("uid"));
+ $this->template->logs = iterator_to_array($logs);
+ $this->template->count = count($this->template->logs);
+ break;
+ }
+ }
+ }
+
+ function renderForUser(): void
+ {
+ if ($_SERVER["REQUEST_METHOD"] !== "POST") $this->notFound();
+
+ $this->assertUserLoggedIn();
+ $this->assertNoCSRF();
+
+ switch ($this->queryParam("act")) {
+ case "countries":
+ $c = $this->countries->getList(TRUE);
+ $list = [];
+
+ foreach ($c as $country) {
+ if ($this->postParam("q")) {
+ $q = trim(mb_strtolower($this->postParam("q")));
+
+ $name = trim(mb_strtolower($country["name"]));
+ $native_name = trim(mb_strtolower($country["native_name"]));
+
+ if ($q == $name || $q == $native_name) {
+ $list[] = $country;
+ break;
+ }
+
+ preg_match('/' . $q . '/i', $name, $name_matches);
+ preg_match('/' . $q . '/i', $native_name, $native_name_matches);
+
+ if (sizeof($name_matches) > 0 || sizeof($native_name_matches) > 0) {
+ $list[] = $country;
+ }
+ } else {
+ $list[] = $country;
+ }
+ }
+
+ $this->returnJson(["list" => $list]);
+ break;
+
+ case "cities":
+ $country = $this->countries->get((int)$this->postParam("country"));
+ if (!$country || $country->isDeleted()) $this->returnJson(["success" => false, "error" => "Страна не найдена"]);
+
+ $cities = $this->cities->getList($country->getId(), false, true);
+ $list = [];
+
+ foreach ($cities as $city) {
+ if ($this->postParam("q")) {
+ $q = trim(mb_strtolower($this->postParam("q")));
+
+ $name = trim(mb_strtolower($city["name"]));
+ $native_name = trim(mb_strtolower($city["native_name"]));
+
+ if ($q == $name || $q == $native_name) {
+ $list[] = $city;
+ break;
+ }
+
+ preg_match('/' . $q . '/i', $name, $name_matches);
+ preg_match('/' . $q . '/i', $native_name, $native_name_matches);
+
+ if (sizeof($name_matches) > 0 || sizeof($native_name_matches) > 0) {
+ $list[] = $city;
+ }
+ } else {
+ $list[] = $city;
+ }
+ }
+
+ $this->returnJson(["success" => true, "list" => $list]);
+ break;
+
+ case "schools":
+ $city = $this->cities->get((int)$this->postParam("city"));
+ if (!$city) $this->notFound();
+
+ $schools = $this->education->getSchools($city->getCountry()->getId(), $city->getId());
+ break;
+
+ case "country":
+ $country = $this->countries->get((int)$this->queryParam("id"));
+ if (!$country || $country->isDeleted()) $this->returnJson(["success" => false, "error" => "Страна не найдена"]);
+
+ $city_id = NULL;
+ if ($this->queryParam("city")) {
+ $city = $this->cities->get((int)$this->queryParam("city"));
+ if ($city && ($city->getCountry()->getId() === $country->getId())) {
+ $city_id = $city->getId();
+ }
+ }
+
+ if ($this->queryParam("edu")) {
+ $view = in_array($this->queryParam("view"), ["schools", "universities", "faculties"]) ? $this->queryParam("view") : "schools";
+ if ($view === "schools") {
+ $schools = $this->education->getSchools($country->getId(), $city_id);
+ $response = [];
+ foreach ($schools as $school) {
+ $response[] = $school->getSimplified();
+ }
+ } else if ($view === "faculties") {
+ $university = $this->education->getUniversity((int)$this->queryParam("uid"));
+ if (!$university) $this->returnJson(["success" => false, "error" => "Университет не найден"]);
+
+ $faculties = iterator_to_array($this->faculties->getList((int)$this->queryParam("uid"), false, true));
+ $response = $faculties;
+ } else {
+ $universities = $this->education->getUniversities($country->getId(), $city_id);
+ $response = [];
+
+ if ($this->queryParam("uid") && $this->queryParam("n") === "faculties") {
+ foreach ($universities as $university) {
+ if ($university->getId() === (int)$this->queryParam("uid")) {
+ $_faculties = $university->getFaculties();
+ foreach ($_faculties as $faculty) {
+ $_faculty = $faculty->getSimplified();
+ $specializations = $faculty->getSpecializations(false, true);
+ $_faculty["specializations"] = [];
+ foreach ($specializations as $specialization) {
+ $_faculty["specializations"][] = $specialization;
+ }
+ $response[] = $_faculty;
+ }
+ }
+ }
+ } else if ($this->queryParam("fid") && $this->queryParam("n") === "specializations") {
+ $faculty = $this->faculties->get((int)$this->queryParam("fid"));
+ $response = iterator_to_array($faculty->getSpecializations(false, true));
+ } else {
+ foreach ($universities as $university) {
+ $_university = $university->getSimplified();
+ $_faculties = $university->getFaculties();
+ $_university["faculties"] = [];
+ foreach ($_faculties as $key => $value) {
+ $_faculty = $value->getSimplified();
+ $specializations = $value->getSpecializations(false, true);
+ $_faculty["specializations"] = [];
+ foreach ($specializations as $specialization) {
+ $_faculty["specializations"][] = $specialization;
+ }
+ $_university["faculties"][$key] = $_faculty;
+ }
+
+ $response[] = $_university;
+ }
+ }
+ }
+
+ $response = ["success" => true, "list" => $response];
+ if ($city_id) $response["city"] = $city->getNativeName();
+ $this->returnJson($response);
+ }
+ break;
+
+ case "new_request":
+ $view = in_array($this->queryParam("tab"), ["cities", "schools", "universities", "faculties", "specializations"]) ? $this->queryParam("tab") : "cities";
+
+ $country = $this->countries->get((int)$this->postParam("country"));
+ if (!$country || $country->isDeleted())
+ $this->returnJson(["success" => false, "error" => "Страна не найдена"]);
+
+ $models = [
+ "cities" => "openvk\\Web\\Models\\Entities\\GeodbCity",
+ "schools" => "openvk\\Web\\Models\\Entities\\GeodbSchool",
+ "universities" => "openvk\\Web\\Models\\Entities\\GeodbUniversity",
+ "faculties" => "openvk\\Web\\Models\\Entities\\GeodbFaculty",
+ "specializations" => "openvk\\Web\\Models\\Entities\\GeodbSpecialization"
+ ];
+
+ $repos = [
+ "cities" => "openvk\\Web\\Models\\Repositories\\GeodbCities",
+ "schools" => "openvk\\Web\\Models\\Repositories\\GeodbEducation",
+ "universities" => "openvk\\Web\\Models\\Repositories\\GeodbEducation",
+ "faculties" => "openvk\\Web\\Models\\Repositories\\GeodbFaculties",
+ "specializations" => "openvk\\Web\\Models\\Repositories\\GeodbSpecializations",
+ ];
+
+ if (!$this->postParam("name"))
+ $this->returnJson(["success" => false, "error" => "Вы не ввели название " . ($view !== "cities" ? "" : "на английском")]);
+
+ if ($view === "cities" && !$this->postParam("native_name"))
+ $this->returnJson(["success" => false, "error" => "Вы не ввели родное название"]);
+
+ $item = new $models[$view];
+ $item->setName($this->postParam("name"));
+
+ if ($view !== "cities") {
+ $city = $this->cities->get((int)$this->postParam("city"));
+ if (!$city)
+ $this->returnJson(["success" => false, "error" => "Город не найден"]);
+
+ if (in_array($view, ["faculties", "specializations"])) {
+ $university = $this->education->getUniversity((int)$this->postParam("uid"));
+ if (!$university)
+ $this->returnJson(["success" => false, "error" => "Университет не найден"]);
+
+ if ($view === "faculties") $item->setUniversity($university->getId());
+
+ if ($view === "specializations") {
+ $faculty = $this->faculties->get((int)$this->postParam("fid"));
+ if (!$faculty)
+ $this->returnJson(["success" => false, "error" => "Факультет не найден"]);
+
+ $item->setFaculty((int)$this->postParam("fid"));
+ $item->setCountry($country->getId());
+ }
+ } else {
+ $item->setCountry($country->getId());
+ $item->setCity($city->getId());
+ }
+ } else {
+ $item->setCountry($country->getId());
+ $item->setNative_Name($this->postParam("native_name") ?? "");
+ }
+
+ $item->setIs_Request($this->user->identity->getId());
+ $item->save($this->user->identity, (new $repos[$view])->getTable($view));
+ $this->returnJson(["success" => true]);
+ break;
+
+ default:
+ $this->returnJson(["success" => false, "error" => "Неизвестная ошибка"]);
+ break;
+ }
+ }
+}
diff --git a/Web/Presenters/OpenVKPresenter.php b/Web/Presenters/OpenVKPresenter.php
index 710713e52..87900f2aa 100755
--- a/Web/Presenters/OpenVKPresenter.php
+++ b/Web/Presenters/OpenVKPresenter.php
@@ -7,7 +7,7 @@
use Latte\Engine as TemplatingEngine;
use openvk\Web\Models\Entities\IP;
use openvk\Web\Themes\Themepacks;
-use openvk\Web\Models\Repositories\{IPs, Users, APITokens, Tickets};
+use openvk\Web\Models\Repositories\{GeodbRights, IPs, Users, APITokens, Tickets};
use WhichBrowser;
abstract class OpenVKPresenter extends SimplePresenter
@@ -261,6 +261,9 @@ function onStartup(): void
$this->template->ticketAnsweredCount = (new Tickets)->getTicketsCountByUserId($this->user->id, 1);
if($user->can("write")->model("openvk\Web\Models\Entities\TicketReply")->whichBelongsTo(0))
$this->template->helpdeskTicketNotAnsweredCount = (new Tickets)->getTicketCount(0);
+
+ if ($this->user->identity->canEditGeodb())
+ $this->template->geodbRequestsCount = (new GeodbRights)->getRequestsCount();
}
header("X-OpenVK-User-Validated: $userValidated");
diff --git a/Web/Presenters/SearchPresenter.php b/Web/Presenters/SearchPresenter.php
index fadf9954c..26b35775f 100644
--- a/Web/Presenters/SearchPresenter.php
+++ b/Web/Presenters/SearchPresenter.php
@@ -1,7 +1,7 @@
$this->queryParam("type"),
"city" => $this->queryParam("city") != "" ? $this->queryParam("city") : NULL,
+ "country" => $this->queryParam("country") != "" ? $this->queryParam("country") : NULL,
"maritalstatus" => $this->queryParam("maritalstatus") != 0 ? $this->queryParam("maritalstatus") : NULL,
"with_photo" => $this->queryParam("with_photo"),
"status" => $this->queryParam("status") != "" ? $this->queryParam("status") : NULL,
diff --git a/Web/Presenters/UserPresenter.php b/Web/Presenters/UserPresenter.php
index 9cfa36544..723aae5fc 100644
--- a/Web/Presenters/UserPresenter.php
+++ b/Web/Presenters/UserPresenter.php
@@ -3,9 +3,20 @@
use Nette\InvalidStateException;
use openvk\Web\Util\Sms;
use openvk\Web\Themes\Themepacks;
-use openvk\Web\Models\Entities\{Photo, Post, EmailChangeVerification};
+use openvk\Web\Models\Entities\{GeodbFaculty, Photo, Post, EmailChangeVerification};
use openvk\Web\Models\Entities\Notifications\{CoinsTransferNotification, RatingUpNotification};
-use openvk\Web\Models\Repositories\{Users, Clubs, Albums, Videos, Notes, Vouchers, EmailChangeVerifications};
+use openvk\Web\Models\Repositories\{GeodbCities,
+ GeodbCountries,
+ GeodbEducation,
+ GeodbFaculties,
+ GeodbSpecializations,
+ Users,
+ Clubs,
+ Albums,
+ Videos,
+ Notes,
+ Vouchers,
+ EmailChangeVerifications};
use openvk\Web\Models\Exceptions\InvalidUserNameException;
use openvk\Web\Util\Validator;
use Chandler\Security\Authenticator;
@@ -202,6 +213,24 @@ function renderEdit(): void
$user->setWebsite(NULL);
else
$user->setWebsite((!parse_url($website, PHP_URL_SCHEME) ? "https://" : "") . $website);
+
+ $country_id = $this->postParam("country-id") ?? 0;
+ if ($country_id) {
+ $country = (new GeodbCountries)->get((int) $country_id);
+ if ($country) {
+ $user->setCountry_Id($country_id);
+
+ $city_id = $this->postParam("city-id") ?? 0;
+ if ($city_id) {
+ $city = (new GeodbCities)->get((int) $city_id);
+ if ($city) {
+ if ($city->getCountry()->getId() === $country->getId()) {
+ $user->setCity_Id($city->getId());
+ }
+ }
+ }
+ }
+ }
} elseif($_GET['act'] === "interests") {
$user->setInterests(empty($this->postParam("interests")) ? NULL : ovk_proc_strtr($this->postParam("interests"), 300));
$user->setFav_Music(empty($this->postParam("fav_music")) ? NULL : ovk_proc_strtr($this->postParam("fav_music"), 300));
@@ -246,6 +275,51 @@ function renderEdit(): void
$this->returnJson([
"success" => true
]);
+ } elseif($_GET['act'] === "education") {
+ if ($this->requestParam("school-id")) {
+ $school = (new GeodbEducation)->getSchool((int) $this->postParam("school-id"));
+ if ($school) {
+ $user->setSchool_Id($school->getId());
+ }
+
+ $years = implode("**", [
+ ((int)$this->postParam("edu_start")) ?? NULL,
+ ((int)$this->postParam("edu_end")) ?? NULL,
+ ((int)$this->postParam("edu_graduation")) ?? NULL,
+ ]);
+
+ $user->setSchool_Years($years);
+ $user->setSchool_Specialization(mb_strlen(trim($this->postParam("edu_specialization"))) > 0 ? $this->postParam("edu_specialization") : NULL);
+ } else if ($this->requestParam("university-id")) {
+ $university = (new GeodbEducation)->getUniversity((int) $this->postParam("university-id"));
+ if ($university) {
+ $user->setUniversity($university->getId());
+
+ if ($this->postParam("faculty-id")) {
+ $faculty = (new GeodbFaculties)->get((int)$this->postParam("faculty-id"));
+ if ($faculty && ($faculty->getUniversity()->getId() === $university->getId())) {
+ $user->setUniversity_Faculty($faculty->getId());
+
+ if ($this->postParam("specialization-id")) {
+ $specialization = (new GeodbSpecializations)->get((int) $this->postParam("specialization-id"));
+ if ($specialization && ($specialization->getFaculty()->getId() === $faculty->getId()) && ($specialization->getUniversity()->getId() === $university->getId())) {
+ $user->setUniversity_Specialization($specialization->getId());
+ }
+ }
+ }
+ }
+
+ $years = implode("**", [
+ ((int)$this->postParam("edu_university_start")) ?? NULL,
+ ((int)$this->postParam("edu_university_end")) ?? NULL,
+ ((int)$this->postParam("edu_university_graduation")) ?? NULL,
+ ]);
+
+ $user->setUniversity_Years($years);
+ }
+ } else {
+ $this->flashFail("err", tr("error"), "Вы не выбрали школу или университет");
+ }
}
try {
@@ -261,7 +335,7 @@ function renderEdit(): void
}
$this->template->mode = in_array($this->queryParam("act"), [
- "main", "contacts", "interests", "avatar", "backdrop"
+ "main", "contacts", "education", "interests", "avatar", "backdrop"
]) ? $this->queryParam("act")
: "main";
diff --git a/Web/Presenters/templates/@layout.xml b/Web/Presenters/templates/@layout.xml
index 1718c4990..82a59f55b 100644
--- a/Web/Presenters/templates/@layout.xml
+++ b/Web/Presenters/templates/@layout.xml
@@ -201,9 +201,17 @@
{var $canAccessAdminPanel = $thisUser->getChandlerUser()->can("access")->model("admin")->whichBelongsTo(NULL)}
{var $canAccessHelpdesk = $thisUser->getChandlerUser()->can("write")->model('openvk\Web\Models\Entities\TicketReply')->whichBelongsTo(0)}
+ {var $canEditGeodb = $thisUser->canEditGeodb()}
{var $menuLinksAvaiable = sizeof(OPENVK_ROOT_CONF['openvk']['preferences']['menu']['links']) > 0 && $thisUser->getLeftMenuItemStatus('links')}
|
+
+ |
+
+
+
+ лог действий
+
+ |
+
|
+
+ |
+
+
+
+
+
+ {$log->getType()} {$log->getObjectType()} {$log->getObjectName()}
+
+
+
+ {$log->getLogsText()|noescape}+ |
+
|
+
+ |
+
+
+
+ предлагает добавить {$type}
+ {$mode === "cities" ? $request[0]->getNativeName() : $request[0]->getName()}
+
+
+
+
+
+ |
+
{_main}| + Школа: + | ++ + {$user->getSchool()->getName()} + + | +
| + Год начала обучения: + | ++ + {$user->getSchoolYears()[0]} + + | +
| + Год окончания обучения: + | ++ + {$user->getSchoolYears()[1]} + + | +
| + Год выпуска: + | ++ + {$user->getSchoolYears()[2]} + + | +
| + Специализация: + | ++ + {$user->getSchoolSpecialization()} + + | +
| + Университет: + | ++ + {$user->getUniversity()->getName()} + + | +
| + Год начала обучения: + | ++ + {$user->getUniversityYears()[0]} + + | +
| + Год окончания обучения: + | ++ + {$user->getUniversityYears()[1]} + + | +
| + Год выпуска: + | ++ + {$user->getUniversityYears()[2]} + + | +
| + Факультет: + | ++ + {$user->getUniversityFaculty()->getName()} + + | +
| + Специализация: + | ++ + {$user->getUniversitySpecialization()->getName()} + + | +