ertttert
Books-CMS.clan.su

Создание модуля ноды

Если вам понадобится создать в Drupal новый тип контента, то, следуя традиции, придется написать модуль ноды, который будет отвечать за выполнение и предоставление новых и интересных вещей, необходимых этому типу контента. Здесь сказано “следуя традиции”, т.к. последние веяния в среде Drupal позволяют создавать типы контента в интерфейсе администрирования, расширяя их возможности добровольно разработанными модулями — без написания модуля с самого начала. В настоящей главе рассматриваются оба этих решения.

Мы напишем модуль ноды, который позволит пользователям добавлять на сайт объявления о рабочих вакансиях. Нода вакансии будет содержать заголовок, тело с текстом объявления и поле для ввода названия компании. Для заголовка и тела объявления будут использованы встроенные ноды title и body, стандартные для всех нод Drupal. А для названия компании потребуется новое специальное поле.

Начнем с создания папки с именем job_post в каталоге your sites/all/modules/custom.

Создание файла .install

Файл .install для модуля вакансий выполняет все операции по установке: определение типа ноды, создание полей, составляющих новый тип ноды, и выполнение процесса деинсталляции модуля:

<?php
/**
* @file
* Инсталляция файла для модуля Job Post.
*/

/**
* Реализация hook_install().
* - Добавление поля тела.
* - Настройка поля тела.
* - Создание поля для названия компании.
*/

function job_post_install() {
 node_types_rebuild();
 $types = node_type_get_types();
 // Добавление поля тела в тип ноды.
 node_add_body_field($types['job_post']);
 // Загрузка определения экземпляра для тела типа контента.
 $body_instance = field_info_instance('node', 'body', 'job_post');

 // Настройка поля тела.
 $body_instance['type'] = 'text_summary_or_trimmed';

 // Сохранение изменений в экземпляре поля тела.
 field_update_instance($body_instance);

 // Создание всех полей, добавляемых в тип контента.
 foreach (_job_post_installed_fields() as $field) {
    field_create_field($field);
 }

 // Создание всех экземпляров полей.
 foreach (_job_post_installed_instances() as $instance) {
    $instance['entity_type'] = 'node';
    $instance['bundle'] = 'job_post';
    field_create_instance($instance);
 }
}

/**
* Возврат структурированного массива с определением полей,
* созданного данным типом контента.
* В модуле вакансий имеется лишь одно дополнительное поле – название компании.
* Другие поля можно добавить, определив их в данной функции как
* дополнительные элементы в приведенном ниже массиве.
*/

function _job_post_installed_fields() {
 $t = get_t();
 return array(
    'job_post_company' => array(
      'field_name' => 'job_post_company',
      'label' => $t('Company posting the job listing'),
      // Компания, поместившая объявление
      'type' => 'text',
    ),
 );
}


/**
* Возврат структурированного массива с определениями экземпляров полей,
* связанных с данным типом контента.
*/

function _job_post_installed_instances() {
 $t = get_t();
 return array(
 'job_post_company' => array(
 'field_name' => 'job_post_company',
 'type' => 'text',
 'label' => $t('Company posting the job listing'),
 'widget' => array(
 'type' => 'text_textfield',
 ),
 'display' => array(
 'example_node_list' => array(
 'label' => $t('Company posting the job listing'),
 'type' => 'text',
 ),
 ),
 ),
 );
}

/**
* Реализация hook_uninstall().
*/

function job_post_uninstall() {
 // Сбор всего контента, который может быть создан при активации этого модуля.
 $sql = 'SELECT nid FROM {node} n WHERE n.type = :type';
 $result = db_query($sql, array(':type' => 'job_post'));
 $nids = array();
 foreach ($result as $row) {
 $nids[] = $row->nid;
 }

 // Одновременное удаление всех нод.
 node_delete_multiple($nids);
 // Перебор всех определенных в модуле полей и удаление
 // всех экземпляров полей, их данных и самих полей.
 foreach (array_keys(_job_post_installed_fields()) as $field) {
 field_delete_field($field);
 }

 // Проход в цикле по всем остальным экземплярам полей, присоединенных к типу
 // контента job_post (таких как поле тела), и их удаление по отдельности.
 $instances = field_info_instances('node', 'job_post');
 foreach ($instances as $instance_name => $instance) {
 field_delete_instance($instance);
 }

 // Удаление типа контента.
 node_type_delete('job_post');

 // Удаление информации о полях.
 field_purge_batch(1000);
}


