«Сервис свободных аккаунтов» за день с Next Code

в 13:32, , рубрики: css, framework, JS, php, Веб-разработка, метки: , ,

Основная идея

Например, вы зашли на сайт в поисках чего-либо. Доступ к контенту ограничен. Есть два варианта: зарегистрироваться или поискать тот же контент на другом сайте. Велика вероятность, что данный сайт вам больше не пригодится, и захламлять свою почту спамом, да и просто делать какие-то лишние действия (регистрация, подтверждение) мало кому захочется. В таком случае, вы вводите адрес сайта в сервисе, и смотрите, есть ли свободные аккаунты для данного сайта. Свободным аккаунтом может быть любой логин и пароль, который другой пользователь посчитал не нужным, и решил поделиться им с другими, дабы сократить их время.
Идея сайта родилась в процессе трудового дня. На разработку потребовался один рабочий день. Мотивация – желание доказать что есть люди, готовые помогать другим пользователям интернета бесплатно, и подобного рода проекты могут жить.
Сервис создавался с помощью all-in-one фреймворка Next Code. Кому интересно как — добро пожаловать под кат.

Next Code

Фреймворк состоит из:
• NextJS – JS ядро, включающее обработку ajax запросов, отладчик, базовые функции
• NextUIJS – визуальные компоненты и расширения
• NextCSS – набор CSS стилей для быстрой вёрстки
• XCode – PHP ядро, включающее работу с БД, работу с шаблонами, отладчик, установщик приложений, парсеры и многое другое.
Сам фреймворк разрабатывается для собственных нужд. Многое сделано, но не все идеи воплощены. Продакшен версия будет open-source. Если будет интересно, напишу отдельную статью о внутренностях и всех особенностях, коих не мало.

Процесс разработки

Конфигурируем XCode

Для начала работы выбираем необходимые компоненты для отображения и работы сайта.
Итак нам понадобится:
1. Менеджер БД
2. Драйвер MySQL
3. Менеджер шаблонов
4. Драйвер Smarty
5. Установщик приложений
6. Обработчик пользовательский запросов
7. Плагин работы с числами
Конфигурирование происходит путём настройки ini файлов каждого необходимого компонента. Для того чтобы компонент можно было использовать в процессе работы, ini файл с настройками необходимо положить в папку конфигурации.
Например, ini файл (plugins/numeric.ini) для плагина работы с числами выглядит следующим образом:
[plugin]
name = numeric
class = plugin.numeric.default

Создание приложения

Весь сервис представляет собой одно приложение – freeacc.
Приложение включает в себя:
1. класс xcFreeAcc_Application (внутрисистемное имя – application.freeacc)
2. конфигурационный файл
3. сущность freeacc_account для хранения аккаунтов
4. сущность freeacc_site – для хранения сайтов
5. сущность freeacc_verify – для хранения оценок доступности аккаунта
6. список резервируемых запросов
7. шаблон страниц
Приложение хранится в репозитории по адресу application/freeacc/
Чтобы система определила приложение необходимо произвести его установку.

xc("call.application.freeacc::__install");

Функция __install выполняет следующие действия:

public static function __install()
{
$app_id = xc::query( "api.application.install", xc::query( "setting", "name", "application", __class__ ), xc::query( "setting", "caption", "application", __class__ ) );
xc::query( "api.application.registerComponents", xc::query( "setting", "name", "application", __class__ ), $app_id );
}

В первой строчке вызывается API установщика приложений, с передачей имени и заголовка приложения (значения берутся из конфигурационного файла).
Вторая строчка создаёт сущности и резервирует запросы для приложения.
Приложение готово к работе!

Создание шаблонов

Исходя из принципов MVC для работы приложения необходим tpl файл с вёрсткой, и php файл в качестве контроллера. В качестве модели выступает класс приложения.
Код tpl файла

