Счетчик скачиваний

#
Счетчик скачиваний
1) Может кому-то пригодится.
2) Может кто-то усовершенствует и исправит ошибки.

Сделал счетчик скачиваний для файлов, добавленных, как допсвойство для ИЭ.

Принцип такой:
1. Создается допсвойство "счетчик скачиваний" (число). По-умолчанию = 0.

2. Создается php-страница, управляющая счетчиком.
Для этого в структуре добавляется раздел, например, "счетчик" с адресом "count".
Тип - Динамическая страница.
В Настройках динамической страницы следующий код
<?php
$entity_id = Core_Array::getPost('entity_id');
$property_id = Core_Array::getPost('property_id');
$oProperty_Value = Core_Entity::factory('Property_Value_Int');
$oProperty_Value->queryBuilder()
   ->where('property_id', '=', $property_id)
   ->where('entity_id', '=', $entity_id);
$aProperty_Value_String = $oProperty_Value->findAll();

foreach ($aProperty_Value_String as $oValue)
{
$count = $oValue->value;
$oValue->value = ++$count;
$oValue->save();
}
exit();
?>

Данный код будет корректно работать с единичным допсвойством. Если нужно работать с массивом (в допсвойстве), то код придется доработать. По идее я мог бы брать только первый элемент массива, но поставил перебор на будущее.

3. Перехватывается клик по ссылке скачивания.
4. Скрипт обращается к странице php. Счетчик увеличивается на единицу.
5. Увеличиваются счетчики на текущей странице.


Для обращения к допсвойству мне нужен id допсвойства и id информационного элемента.
Я их беру из XML и с помощью xls записываю в атрибуты ссылки.
XML-тег допсвойства у меня dmp3.
Id допсвойства = 120
Их нужно заменить на соответствующие(!).
xsl ссылки:
<a class="download dmp3" entity_id='{@id}' property_id='120' count_d='{property_value[tag_name="dmp3"]/value}' title="Количество скачиваний: {property_value[tag_name='dmp3']/value}" href="{dir}{property_value[tag_name='mp3']/file}">

В итоге получается ссылка типа:
Цитата:
<a class="download dmp3" entity_id="159" property_id="120" count_d="4" title="Количество скачиваний: 4" href="/upload/information_system/....">

"count_d" - у меня используется для отображения счетчика в title. Можно было бы перебирать title с помощью JS. Но я решил, что так проще.

Сам перехватчик расположен в JavaQuery-файле проекта.
   $('.download').click(function() {
   var $entity_id = $(this).attr('entity_id');
   var $property_id = $(this).attr('property_id');         
   var $count_d = Number($(this).attr('count_d'))+1;   
   $(this).attr('count_d', $count_d);
   $(this).attr('title', 'Количество скачиваний: '+$count_d);

   // Обновление счетчиков на странице
   if ($property_id == '120') {
      $('.dmp3').text('Скачиваний mp3: '+$count_d);
   };

   // Если есть файлы других типов, добавляем
   if ($property_id == '121') {
      $('.dpdf').text('Скачиваний pdf: '+$count_d);
   };   

   // Скрипт обращается к php. Счетчик увеличивается на единицу.
   $.post("/count/",    
     {
       entity_id: $entity_id,
       property_id: $property_id
     });

});
#
Re: Счетчик скачиваний
Stepan0v писал(а):
в JavaQuery-файле проекта
первый раз встречаю такую расшифровку для jQuery

А теперь по существу.
Из того кода, который вы привели, видно, что счетчик спроектирован неудачно.

Во1х, зачем отдельная php-страница, когда то что вы сделали можно добавить в настройки ТДС и обслуживать это действие текущим узлом текущей ИС?