Создание файла .info

Давайте также создадим файл job_post.info и добавим его в папку job post:

name = Job Post
description = A job posting content type
package = Pro Drupal Development
core = 7.x
files[] = job_post.install
files[] = job_post.module

Создание файла .module

И, наконец, нам нужен сам файл модуля. Создайте файл по имени job_post.module и сохраните его в папке sites/all/modules/custom/job_posting. После завершения создания модуля его можно активировать на странице со списками модулей (Modules). Начнем с открывающего дескриптора PHP и краткого комментария.

<?php
/**
* @file
* Модуль для типа ноды job_post.
*/

Предоставление информации о типе ноды

Теперь все готово для добавления хуков в файл job_post.module. Сначала реализуем хук hook_node_info(). Drupal вызывает этот хук в процессе выяснения доступных типов нод. Здесь можно добавить некоторые метаданные о нашем модуле.

/**
* Реализация hook_node_info() для типа job_post.
*/

function job_post_node_info() {

 return array(
  'job_post' => array(
    'name' => t('Job Post'), // Объявление о рабочей вакансии
   'base' => 'job_post',
   'description' => t('Use this content type to post a job.'),
   // Тип контента для объявлений о вакансиях.
   'has_title' => TRUE,
   'title_label' => t('Job Title'), // Название работы
   'help' => t('Enter the job title, job description,and the name of the company that posted the job'),
   // Введите название работы, ее описание и название компании,
   // поместившей объявление,/comm.
  ),
 );
}

В одном модуле могут быть определены несколько типов нод, поэтому возвращаемое значение должно быть массивом. Ниже приведен список значений метаданных, которые могут быть указаны в хуке node_info().

  • name. Читабельное для человека имя типа ноды. Является обязательным.
  • base. Базовая строка для создания обратных вызовов, соответствующих данному типу ноды (т.е. если базовая строка определена как example_foo, то при вставке ноды этого типа будет вызвана функция example_foo_insert). Такая строка обычно, хотя и не всегда, совпадает с именем модуля. Является обязательной.
  • description. Краткое описание типа ноды. Является обязательным.
  • help. Подсказка, выводимая пользователю при создании ноды данного типа. Не является обязательной (по умолчанию '').
  • has_title. Логическое значение, указывающее, имеет ли данный тип ноды поле заголовка. Не является обязательным (по умолчанию TRUE).
  • title_label. Метка для поля заголовка для данного типа контента. Не является обязательной (по умолчанию содержит строку Title).
  • locked. Булевское значение, указывающее, может ли администратор изменить машинное имя данного типа. FALSE — может изменять (не заблокировано), TRUE — имя не изменяемое (заблокировано). Не является обязательным (по умолчанию TRUE).
На заметку! Внутреннее поле имени name, упомянутое в этом списке (base), используется для создания URL-адреса ссылок Add new content (Добавить новый контент). Например, в качестве внутреннего имени нашего типа ноды мы используем строку job_post (ключ возвращаемого массива), поэтому для создания нового объявления о вакансии пользователи будут направлены по адресу http://example.com/?q=node/add/job_post. Обычно не стоит делать это значение изменяемым (locked = FALSE). Внутреннее имя хранится в столбце type таблиц node и node_revisions.

Изменение обратного вызова меню

Для реализации хука hook_menu() не обязательно наличие ссылки на странице Add new content (Добавить новый контент). Среда Drupal автоматически распознает новый тип контента и добавляет его на страницу http://example.com/?q=node/add, как показано на рис. 7.2. Прямая ссылка на форму отправки ноды будет выглядеть как http://example.com/?q=node/add/job_post. Имя и описание берутся из значений, определенных в job_post_node_info().

Если прямая ссылка не нужна, ее можно удалить в хуке hook_menu_alter(). Например, следующий код удалит страницу для всех пользователей, у которых нет права на администрирование нод:

/**
* Реализация of hook_menu_alter().
*/
function job_post_menu_alter(&$callbacks) {
// Если у пользователя нет права администрирования нод, элемент меню
// job_post деактивируется: в его обратный вызов доступа заносится FALSE.
if (!user_access('administer nodes')) {
 $callbacks['node/add/job_post']['access callback'] = FALSE;
 // Необходимо сбросить аргументы доступа, иначе Drupal использует
 // user_access() в качестве стандартного обратного вызова доступа.
 unset($callbacks['node/add/job_post']['access arguments']);
 }
}