<div class="xc-fullpage-layout">
    <div class="xc-layout-header">
        <div class="xc-layout-frame">
            <div class="xc-grid">
                <div class="block logo xc-column"><a href="/"><img src="{$MEDIAPATH}/logo.png" /></a></div>
                <div class="block motto xc-column"><span class="delimiter">|</span> <span class="motto">сервис свободных аккаунтов</span></div>
            </div>
            <div class="block description">
                <span>Сервис предлагает воспользоваться уже ранее созданным, свободным аккаунтом, чтобы пропустить процедуру регистрации</span>
            </div>
        </div>
    </div>
    <div class="xc-layout-content xc-center">
        <div class="xc-layout-frame">
	    {if $self}
            	{$self}
	    {else}
	      	{$likes}
	    {/if}
            <form title="Добавить аккаунт" id="addForm" action="freeacc/forms/add_form" class="ui-component-form" data-valid-timeout="3000" data-valid-message="Пожалуйста, подождите..." data-valid-area=">footer.ui-element-validation">
                <fieldset class="fields">
                    <div class="header">
                        <h2>Поделиться свободным аккаунтом:</h2>
                    </div>
                    <ul class="xc-grid">
                        <li class="item ui-component xc-column">
                            <div class="xc-grid">
                                <div class="field xc-column"><input name="url" title="Сайт" placeholder="введите адрес сайта..." class="ui-component-edit" pattern="site" type="text" required /></div>
                                <div class="field xc-column"><input name="login" title="Логин" placeholder="введите логин..." class="ui-component-edit" type="text" required /></div>
                                <div class="field xc-column"><input name="password" title="Пароль" placeholder="введите пароль..." class="ui-component-edit" type="text" required /></div>
                            </div>
                        </li>
                        <li class="item control xc-column">
                            <button class="ui-component-button" type="submit">добавить</button>
                        </li>
                    </ul>
                </fieldset>
                <footer class="ui-element-validation">
                </footer>
            </form>
            <form title="Получить аккаунты" id="requestForm" data-callback-function="postRequest" data-action="none" class="ui-component-form" data-valid-timeout="3000" data-valid-message="Пожалуйста, подождите..." data-valid-area=">footer.ui-element-validation">
                <fieldset class="fields">
                    <div class="header">
                        <h2>Найти свободный аккаунт: *</h2>
                    </div>
                    <ul class="xc-grid">
                        <li class="item ui-component xc-column">
                            <div class="field"><input name="url" title="Сайт" placeholder="введите адрес сайта..." class="ui-component-edit" pattern="site" type="text" required /></div>
                        </li>
                        <li class="item control xc-column">
                            <button class="ui-component-button" type="submit">искать</button>
                        </li>
                    </ul>
                </fieldset>
                <div class="description">
                    * Поиск совершенно бесплатный. Аккаунты добавляются другими пользователями. Администрация сайта не несёт никакой ответственности за содержание аккаунтов!
                </div>
                <footer class="ui-element-validation">
                    
                </footer>
            </form>
		{if !$self}
		<div class="block table xc-full">
		    <div class="site">
		        <span>в базе <b>{$accounts->asFormat(0,"."," ")}</b> {$accounts->getDeclension(array("аккаунтов","аккаунт","аккаунта"))} для <b>{$sites->asFormat(0,"."," ")}</b> {$sites->getDeclension(array("сайтов","сайта","сайтов"))}</span> 
		    </div>
		    <div class="table">
			<div class="xc-grid xc-full" data-account="{$item.id}">
			    <div class="header">Популярные сайты</div>
		        {foreach from=$favorites item=item}
		            <div class="xc-item"><a href="/{$item.url}/">{$item.url}</a> ({$item.cnt})</div>
		        {/foreach}
		        </div>
		    </div>
		</div>
		{/if}
        </div>
    </div>
    <div class="xc-layout-footer">
        <div class="xc-layout-frame">
        </div>
    </div>
</div>
    <div id="alertModal" data-popup-modal="true" class="ui-popup">
    </div>
    <div id="alertPopup" class="ui-popup popup">
    </div>
    <div id="alertMessage" data-popup-modal="true" class="ui-popup message">
    </div>

