PHP hook, building hooks in your application
Introduction
One of the real challenges in building any type of framework, core or application is making it possible for the developers to hook into the business logic at specific points. Since PHP is not event based, nor it works with interrupts you have to come up an alternative.
The test case
Lets assume we are the main developers of a webshop framework. Programmers can use our framework to build complete webshops. Programmers can manage the orders that are placed on the webshop with the order class. The order class is part of our framework and we don’t want it to be extended by any programmer. However we don’t want to limit to programmers in their possibilities to hook into the orders process.
For example programmers should be able to send an email to the webshopowner if an order changes from one specific delivery status to another. This functionality is not part of the default behavior in our framework and is custom for the progammers webshop implementation.
Like said before, PHP doesn’t provide interrupts or real events so we need to come up with another way to implement hooks into our application. Lets take a look at the observer pattern.
Implementing the Observer pattern
The observer pattern is a design-pattern that describes a way for objects to be notified to specific state-changes in objects of the application.
For the first implementation we can use SPL. The SPL provides in two simple objects:
SPLSubject
- attach (new observer to attach)
- detach (existing observer to detach)
- notify (notify all observers)
SPLObserver
- update (Called from the subject (i.e. when it’s value has changed).
iOrderRef = $iOrderRef;
// Get order information from the database or an other resources
$this->iStatus = Order::STATUS_SHIPPED;
}
/**
* Attach an observer
*
* @param SplObserver $oObserver
* @return void
*/
public function attach(SplObserver $oObserver)
{
$sHash = spl_object_hash($oObserver);
if (isset($this->aObservers[$sHash])) {
throw new Exception('Observer is already attached');
}
$this->aObservers[$sHash] = $oObserver;
}
/**
* Detach observer
*
* @param SplObserver $oObserver
* @return void
*/
public function detach(SplObserver $oObserver)
{
$sHash = spl_object_hash($oObserver);
if (!isset($this->aObservers[$sHash])) {
throw new Exception('Observer not attached');
}
unset($this->aObservers[$sHash]);
}
/**
* Notify the attached observers
*
* @param string $sEvent, name of the event
* @param mixed $mData, optional data that is not directly available for the observers
* @return void
*/
public function notify()
{
foreach ($this->aObservers as $oObserver) {
try {
$oObserver->update($this);
} catch(Exception $e) {
}
}
}
/**
* Add an order
*
* @param array $aOrder
* @return void
*/
public function delete()
{
$this->notify();
}
/**
* Return the order reference number
*
* @return int
*/
public function getRef()
{
return $this->iOrderRef;
}
/**
* Return the current order status
*
* @return int
*/
public function getStatus()
{
return $this->iStatus;
}
/**
* Update the order status
*/
public function updateStatus($iStatus)
{
$this->notify();
// ...
$this->iStatus = $iStatus;
// ...
$this->notify();
}
}
/**
* Order status handler, observer that sends an email to secretary
* if the status of an order changes from shipped to delivered, so the
* secratary can make a phone call to our customer to ask for his opinion about the service
*
* @package Shop
*/
class OrderStatusHandler implements SplObserver
{
/**
* Previous orderstatus
* @var int
*/
protected $iPreviousOrderStatus;
/**
* Current orderstatus
* @var int
*/
protected $iCurrentOrderStatus;
/**
* Update, called by the observable object order
*
* @param Observable_Interface $oSubject
* @param string $sEvent
* @param mixed $mData
* @return void
*/
public function update(SplSubject $oSubject)
{
if(!$oSubject instanceof Order) {
return;
}
if(is_null($this->iPreviousOrderStatus)) {
$this->iPreviousOrderStatus = $oSubject->getStatus();
} else {
$this->iCurrentOrderStatus = $oSubject->getStatus();
if($this->iPreviousOrderStatus === Order::STATUS_SHIPPED && $this->iCurrentOrderStatus === Order::STATUS_DELIVERED) {
$sSubject = sprintf('Order number %d is shipped', $oSubject->getRef());
//mail('secratary@example.com', 'Order number %d is shipped', 'Text');
echo 'Mail sended to the secratary to help her remember to call our customer for a survey.';
}
}
}
}
$oOrder = new Order(26012011);
$oOrder->attach(new OrderStatusHandler());
$oOrder->updateStatus(Order::STATUS_DELIVERED);
$oOrder->delete();
?>
There are several problems with the implementation above. To most important disadvantage is that we have only one update method in our observer. In this update method we don’t know when and why we are getting notified, just that something happened. We should keep track of everything that happens in the subject. (Or use debug_backtrace… just joking, don’t even think about using it that way ever!).
Taking it a step further, events
Lets take a look at the next example, we will extend the Observer implementation with some an additional parameter for the eventname that occured.
Finishing up, optional data
iOrderRef = $iOrderRef;
// Get order information from the database or something else...
$this->iStatus = Order::STATUS_SHIPPED;
}
/**
* Attach an observer
*
* @param Observer_Interface $oObserver
* @return void
*/
public function attachObserver(Observer_Interface $oObserver)
{
$sHash = spl_object_hash($oObserver);
if (isset($this->aObservers[$sHash])) {
throw new Exception('Observer is already attached');
}
$this->aObservers[$sHash] = $oObserver;
}
/**
* Detach observer
*
* @param Observer_Interface $oObserver
* @return void
*/
public function detachObserver(Observer_Interface $oObserver)
{
$sHash = spl_object_hash($oObserver);
if (!isset($this->aObservers[$sHash])) {
throw new Exception('Observer not attached');
}
unset($this->aObservers[$sHash]);
}
/**
* Notify the attached observers
*
* @param string $sEvent, name of the event
* @param mixed $mData, optional data that is not directly available for the observers
* @return void
*/
public function notifyObserver($sEvent, $mData=null)
{
foreach ($this->aObservers as $oObserver) {
try {
$oObserver->update($this, $sEvent, $mData);
} catch(Exception $e) {
}
}
}
/**
* Add an order
*
* @param array $aOrder
* @return void
*/
public function add($aOrder = array())
{
$this->notifyObserver('onAdd');
}
/**
* Return the order reference number
*
* @return int
*/
public function getRef()
{
return $this->iOrderRef;
}
/**
* Return the current order status
*
* @return int
*/
public function getStatus()
{
return $this->iStatus;
}
/**
* Update the order status
*/
public function updateStatus($iStatus)
{
$this->notifyObserver('onBeforeUpdateStatus');
// ...
$this->iStatus = $iStatus;
// ...
$this->notifyObserver('onAfterUpdateStatus');
}
}
/**
* Order status handler, observer that sends an email to secretary
* if the status of an order changes from shipped to delivered, so the
* secratary can make a phone call to our customer to ask for his opinion about the service
*
* @package Shop
*/
class OrderStatusHandler implements Observer_Interface
{
protected $iPreviousOrderStatus;
protected $iCurrentOrderStatus;
/**
* Update, called by the observable object order
*
* @param Observable_Interface $oObservable
* @param string $sEvent
* @param mixed $mData
* @return void
*/
public function update(Observable_Interface $oObservable, $sEvent, $mData=null)
{
if(!$oObservable instanceof Order) {
return;
}
switch($sEvent) {
case 'onBeforeUpdateStatus':
$this->iPreviousOrderStatus = $oObservable->getStatus();
return;
case 'onAfterUpdateStatus':
$this->iCurrentOrderStatus = $oObservable->getStatus();
if($this->iPreviousOrderStatus === Order::STATUS_SHIPPED && $this->iCurrentOrderStatus === Order::STATUS_DELIVERED) {
$sSubject = sprintf('Order number %d is shipped', $oObservable->getRef());
//mail('secratary@example.com', 'Order number %d is shipped', 'Text');
echo 'Mail sended to the secratary to help her remember to call our customer for a survey.';
}
}
}
}
$oOrder = new Order(26012011);
$oOrder->attachObserver(new OrderStatusHandler());
$oOrder->updateStatus(Order::STATUS_DELIVERED);
$oOrder->add();
?>
Now we are able to take action on different events that occur.
Disadvantages
Although this implementation works quite well there are some drawbacks. One of those drawbacks is that we need to dispatch an event in our framework, if we don’t programmers can’t hook into our application. Triggering events everywhere give us a small performance penalty however I do think this way of working gives the programmers a nice way to hook into your application on those spots that you want them to hook in.
Just for the record
Notice that this code is just an example and can still use some improvements, for example: each observer is initialized even it will maybe never be notified, therefore I suggest to make use of lazy in some cases for loading the objects. There are other systems to hook into an application, more to follow!
Экскурсии Казани — ваш гид в столице Татарстана
Казань экскурсии — это возможность открыть для себя один из самых ярких городов России, где переплетаются культура Востока и Запада, ислам и православие, старинная архитектура и современные музеи. Если вы ищете экскурсии в Казани с опытными гидами, комфортным транспортом и насыщенной программой — вы по адресу.
[url=https://kaztur.ru/golubie-ozera-ekskursiya/]экскурсия на голубые озера в казани[/url]
Почему экскурсии по Казани с нами — лучший выбор?
Ежедневные выезды
Профессиональные гиды-историки
Удобные автобусные маршруты
Доступ ко всем главным достопримечательностям
Прозрачные цены, возможность онлайн-бронирования
Лучшие экскурсии в Казани — Топ-7 маршрутов
Обзорная экскурсия по Казани
Классическая экскурсия Казань, включающая посещение Казанского Кремля, набережной, Старо-Татарской слободы, мечети Кул Шариф, улицы Баумана и других знаковых мест. Отличный старт для знакомства с городом.
Ключевые слова: казань экскурсия, экскурсия по казани, экскурсии в казани
Вечерняя экскурсия по Казани
Незабываемое путешествие в мир огней и архитектуры. Вечером Казань преображается, а наши вечерние экскурсии по Казани покажут её во всей красе.
Ключевые вхождения: экскурсия по вечерней казани, вечерние экскурсии в казани
Экскурсия на Голубые озёра
Погружение в природу Татарстана. Прозрачные воды, прогулки, купание и свежий воздух — идеальный отдых для всей семьи. Популярный маршрут как летом, так и зимой.
Ключевые слова: экскурсии казань, казань экскурсии, экскурсии в казани
https://kaztur.ru/ekskursiya-v-innopolis-iz-kazani-obzor-czeny-bronirovanie/
экскурсии по казани
Частные и групповые экскурсии в Казани
Мы предлагаем как групповые экскурсии в Казани, так и индивидуальные маршруты с персональным гидом. Вы можете заказать как стандартную экскурсию по Казани, так и уникальный тур, разработанный специально под ваши интересы.
Прямые вхождения:
заказать экскурсию казань
экскурсии казань с гидом
казань экскурсия индивидуальная
Тематические экскурсии по Казани
Религиозная Казань
Путешествие по храмам, мечетям и монастырям Казани. Вы узнаете, как мирно сосуществуют ислам и православие в одном городе.
Историческая Казань
Маршруты, охватывающие историю Казанского ханства, Золотой Орды и Российской империи. Отличный выбор для школьников, студентов и всех, кто интересуется историей.
Гастрономическая Казань
Попробуйте чак-чак, эчпочмак, губадию и другие блюда татарской кухни в лучших ресторанах города. Вкусная экскурсия по Казани — гастроформат!
Сколько стоят экскурсии по Казани?
Цены на экскурсии в Казани начинаются от 600 ?. Все экскурсии включают:
сопровождение лицензированного гида
комфортный транспорт (при необходимости)
входные билеты (в зависимости от маршрута)
MelvinBrova
13 Oct 25 at 7:43 pm
Admiring the persistence you put into your blog and in depth
information you provide. It’s good to come across a blog every
once in a while that isn’t the same unwanted rehashed information. Fantastic
read! I’ve saved your site and I’m including your RSS feeds
to my Google account.
Rikdom Bitrad
13 Oct 25 at 7:44 pm
перепланировка нежилого помещения в нежилом здании законодательство [url=http://www.pereplanirovka-nezhilogo-pomeshcheniya11.ru]перепланировка нежилого помещения в нежилом здании законодательство[/url] .
pereplanirovka nejilogo pomesheniya_kler
13 Oct 25 at 7:44 pm
аренда грузоподъемной техники [url=http://arenda-mini-ekskavatora-v-moskve-2.ru]аренда грузоподъемной техники[/url] .
arenda mini ekskavatora v moskve_pcKt
13 Oct 25 at 7:45 pm
переустройство нежилого помещения [url=pereplanirovka-nezhilogo-pomeshcheniya11.ru]переустройство нежилого помещения[/url] .
pereplanirovka nejilogo pomesheniya_uxer
13 Oct 25 at 7:48 pm
экскаватор погрузчик аренда москва и область [url=www.arenda-ekskavatora-pogruzchika-cena-2.ru/]www.arenda-ekskavatora-pogruzchika-cena-2.ru/[/url] .
arenda ekskavatora pogryzchika cena_gqst
13 Oct 25 at 7:49 pm
https://probilets.com/
Johniesweli
13 Oct 25 at 7:49 pm
электрокарнизы для штор [url=http://karniz-elektroprivodom.ru/]электрокарнизы для штор[/url] .
karniz elektroprivodom shtor kypit_xsei
13 Oct 25 at 7:49 pm
натяжные потолки официальный сайт самара [url=https://stretch-ceilings-samara.ru/]stretch-ceilings-samara.ru[/url] .
natyajnie potolki samara_ghkl
13 Oct 25 at 7:52 pm
карниз моторизованный [url=https://elektrokarnizy797.ru/]https://elektrokarnizy797.ru/[/url] .
elektrokarnizi_btMl
13 Oct 25 at 7:52 pm
аренда экскаватора стоимость [url=http://arenda-ekskavatora-pogruzchika-cena-2.ru/]http://arenda-ekskavatora-pogruzchika-cena-2.ru/[/url] .
arenda ekskavatora pogryzchika cena_eqst
13 Oct 25 at 7:52 pm
В эссе [url=https://www.igor-scherbakov.ru/muzykant-v-sovremennom-mire]«Музыкант в современном мире»[/url] поднимается вопрос о роли артиста в эпоху цифровых технологий и массовой культуры. Щербаков утверждает, что подлинное искусство остаётся востребованным, если оно искренне и профессионально. Его взгляд вдохновляет сохранять верность своему призванию.
AnekWap
13 Oct 25 at 7:52 pm
Just swapped USDC for $MTAUR. Vesting worth extending. Project’s potential vast.
mtaur token
WilliamPargy
13 Oct 25 at 7:53 pm
This site was… how do you say it? Relevant!! Finally I’ve found something that helped me.
Many thanks!
Vision Kantrex X
13 Oct 25 at 7:57 pm
карниз для штор с электроприводом [url=http://www.karniz-shtor-elektroprivodom.ru]карниз для штор с электроприводом[/url] .
karniz dlya shtor s elektroprivodom_dqer
13 Oct 25 at 7:58 pm
согласование перепланировки нежилого здания [url=https://pereplanirovka-nezhilogo-pomeshcheniya11.ru/]https://pereplanirovka-nezhilogo-pomeshcheniya11.ru/[/url] .
pereplanirovka nejilogo pomesheniya_rqer
13 Oct 25 at 8:00 pm
трактор погрузчик аренда [url=http://www.arenda-ekskavatora-pogruzchika-cena-2.ru]http://www.arenda-ekskavatora-pogruzchika-cena-2.ru[/url] .
arenda ekskavatora pogryzchika cena_rest
13 Oct 25 at 8:00 pm
карниз для штор электрический [url=www.karniz-elektroprivodom.ru/]карниз для штор электрический[/url] .
karniz elektroprivodom shtor kypit_pbei
13 Oct 25 at 8:02 pm
Лечение начинается с короткой оценки рисков и выбора безопасной точки старта. Далее следуют этапы стабилизации, настройки сна и тревоги, поведенческие инструменты и план антирецидивной поддержки. Ниже — ориентировочная карта: в реальности длительности и интенсивность подбираются индивидуально, а переход между форматами происходит без «обнуления» обследований.
Выяснить больше – [url=https://narkologicheskaya-klinika-v-spb14.ru/]частная наркологическая клиника санкт-петербург[/url]
Elliottper
13 Oct 25 at 8:02 pm
аренда навесного оборудования на экскаватор [url=http://www.arenda-ekskavatora-pogruzchika-cena-2.ru]аренда навесного оборудования на экскаватор[/url] .
arenda ekskavatora pogryzchika cena_fhst
13 Oct 25 at 8:05 pm
потолочкин натяжные [url=https://www.natyazhnye-potolki-samara-1.ru]https://www.natyazhnye-potolki-samara-1.ru[/url] .
natyajnie potolki samara_tuor
13 Oct 25 at 8:07 pm
горизонтальные жалюзи с электроприводом [url=zhalyuzi-s-elektroprivodom77.ru]горизонтальные жалюзи с электроприводом[/url] .
jaluzi na okna s elektroprivodom_jwpa
13 Oct 25 at 8:09 pm
ynaix – Found useful info here, makes me trust the site more.
Cesar Hinokawa
13 Oct 25 at 8:11 pm
перепланировка здания [url=http://pereplanirovka-nezhilogo-pomeshcheniya10.ru/]перепланировка здания[/url] .
pereplanirovka nejilogo pomesheniya_vrSr
13 Oct 25 at 8:12 pm
sneak a peek at this web-site.
PHP hook, building hooks in your application – Sjoerd Maessen blog at Sjoerd Maessen blog
sneak a peek at this web-site.
13 Oct 25 at 8:12 pm
можно ли купить диплом медсестры [url=www.frei-diplom14.ru/]можно ли купить диплом медсестры[/url] .
Diplomi_uhoi
13 Oct 25 at 8:16 pm
https://probilets.com/
Stanleytog
13 Oct 25 at 8:16 pm
согласование перепланировки в нежилом здании [url=https://pereplanirovka-nezhilogo-pomeshcheniya11.ru]согласование перепланировки в нежилом здании[/url] .
pereplanirovka nejilogo pomesheniya_pker
13 Oct 25 at 8:18 pm
Just want to say your article is as astonishing.
The clearness to your post is just excellent and i could assume you’re
an expert on this subject. Well with your permission allow me to take hold of your feed to stay up to date with
drawing close post. Thanks a million and please continue the gratifying work.
utländska casino
13 Oct 25 at 8:18 pm
услуги экскаватора москва [url=http://arenda-mini-ekskavatora-v-moskve-2.ru/]услуги экскаватора москва[/url] .
arenda mini ekskavatora v moskve_ufKt
13 Oct 25 at 8:19 pm
электрокарниз москва [url=https://elektrokarnizy797.ru]https://elektrokarnizy797.ru[/url] .
elektrokarnizi_vfMl
13 Oct 25 at 8:21 pm
This article was really interesting, thank you for sharing it.
I appreciate the way you explained the ideas, it was easy to follow and kept my attention all the way through.
While reading, I started thinking about how special it is to choose
custom jewelry that actually show personality.
Recently I have been looking at family jewelry pieces, and your post reminded me that gifts can also be a personal expression.
I will definitely save this site because I find it valuable, and
I look forward to reading more in the future.
Thanks again for the effort you put into this content, it really motivates people who are interested in style.
personalized necklace online
13 Oct 25 at 8:21 pm
электрокарнизы для штор купить в москве [url=http://www.karniz-elektroprivodom.ru]http://www.karniz-elektroprivodom.ru[/url] .
karniz elektroprivodom shtor kypit_udei
13 Oct 25 at 8:22 pm
Minotaurus token’s security priority wins trust. Presale’s low min buy accessible. Battles engaging.
minotaurus presale
WilliamPargy
13 Oct 25 at 8:26 pm
Just heard about Kerassentials. It seems like a promising
solution for toenail fungus. Natural components are a huge plus!
I look forward to the results! I want to learn more: https://us-kerassentials-usa.com/
Kerassentials
13 Oct 25 at 8:28 pm
электрокарниз купить в москве [url=https://www.karniz-shtor-elektroprivodom.ru]электрокарниз купить в москве[/url] .
karniz dlya shtor s elektroprivodom_suer
13 Oct 25 at 8:28 pm
эллиптический тренажер proxima Беговая дорожка Oxygen Fitness сочетает надежность и инновации от известного бренда. Модели вроде OXY-400 или Elite имеют мощный мотор 2-2,5 л.с., скорость до 18 км/ч и 12 предустановленных программ для разнообразия тренировок. Амортизация Soft System защищает суставы, а LED-дисплей отображает все ключевые метрики: пульс, расстояние, скорость. Складной дизайн с гидравлическим подъемом упрощает хранение, а колеса для транспортировки — перемещение. Подходит для дома или офиса, выдерживает до 130 кг. Пользователи хвалят тихую работу и долговечность. Цена от 30 000 рублей, с гарантией 2 года. Тренировки на Oxygen Fitness ускоряют метаболизм, укрепляют сердечную систему и помогают в похудении.
JamesDrips
13 Oct 25 at 8:29 pm
https://www.live4cup.com/f-sp1793512-.html#p1793512
stwxvha
13 Oct 25 at 8:30 pm
электрокарниз недорого [url=https://www.karniz-elektroprivodom.ru]https://www.karniz-elektroprivodom.ru[/url] .
karniz elektroprivodom shtor kypit_msei
13 Oct 25 at 8:33 pm
https://info71604.pages10.com/un-arma-secreta-para-detox-examen-de-orina-73117765
Detox para examen de muestra se ha vuelto en una opcion cada vez mas conocida entre personas que buscan eliminar toxinas del cuerpo y superar pruebas de analisis de drogas. Estos formulas estan disenados para ayudar a los consumidores a limpiar su cuerpo de residuos no deseadas, especialmente aquellas relacionadas con el uso de cannabis u otras sustancias.
El buen detox para examen de fluido debe brindar resultados rapidos y efectivos, en gran cuando el tiempo para limpiarse es limitado. En el mercado actual, hay muchas opciones, pero no todas aseguran un proceso seguro o efectivo.
Que funciona un producto detox? En terminos simples, estos suplementos actuan acelerando la depuracion de metabolitos y componentes a traves de la orina, reduciendo su concentracion hasta quedar por debajo del umbral de deteccion de algunos tests. Algunos funcionan en cuestion de horas y su efecto puede durar entre 4 a seis horas.
Resulta fundamental combinar estos productos con adecuada hidratacion. Beber al menos dos litros de agua al dia antes y despues del consumo del detox puede mejorar los resultados. Ademas, se aconseja evitar alimentos pesados y bebidas procesadas durante el proceso de uso.
Los mejores productos de limpieza para orina incluyen ingredientes como extractos de naturales, vitaminas del tipo B y minerales que favorecen el funcionamiento de los sistemas y la funcion hepatica. Entre las marcas mas populares, se encuentran aquellas que presentan certificaciones sanitarias y estudios de resultado.
Para usuarios frecuentes de cannabis, se recomienda usar detoxes con ventanas de accion largas o iniciar una preparacion previa. Mientras mas prolongada sea la abstinencia, mayor sera la potencia del producto. Por eso, combinar la disciplina con el uso correcto del detox es clave.
Un error comun es suponer que todos los detox actuan igual. Existen diferencias en formulacion, sabor, metodo de toma y duracion del resultado. Algunos vienen en envase liquido, otros en capsulas, y varios combinan ambos.
Ademas, hay productos que incorporan fases de preparacion o preparacion previa al dia del examen. Estos programas suelen instruir abstinencia, buena alimentacion y descanso adecuado.
Por ultimo, es importante recalcar que ninguno detox garantiza 100% de exito. Siempre hay variables individuales como metabolismo, frecuencia de consumo, y tipo de examen. Por ello, es vital seguir todas instrucciones del fabricante y no confiarse.
JuniorShido
13 Oct 25 at 8:34 pm
мини экскаватор аренда [url=http://arenda-mini-ekskavatora-v-moskve-2.ru]http://arenda-mini-ekskavatora-v-moskve-2.ru[/url] .
arenda mini ekskavatora v moskve_quKt
13 Oct 25 at 8:37 pm
I don’t even know how I ended up here, but I thought
this post was good. I do not know who you are but certainly you
are going to a famous blogger if you are not already 😉 Cheers!
nft
13 Oct 25 at 8:38 pm
Процесс лечения организован поэтапно, что делает его последовательным и результативным.
Подробнее можно узнать тут – http://narkologicheskaya-klinika-v-permi0.ru/narkolog-perm-zapis/
RobertBlugs
13 Oct 25 at 8:39 pm
Hi there, just became aware of your blog through Google, and found that it’s truly informative.
I’m gonna watch out for brussels. I’ll appreciate if you continue this in future.
Lots of people will be benefited from your writing. Cheers!
insights
13 Oct 25 at 8:39 pm
Вывод из запоя направлен не только на снятие острых симптомов, но и на комплексное восстановление организма. Работа специалистов позволяет стабилизировать состояние и создать условия для дальнейшего лечения зависимости.
Подробнее тут – [url=https://vyvod-iz-zapoya-tver0.ru/]врач вывод из запоя[/url]
Davidboots
13 Oct 25 at 8:40 pm
переустройство нежилого помещения [url=www.pereplanirovka-nezhilogo-pomeshcheniya11.ru]переустройство нежилого помещения[/url] .
pereplanirovka nejilogo pomesheniya_iaer
13 Oct 25 at 8:40 pm
zyloprim for sale
zyloprim for sale
13 Oct 25 at 8:42 pm
потолочкин ру натяжные потолки [url=https://stretch-ceilings-samara-1.ru]потолочкин ру натяжные потолки[/url] .
natyajnie potolki samara_jysl
13 Oct 25 at 8:42 pm
электрокарнизы для штор цена [url=https://www.karniz-elektroprivodom.ru]электрокарнизы для штор цена[/url] .
karniz elektroprivodom shtor kypit_nrei
13 Oct 25 at 8:45 pm
هشدار حساس به وبسایتهای بازیهای شرطی
آنلاین. من در نقش شخصی که اتفاق خودم کردهام، اعلام
میکنم که چنین پلتفرمها ابزاربرای دزدی پول
شما هستند. فعالیت ابتدایی خوشایند است، اما بعداً الگوریتمها طوری طراحی میگردند
که کاربر پایانه بازنده گردید.
خطر وابستگی قویتر از تمام عامل دیگری است و قادر است سلامتتان را ویران کند.
دور کنید!
شرط بندی غیرقانونی
13 Oct 25 at 8:47 pm