Определение прав, специфичных для данного типа ноды, с помощью hook_permission()

Обычно в права для типов нод, определенных в модуле, входит возможность создавать ноду данного типа, изменять созданную ноду и изменять любую ноду заданного типа. Они определяются в коде hook_permission() как create job_post, edit own job_post, edit any job_post и т.д. Однако их еще понадобится определить в модуле. Сейчас мы создадим их с помощью хука hook_permission():

/**
* Реализация hook_permission().
*/
function job_post_permission() {
return array(

 'create job post' => array(
 'title' => t('Create a job post'),
 // Создание объявления о вакансии
 'description' => t('Create a job post'),
 // Создание объявления о вакансии
 ),

 'edit own job post' => array(
 'title' => t('Edit own job post'),
 // Редактирование собственного объявления о вакансии
 'description' => t('Edit your own job posting'),
 // Редактирование собственного объявления о вакансии
 ),

 'edit any job post' => array(
 'title' => t('Edit any job post'),
 // Редактирование любого объявления о вакансии
 'description' => t('Edit any job posting'),
 // Редактирование любого объявления о вакансии
 ),

 'delete own job post' => array(
 'title' => t('Delete own job post'),
 // Удаление собственного объявления о вакансии
 'description' => t('Delete own job posting'),
 // Удаление собственного объявления о вакансии
 ),

 'delete any job post' => array(
 'title' => t('Delete any job post'),
 // Удаление любого объявления о вакансии
 'description' => t('Delete any job posting'),
 // Удаление любого объявления о вакансии
 ),
 );
}

Если теперь на странице People (Люди) перейти на вкладку Permissions (Права доступа), только что определенные права будут там, и их можно использовать для назначения ролям пользователей.

Ограничение доступа к типу ноды с помощью hook_access()

Мы определили права доступа в хуке hook_perm(), но как они реализуются? Модули нод могут ограничить доступ к определенным в них типам нод с помощью хука hook_access(). Суперпользователь (пользователь с идентификатором 1) может обойти все проверки доступа, поэтому в данном случае этот хук не вызывается. Если данный хук не определен для нашего типа ноды, все проверки доступа завершатся неудачей, и, значит, только суперпользователь и пользователи с правами администрирования нод могут создавать, редактировать и удалять контент этого типа.

/**
* Реализация hook_access().
*/

function job_access($op, $node, $account) {
$is_author = $account->uid == $node->uid;

switch ($op) {

 case 'create':
 // Разрешить, если у роли пользователя есть право создания объявления.
 if (user_access('create job', $account)) {return NODE_ACCESS_ALLOW;}

 case 'update':
 // Разрешить, если у роли пользователя есть право правки своего
 // объявления и пользователь является автором, либо если у роли
 // пользователя есть право редактирования любого объявления.
 if (user_access('edit own job', $account) && $is_author || user_access('edit any job', $account)) 
 {return NODE_ACCESS_ALLOW;}

 case 'delete':
 // Разрешить, если у роли пользователя есть право удаления своего
 // объявления и пользователь является автором, либо если у роли
 // пользователя есть право удаления любого объявления.
 if (user_access('delete own job', $account) && $is_author || user_access('delete any job', $account)) 
 {return NODE_ACCESS_ALLOW;}
 }
}

Эта функция позволяет пользователям создавать ноды объявлений о вакансиях, если у их ролей есть право создания объявления о вакансии. Они могут изменять объявления, если у их ролей имеется право редактирования собственного объявления, и они являются авторами, либо у них есть право редактирования любого объявления. Пользователи с правами удаления собственных объявлений могут удалять свои объявления, а пользователи с правами удаления любых объявлений могут удалять любые ноды типа job post.

Еще одно значение $op, которое передается в функцию hook_node_access() — это view, которое позволяет управлять тем, кто может просматривать данную ноду. Однако учтите, что hook_node_access() вызывается лишь для страниц с отображением одной ноды. Хук hook_node_access() не предотвратит просмотр ноды в представлении тизера на странице со списком нескольких нод. Можно, конечно, поработать и с другими хуками и непосредственно манипулировать значением $node->teaser, но это неудачный подход. Лучшим решением будет использовать хук hook_node_grants(), о котором будет рассказано чуть ниже.

Настройка формы для нашего типа ноды

