final
Этот коммит содержится в:
родитель
b6f7196aa5
Коммит
ef07700d53
71
README.md
71
README.md
@ -1,6 +1,9 @@
|
|||||||
PTEST
|
PTEST
|
||||||
=====
|
=====
|
||||||
|
|
||||||
|
Рабочая версия скрипта развернута здесь:
|
||||||
|
<http://ptest.i2g.ru/>
|
||||||
|
|
||||||
Задание
|
Задание
|
||||||
-------
|
-------
|
||||||
|
|
||||||
@ -32,17 +35,71 @@ PTEST
|
|||||||
Развертывание
|
Развертывание
|
||||||
-------------
|
-------------
|
||||||
|
|
||||||
|
Скачать архив <https://mygit.i2g.ru/ptest/snapshot/ptest-master.zip>
|
||||||
|
|
||||||
|
Настроить любимый веб-сервер на папку `public`.
|
||||||
|
|
||||||
|
Мой конфиг для nginx
|
||||||
|
|
||||||
|
|
||||||
|
```
|
||||||
|
server {
|
||||||
|
server_name ptest.i2g.ru;
|
||||||
|
root /mnt/160/sites/ptest.i2g/public;
|
||||||
|
|
||||||
|
location / {
|
||||||
|
try_files $uri /index.php?$query_string;
|
||||||
|
}
|
||||||
|
location ~ ^/index\.php(/|$) {
|
||||||
|
fastcgi_split_path_info ^(.+?\.php)(|/.*)$;
|
||||||
|
include fastcgi_params;
|
||||||
|
fastcgi_param HTTP_PROXY "";
|
||||||
|
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
|
||||||
|
fastcgi_param PATH_INFO $fastcgi_path_info;
|
||||||
|
fastcgi_intercept_errors on;
|
||||||
|
# PHP 5 socket location.
|
||||||
|
fastcgi_pass unix:/var/run/php5-fpm.sock;
|
||||||
|
}
|
||||||
|
|
||||||
|
location = /favicon.ico {
|
||||||
|
log_not_found off;
|
||||||
|
access_log off;
|
||||||
|
}
|
||||||
|
|
||||||
|
location = /robots.txt {
|
||||||
|
allow all;
|
||||||
|
log_not_found off;
|
||||||
|
access_log off;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
###MySQL/MariaDB
|
||||||
|
|
||||||
|
1. Импортировать `dump.sql` в базу данных.
|
||||||
|
2. Установить параметры в файле `src/start.php`
|
||||||
|
|
||||||
|
### Composer
|
||||||
|
|
||||||
|
Чтобы скрипт заработал нужно создать автозарузчик классов при помощи
|
||||||
|
[Composer](https://getcomposer.org/download/ "Загрузка пакетного менеджера для PHP-библиотек Composer")
|
||||||
|
|
||||||
```
|
```
|
||||||
composer install
|
composer install
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Впринципе после этого приложение должно заработать.
|
||||||
|
|
||||||
|
### По желанию
|
||||||
|
|
||||||
|
Для генерации CSS, js и прочей рутины я использую Grunt.
|
||||||
|
Чтобы его установить нужны следующие команды
|
||||||
|
|
||||||
```
|
```
|
||||||
cd grunt
|
cd grunt
|
||||||
npm install
|
npm install
|
||||||
cd css
|
cd css
|
||||||
git clone https://github.com/IgorVBelousov/ShortCSS.git
|
git clone https://github.com/IgorVBelousov/ShortCSS.git
|
||||||
git clone https://mygit.i2g.ru/normalize/
|
git clone https://mygit.i2g.ru/normalize/
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
14
dump.sql
14
dump.sql
Различия файлов скрыты, потому что одна или несколько строк слишком длинны
@ -102,7 +102,7 @@ class App {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Запуск маршрутов
|
* Запуск приложения
|
||||||
*/
|
*/
|
||||||
public function run(){
|
public function run(){
|
||||||
foreach ( $this->route_table as $route_array ) {
|
foreach ( $this->route_table as $route_array ) {
|
||||||
|
@ -24,6 +24,9 @@ class Model {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Сохраниние объекта
|
||||||
|
*/
|
||||||
public function save() {
|
public function save() {
|
||||||
$operation = "INSERT INTO ";
|
$operation = "INSERT INTO ";
|
||||||
$suffix = "";
|
$suffix = "";
|
||||||
@ -56,6 +59,13 @@ class Model {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Поиск первого вхождения по условию
|
||||||
|
*
|
||||||
|
* @param string $condition SQL-строка, которая будет идти после WHERE
|
||||||
|
*
|
||||||
|
* @return bool|object false или объект
|
||||||
|
*/
|
||||||
static public function findFirst( $condition ) {
|
static public function findFirst( $condition ) {
|
||||||
global $app;
|
global $app;
|
||||||
$child_model_name = get_called_class();
|
$child_model_name = get_called_class();
|
||||||
@ -74,6 +84,13 @@ class Model {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Поиск объектов по условию
|
||||||
|
*
|
||||||
|
* @param string $condition SQL-строка, которая будет идти после WHERE
|
||||||
|
*
|
||||||
|
* @return array|bool false или массив объектов
|
||||||
|
*/
|
||||||
static public function find( $condition ) {
|
static public function find( $condition ) {
|
||||||
global $app;
|
global $app;
|
||||||
$child_model_name = get_called_class();
|
$child_model_name = get_called_class();
|
||||||
@ -98,6 +115,11 @@ class Model {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Получение количества записей в таблице
|
||||||
|
*
|
||||||
|
* @return integer
|
||||||
|
*/
|
||||||
public function count() {
|
public function count() {
|
||||||
$child_model_name = get_called_class();
|
$child_model_name = get_called_class();
|
||||||
$model = new $child_model_name;
|
$model = new $child_model_name;
|
||||||
|
@ -104,6 +104,21 @@ a
|
|||||||
-m 26 0
|
-m 26 0
|
||||||
-lh 24
|
-lh 24
|
||||||
|
|
||||||
|
.add-link
|
||||||
|
-d inline-block
|
||||||
|
-fl right
|
||||||
|
|
||||||
|
&__a
|
||||||
|
-br 1 solid $link_color_border imp
|
||||||
|
-p 7 14
|
||||||
|
b-radius 3
|
||||||
|
|
||||||
|
&:visited
|
||||||
|
-c $link_color
|
||||||
|
|
||||||
|
&:hover
|
||||||
|
-br 1 solid $link_hover_color_border imp
|
||||||
|
|
||||||
.sort
|
.sort
|
||||||
-d table-row
|
-d table-row
|
||||||
+media('max-width:424px')
|
+media('max-width:424px')
|
||||||
@ -212,6 +227,7 @@ article
|
|||||||
-h (120/2)
|
-h (120/2)
|
||||||
clear both
|
clear both
|
||||||
-d block
|
-d block
|
||||||
|
-mb 6
|
||||||
|
|
||||||
form
|
form
|
||||||
-w 320
|
-w 320
|
||||||
@ -246,6 +262,17 @@ form
|
|||||||
&:focus
|
&:focus
|
||||||
-brb 2 solid $link_hover_color_border
|
-brb 2 solid $link_hover_color_border
|
||||||
|
|
||||||
|
&__submit
|
||||||
|
-c $link_color
|
||||||
|
-br 1 solid $link_color_border
|
||||||
|
-p 7 14
|
||||||
|
b-radius 3
|
||||||
|
-bgc white
|
||||||
|
|
||||||
|
&:hover
|
||||||
|
-c $link_hover_color
|
||||||
|
-br 1 solid $link_hover_color_border
|
||||||
|
|
||||||
.i-user
|
.i-user
|
||||||
sprite_sprite(sprite_account)
|
sprite_sprite(sprite_account)
|
||||||
-mb -6
|
-mb -6
|
||||||
|
Различия файлов скрыты, потому что одна или несколько строк слишком длинны
@ -271,6 +271,26 @@ a.to-front:visited:hover {
|
|||||||
margin: 26px 0;
|
margin: 26px 0;
|
||||||
line-height: 24px;
|
line-height: 24px;
|
||||||
}
|
}
|
||||||
|
.add-link {
|
||||||
|
display: inline-block;
|
||||||
|
float: right;
|
||||||
|
}
|
||||||
|
.add-link__a {
|
||||||
|
border: 1px solid rgba(0,99,255,0.3) !important;
|
||||||
|
padding: 7px 14px;
|
||||||
|
-webkit-border-radius: 3px;
|
||||||
|
-moz-border-radius: 3px;
|
||||||
|
-o-border-radius: 3px;
|
||||||
|
-ms-border-radius: 3px;
|
||||||
|
-khtml-border-radius: 3px;
|
||||||
|
border-radius: 3px;
|
||||||
|
}
|
||||||
|
.add-link__a:visited {
|
||||||
|
color: #0063ff;
|
||||||
|
}
|
||||||
|
.add-link__a:hover {
|
||||||
|
border: 1px solid rgba(255,71,93,0.24) !important;
|
||||||
|
}
|
||||||
.sort {
|
.sort {
|
||||||
display: table-row;
|
display: table-row;
|
||||||
}
|
}
|
||||||
@ -355,6 +375,7 @@ article+article {
|
|||||||
height: 60px;
|
height: 60px;
|
||||||
clear: both;
|
clear: both;
|
||||||
display: block;
|
display: block;
|
||||||
|
margin-bottom: 6px;
|
||||||
}
|
}
|
||||||
form {
|
form {
|
||||||
width: 320px;
|
width: 320px;
|
||||||
@ -390,6 +411,22 @@ form {
|
|||||||
.form-element__textarea:focus {
|
.form-element__textarea:focus {
|
||||||
border-bottom: 2px solid rgba(255,71,93,0.24);
|
border-bottom: 2px solid rgba(255,71,93,0.24);
|
||||||
}
|
}
|
||||||
|
.form-element__submit {
|
||||||
|
color: #0063ff;
|
||||||
|
border: 1px solid rgba(0,99,255,0.3);
|
||||||
|
padding: 7px 14px;
|
||||||
|
-webkit-border-radius: 3px;
|
||||||
|
-moz-border-radius: 3px;
|
||||||
|
-o-border-radius: 3px;
|
||||||
|
-ms-border-radius: 3px;
|
||||||
|
-khtml-border-radius: 3px;
|
||||||
|
border-radius: 3px;
|
||||||
|
background-color: #fff;
|
||||||
|
}
|
||||||
|
.form-element__submit:hover {
|
||||||
|
color: #ff475d;
|
||||||
|
border: 1px solid rgba(255,71,93,0.24);
|
||||||
|
}
|
||||||
.i-user {
|
.i-user {
|
||||||
background-image: url("/image/sprite.png");
|
background-image: url("/image/sprite.png");
|
||||||
background-size: 56px 56px;
|
background-size: 56px 56px;
|
||||||
|
@ -29,16 +29,20 @@ class AdModel extends Model{
|
|||||||
protected $table_pdate;
|
protected $table_pdate;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return mixed
|
* Получить id
|
||||||
|
*
|
||||||
|
* @return integer|null
|
||||||
*/
|
*/
|
||||||
public function getId() {
|
public function getId() {
|
||||||
return (int) $this->table_id;
|
return (int) $this->table_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param $username
|
* Установить имя пользователя
|
||||||
*
|
*
|
||||||
* @return bool|string
|
* @param string $username имя пользавтеля
|
||||||
|
*
|
||||||
|
* @return bool|string true в случае успеха. иначе сообщение с разъяснениями
|
||||||
*/
|
*/
|
||||||
public function setUserName( $username ) {
|
public function setUserName( $username ) {
|
||||||
if ( preg_match( '/[a-z,\d]{3,}/i', $username ) ) {
|
if ( preg_match( '/[a-z,\d]{3,}/i', $username ) ) {
|
||||||
@ -49,14 +53,21 @@ class AdModel extends Model{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Получить имя пользователя
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
public function getUserName(){
|
public function getUserName(){
|
||||||
return $this->table_username;
|
return $this->table_username;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param mixed $email
|
* Установка e-mail
|
||||||
*
|
*
|
||||||
* @return bool|string
|
* @param string $email
|
||||||
|
*
|
||||||
|
* @return bool|string true в случае успеха. иначе сообщение с разъяснениями
|
||||||
*/
|
*/
|
||||||
public function setEmail( $email ) {
|
public function setEmail( $email ) {
|
||||||
if ( preg_match('/.+@.+\..+/i', $email ) ) {
|
if ( preg_match('/.+@.+\..+/i', $email ) ) {
|
||||||
@ -68,6 +79,8 @@ class AdModel extends Model{
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Получить e-mail
|
||||||
|
*
|
||||||
* @return mixed
|
* @return mixed
|
||||||
*/
|
*/
|
||||||
public function getEmail() {
|
public function getEmail() {
|
||||||
@ -75,9 +88,11 @@ class AdModel extends Model{
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param mixed $homepage
|
* Установка домашней страницы
|
||||||
*
|
*
|
||||||
* @return bool|string
|
* @param string $homepage URL
|
||||||
|
*
|
||||||
|
* @return bool|string true в случае успеха. иначе сообщение с разъяснениями
|
||||||
*/
|
*/
|
||||||
public function setHomepage( $homepage ) {
|
public function setHomepage( $homepage ) {
|
||||||
if ( preg_match('|https?://.*\..*|i', $homepage ) ) {
|
if ( preg_match('|https?://.*\..*|i', $homepage ) ) {
|
||||||
@ -89,6 +104,8 @@ class AdModel extends Model{
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Получение домашней страницы
|
||||||
|
*
|
||||||
* @return mixed
|
* @return mixed
|
||||||
*/
|
*/
|
||||||
public function getHomepage() {
|
public function getHomepage() {
|
||||||
@ -96,6 +113,8 @@ class AdModel extends Model{
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Установка IP адреса
|
||||||
|
*
|
||||||
* @param mixed $ip
|
* @param mixed $ip
|
||||||
*/
|
*/
|
||||||
public function setIp( $ip ) {
|
public function setIp( $ip ) {
|
||||||
@ -103,6 +122,8 @@ class AdModel extends Model{
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Получение IP адреса
|
||||||
|
*
|
||||||
* @return mixed
|
* @return mixed
|
||||||
*/
|
*/
|
||||||
public function getIp() {
|
public function getIp() {
|
||||||
@ -110,6 +131,8 @@ class AdModel extends Model{
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Установка данных User-Agent
|
||||||
|
*
|
||||||
* @param mixed $browser
|
* @param mixed $browser
|
||||||
*/
|
*/
|
||||||
public function setBrowser( $browser ) {
|
public function setBrowser( $browser ) {
|
||||||
@ -117,6 +140,8 @@ class AdModel extends Model{
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Получение данных User-Agent
|
||||||
|
*
|
||||||
* @return mixed
|
* @return mixed
|
||||||
*/
|
*/
|
||||||
public function getBrowser() {
|
public function getBrowser() {
|
||||||
@ -124,6 +149,8 @@ class AdModel extends Model{
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Установка текста
|
||||||
|
*
|
||||||
* @param mixed $text
|
* @param mixed $text
|
||||||
*/
|
*/
|
||||||
public function setText( $text ) {
|
public function setText( $text ) {
|
||||||
@ -131,6 +158,8 @@ class AdModel extends Model{
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Получение текста
|
||||||
|
*
|
||||||
* @return mixed
|
* @return mixed
|
||||||
*/
|
*/
|
||||||
public function getText() {
|
public function getText() {
|
||||||
@ -138,6 +167,8 @@ class AdModel extends Model{
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Установка даты
|
||||||
|
*
|
||||||
* @param mixed $date
|
* @param mixed $date
|
||||||
*/
|
*/
|
||||||
public function setDate( $date ) {
|
public function setDate( $date ) {
|
||||||
@ -145,20 +176,28 @@ class AdModel extends Model{
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Получение даты
|
||||||
* @return mixed
|
* @return mixed
|
||||||
*/
|
*/
|
||||||
public function getDate() {
|
public function getDate() {
|
||||||
return $this->table_pdate;
|
return $this->table_pdate;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Получение количества страниц
|
||||||
|
*
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
public function countPages() {
|
public function countPages() {
|
||||||
return ceil($this->count()/25);
|
return (int) ceil($this->count()/25);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param int $page_number
|
* Получение массива объектов для вывода на страницах
|
||||||
* @param string $sort_by
|
*
|
||||||
* @param string $order
|
* @param integer $page_number номер страницы
|
||||||
|
* @param string $sort_by сортировка по столбцу
|
||||||
|
* @param string $order сортировка по возрастанию или убыванию
|
||||||
*
|
*
|
||||||
* @return mixed
|
* @return mixed
|
||||||
*/
|
*/
|
||||||
|
@ -11,10 +11,22 @@ namespace PTEST\M;
|
|||||||
|
|
||||||
class CAPTCHAModel {
|
class CAPTCHAModel {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Проверка даных капчи
|
||||||
|
*
|
||||||
|
* @param string $code
|
||||||
|
*
|
||||||
|
* @return bool|string
|
||||||
|
*/
|
||||||
public function verify( $code ) {
|
public function verify( $code ) {
|
||||||
return strtoupper( $code ) == $_SESSION['CAPTCHA'] ? true : "Неверный код с картинки";
|
return strtoupper( $code ) == $_SESSION['CAPTCHA'] ? true : "Неверный код с картинки";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Генерирование изображения
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
public function getImage() {
|
public function getImage() {
|
||||||
global $app;
|
global $app;
|
||||||
$letters = 'ABDEFABDEFGKLMNPRSTWXYZ482GKLMNABDEFGKLMNPRSTWXYZ482PRSTWXYZ482'; // алфавит
|
$letters = 'ABDEFABDEFGKLMNPRSTWXYZ482GKLMNABDEFGKLMNPRSTWXYZ482PRSTWXYZ482'; // алфавит
|
||||||
|
@ -40,6 +40,7 @@ if ($this->sort_by == 'mail') {
|
|||||||
}
|
}
|
||||||
?>
|
?>
|
||||||
<h1 class="page-title"><?php echo $this->page_title ?></h1>
|
<h1 class="page-title"><?php echo $this->page_title ?></h1>
|
||||||
|
<div class="add-link"><a href="/new/" class="add-link__a">Добавить объявление</a></div>
|
||||||
<div class="sort">
|
<div class="sort">
|
||||||
<div class="sort__cell">Сортировка:</div>
|
<div class="sort__cell">Сортировка:</div>
|
||||||
<div class="sort__cell"><a href="<?php echo $one_href ?>"><?php echo $one_arr ?>Дата</a></div>
|
<div class="sort__cell"><a href="<?php echo $one_href ?>"><?php echo $one_arr ?>Дата</a></div>
|
||||||
|
@ -30,8 +30,9 @@ ob_start();
|
|||||||
<textarea class="form-element__textarea" name="text" id="" cols="30" rows="10" placeholder="Текст объявления" tabindex="5"><?php echo ($this->post_data->text)?$this->post_data->text:'';?></textarea>
|
<textarea class="form-element__textarea" name="text" id="" cols="30" rows="10" placeholder="Текст объявления" tabindex="5"><?php echo ($this->post_data->text)?$this->post_data->text:'';?></textarea>
|
||||||
<div class="form-element__error"><?php echo ($this->errors->text)?$this->errors->text:''; ?></div>
|
<div class="form-element__error"><?php echo ($this->errors->text)?$this->errors->text:''; ?></div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="form-element">
|
||||||
<input type="submit" value="Отправить">
|
<input type="submit" value="Отправить" class="form-element__submit">
|
||||||
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</article>
|
</article>
|
||||||
|
@ -37,7 +37,6 @@ $app->setRoute( '|^/(?<column>mail)/(?<order>asc)/(page/(?<id>\d+)/)?$|', 'Index
|
|||||||
$app->setRoute( '|^/(?<column>mail)/(?<order>desc)/(page/(?<id>\d+)/)?$|', 'Index', 'sort');
|
$app->setRoute( '|^/(?<column>mail)/(?<order>desc)/(page/(?<id>\d+)/)?$|', 'Index', 'sort');
|
||||||
$app->setRoute( '|^/full/(?<id>\d+)/$|', 'Index', 'full');
|
$app->setRoute( '|^/full/(?<id>\d+)/$|', 'Index', 'full');
|
||||||
$app->setRoute( '|^/new/$|', 'Index', 'new');
|
$app->setRoute( '|^/new/$|', 'Index', 'new');
|
||||||
$app->setRoute( '|^/view_table/((?<id>\d+)/)*$|', 'Index', 'table');
|
|
||||||
$app->setRoute( '/^.*$/', 'error404' );
|
$app->setRoute( '/^.*$/', 'error404' );
|
||||||
|
|
||||||
$app->run();
|
$app->run();
|
Загрузка…
Ссылка в новой задаче
Block a user