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')} {_admin} + + Заявки Геодб + {if $geodbRequestsCount > 0} + ({$geodbRequestsCount}) + {/if} + + Страны {_helpdesk} {if $helpdeskTicketNotAnsweredCount > 0} ({$helpdeskTicketNotAnsweredCount}) diff --git a/Web/Presenters/templates/Geodb/AddCity.xml b/Web/Presenters/templates/Geodb/AddCity.xml new file mode 100644 index 000000000..6fd71a03d --- /dev/null +++ b/Web/Presenters/templates/Geodb/AddCity.xml @@ -0,0 +1,19 @@ +{extends "../@layout.xml"} + +{block title}Добавить город{/block} +{block header}{include title}{/block} + +{block content} + {include "./tabs.xml", mode => $mode, country => $country} +
+
+

{$country->getCanonicalName()} → Добавить город

+
+ + + + + +
+
+{/block} diff --git a/Web/Presenters/templates/Geodb/AddCountry.xml b/Web/Presenters/templates/Geodb/AddCountry.xml new file mode 100644 index 000000000..c595bba08 --- /dev/null +++ b/Web/Presenters/templates/Geodb/AddCountry.xml @@ -0,0 +1,41 @@ +{extends "../@layout.xml"} + +{block title}Добавить страну{/block} +{block header}{include title}{/block} + +{block content} + {include "./tabs.xml", mode => $mode, country => $country} +
+
+

Добавить страну

+
+ + +
+ Флаг: +
+ + + + + +
+ +
+{/block} diff --git a/Web/Presenters/templates/Geodb/AddEdu.xml b/Web/Presenters/templates/Geodb/AddEdu.xml new file mode 100644 index 000000000..657ba5832 --- /dev/null +++ b/Web/Presenters/templates/Geodb/AddEdu.xml @@ -0,0 +1,41 @@ +{extends "../@layout.xml"} + +{block title}{$title}{/block} +{block header}{include title}{/block} + +{block content} + {include "./tabs.xml", mode => $mode, country => $country} +
+
+
+

{$country->getCanonicalName()} → {include title}

+
+
+ + Город: + + + + +
+
+ + + + +
Ничего не найдено
+ + +
+ + + + + +
+
+
+ {include "./GeodbForAdmins.js.xml", view => $view} +{/block} diff --git a/Web/Presenters/templates/Geodb/City.xml b/Web/Presenters/templates/Geodb/City.xml new file mode 100644 index 000000000..24f8a8a44 --- /dev/null +++ b/Web/Presenters/templates/Geodb/City.xml @@ -0,0 +1,19 @@ +{extends "../@layout.xml"} + +{block title}Редактировать город{/block} +{block header}{include title}{/block} + +{block content} +{include "./tabs.xml", mode => $mode, country => $country} +
+
+

{$country->getCanonicalName()} → {$city->getCanonicalName()}

+
+ + + + + +
+
+{/block} diff --git a/Web/Presenters/templates/Geodb/Countries.xml b/Web/Presenters/templates/Geodb/Countries.xml new file mode 100644 index 000000000..22b419126 --- /dev/null +++ b/Web/Presenters/templates/Geodb/Countries.xml @@ -0,0 +1,63 @@ +{extends "../@layout.xml"} + +{block title}Страны{/block} +{block header}{include title}{/block} + +{block content} +{include "./tabs.xml", mode => $mode, country => $country} +
+
+
+ +
+
+
+
+ {include "../components/nothing.xml"} +
+
+
+ +