Итак, у нас имеются метаданные и права доступа, определенные для нового типа ноды. Теперь нужно создать форму ноды, чтобы пользователи могли вводить объявления о вакансиях. Для этого понадобится реализовать хук hook_form(). В Drupal имеется стандартная форма ноды, содержащая заголовок, тело и все дополнительные поля, которые были определены. Для типа контента объявлений о вакансиях такая форма вполне годится, так что мы используем ее для отображения формы добавления/редактирования.

/**
* Реализация hook_form() на основе стандартой формы.
*/
function job_post_form($node, $form_state) {
return node_content_form($node, $form_state);
}
На заметку! Если вы не знакомы с API-интерфейсом форм, обратитесь к главе 10.

Если вы являетесь администратором сайта и активировали данный модуль, можете теперь перейти на страницу Add contentJob Post (Добавить контент→Объявление о вакансии) и просмотреть только что созданную форму (рис. 7.3).

При работе с формой ноды, если это не обобщенная форма, модуль ноды выполняет проверку и сохранение всех стандартных полей, о которых известно модулю внутри формы ноды (вроде полей title и body), а также предоставляет вам (разработчику) хуки для проверки и сохранения всех собственных полей. Рассмотрим эти возможности.

Проверка полей с помощью hook_validate()

При отправке ноды нашего типа модуль вызывается через хук hook_validate(). Поэтому, когда пользователь отправляет форму для создания или изменения объявления о вакансии, вызов hook_validate() найдет функцию job_post_validate(), чтобы проверить данные, введенные в специальных полях. После получения этих данных их можно изменить с помощью form_set_value(), а с помощью form_set_error() можно установить код ошибки.

/**
* Реализация hook_validate().
*/
function job_post_validate($node) {
 // Принудительное применение требования: название компании
 // должно содержать не менее 2 символов.
 if (isset($node->job_post_company) && 
 strlen($node->job_post_company['und'][0]['value']) < 2) {
 form_set_error('job_post_company',
 t('The company name is too short. It must be at least 2 characters.'),
 // Слишком короткое название компании. Должно быть не менее 2 символов.
 $limit_validation_errors = NULL);
 }
}

Кроме того, мы уже определили минимальное количество слов для поля body field в хуке hook_node_info(), и Drupal выполнит эту проверку самостоятельно. Однако поле punchline является дополнительным полем, добавленным к форме типа ноды, поэтому за его проверку (а также за загрузку и сохранение) отвечаете вы.

Сохранение данных с помощью hook_insert()

При сохранении новой ноды вызывается хук hook_insert(). Здесь перед сохранением можно выполнить любую специальную обработку содержимого ноды. Данный хук вызывается только для модуля, определенного в метаданных типа ноды. Эта информация определена в ключе base хука hook_node_info() (см. раздел “Предоставление информации о типе ноды” ранее в главе). Например, если ключ base содержит значение job_post, то вызывается job_post_insert(). Если активирован модуль описания книг и создана новая нода типа book, то функция job_post_insert() не будет вызвана; вместо нее будет выполнен вызов book_insert(), т.к. в модуле book.module тип ноды определен с помощью ключа base со значением book.

На заметку! Если требуется что-то сделать с нодой другого типа при ее вставке, используйте вызов hook_nodeapi() для внедрения в общий процесс отправки ноды. См. раздел “Работа с нодами произвольного типа с помощью hook_node_xxxxx()” далее в главе.

Ниже приведен текст функции hook_insert() для модуля job_post.module. Мы будем создавать запись в таблице слежения при каждом создании новой ноды объявления о вакансии.

/**
* Реализация hook_insert().
*/
function job_post_insert($node) {
// Запись в журнал информации об объявлении.
watchdog('job post', 'A new job post titled: '.$node->title.' for company: '.
$node->job_post_company['und'][0]['value'].
' was added by UID: '.$node->uid, $variables = array(),
WATCHDOG_NOTICE, $link = 'node/'.$node->nid);
}

Поддержка актуальности данных с помощью hook_update()

Хук update() вызывается при редактировании ноды, когда основные данные ноды уже сохранены в базе данных. В этот момент можно записать изменения в связанные таблицы базы данных. Как и hook_insert(), этот хук вызывается только для текущего типа ноды. Например, если ключ module для типа ноды в hook_node_info() содержит значение job_post, то осуществляется вызов job_post_update().