Во2х, зачем тут jQuery? В текущей реализации страница все равно перезагрузится при щелчке по ссылке, т.е. смысла в динамическом обновлении счетчика на странице нет никакого. (ну то есть, как бы, если у вас тег A и вы делаете щелкаете на нам мышью, и обработчик повешен на jQuery click() и в нем нет preventDefault() или обработчик задан через onClick и не возвращает false то произойдет переход по ссылке с перезагрузкой страницы. А значит на текущей странице уже нет смысла что-то обновлять, пользователь это не успеет увидеть, а когда загрузится новая страница там уже будут новые значения сразу.

Ну и в3х, вы скажете, что jQuery у вас используется для отправки запроса на сервер, чтобы увеличить в БД значение счетчика. И я вам отвечу, что и для этого jQuery вам не нужно!
Вы же, переходя по ссылке, фактически отправляете на сервер запрос. Так вот этим и надо воспользоваться! В href этой ссылки надо указать не прямой путь к скачиваемому файлу, а некий action, например, download и entity_id а сам запрос адресовать на корень раздела инфосистемы.
Далее, в настройках ТДС вы проверете, не передано ли $_GET['action'] == 'download', и если да то:
- получаете entity_id
- проверяете, есть ли такой инфоэлемент в инфосистеме
- если да, то есть ли у него нужное доп.свойство с файлом
- если да, вычисляете путь к файлу и проверяете существование самого файла,
- если да, то пытаетесь получить текущее значение счетчика (если удачно то прибавляем единицу, если значения для свойства еще не задано то ставим 1)
- сохраняете в доп.свойство счетчика его новое значение
- отдаете header location на путь к файлу (файл начнет отдаваться пользователю)

-- если на любой вопрос "если да" правильный ответ "нет" то просто выходите из обработчика action=download или, например, отдаете ошибку 404.

Значения идентификаторов свойств счетчика и файла можно захардкодить прямо в ТДС (хотя это, конечно, по-скотски), или же вынести их в _параметры_ ТДС (не путать с _настройками_) и задавать в настройках узла структуры а в ТДС получать их в переменную обычным путем.

Что мы имеем при таком решении:
1. нам не нужна отдельная php-страница.
2. код работы со счетчиком лежит там же, где и работа с другими сущностями ИС, а не размазан по разным местам сайта. Приятно когда код логически сгруппирован.
3. нам не нужно jQuery и вообще инкрементирование счетчика никак не зависит от среды пользователя, а это всегда хорошо. Например, в браузерах с отключенным js, или в мобильных браузерах с плохой поддержкой js ваш счетчик работать не будет, а мой будет Из всех способов совершения действия всегда лучше выбирать самый прямой, минуя ненужных посредников.
4. отдавая пользователю файл мы можем вместо information_system_item_bla-bla-bla.mp3 задать файлу внятное человекопонятное имя, которое хранится в полях доп.свойства. Мелочь а приятно.
5. меньшая зависимость кода от параметров, передаваемых пользователем. в вашем случае туда-сюда гоняются entity_id и property_id а в моем только entity_id, все остальное задается через админку. Таким образом, у пользователя меньше шансов что-нибудь сломать. Например, пользователю может стать интересно, что будет, если передать другое значение property_id

Как-то так
Заказов не беру. Консультирую редко.
#
Re: Re: Счетчик скачиваний
Kotoff,
Цитата:
первый раз встречаю такую расшифровку для jQuery

Меня тоже смутило, то это чтобы не писать, что скрипт написан на JQuere, расположен... А так одно слово.
Цитата:
зачем отдельная php-страница, когда-то что вы сделали можно добавить в настройки ТДС и обслуживать это действие текущим узлом текущей ИС?

Счетчик может относиться к разным ИС. Если одна, то логично добавить в настройки ТДС.

Цитата:
В текущей реализации страница все равно перезагрузится при щелчке по ссылке

У меня файлы открываются в новой вкладке, а страница не перезагружается. Это же скачивание. Я просто убрал target="blank" чтобы не смущал.

Цитата:
В href этой ссылки надо указать не прямой путь к скачиваемому файлу, а некий action, например, download и entity_id а сам запрос адресовать на корень раздела инфосистемы.

Хорошее решение. Только не для скачивания.
Если по ссылке кликнут правой кнопкой и захотят "Сохранить по ссылке...", то в этом случае ничего не скачается.
В моем случае скачается, но не добавится счетчик (как бы это отловить?). В общем, хотелось не внедрять, в надстроить, чтобы сам функционал от этого не пострадал.

Цитата:
— проверяете, есть ли такой инфоэлемент в инфосистеме
— если да, то есть ли у него нужное доп.свойство с файлом

Может быть такое, что свойство есть, а элемента нет?
Я бы сразу искал допсвойство. Если его хотят скачать и оно есть, то почему бы не отдать?

Спасибо за советы.
#
Re: Счетчик скачиваний
Stepan0v писал(а):
что скрипт написан на JQuere, расположен… А так одно слово
Stepan0v, запомните, правильно пишется jQuery и никак иначе. JQuere, JavaQuery - это все какая неграмотная самодеятельность.

Stepan0v писал(а):
Счетчик может относиться к разным ИС. Если одна, то логично добавить в настройки ТДС.
Вы неправильно разделяете понятия ИС и ТДС.
Одна и та же ТДС может обслуживать разные ИС, привязанные к разным узлам структуры. Поэтому ваш аргумент некорректен.

Stepan0v писал(а):
Хорошее решение. Только не для скачивания.
Если по ссылке кликнут правой кнопкой и захотят «Сохранить по ссылке…», то в этом случае ничего не скачается.

Отнюдь. Вот вам пример: http://www.elcomspb.ru/press_centre/elcominfo/number_6/
На этой странице, скачивание начинается автоматически, но если его отменить, то в тексте есть слова "воспользуйтесь <прямой ссылкой> для загрузки", прямая ссылка имеет вид http://www.elcomspb.ru/press_centre/elcominfo/number_6/?action=download&item_id=1137 делаем "Сохранить как" и получаем нужный безо всяких проблем. Назовите мне браузер, в котором это не работает.
(кстати, сайт на HostCMS, скачивание реализовано как раз вышеописанным способом)

Stepan0v писал(а):
В моем случае скачается, но не добавится счетчик (как бы это отловить?).
А вот только так и отловить - через ссылку с action и entity_id. Это единственный способ, гарантирующий инкремент счетчика при скачивании.

Stepan0v писал(а):
Может быть такое, что свойство есть, а элемента нет?
Это как? О_о
Вы тут путаете понятия. Есть само доп.свойство - у которого описан тип (строка/флажок/текстовы блок/файл), название, имя в xml и т.п. - оно привязано к ИС в целом.
А есть _значения_ доп.свойства для конкретного элемента. И они привязаны к конкретному элементу (ну или группе, это значения доп.свойства группы).
При этом возможна ситуация, когда инфоэлемент существует, а значение доп.свойства для него - нет. Например, если мы это значение не задавали - типичная ситуация: элемент создали, а mp3-файл для него не указали. При попытке получить значение этого доп.свойства для такого элемента получим NULL.
Но вот ситуация, когда у вас инфоэлемента нет, а _значение_ доп.свойства для него есть - невозможна. Если у вас такое встречается то это указывает, как минимум, на ошибки в БД.
Просто обычно никто в речи не делает специальный акцент на разнице между доп.свойством и его значением, ну вроде как само собой подразумевается что эта разница есть.

Stepan0v писал(а):
Я бы сразу искал допсвойство. Если его хотят скачать и оно есть, то почему бы не отдать?
Торопитесь вы
И оставляете потенциальную дыру в безопасности.
Правильный путь - сначала убедиться, что существует указанный инфоэлемент. Затем, по-хорошему, надо проверить, что текущий пользователь сайта имеет право доступа к этому элементу. И только затем уже проверять, существует ли значение нужного доп.свойства для этого элемента.

Stepan0v писал(а):
У меня файлы открываются в новой вкладке, а страница не перезагружается. Это же скачивание. Я просто убрал target=«blank» чтобы не смущал.
Тогда берем мое решение и все-таки немного дополняем его на js. Вешаем-таки обработчик на onclick для ссылки на файл.
В обработчике делаем preventDefault(), из ссылки получаем ее href (с action=download&entity_id=123) динамически создаем невидимый iframe, присваиваем ему полученную ссылку - файл начинает скачиваться на текущей странице, затем делаем небольшую задержку (где-то 500мс, чтобы успел увеличиться счетчик) и аяксом запрашиваем _значение_ счетчика для данного инфоэлемента (action=get_count&entity_id=123) которое и вставляем на страницу.
Задержка в 500 ms нужна из-за того, что увеличение счетчика и запрос его значения - теперь асинхронные действия, надо дать счетчику шанс на то, чтобы он успел увеличиться.
Для action=get_count придется добавить еще один обработчик в настройки ТДС, в конце обработчика обязательно exit().
Заказов не беру. Консультирую редко.
Авторизация