+ + [#{$country->getId()}] {$country->getCanonicalName()} +

+
+
+ +
|
+ +
|
+ +
+
+
+
+
+
+
+
+
+
+ {include "./GeodbForAdmins.js.xml", countries => $countries} +
+{/block} diff --git a/Web/Presenters/templates/Geodb/Country.xml b/Web/Presenters/templates/Geodb/Country.xml new file mode 100644 index 000000000..570006de0 --- /dev/null +++ b/Web/Presenters/templates/Geodb/Country.xml @@ -0,0 +1,199 @@ +{extends "../@layout.xml"} + +{block title}Страна{/block} +{block header}{include title}{/block} + +{block content} +{include "./tabs.xml", mode => $mode, country => $country} +
+
+

+ {$country->getCanonicalName()} + + → + + {if $city}{$city->getName()}{/if} + + +

+
+
+ +
+
+
+
+
+ +
+ Вузы +
+
+
+
+
+
+ +
+
+
+
+ + Город: + + + + +
+ +
+
+
+ {include "../components/nothing.xml"} +
+ + +
+
+
+
+ {include "../components/nothing.xml"} +
+ +
+
+
+ {include "../components/nothing.xml"} +
+ +
+ {include "./GeodbForAdmins.js.xml", country => $country, city => $city} +
+
+{/block} diff --git a/Web/Presenters/templates/Geodb/Editors.xml b/Web/Presenters/templates/Geodb/Editors.xml new file mode 100644 index 000000000..8a6f6a92d --- /dev/null +++ b/Web/Presenters/templates/Geodb/Editors.xml @@ -0,0 +1,153 @@ +{extends "../@layout.xml"} + +{block title}Редакторы базы{/block} +{block header}{include title}{/block} + +{block content} +{include "./tabs.xml", mode => $mode, country => $country} +
+
+
+ Добавить редактора базы +
+ +
+
+
+

Редакторы базы

+
+ +
+
+
+
+ {include "../components/nothing.xml"} +
+
+ {var $user = $editor[0]->getUser()} + + + + + + + +
+ + Фотография профиля + + + +
+
+
+

+
+ + + {$country->getCanonicalName()} + +
+ + + + + + образование + + + + + + + + города + + +
+ + Удалить + +
+

+
+
+
+
+ {include "./GeodbForAdmins.js.xml", countries => $countries, country => $country} +
+{/block} diff --git a/Web/Presenters/templates/Geodb/GeodbForAdmins.js.xml b/Web/Presenters/templates/Geodb/GeodbForAdmins.js.xml new file mode 100644 index 000000000..362178027 --- /dev/null +++ b/Web/Presenters/templates/Geodb/GeodbForAdmins.js.xml @@ -0,0 +1,951 @@ +{block content} + +{/block} diff --git a/Web/Presenters/templates/Geodb/GeodbForEdit.js.xml b/Web/Presenters/templates/Geodb/GeodbForEdit.js.xml new file mode 100644 index 000000000..eb3906e1e --- /dev/null +++ b/Web/Presenters/templates/Geodb/GeodbForEdit.js.xml @@ -0,0 +1,591 @@ +{block content} + +{/block} diff --git a/Web/Presenters/templates/Geodb/Logs.xml b/Web/Presenters/templates/Geodb/Logs.xml new file mode 100644 index 000000000..eb75bc105 --- /dev/null +++ b/Web/Presenters/templates/Geodb/Logs.xml @@ -0,0 +1,43 @@ +{extends "../@layout.xml"} + +{block title}Логи{/block} +{block header}{include title}{/block} + +{block content} +{include "./tabs.xml", mode => $mode, country => $country} +
+
+
+ {include "../components/nothing.xml"} +
+
+
+ {var $user = $log->getUser()} + + + + + + + +
+ + Фотография профиля + + +
+ +
+ {$log->getType()} {$log->getObjectType()} {$log->getObjectName()} +
+
+
{$log->getLogsText()|noescape}
+
+
+
+
+
+
+{/block} diff --git a/Web/Presenters/templates/Geodb/Requests.xml b/Web/Presenters/templates/Geodb/Requests.xml new file mode 100644 index 000000000..c66204cb7 --- /dev/null +++ b/Web/Presenters/templates/Geodb/Requests.xml @@ -0,0 +1,104 @@ +{extends "../@layout.xml"} + +{block title}Заявки Геодб{/block} +{block header}{include title}{/block} + +{block content} +
+ +
+
+ +
+
{include "../components/nothing.xml"}
+
+
+
+
+ + + + + + + +
+ + Фотография профиля + + +
+ + предлагает добавить {$type} + {$mode === "cities" ? $request[0]->getNativeName() : $request[0]->getName()} + + +
+
+
+
+ + + + +
+
+
+
+
+
+ {if $country || $current_country} + {include "./GeodbForAdmins.js.xml", countries => $countries} + {/if} +{/block} diff --git a/Web/Presenters/templates/Geodb/School.xml b/Web/Presenters/templates/Geodb/School.xml new file mode 100644 index 000000000..a2322d622 --- /dev/null +++ b/Web/Presenters/templates/Geodb/School.xml @@ -0,0 +1,96 @@ +{extends "../@layout.xml"} + +{block title}{$title}{/block} +{block header}{include title}{/block} + +{block content} +{include "./tabs.xml", mode => $mode, country => $country} +
+ +

{$school->getCity()->getNativeName()} → {$school->getName()}

+
+
+ + Город: + + + + +
+
+
+ +
+ +
Ничего не найдено
+ + +
+ + + + +
+ +
+
+
+
+
+

Факультеты

+ +
+ +
+ {include "../components/nothing.xml"} +
+ +
+{include "./GeodbForAdmins.js.xml", mode => $mode} +
+{/block} diff --git a/Web/Presenters/templates/Geodb/tabs.xml b/Web/Presenters/templates/Geodb/tabs.xml new file mode 100644 index 000000000..1f9fcab20 --- /dev/null +++ b/Web/Presenters/templates/Geodb/tabs.xml @@ -0,0 +1,61 @@ +{block tabs} + + +{/block} diff --git a/Web/Presenters/templates/Search/Index.xml b/Web/Presenters/templates/Search/Index.xml index 4d629890a..ec9f27b23 100644 --- a/Web/Presenters/templates/Search/Index.xml +++ b/Web/Presenters/templates/Search/Index.xml @@ -51,7 +51,7 @@ {/if} {if !is_null($_GET['city']) && $_GET['city'] != "" && $x->getPrivacySetting("page.info.read") > 1} - + {_city}: {$x->getCity()} @@ -293,6 +293,7 @@
{_main}
+ {_s_now_on_site} diff --git a/Web/Presenters/templates/User/Edit.xml b/Web/Presenters/templates/User/Edit.xml index 6df070ea8..5515bd9f5 100644 --- a/Web/Presenters/templates/User/Edit.xml +++ b/Web/Presenters/templates/User/Edit.xml @@ -12,6 +12,7 @@ {block content} {var $isMain = $mode === 'main'} {var $isContacts = $mode === 'contacts'} + {var $isEducation = $mode === 'education'} {var $isInterests = $mode === 'interests'} {var $isAvatar = $mode === 'avatar'} {var $isBackDrop = $mode === 'backdrop'} @@ -28,6 +29,9 @@ + @@ -205,10 +209,51 @@ - {_city}: + Страна: - + getCountry()}value='{$user->getCountry()}'{/if} /> + + + + + + + +
Ничего не найдено
+ + + + + + Город: + + + getCity()}value='{$user->getCity()}'{/if} /> + Я не могу найти свой город + + + + + + + +
Ничего не найдено
+ @@ -231,6 +276,198 @@ + {include "../Geodb/GeodbForEdit.js.xml", user => $user} + + {elseif $isEducation} + +