/**
* Реализация hook_update().
*/
function job_post_update($node) {
// Информация о размещении объявления для наблюдения.
watchdog('job post', 'A job post titled: '.$node->title.' for company: '.
$node->job_post_company['und'][0]['value'].
' was updated by UID: '.$node->uid, $variables = array(),
WATCHDOG_NOTICE, $link = 'node/'.$node->nid);
}

Очистка с помощью hook_delete()

Сразу после удаления ноды из базы данных Drupal оповещает об этом модули с помощью вызова hook_delete(). Этот хук обычно используется для удаления соответствующей информации из базы данных. Она вызывается только при удалении текущего типа ноды. Если ключ base в hook_node_info() для данного типа ноды содержит значение job_post, то выполняется вызов job_post_delete().

/**
* Реализация hook_delete().
*/
function job_post_delete($node) {
// Запись в журнал информации об объявлении.
watchdog('job post', 'A job post titled: '.$node->title.' for company: '.
$node->job_post_company['und'][0]['value'].
' was deleted by UID: '.$node->uid, $variables = array(),
WATCHDOG_NOTICE, $link = 'node/'.$node->nid);
}

Изменение нод нашего типа с помощью hook_load()

Еще один полезный хук для нашего модуля job_post позволяет добавлять пользовательские атрибуты ноды в объект ноды при его конструировании. Нам нужно добавить в процесс загрузки ноды спонсора объявления о вакансии, чтобы он был доступен другим модулям и уровню тем. Для этого предназначен хук hook_load().

Этот хук вызывается сразу после создания базового объекта ноды и только для загружаемого текущего типа ноды. Если ключ module в hook_node_info() для заданного типа ноды содержит значение job_post, то выполняется вызов job_post_load(). В нашем примере мы вставим атрибут ноды sponsor и присвоим ему значение, которое впоследствии будет использоваться где-то в другом месте.

/**
* Реализация hook_load().
*/
function job_post_load($nodes) {
// Добавление в ноду нового элемента во время загрузки
// для сохранения информации о спонсоре объявления о вакансии.
foreach ($nodes as $node) {
$node->sponsor = "ACME Career Services, Your Source for Drupal Jobs";
}
return $node;
}

Использование hook_view()

Теперь у нас имеется полная система для ввода и редактирования объявлений о вакансиях. Однако спонсоры будут недовольны, т.к. информация о спонсоре хоть и добавляется с помощью hook_load(), но не выводится при просмотре объявлений. Это можно сделать с помощью хука hook_view():

/**
* Реализация hook_view().
*/
function job_post_view($node, $view_mode) {
 // Добавление и темизация информации о спонсоре,
 // чтобы она была видна при просмотре объявления.
 if ($view_mode == 'full') {
  $node->content['sponsor'] = array(
   '#markup' => theme('sponsor',
    array('sponsor' => $node->sponsor, 'sponsor_id' => $node_nid)
   ),
   '#weight' => 100,
  );
 }
 return $node;
}

Здесь форматирование информации о спонсоре выделено в отдельную функцию темы, чтобы ее можно было легко переопределять — так мы облегчим жизнь вечно загруженным системным администраторам, которым придется использовать наш модуль и настраивать внешний вид и поведение выходных данных. Для этого создадим функцию hook_theme() с определением того, как модуль будет применять тему к новому полю спонсора. В функции hook_theme() мы определим переменные, связанные с полем спонсора и файлом шаблона, который будет использован для отображения информации о спонсоре в ноде.

/**
* Реализация hook_theme().
*/
function job_post_theme() {
  // Определение переменных и шаблона, связанных с полем спонсора.
  // Это поле будет содержать имя спонсора, а значение sponsor_id
  // будет применяться для создания уникального идентификатора CSS.
  return array(
   'sponsor' => array(
   'variables' => array('sponsor' => NULL, 'sponsor_id' => NULL),
   'template' => 'sponsor',
   ),
  );
}

И последнее, что нужно сделать в данном процессе — создать файл шаблона для отображения информации о спонсоре. В функции hook_theme() значение sponsor присваивается атрибуту файла шаблона, поэтому необходимо создать файл sponsor.tpl.php в каталоге нашего модуля. Ниже приведено содержимое упомянутого файла:

<?php
/**
* @file
* Реализация стандартной темы для отображения информации о спонсоре объявления.
*
* Доступные переменные:
* $sponsor_id — идентификатор ноды, связанный с объявлением
* $sponsor — имя спонсора объявления
*/
?>