</body>

Контроллер, созданный для обработки данного шаблона следующий:

$self = "";

xc("tpl likes=freeacc/blocks/likes comments=freeacc/blocks/comments :fetch");
if (isset(xc("tpl")->variable("this")->extra['site']))
{
    xc("tpl")->assign("site",xc("tpl")->variable("this")->extra['site']);
    $accounts = xc("call.application.freeacc::getAccounts",xc("tpl")->variable("this")->extra['site']);
    $self = xc("tpl freeacc/blocks/accounts")->apply($accounts);
}
else
{
    xc("tpl")->assign("accounts",xc("plugin.numeric",true)->setData(xc("db freeacc_account")->fields("COUNT(*) as cnt")->cnt));
    xc("tpl")->assign("sites",xc("plugin.numeric",true)->setData(xc("db freeacc_site")->fields("COUNT(*) as cnt")->cnt));
    xc("tpl")->assign("favorites",xc("db freeacc_account:group(url):order(cnt down):limit(0,20)")->fields("url,COUNT(#id#) as cnt"));
}
xc("tpl")->assign("self", $self);

Думаю для любого веб программиста, шаблон «вида» не вызовет никаких затруднений при чтении.
Контроллер выполняет следующие действия:
• Создаёт переменные likes и comments для вывода лайков и комментариев Вконтакте
• Проверяет наличие сайта в запросе (если сайта нет, то мы на главной)
• Помещает требуемый сайт в переменную site для быстрого доступа внутри шаблона
• Вызывает функцию приложения для получения аккаунтов требуемого сайта
• Обрабатывает шаблон с таблицей аккаунтов
• Создаёт переменную accounts с количеством аккаунтов в БД
• Создаёт переменную sites с количеством сайтов в БД
• Создаёт переменную favorites с 20 сайтами, к которым больше всего аккаунтов
Обработчик формы добавления выглядит следующим образом:

$id = xc("call.application.freeacc::addAccount",$_GET['fields']);
if ($id)
{
    $GLOBALS['_RESULT']["result"] = "";
    $GLOBALS['_RESULT']["debug"]["info"] = "Аккаунт добавлен";
    $GLOBALS['_RESULT']["debug"]["type"] = "success";
}
else
{
    $GLOBALS['_RESULT']["result"] = "";
    $GLOBALS['_RESULT']["debug"]["info"] = "Неизвестная ошибка";
    $GLOBALS['_RESULT']["debug"]["type"] = "fail";
}

Визуализируем шаблон

$(function()
{
    $(".block.table a.verify").live("click",function()
    {
        var obj = $(this);
        $$.database.get("ajax").onReadyState(function(result)
        {
            obj.parent().empty().text(" ");   
        });
        $$.database.get("ajax").send({"mode": "ajax", "type": "API", "api": "freeacc.account.verify", "parameters":[$(this).parents("div[data-account]").attr("data-account")]});  
    });
    
    $(".block.table a.unverify").live("click",function()
    {
        var obj = $(this);
        $$.database.get("ajax").onReadyState(function(result)
        {
            obj.parent().empty().text(" ");    
        });
        $$.database.get("ajax").send({"mode": "ajax", "type": "API", "api": "freeacc.account.unverify", "parameters":[$(this).parents("div[data-account]").attr("data-account")]});  
    });
});

function postRequest()
{
    $$.fn.redirect("/"+$$("#requestForm [name='url']").val()+"/");
}

Тематика хаба не позволяет мне указывать ссылку на сервис, т.к это будет считаться рекламой. Для переноса в «Я пиарюсь» нет кармы. Ссылку могу указать в комментариях или в ЛС. Хотя умный читатель без труда допишет ".ru" ;)

P.S мой первый пост на хабре, надеюсь на понимание.
P.P.S готов дописать что не дописал о сервисе или технологиях.
P.P.P.S с русским языком проблемы, так что думаю что на сайте, что в статье есть куча ошибок. Буду рад исправить!

Автор: SergeyRembo

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js