Школа

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ Город: + + +
+ + + + + +
+
+

Университет

+
+ + + + + + + + + + +
+
+ + + + +
+
+ + + + +
+
+ + + + + + + + + + + + + + + + + + + + + +
+ Город: + + +
+ Год начала обучения: + + +
+ Год окончания обучения: + + +
+ Год выпуска: + + +
+ + + + + +
+
+ {include "../Geodb/GeodbForEdit.js.xml", user => $user} {elseif $isInterests} diff --git a/Web/Presenters/templates/User/View.xml b/Web/Presenters/templates/User/View.xml index 1fa710263..e91e8913b 100644 --- a/Web/Presenters/templates/User/View.xml +++ b/Web/Presenters/templates/User/View.xml @@ -468,9 +468,13 @@ + + Страна: + {$user->getCountry()} + {_city}: - {$user->getCity()} + {$user->getCity()} {_address}: @@ -543,6 +547,128 @@ + {/capture} + {capture $uInfo_Education} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ Школа: + + + {$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()} + +
+ {/capture}
@@ -560,6 +686,17 @@
{_no_information_provided}
{/if}
+
+

+ Образование {ifset $thisUser}{if $thisUser->getId() == $user->getId()}[ {_edit} ]{/if}{/ifset} +

+ {if !empty($uInfo_Education)} + {$uInfo_Education|noescape} + {else} +
{_no_information_provided}
+ {/if} +
diff --git a/Web/di.yml b/Web/di.yml index 3363c5deb..556e4dbcf 100644 --- a/Web/di.yml +++ b/Web/di.yml @@ -49,3 +49,11 @@ services: - openvk\Web\Models\Repositories\BannedLinks - openvk\Web\Models\Repositories\ChandlerGroups - openvk\Web\Presenters\MaintenancePresenter + - openvk\Web\Presenters\GeodbPresenter + - openvk\Web\Models\Repositories\GeodbRights + - openvk\Web\Models\Repositories\GeodbCountries + - openvk\Web\Models\Repositories\GeodbCities + - openvk\Web\Models\Repositories\GeodbLogs + - openvk\Web\Models\Repositories\GeodbEducation + - openvk\Web\Models\Repositories\GeodbFaculties + - openvk\Web\Models\Repositories\GeodbSpecializations diff --git a/Web/routes.yml b/Web/routes.yml index d1a0e7aef..62c6b9d61 100644 --- a/Web/routes.yml +++ b/Web/routes.yml @@ -349,6 +349,10 @@ routes: handler: "About->dev" - url: "/tour" handler: "About->tour" + - url: "/editdb" + handler: "Geodb->index" + - url: "/geodb" + handler: "Geodb->forUser" - url: "/{?shortCode}" handler: "UnknownTextRouteStrategy->delegate" placeholders: diff --git a/Web/static/img/common.png b/Web/static/img/common.png new file mode 100644 index 000000000..0c54bf0f1 Binary files /dev/null and b/Web/static/img/common.png differ diff --git a/install/sqls/00038-geodb.sql b/install/sqls/00038-geodb.sql new file mode 100644 index 000000000..9a3f7c403 --- /dev/null +++ b/install/sqls/00038-geodb.sql @@ -0,0 +1,141 @@ +CREATE TABLE `geodb_cities` ( + `id` bigint(20) UNSIGNED NOT NULL, + `country` bigint(20) UNSIGNED NOT NULL, + `name` tinytext COLLATE utf8mb4_unicode_ci NOT NULL, + `native_name` tinytext COLLATE utf8mb4_unicode_ci NOT NULL, + `deleted` tinyint(1) NOT NULL DEFAULT 0, + `is_request` bigint(20) UNSIGNED DEFAULT 0 +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +INSERT INTO `geodb_cities` (`id`, `country`, `name`, `native_name`, `deleted`, `is_request`) VALUES +(1, 1, 'Voskresensk', 'Воскресенск', 0, 0), +(2, 2, 'Los Angeles', 'Лос-Анджелес', 0, 0); + +CREATE TABLE `geodb_countries` ( + `id` bigint(20) UNSIGNED NOT NULL, + `code` tinytext COLLATE utf8mb4_unicode_ci NOT NULL, + `flag` tinytext COLLATE utf8mb4_unicode_ci NOT NULL, + `name` tinytext COLLATE utf8mb4_unicode_ci NOT NULL, + `native_name` tinytext COLLATE utf8mb4_unicode_ci DEFAULT NULL, + `deleted` tinyint(1) NOT NULL DEFAULT 0, + `is_log` tinyint(1) NOT NULL DEFAULT 0 +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +INSERT INTO `geodb_countries` (`id`, `code`, `flag`, `name`, `native_name`, `deleted`, `is_log`) VALUES +(1, 'ru', 'ru', 'Russia', 'Россия', 0, 0), +(2, 'us', 'us', 'USA', 'США', 0, 0); + +CREATE TABLE `geodb_editors` ( + `id` bigint(20) UNSIGNED NOT NULL, + `uid` bigint(20) UNSIGNED NOT NULL, + `country` bigint(20) UNSIGNED NOT NULL, + `edu` tinyint(1) NOT NULL DEFAULT 0, + `cities` tinyint(1) NOT NULL DEFAULT 0, + `deleted` tinyint(1) NOT NULL DEFAULT 0 +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +CREATE TABLE `geodb_faculties` ( + `id` bigint(20) UNSIGNED NOT NULL, + `university` bigint(20) UNSIGNED NOT NULL, + `name` tinytext COLLATE utf8mb4_unicode_ci NOT NULL, + `deleted` tinyint(1) NOT NULL DEFAULT 0, + `is_request` bigint(20) NOT NULL DEFAULT 0 +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +CREATE TABLE `geodb_logs` ( + `id` bigint(20) UNSIGNED NOT NULL, + `user` bigint(20) UNSIGNED NOT NULL, + `type` int(11) NOT NULL, + `object_table` mediumtext COLLATE utf8mb4_unicode_ci NOT NULL, + `object_model` mediumtext COLLATE utf8mb4_unicode_ci NOT NULL, + `object_id` bigint(20) NOT NULL, + `logs_text` longtext COLLATE utf8mb4_unicode_ci NOT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +CREATE TABLE `geodb_schools` ( + `id` bigint(20) UNSIGNED NOT NULL, + `country` bigint(20) UNSIGNED NOT NULL, + `city` bigint(20) UNSIGNED NOT NULL, + `name` tinytext COLLATE utf8mb4_unicode_ci NOT NULL, + `deleted` tinyint(1) NOT NULL DEFAULT 0, + `is_request` bigint(20) UNSIGNED NOT NULL DEFAULT 0 +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +CREATE TABLE `geodb_specializations` ( + `id` bigint(20) UNSIGNED NOT NULL, + `country` bigint(20) UNSIGNED NOT NULL, + `faculty` bigint(20) UNSIGNED NOT NULL, + `name` tinytext COLLATE utf8mb4_unicode_ci NOT NULL, + `deleted` tinyint(1) NOT NULL DEFAULT 0, + `is_request` bigint(20) UNSIGNED NOT NULL DEFAULT 0 +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +CREATE TABLE `geodb_universities` ( + `id` bigint(20) UNSIGNED NOT NULL, + `country` bigint(20) UNSIGNED NOT NULL, + `city` bigint(20) UNSIGNED NOT NULL, + `name` tinytext COLLATE utf8mb4_unicode_ci NOT NULL, + `deleted` tinyint(1) NOT NULL DEFAULT 0, + `is_request` bigint(20) UNSIGNED NOT NULL DEFAULT 0 +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + + +ALTER TABLE `geodb_cities` + ADD PRIMARY KEY (`id`); + +ALTER TABLE `geodb_countries` + ADD PRIMARY KEY (`id`); + +ALTER TABLE `geodb_editors` + ADD PRIMARY KEY (`id`); + +ALTER TABLE `geodb_faculties` + ADD PRIMARY KEY (`id`); + +ALTER TABLE `geodb_logs` + ADD PRIMARY KEY (`id`); + +ALTER TABLE `geodb_schools` + ADD PRIMARY KEY (`id`); + +ALTER TABLE `geodb_specializations` + ADD PRIMARY KEY (`id`); + +ALTER TABLE `geodb_universities` + ADD PRIMARY KEY (`id`); + +ALTER TABLE `geodb_cities` + MODIFY `id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=3; + +ALTER TABLE `geodb_countries` + MODIFY `id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=3; + +ALTER TABLE `geodb_editors` + MODIFY `id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT; + +ALTER TABLE `geodb_faculties` + MODIFY `id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT; + +ALTER TABLE `geodb_logs` + MODIFY `id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT; + +ALTER TABLE `geodb_schools` + MODIFY `id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT; + +ALTER TABLE `geodb_specializations` + MODIFY `id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT; + +ALTER TABLE `geodb_universities` + MODIFY `id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT; + +ALTER TABLE `profiles` + ADD `country` VARCHAR(60) NULL DEFAULT NULL AFTER `activated`, + ADD `country_id` BIGINT UNSIGNED NULL DEFAULT NULL AFTER `country`, + ADD `city_id` BIGINT UNSIGNED NULL DEFAULT NULL AFTER `country_id`, + ADD `school_id` BIGINT UNSIGNED NULL DEFAULT NULL AFTER `city_id`, + ADD `school_years` TINYTEXT NULL DEFAULT NULL AFTER `school_id`, + ADD `school_specialization` TINYTEXT NULL DEFAULT NULL AFTER `school_years`, + ADD `university_years` TINYTEXT NULL DEFAULT NULL AFTER `school_specialization`, + ADD `university_specialization` TINYTEXT NULL DEFAULT NULL AFTER `university_years`, + ADD `university` BIGINT UNSIGNED NULL DEFAULT NULL AFTER `university_specialization`, + ADD `university_faculty` BIGINT UNSIGNED NULL DEFAULT NULL AFTER `university`; diff --git a/locales/ru.strings b/locales/ru.strings index 6faa5e2e2..410459290 100644 --- a/locales/ru.strings +++ b/locales/ru.strings @@ -1430,3 +1430,22 @@ "mobile_like" = "Нравится"; "mobile_user_info_hide" = "Скрыть"; "mobile_user_info_show_details" = "Показать подробнее"; + +/* Geodb */ +"geodb_cities_zero" = "нет городов"; +"geodb_cities_one" = "$1 город"; +"geodb_cities_few" = "$1 города"; +"geodb_cities_many" = "$1 городов"; +"geodb_cities_other" = "$1 городов"; + +"geodb_schools_zero" = "нет школ"; +"geodb_schools_one" = "$1 школа"; +"geodb_schools_few" = "$1 школы"; +"geodb_schools_many" = "$1 школ"; +"geodb_schools_other" = "$1 школ"; + +"geodb_university_zero" = "нет вузов"; +"geodb_university_one" = "$1 вуз"; +"geodb_university_few" = "$1 вуза"; +"geodb_university_many" = "$1 вузов"; +"geodb_university_other" = "$1 вузов";