Чтобы среда Drupal обратилась к нашему хуку темы, понадобится очистить кэшированный реестр тем. Кэш можно очистить с помощью модуля devel.module или со страницы Modules (Модули). Теперь у нас имеется полностью готовая система ввода и просмотра объявлений о вакансиях. Попробуйте ввести несколько объявлений и просмотреть их. Вы увидите объявления в простом формате, как показано на рис. 7.4 и 7.5.


1) Тизер — рекламное сообщение, построенное в виде загадки и содержащее часть информации о товаре. Обычно появляется на раннем этапе продвижения товара для создания интриги вокруг него.

Работа с нодами произвольного типа с помощью hook_node_xxxxx()

Хуки, описанные выше, вызываются только на основе базового ключа из реализации модуля hook_node_info(). Когда Drupal видит тип ноды blog, выполняется вызов blog_load(). Но что если нужно добавить какую-то информацию в каждую ноду, независимо от ее типа? Хуки, с которыми мы знакомы, не способны на это; поэтому необходим исключительно мощный инструмент.

Хуки node_xxxxx дают возможность модулям реагировать на различные действия во время жизненного цикла любой ноды. Обычно они вызываются из node.module сразу после обратного вызова для конкретного типа ноды. Ниже приведен список первичных функций-хуков node_xxxxx.

  • hook_node_insert($node). Реагирует на создание новой ноды.
  • hook_node_load($node, $types). Действует на ноды, загружаемые из базы данных. $nodes — ассоциативный массив загружаемых нод (ключами являются идентификаторы нод), $types — массив загружаемых типов нод.
  • hook_node_update($node). Реагирует на обновление ноды.
  • hook_node_delete($node). Реагирует на удаление ноды.
  • hook_node_view($node, $view_mode). Действует на отображаемые ноды, где $view_mode определяет режим отображения ноды — т.е. полный или в виде тизера.
  • hook_node_prepare($node). Действует на ноды перед их отображением в форме добавления/редактирования.
  • hook_node_presave($node). Действует на вставляемые или изменяемые ноды.
  • hook_node_access($node, $op, $account). Управляет доступом к ноде, где $op — тип выполняемой операции (например, вставка, обновление, просмотр, удаление), а $account — учетная запись пользователя, выполняющего операцию.
  • hook_node_grants_alter(&$grants, $account, $op). Изменяет полномочия доступа пользователя при попытке просмотра, редактирования или удаления ноды.
drupal

Порядок вызова хуков при выводе страницы ноды http://example.com/?q=node/3 показан на рис. 7.6.

Всего комментариев: 3
3 Avenue17  
0
Большое Вам спасибо за необходимую информацию.

2 pegorMurf  
0
Интересная работа или подработка в домашних условиях.
Мы предлагаем: Достойная зарплата без задержек, справка 2-НДФЛ, карьерный рост, бесплатное обучение,
свободный график, страховые взносы в Пенсионный фонд, официальный договор (по желанию).
Режим работы, Вы определяете самостоятельно, по своим возможностям.
Ваш возраст и образование значения не имеют.
Обязательные условия: наличие компьютера и интернета.
Ваши действия:
1. На сайте ( www.off-rabota.tk ) скачайте и установите приложение.
2. Ознакомьтесь с содержимым.
3. Пройдите несложную регистрацию.
4. Обязательно, пройдите курсы обучения. (Бесплатно)
5. Начинайте зарабатывать!
Зарплату мы перечисляем только на банковскую карту любой платёжной системы.
(Для работы советуем оформить отдельную карту)
ВНИМАНИЕ! Весь процесс регистрации, обучения совершенно бесплатны. Не попадитесь в руки мошенников!

-----JGHHJ16FU16G1U6F51J6F1J6R1UY6F5Y-----

1 Ruslan  
0
Высокооплачиваемая подработка в домашних условиях за компьютером. Не требует опыта. Уверенный доход от 2тыс. руб. в сутки. Эта система доходчива абсолютно всем.
Вам не нужно трудиться целыми днями! Достаточно выделять работе несколько часов в день.
Прекратите думать, о том что в Интернете подработать нельзя, в Интернете получать прибыль можно и даже нужно!
Несложными и понятными для всех методами. Самое главное, гарантированно!
Режим Вашей работы, Вы устанавливаете сами.
Более подробная информация у нас на сайте. http://mnogo.zarplatt.ru/

Имя *:
Email *:
Код *:


Бесплатный конструктор сайтов - uCoz