REBORN - попытка залатать дырки и заставить работать. Трудимся вместе с deepseek
This commit is contained in:
parent
205fb64180
commit
bc1fb7572f
|
|
@ -0,0 +1,204 @@
|
||||||
|
# План работ: wikipoints.ru
|
||||||
|
|
||||||
|
## Статус
|
||||||
|
|
||||||
|
- Бэкап БД: есть (`poi.sql`, 18 таблиц, 868 строк)
|
||||||
|
- Google Maps API key: **просрочен** (`AIzaSyDuWmguxO35oV9WGc6D8xUPvQBaUS4kt78`)
|
||||||
|
- SMS.ru / Alarmer: ключи устарели, но не критично
|
||||||
|
- uLogin: **выпилить**, заменить на вход по email + пароль
|
||||||
|
- Подтверждение email: через **Resend** (добавить колонки `email`, `password`, `emailConfirmed`)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 1. База данных
|
||||||
|
|
||||||
|
### 1.1 Импортировать `poi.sql`
|
||||||
|
```sql
|
||||||
|
mysql -u root -p poi < poi.sql
|
||||||
|
```
|
||||||
|
|
||||||
|
### 1.2 Расширить таблицу `users`
|
||||||
|
```sql
|
||||||
|
ALTER TABLE users
|
||||||
|
ADD COLUMN `email` varchar(255) DEFAULT NULL AFTER `uid`,
|
||||||
|
ADD COLUMN `password` varchar(255) DEFAULT NULL AFTER `email`,
|
||||||
|
ADD COLUMN `emailConfirmed` tinyint(1) NOT NULL DEFAULT 0 AFTER `password`,
|
||||||
|
ADD COLUMN `confirmToken` varchar(64) DEFAULT NULL AFTER `emailConfirmed`,
|
||||||
|
ADD UNIQUE KEY `email` (`email`);
|
||||||
|
```
|
||||||
|
|
||||||
|
Старым пользователям (через uLogin) проставить `emailConfirmed = 1` — они не могут войти по паролю, но не теряют доступ. Новые регистрируются только через email+пароль.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2. Авторизация (выпил uLogin)
|
||||||
|
|
||||||
|
### 2.1 Новый контроллер `AuthController` или методы в `IndexController`
|
||||||
|
|
||||||
|
**actionRegister** — регистрация:
|
||||||
|
- Поля: email, пароль (2 раза), ник
|
||||||
|
- Валидация: email уникальный, пароль ≥ 6 символов
|
||||||
|
- Хеш пароля: `password_hash($pass, PASSWORD_BCRYPT)`
|
||||||
|
- Генерация `confirmToken = bin2hex(random_bytes(32))`
|
||||||
|
- Отправка письма через Resend с ссылкой `/auth/confirm?token=...`
|
||||||
|
- После успеха: флеш-сообщение «Проверьте почту»
|
||||||
|
|
||||||
|
**actionLogin** — вход (заменить старый ulogin):
|
||||||
|
- Форма: email + пароль
|
||||||
|
- Поиск пользователя по email, проверка `password_verify()`
|
||||||
|
- Если `emailConfirmed = 0` — «Подтвердите email»
|
||||||
|
- Успех: `App::userLogin($user)`, редирект
|
||||||
|
|
||||||
|
**actionLogout** — без изменений (уже работает)
|
||||||
|
|
||||||
|
**actionConfirm** — подтверждение email:
|
||||||
|
- Проверить `confirmToken`, проставить `emailConfirmed = 1`, очистить токен
|
||||||
|
- Автоматический вход, редирект на главную
|
||||||
|
|
||||||
|
**actionForgot** — восстановление пароля:
|
||||||
|
- Форма email → поиск пользователя → Resend c токеном сброса
|
||||||
|
- Новая колонка `resetToken` (или переиспользовать `confirmToken`)
|
||||||
|
|
||||||
|
**actionReset** — сброс пароля:
|
||||||
|
- Проверить токен, показать форму нового пароля
|
||||||
|
|
||||||
|
### 2.2 Модель `User` — добавить методы
|
||||||
|
|
||||||
|
```php
|
||||||
|
function getByEmail($email) { ... }
|
||||||
|
static function hashPassword($pass) { return password_hash($pass, PASSWORD_BCRYPT); }
|
||||||
|
function verifyPassword($pass) { return password_verify($pass, $this->password); }
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2.3 Файлы для удаления/изменения
|
||||||
|
|
||||||
|
| Файл | Действие |
|
||||||
|
|------|----------|
|
||||||
|
| `views/modals/login.php` | Переписать целиком: убрать uLogin, вставить форму email+пароль + ссылку на регистрацию |
|
||||||
|
| `controllers/IndexController.php` (actionLogin) | Удалить ulogin-код, заменить на email/пароль |
|
||||||
|
| `views/layouts/*.php` (скрипт ulogin) | Убрать проверку `strpos($script, 'ulogin')` |
|
||||||
|
| `public/js/app.js` | Проверить и убрать ulogin-вызовы |
|
||||||
|
|
||||||
|
### 2.4 Шаблоны
|
||||||
|
|
||||||
|
- `views/modals/register.php` — новый
|
||||||
|
- `views/modals/login.php` — переписать
|
||||||
|
- `views/auth/confirm.php` — новый
|
||||||
|
- `views/auth/forgot.php` — новый
|
||||||
|
- `views/auth/reset.php` — новый
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3. Уведомления через Resend
|
||||||
|
|
||||||
|
### 3.1 Установка (без composer — вручную)
|
||||||
|
|
||||||
|
Скачать и положить в `classes/`:
|
||||||
|
- `classes/Resend.php` — простой класс-обёртка для Resend API (POST https://api.resend.com/emails)
|
||||||
|
- API-ключ через config.php: `'resendKey' => 're_...'`
|
||||||
|
|
||||||
|
### 3.2 Отправка писем
|
||||||
|
|
||||||
|
- Регистрация: подтверждение email (HTML-шаблон)
|
||||||
|
- Восстановление пароля
|
||||||
|
- (Опционально) уведомления о новых точках/комментариях
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 4. Google Maps API ключ
|
||||||
|
|
||||||
|
### 4.1 Файлы для замены
|
||||||
|
|
||||||
|
| Файл | Строка |
|
||||||
|
|------|--------|
|
||||||
|
| `controllers/JsonController.php:384,506` | `AIzaSyDuWmguxO35oV9WGc6D8xUPvQBaUS4kt78` → новый ключ |
|
||||||
|
|
||||||
|
### 4.2 Вынести в config
|
||||||
|
|
||||||
|
Добавить в `config.php`:
|
||||||
|
```php
|
||||||
|
'googleMapsKey' => 'НОВЫЙ_КЛЮЧ',
|
||||||
|
```
|
||||||
|
В коде:
|
||||||
|
```php
|
||||||
|
$key = App::getConfig('googleMapsKey');
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 5. Конфигурация
|
||||||
|
|
||||||
|
### 5.1 `config.php` — изменения
|
||||||
|
|
||||||
|
```php
|
||||||
|
return array(
|
||||||
|
'title' => '...',
|
||||||
|
'description' => '...',
|
||||||
|
'DB' => array(
|
||||||
|
'host' => 'localhost',
|
||||||
|
'user' => 'poi',
|
||||||
|
'password' => '...',
|
||||||
|
'dbname' => 'poi',
|
||||||
|
),
|
||||||
|
'images' => [...],
|
||||||
|
'version' => trim(file_get_contents(...)),
|
||||||
|
'metrika' => false, // отключить, ключей нет
|
||||||
|
'ganalytics' => false, // отключить
|
||||||
|
'disableSMS' => true, // SMS.ru не работает
|
||||||
|
'alarmerKey' => '', // не используется
|
||||||
|
'protocol' => 'http', // пока http
|
||||||
|
'googleMapsKey' => '...', // новый ключ
|
||||||
|
'resendKey' => 're_...', // ключ Resend
|
||||||
|
);
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 6. PHP-совместимость (минимальные правки)
|
||||||
|
|
||||||
|
| Проблема | Правка |
|
||||||
|
|----------|--------|
|
||||||
|
| `__autoload()` | Пока работает в PHP 7.4/8.x (deprecated, но не fatal). Совместимость не сломана |
|
||||||
|
| `die;` → `die();` | Косметика, не блокирует |
|
||||||
|
| PHP4-конструкторы | Проверить `Model.php` и `Controller.php` — если `Class() { parent::Class(); }` — заменить на `__construct()` |
|
||||||
|
| `mysql_*` | Уже нет, везде PDO |
|
||||||
|
|
||||||
|
После всех правок проверить:
|
||||||
|
```bash
|
||||||
|
php -l app.php
|
||||||
|
php -l controllers/*.php
|
||||||
|
php -l models/*.php
|
||||||
|
php -l classes/*.php
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 7. Порядок выполнения
|
||||||
|
|
||||||
|
```
|
||||||
|
1. config_template.php → скопировать, настроить БД, ключи
|
||||||
|
2. Импортировать poi.sql, выполнить ALTER TABLE users
|
||||||
|
3. Добавить класс Resend
|
||||||
|
4. Расширить модель User (email, password, getByEmail)
|
||||||
|
5. Создать AuthController (register, login, logout, confirm, forgot, reset)
|
||||||
|
6. Переписать views/modals/login.php (форма email+pass)
|
||||||
|
7. Создать views/modals/register.php
|
||||||
|
8. Создать шаблоны confirm/forgot/reset
|
||||||
|
9. Заменить Google Maps ключ в JsonController
|
||||||
|
10. Вычистить uLogin из layouts
|
||||||
|
11. Обновить config.php (resendKey, googleMapsKey, disableSMS, metrika/ganalytics)
|
||||||
|
12. Проверить php -l
|
||||||
|
13. Проверить в браузере
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Не делаем (осознанно)
|
||||||
|
|
||||||
|
- SQL-инъекции глобально — править только критичные места
|
||||||
|
- XSS-защита — не трогаем legacy
|
||||||
|
- Миграции — не пишем, всё через sql-файл
|
||||||
|
- Тесты — не пишем
|
||||||
|
- Composer — не добавляем
|
||||||
|
- CSRF — не добавляем
|
||||||
|
- Спрятать пароль БД в .env — в следующей итерации
|
||||||
|
|
@ -13,11 +13,11 @@ class IndexController extends Controller
|
||||||
self::addScript('/js/bootstrap.min.js');
|
self::addScript('/js/bootstrap.min.js');
|
||||||
self::addScript('/js/leaflet.js');
|
self::addScript('/js/leaflet.js');
|
||||||
|
|
||||||
self::addScript('https://maps.google.com/maps/api/js?v=3');
|
// self::addScript('https://maps.google.com/maps/api/js?v=3');
|
||||||
self::addScript('/js/tile/Google.js');
|
// self::addScript('/js/tile/Google.js');
|
||||||
|
|
||||||
self::addScript('https://api-maps.yandex.ru/2.0/?load=package.map&lang=ru-RU');
|
// self::addScript('https://api-maps.yandex.ru/2.0/?load=package.map&lang=ru-RU');
|
||||||
self::addScript('/js/tile/Yandex.js');
|
// self::addScript('/js/tile/Yandex.js');
|
||||||
|
|
||||||
self::addScript('/js/app.js?ver=' . App::getConfig('version'));
|
self::addScript('/js/app.js?ver=' . App::getConfig('version'));
|
||||||
self::addScript('/js/jquery.cookie.js');
|
self::addScript('/js/jquery.cookie.js');
|
||||||
|
|
@ -108,32 +108,74 @@ class IndexController extends Controller
|
||||||
|
|
||||||
static function actionLogin()
|
static function actionLogin()
|
||||||
{
|
{
|
||||||
$source = file_get_contents('https://ulogin.ru/token.php?token=' . $_POST['token'] . '&host=' . $_SERVER['HTTP_HOST']);
|
$email = isset($_POST['email']) ? trim($_POST['email']) : '';
|
||||||
$uLoginUser = json_decode($source, true);
|
$password = isset($_POST['password']) ? $_POST['password'] : '';
|
||||||
$uLoginUser['identity'] = md5($uLoginUser['uid'] . $uLoginUser['network'] . '=P');
|
|
||||||
|
|
||||||
$user = User::model()->getByUID($uLoginUser['identity']);
|
if (!$email || !$password) {
|
||||||
|
$_SESSION['login_error'] = 'Заполните email и пароль.';
|
||||||
|
App::redirect(isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : '/');
|
||||||
|
}
|
||||||
|
|
||||||
if (!$user->id) {
|
$user = User::model()->getByEmail($email);
|
||||||
$user = $user->add(array(
|
|
||||||
'uid' => $uLoginUser['identity'],
|
if (!$user || !$user->id || !$user->verifyPassword($password)) {
|
||||||
'nick' => $uLoginUser['nickname'],
|
$_SESSION['login_error'] = 'Неверный email или пароль.';
|
||||||
'name' => $uLoginUser['first_name'],
|
App::redirect(isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : '/');
|
||||||
'profile' => $uLoginUser['profile'],
|
}
|
||||||
'network' => $uLoginUser['network'],
|
|
||||||
'photo' => $uLoginUser['photo_big'],
|
if (!$user->emailConfirmed) {
|
||||||
|
$_SESSION['login_error'] = 'Email не подтверждён. Проверьте почту.';
|
||||||
|
App::redirect(isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : '/');
|
||||||
|
}
|
||||||
|
|
||||||
|
App::userLogin($user);
|
||||||
|
unset($_SESSION['login_error']);
|
||||||
|
App::redirect(isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : '/');
|
||||||
|
}
|
||||||
|
|
||||||
|
static function actionRegister()
|
||||||
|
{
|
||||||
|
$email = isset($_POST['email']) ? trim($_POST['email']) : '';
|
||||||
|
$nick = isset($_POST['nick']) ? trim($_POST['nick']) : '';
|
||||||
|
$password = isset($_POST['password']) ? $_POST['password'] : '';
|
||||||
|
$password2 = isset($_POST['password2']) ? $_POST['password2'] : '';
|
||||||
|
|
||||||
|
$error = '';
|
||||||
|
if (!$email || !$nick || !$password) {
|
||||||
|
$error = 'Заполните все поля.';
|
||||||
|
} elseif ($password !== $password2) {
|
||||||
|
$error = 'Пароли не совпадают.';
|
||||||
|
} elseif (strlen($password) < 6) {
|
||||||
|
$error = 'Пароль должен быть не менее 6 символов.';
|
||||||
|
} elseif (User::model()->getByEmail($email)) {
|
||||||
|
$error = 'Этот email уже зарегистрирован.';
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($error) {
|
||||||
|
$_SESSION['register_error'] = $error;
|
||||||
|
App::redirect(isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : '/');
|
||||||
|
}
|
||||||
|
|
||||||
|
$user = User::model()->add(array(
|
||||||
|
'uid' => md5($email . time()),
|
||||||
|
'email' => $email,
|
||||||
|
'nick' => $nick,
|
||||||
|
'name' => $nick,
|
||||||
|
'password' => User::hashPassword($password),
|
||||||
|
'profile' => '',
|
||||||
|
'network' => 'email',
|
||||||
|
'photo' => '',
|
||||||
|
'emailConfirmed' => 0,
|
||||||
|
'confirmToken' => bin2hex(random_bytes(32)),
|
||||||
));
|
));
|
||||||
|
|
||||||
if (!$user) {
|
if (!$user) {
|
||||||
return false;
|
$_SESSION['register_error'] = 'Ошибка регистрации. Попробуйте позже.';
|
||||||
}
|
App::redirect('/');
|
||||||
}
|
}
|
||||||
|
|
||||||
$target = App::getBasedir().'public/img/avatars/'.$user->id.'.jpg';
|
$_SESSION['register_success'] = 'Регистрация прошла успешно! Подтвердите email, перейдя по ссылке в письме.';
|
||||||
Image::createAvatar($uLoginUser['photo_big'], $target);
|
App::redirect('/');
|
||||||
|
|
||||||
App::userLogin($user);
|
|
||||||
App::redirect(isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : '/');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static function actionSitemap()
|
static function actionSitemap()
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@ class LpController extends Controller
|
||||||
|
|
||||||
public function __construct()
|
public function __construct()
|
||||||
{
|
{
|
||||||
|
App::error404();
|
||||||
self::$layout = 'layouts/lp.php';
|
self::$layout = 'layouts/lp.php';
|
||||||
self::addScript('/js/jquery-2.1.0.min.js');
|
self::addScript('/js/jquery-2.1.0.min.js');
|
||||||
self::addScript('/js/jquery-ui-1.10.4.custom.min.js');
|
self::addScript('/js/jquery-ui-1.10.4.custom.min.js');
|
||||||
|
|
|
||||||
|
|
@ -28,6 +28,31 @@ class User extends Model
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getByEmail($email)
|
||||||
|
{
|
||||||
|
$res = App::DB()->query('SELECT `id` FROM `' . $this->_tableName_ . '` WHERE `email` = ' . App::DB()->quote($email));
|
||||||
|
if ($res) {
|
||||||
|
$res = $res->fetch(PDO::FETCH_ASSOC);
|
||||||
|
if ($res) {
|
||||||
|
return $this->getByPK((int) $res['id']);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static function hashPassword($password)
|
||||||
|
{
|
||||||
|
return password_hash($password, PASSWORD_BCRYPT);
|
||||||
|
}
|
||||||
|
|
||||||
|
function verifyPassword($password)
|
||||||
|
{
|
||||||
|
if (!$this->password) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return password_verify($password, $this->password);
|
||||||
|
}
|
||||||
|
|
||||||
function getPointsCount()
|
function getPointsCount()
|
||||||
{
|
{
|
||||||
return Point::model()->getCountByUser($this->id);
|
return Point::model()->getCountByUser($this->id);
|
||||||
|
|
|
||||||
|
|
@ -70,18 +70,19 @@ function init(lat, lng) {
|
||||||
L.control.scale({imperial: false}).addTo(myMap);
|
L.control.scale({imperial: false}).addTo(myMap);
|
||||||
|
|
||||||
// layers['quest'] = L.tileLayer('https://otile1-s.mqcdn.com/tiles/1.0.0/osm/{z}/{x}/{y}.png', {attribution: 'Map data © <a href="http://openstreetmap.org" target="_blank">OpenStreetMap</a> contributors, <a href="http://creativecommons.org/licenses/by-sa/2.0/" target="_blank">CC-BY-SA</a>, Imagery © <a href="http://mapbox.com" target="_blank">Mapbox</a> | Points data © <a href="http://wikipoints.ru" target="_blank">WIKIPOINTS.RU</a>', maxZoom: 18});
|
// layers['quest'] = L.tileLayer('https://otile1-s.mqcdn.com/tiles/1.0.0/osm/{z}/{x}/{y}.png', {attribution: 'Map data © <a href="http://openstreetmap.org" target="_blank">OpenStreetMap</a> contributors, <a href="http://creativecommons.org/licenses/by-sa/2.0/" target="_blank">CC-BY-SA</a>, Imagery © <a href="http://mapbox.com" target="_blank">Mapbox</a> | Points data © <a href="http://wikipoints.ru" target="_blank">WIKIPOINTS.RU</a>', maxZoom: 18});
|
||||||
layers['sputnik'] = L.tileLayer('https://{s}.sputnik.wikipoints.ru/{z}/{x}/{y}.png', {attribution: 'Map data © <a href="http://openstreetmap.org" target="_blank">OpenStreetMap</a> contributors, <a href="http://sputnik.ru" target="_blank">Sputnik</a>, <a href="http://creativecommons.org/licenses/by-sa/2.0/" target="_blank">CC-BY-SA</a> | Points data © <a href="http://wikipoints.ru" target="_blank">WIKIPOINTS.RU</a>', maxZoom: 18});
|
// layers['sputnik'] = L.tileLayer('https://{s}.sputnik.wikipoints.ru/{z}/{x}/{y}.png', {attribution: 'Map data © <a href="http://openstreetmap.org" target="_blank">OpenStreetMap</a> contributors, <a href="http://sputnik.ru" target="_blank">Sputnik</a>, <a href="http://creativecommons.org/licenses/by-sa/2.0/" target="_blank">CC-BY-SA</a> | Points data © <a href="http://wikipoints.ru" target="_blank">WIKIPOINTS.RU</a>', maxZoom: 18});
|
||||||
|
// layers['sputnik'] = L.tileLayer('https://{s}.tilessputnik.ru/{z}/{x}/{y}.png', {attribution: 'Map data © <a href="http://openstreetmap.org" target="_blank">OpenStreetMap</a> contributors, <a href="http://sputnik.ru" target="_blank">Sputnik</a>, <a href="http://creativecommons.org/licenses/by-sa/2.0/" target="_blank">CC-BY-SA</a> | Points data © <a href="http://wikipoints.ru" target="_blank">WIKIPOINTS.RU</a>', maxZoom: 18});
|
||||||
layers['osm'] = L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {attribution: 'Map data © <a href="http://openstreetmap.org" target="_blank">OpenStreetMap</a> contributors, <a href="http://creativecommons.org/licenses/by-sa/2.0/" target="_blank">CC-BY-SA</a> | Points data © <a href="http://wikipoints.ru" target="_blank">WIKIPOINTS.RU</a>', maxZoom: 18});
|
layers['osm'] = L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {attribution: 'Map data © <a href="http://openstreetmap.org" target="_blank">OpenStreetMap</a> contributors, <a href="http://creativecommons.org/licenses/by-sa/2.0/" target="_blank">CC-BY-SA</a> | Points data © <a href="http://wikipoints.ru" target="_blank">WIKIPOINTS.RU</a>', maxZoom: 18});
|
||||||
layers['topo'] = L.tileLayer('https://topo.wikipoints.ru/?z={z}&x={x}&y={y}&ver=0216', {attribution: 'Map data © <a href="http://openstreetmap.org" target="_blank">OpenStreetMap</a> contributors, <a href="http://creativecommons.org/licenses/by-sa/2.0/" target="_blank">CC-BY-SA</a>, Imagery © <a href="http://www.marshruty.ru/" target="_blank">Маршруты.ру</a> | Points data © <a href="http://wikipoints.ru" target="_blank">WIKIPOINTS.RU</a>', maxZoom: 15});
|
layers['topo'] = L.tileLayer('https://topo.wikipoints.ru/?z={z}&x={x}&y={y}&ver=0216', {attribution: 'Map data © <a href="http://openstreetmap.org" target="_blank">OpenStreetMap</a> contributors, <a href="http://creativecommons.org/licenses/by-sa/2.0/" target="_blank">CC-BY-SA</a>, Imagery © <a href="http://www.marshruty.ru/" target="_blank">Маршруты.ру</a> | Points data © <a href="http://wikipoints.ru" target="_blank">WIKIPOINTS.RU</a>', maxZoom: 15});
|
||||||
layers['google'] = new L.Google('HYBRID');
|
// layers['google'] = new L.Google('HYBRID');
|
||||||
layers['yandexMap'] = new L.Yandex();
|
// layers['yandexMap'] = new L.Yandex();
|
||||||
layers['yandex'] = new L.Yandex('hybrid');
|
// layers['yandex'] = new L.Yandex('hybrid');
|
||||||
|
|
||||||
if ($.cookie('mapLayer') && $.cookie('mapLayer') == 'quest') {
|
if ($.cookie('mapLayer') && ($.cookie('mapLayer') != 'osm' || $.cookie('mapLayer') != 'topo')) {
|
||||||
setLayer('sputnik');
|
setLayer('osm');
|
||||||
}
|
}
|
||||||
|
|
||||||
setLayer($.cookie('mapLayer') ? $.cookie('mapLayer') : 'sputnik');
|
setLayer($.cookie('mapLayer') ? $.cookie('mapLayer') : 'osm');
|
||||||
|
|
||||||
initCategories(); // getPoints внутри
|
initCategories(); // getPoints внутри
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -29,13 +29,8 @@ if (App::$user) {
|
||||||
<span id="boxClose" onclick="closeBox();">×</span>
|
<span id="boxClose" onclick="closeBox();">×</span>
|
||||||
<div id="boxLayers">
|
<div id="boxLayers">
|
||||||
<h3>Карты</h3>
|
<h3>Карты</h3>
|
||||||
<!-- <span class="dot layers questLayer">⚫ </span><a onclick="setLayer('quest');return false;" class="layers questLayer">map Quest</a><br/>-->
|
|
||||||
<span class="dot layers sputnikLayer">⚫ </span><a onclick="setLayer('sputnik');return false;" class="layers sputnikLayer">OSM-Sputnik</a><br/>
|
|
||||||
<span class="dot layers osmLayer">⚫ </span><a onclick="setLayer('osm');return false;" class="layers osmLayer">Open Street Map</a><br/>
|
<span class="dot layers osmLayer">⚫ </span><a onclick="setLayer('osm');return false;" class="layers osmLayer">Open Street Map</a><br/>
|
||||||
<span class="dot layers topoLayer">⚫ </span><a onclick="setLayer('topo');return false;" class="layers topoLayer">Генштаб от маршруты.ру</a><br/>
|
<span class="dot layers topoLayer">⚫ </span><a onclick="setLayer('topo');return false;" class="layers topoLayer">Генштаб от маршруты.ру</a><br/>
|
||||||
<span class="dot layers googleLayer">⚫ </span><a onclick="setLayer('google');return false;" class="layers googleLayer">Google maps</a><br/>
|
|
||||||
<span class="dot layers yandexLayer">⚫ </span><a onclick="setLayer('yandex');return false;" class="layers yandexLayer">Яндекс.Карты</a><br/>
|
|
||||||
<span class="dot layers yandexMapLayer">⚫ </span><a onclick="setLayer('yandexMap');return false;" class="layers yandexMapLayer">Яндекс.Карты (схема)</a><br/>
|
|
||||||
</div>
|
</div>
|
||||||
<div id="boxFilter">
|
<div id="boxFilter">
|
||||||
<h3>Фильтры и поиск</h3>
|
<h3>Фильтры и поиск</h3>
|
||||||
|
|
@ -132,7 +127,7 @@ if (App::$user) {
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
</div>
|
</div>
|
||||||
<?= App::$user ? '' : self::renderPartial('modals/login.php', null, true) ?>
|
<?= App::$user ? '' : self::renderPartial('modals/login.php', null, true) . self::renderPartial('modals/register.php', null, true) ?>
|
||||||
<?= App::$user ? self::renderPartial('modals/addPoint.php', array('categories' => Category::model()->getCategoriesForChoise()), true) : '' ?>
|
<?= App::$user ? self::renderPartial('modals/addPoint.php', array('categories' => Category::model()->getCategoriesForChoise()), true) : '' ?>
|
||||||
<?= self::renderPartial('modals/categories.php', array('categories' => $categories), true) ?>
|
<?= self::renderPartial('modals/categories.php', array('categories' => $categories), true) ?>
|
||||||
<?= self::renderPartial('modals/image.php', array(), true) ?>
|
<?= self::renderPartial('modals/image.php', array(), true) ?>
|
||||||
|
|
|
||||||
|
|
@ -49,7 +49,7 @@
|
||||||
|
|
||||||
<?php if ($scripts): ?>
|
<?php if ($scripts): ?>
|
||||||
<?php foreach ($scripts as $script): ?>
|
<?php foreach ($scripts as $script): ?>
|
||||||
<script src="<?= $script ?>" <?= (strpos($script, 'ulogin') !== FALSE) ? 'async':'' ?> type="text/javascript"></script>
|
<script src="<?= $script ?>" type="text/javascript"></script>
|
||||||
<?php endforeach; ?>
|
<?php endforeach; ?>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
</html>
|
</html>
|
||||||
|
|
@ -60,7 +60,7 @@
|
||||||
|
|
||||||
<?php if ($scripts): ?>
|
<?php if ($scripts): ?>
|
||||||
<?php foreach ($scripts as $script): ?>
|
<?php foreach ($scripts as $script): ?>
|
||||||
<script src="<?= $script ?>" <?= (strpos($script, 'ulogin') !== FALSE) ? 'async':'' ?> type="text/javascript"></script>
|
<script src="<?= $script ?>" type="text/javascript"></script>
|
||||||
<?php endforeach; ?>
|
<?php endforeach; ?>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
</html>
|
</html>
|
||||||
|
|
@ -13,7 +13,7 @@
|
||||||
|
|
||||||
<?php if ($scripts): ?>
|
<?php if ($scripts): ?>
|
||||||
<?php foreach ($scripts as $script): ?>
|
<?php foreach ($scripts as $script): ?>
|
||||||
<script src="<?= $script ?>" <?= (strpos($script, 'ulogin') !== FALSE) ? 'async':'' ?> type="text/javascript"></script>
|
<script src="<?= $script ?>" type="text/javascript"></script>
|
||||||
<?php endforeach; ?>
|
<?php endforeach; ?>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@
|
||||||
|
|
||||||
<?php if ($scripts): ?>
|
<?php if ($scripts): ?>
|
||||||
<?php foreach ($scripts as $script): ?>
|
<?php foreach ($scripts as $script): ?>
|
||||||
<script src="<?= $script ?>" <?= (strpos($script, 'ulogin') !== FALSE) ? 'async':'' ?> type="text/javascript"></script>
|
<script src="<?= $script ?>" type="text/javascript"></script>
|
||||||
<?php endforeach; ?>
|
<?php endforeach; ?>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,7 @@
|
||||||
|
|
||||||
<?php if ($scripts): ?>
|
<?php if ($scripts): ?>
|
||||||
<?php foreach ($scripts as $script): ?>
|
<?php foreach ($scripts as $script): ?>
|
||||||
<script src="<?= $script ?>" <?= (strpos($script, 'ulogin') !== FALSE) ? 'async':'' ?> type="text/javascript"></script>
|
<script src="<?= $script ?>" type="text/javascript"></script>
|
||||||
<?php endforeach; ?>
|
<?php endforeach; ?>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,3 @@
|
||||||
<script src="//ulogin.ru/js/ulogin.js" async type="text/javascript"></script>
|
|
||||||
<div class="modal fade" id="loginModal" tabindex="-1" role="dialog" aria-hidden="true" style="display: none;">
|
<div class="modal fade" id="loginModal" tabindex="-1" role="dialog" aria-hidden="true" style="display: none;">
|
||||||
<div class="modal-dialog">
|
<div class="modal-dialog">
|
||||||
<div class="modal-content">
|
<div class="modal-content">
|
||||||
|
|
@ -6,18 +5,30 @@
|
||||||
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
|
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
|
||||||
<h4 class="modal-title">Вход на сайт</h4>
|
<h4 class="modal-title">Вход на сайт</h4>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-body" style="text-align: center; padding-bottom: 0;">
|
<form method="post" action="/index/login/">
|
||||||
|
<div class="modal-body" style="padding-bottom: 0;">
|
||||||
<p style="text-align: justify; text-indent: 15px;">
|
<p style="text-align: justify; text-indent: 15px;">
|
||||||
Для добавления точек, создания коллекции точек в избранном, сохранения маршрутов и использования ряда других функций, необходимо выполнить вход на сайт. Вход осуществляется через учётную запись в любой социальной сети. При этом вам не нужно вводить пароль - всё очень просто!
|
Для добавления точек, создания коллекции точек в избранном, сохранения маршрутов и использования ряда других функций, необходимо выполнить вход на сайт.
|
||||||
</p>
|
</p>
|
||||||
<p style="text-align: justify; text-indent: 15px;">
|
<?php if (isset($_SESSION['login_error']) && $_SESSION['login_error']): ?>
|
||||||
Мы сохраняем только ваше имя, ник и аватарку, не запрашивая лишних данных. Приятных путешествий!
|
<div class="alert alert-danger"><?= htmlspecialchars($_SESSION['login_error']) ?></div>
|
||||||
</p>
|
<?php unset($_SESSION['login_error']); ?>
|
||||||
<div style="display: inline-block;" id="uLogin" data-ulogin="display=panel;fields=first_name,nickname,photo_big;providers=twitter,mailru,vkontakte,google,yandex,facebook,instagram;hidden=odnoklassniki,livejournal,openid,foursquare,tumblr;redirect_uri=<?= App::getConfig('protocol', 'https') ?>%3A%2F%2F<?= $_SERVER['HTTP_HOST'] ?>%2Findex%2Flogin"></div>
|
<?php endif; ?>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="loginEmail">Email</label>
|
||||||
|
<input type="email" class="form-control" id="loginEmail" name="email" placeholder="email@example.com" required>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="loginPassword">Пароль</label>
|
||||||
|
<input type="password" class="form-control" id="loginPassword" name="password" placeholder="Пароль" required>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-footer">
|
<div class="modal-footer">
|
||||||
|
<button type="submit" class="btn btn-success">Войти</button>
|
||||||
|
<button type="button" class="btn btn-link" onclick="$('#loginModal').modal('hide');$('#registerModal').modal('show');">Регистрация</button>
|
||||||
<button type="button" class="btn btn-default" data-dismiss="modal">Отмена</button>
|
<button type="button" class="btn btn-default" data-dismiss="modal">Отмена</button>
|
||||||
</div>
|
</div>
|
||||||
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -0,0 +1,43 @@
|
||||||
|
<div class="modal fade" id="registerModal" tabindex="-1" role="dialog" aria-hidden="true" style="display: none;">
|
||||||
|
<div class="modal-dialog">
|
||||||
|
<div class="modal-content">
|
||||||
|
<div class="modal-header">
|
||||||
|
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
|
||||||
|
<h4 class="modal-title">Регистрация</h4>
|
||||||
|
</div>
|
||||||
|
<form method="post" action="/index/register/">
|
||||||
|
<div class="modal-body" style="padding-bottom: 0;">
|
||||||
|
<?php if (isset($_SESSION['register_error']) && $_SESSION['register_error']): ?>
|
||||||
|
<div class="alert alert-danger"><?= htmlspecialchars($_SESSION['register_error']) ?></div>
|
||||||
|
<?php unset($_SESSION['register_error']); ?>
|
||||||
|
<?php endif; ?>
|
||||||
|
<?php if (isset($_SESSION['register_success']) && $_SESSION['register_success']): ?>
|
||||||
|
<div class="alert alert-success"><?= htmlspecialchars($_SESSION['register_success']) ?></div>
|
||||||
|
<?php unset($_SESSION['register_success']); ?>
|
||||||
|
<?php endif; ?>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="regEmail">Email</label>
|
||||||
|
<input type="email" class="form-control" id="regEmail" name="email" placeholder="email@example.com" required>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="regNick">Имя (ник)</label>
|
||||||
|
<input type="text" class="form-control" id="regNick" name="nick" placeholder="Ваше имя" required>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="regPassword">Пароль</label>
|
||||||
|
<input type="password" class="form-control" id="regPassword" name="password" placeholder="Минимум 6 символов" minlength="6" required>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="regPassword2">Повторите пароль</label>
|
||||||
|
<input type="password" class="form-control" id="regPassword2" name="password2" placeholder="Повторите пароль" minlength="6" required>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="modal-footer">
|
||||||
|
<button type="submit" class="btn btn-success">Зарегистрироваться</button>
|
||||||
|
<button type="button" class="btn btn-link" onclick="$('#registerModal').modal('hide');$('#loginModal').modal('show');">Уже есть аккаунт? Войти</button>
|
||||||
|
<button type="button" class="btn btn-default" data-dismiss="modal">Отмена</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
@ -55,20 +55,7 @@ $oldIndex = $pagesCount+1;
|
||||||
<?php else: ?>
|
<?php else: ?>
|
||||||
<br/>
|
<br/>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
<div class="row">
|
|
||||||
<div class="col-md-12" style="text-align: center;">
|
|
||||||
<script async src="//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script>
|
|
||||||
<!-- Point - DOWN -->
|
|
||||||
<ins class="adsbygoogle"
|
|
||||||
style="display:block"
|
|
||||||
data-ad-client="ca-pub-0069680015252793"
|
|
||||||
data-ad-slot="4972494746"
|
|
||||||
data-ad-format="auto"></ins>
|
|
||||||
<script>
|
|
||||||
(adsbygoogle = window.adsbygoogle || []).push({});
|
|
||||||
</script>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<hr/>
|
<hr/>
|
||||||
<?= self::renderPartial('randomPoint.php', array('randomPoint'=>$randomPoint), true)?>
|
<?= self::renderPartial('randomPoint.php', array('randomPoint'=>$randomPoint), true)?>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,6 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-4">
|
<div class="col-md-4">
|
||||||
<h4 style="text-align: center;">Контакты</h4>
|
<h4 style="text-align: center;">Контакты</h4>
|
||||||
Телефон: <a href="tel:+79046106141">+7 (904) 610-6141</a><br/>
|
|
||||||
EMail: info@wikipoints.ru<br/>
|
EMail: info@wikipoints.ru<br/>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-4">
|
<div class="col-md-4">
|
||||||
|
|
|
||||||
|
|
@ -51,16 +51,6 @@ $oldIndex = $pagesCount+1;
|
||||||
}
|
}
|
||||||
?>
|
?>
|
||||||
<br/><br/>
|
<br/><br/>
|
||||||
<script async src="//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script>
|
|
||||||
<!-- Point-TOP -->
|
|
||||||
<ins class="adsbygoogle"
|
|
||||||
style="display:block"
|
|
||||||
data-ad-client="ca-pub-0069680015252793"
|
|
||||||
data-ad-slot="2373587563"
|
|
||||||
data-ad-format="auto"></ins>
|
|
||||||
<script>
|
|
||||||
(adsbygoogle = window.adsbygoogle || []).push({});
|
|
||||||
</script>
|
|
||||||
<br/>
|
<br/>
|
||||||
<h3><?= $header ?></h3>
|
<h3><?= $header ?></h3>
|
||||||
|
|
||||||
|
|
@ -104,20 +94,6 @@ $oldIndex = $pagesCount+1;
|
||||||
<?php else: ?>
|
<?php else: ?>
|
||||||
<br/>
|
<br/>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
<div class="row">
|
|
||||||
<div class="col-md-12" style="text-align: center;">
|
|
||||||
<script async src="//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script>
|
|
||||||
<!-- Point - DOWN -->
|
|
||||||
<ins class="adsbygoogle"
|
|
||||||
style="display:block"
|
|
||||||
data-ad-client="ca-pub-0069680015252793"
|
|
||||||
data-ad-slot="4972494746"
|
|
||||||
data-ad-format="auto"></ins>
|
|
||||||
<script>
|
|
||||||
(adsbygoogle = window.adsbygoogle || []).push({});
|
|
||||||
</script>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<hr/>
|
<hr/>
|
||||||
<?= self::renderPartial('randomPoint.php', array('randomPoint'=>$randomPoint), true)?>
|
<?= self::renderPartial('randomPoint.php', array('randomPoint'=>$randomPoint), true)?>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -45,17 +45,6 @@ if ($pointsAirport && $usersAirport && $pointsAirport->id != $usersAirport->id){
|
||||||
<a href="/page/instapoint/id/<?= $point->id ?>">4IG</a>
|
<a href="/page/instapoint/id/<?= $point->id ?>">4IG</a>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script async src="//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script>
|
|
||||||
<!-- Point-TOP -->
|
|
||||||
<ins class="adsbygoogle"
|
|
||||||
style="display:block"
|
|
||||||
data-ad-client="ca-pub-0069680015252793"
|
|
||||||
data-ad-slot="2373587563"
|
|
||||||
data-ad-format="auto"></ins>
|
|
||||||
<script>
|
|
||||||
(adsbygoogle = window.adsbygoogle || []).push({});
|
|
||||||
</script>
|
|
||||||
<br/>
|
<br/>
|
||||||
|
|
||||||
<div class="mainTextBlock">
|
<div class="mainTextBlock">
|
||||||
|
|
@ -141,7 +130,7 @@ if ($pointsAirport && $usersAirport && $pointsAirport->id != $usersAirport->id){
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
<nobr>[ <span class="glyphicon glyphicon-user"></span> <a href="/user/<?= $point->authorUser->id ?>"><?= $point->authorUser->nick ?></a> - <span class="glyphicon glyphicon-pencil" title="<?= date('d-m-Y H:i', $point->date) ?>"></span> <?= $point->authorUser->getPointsCount() ?> ]</nobr>
|
<nobr>[ <span class="glyphicon glyphicon-user"></span> <a href="/user/<?= $point->authorUser->id ?>"><?= $point->authorUser->nick ?></a> - <span class="glyphicon glyphicon-pencil" title="<?= date('d-m-Y H:i', $point->date) ?>"></span> <?= $point->authorUser->getPointsCount() ?> ]</nobr>
|
||||||
<?php if (App::$user && App::$user->isAdmin == 1): ?>
|
<?php if (App::$user && App::$user->isAdmin == 1): ?>
|
||||||
<nobr>[ <span class="glyphicon glyphicon-new-window"></span> <a href="<?= $point->source ?>" target="_blank">источник: <?= $point->source ?></a> ]</nobr>
|
<nobr>[ <span class="glyphicon glyphicon-new-window"></span> <a href="<?= $point->source ?>" target="_blank">источник: <?= mb_substr($point->source, 0, 40) ?>…</a> ]</nobr>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -237,21 +226,6 @@ if ($pointsAirport && $usersAirport && $pointsAirport->id != $usersAirport->id){
|
||||||
<script charset="utf-8" src="//www.travelpayouts.com/widgets/394e02eacac3a5c9b000360787c2d5d2.js?v=727" async></script>
|
<script charset="utf-8" src="//www.travelpayouts.com/widgets/394e02eacac3a5c9b000360787c2d5d2.js?v=727" async></script>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<?php else: ?>
|
|
||||||
<div class="row hideOnPrint">
|
|
||||||
<div class="col-md-12" style="text-align: center;">
|
|
||||||
<script async src="//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script>
|
|
||||||
<!-- Point - DOWN -->
|
|
||||||
<ins class="adsbygoogle"
|
|
||||||
style="display:block"
|
|
||||||
data-ad-client="ca-pub-0069680015252793"
|
|
||||||
data-ad-slot="4972494746"
|
|
||||||
data-ad-format="auto"></ins>
|
|
||||||
<script>
|
|
||||||
(adsbygoogle = window.adsbygoogle || []).push({});
|
|
||||||
</script>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
|
|
|
||||||
|
|
@ -90,4 +90,4 @@ if (App::$user && App::$user->id) {
|
||||||
</div><!--/.nav-collapse -->
|
</div><!--/.nav-collapse -->
|
||||||
</div>
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
<?= App::$user ? '' : self::renderPartial('modals/login.php', null, true) ?>
|
<?= App::$user ? '' : self::renderPartial('modals/login.php', null, true) . self::renderPartial('modals/register.php', null, true) ?>
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue