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://transformatornye-podstancii-kupit1.ru/]https://transformatornye-podstancii-kupit1.ru/[/url] .
transformatornie podstancii kypit_jior
22 Aug 25 at 5:24 am
Its like you read my mind! You seem to know so much about this,
such as you wrote the ebook in it or something.
I feel that you just can do with a few percent to drive the message home a bit, however instead of that, that is magnificent blog.
A fantastic read. I will definitely be back.
Unikaj nieprzyjemnych otarć! Wybierz bezszwowe stringi dla zapewnienia pełnej wygody.
22 Aug 25 at 5:24 am
Pretty section of content. I just stumbled upon your
site and in accession capital to assert that I get in fact enjoyed account
your blog posts. Any way I will be subscribing to your augment
and even I achievement you access consistently quickly.
sl860.com
22 Aug 25 at 5:25 am
I don’t even know the way I stopped up right here,
but I assumed this submit was once great. I don’t recognize who you might be however certainly you’re
going to a famous blogger in the event you aren’t already.
Cheers!
Morentix
22 Aug 25 at 5:25 am
Medication information leaflet. Cautions.
can i purchase generic erythromycin online
Everything about drug. Get now.
can i purchase generic erythromycin online
22 Aug 25 at 5:27 am
https://www.rwaq.org/users/kingfishercyceka-20250818103103
GroverPycle
22 Aug 25 at 5:28 am
Remarkable! Its really awesome post, I have got much clear
idea on the topic of from this post.
Arbiquant
22 Aug 25 at 5:31 am
It’s a shame you don’t have a donate button! I’d certainly donate to
this superb blog! I guess for now i’ll settle for book-marking and adding your RSS feed to my Google account.
I look forward to brand new updates and will talk about this site
with my Facebook group. Talk soon!
Faircroft Corebit
22 Aug 25 at 5:33 am
комплектная трансформаторная подстанция цена [url=http://www.transformatornye-podstancii-kupit1.ru]http://www.transformatornye-podstancii-kupit1.ru[/url] .
transformatornie podstancii kypit_mgor
22 Aug 25 at 5:33 am
can i buy cheap prednisone for sale
how can i get cheap prednisone without prescription
22 Aug 25 at 5:34 am
Hello everybody, here every one is sharing these kinds of experience, so
it’s pleasant to read this website, and I
used to visit this website everyday.
SPA in Karachi
22 Aug 25 at 5:35 am
Удобный доступ к игровым возможностям доступен на ero-seks.ru.
WilliamNex
22 Aug 25 at 5:35 am
DreamCloud Mattress seems like a solid choice!
The review really helped me understand its comfort and support features.
Dreamcloud Mattress
22 Aug 25 at 5:40 am
https://sonturkhaber.com/
Johnnylew
22 Aug 25 at 5:41 am
Hello, I enjoy reading all of your post. I like to
write a little comment to support you.
cocaine
22 Aug 25 at 5:44 am
прибор узи [url=https://www.kupit-uzi-apparat26.ru]https://www.kupit-uzi-apparat26.ru[/url] .
kypit yzi apparat_humr
22 Aug 25 at 5:49 am
https://www.metooo.io/u/689c83d9d7d8a37ce235d18e
GroverPycle
22 Aug 25 at 5:49 am
лампа лупа косметологическая тележка косметологическая металлическая
kosmetologicheskoe-oborudovanie-442
22 Aug 25 at 5:49 am
Hey hey, smart tߋ rush for top primary positions, ƅecause thеѕe highlight math ɑnd literacy,
key to O-Level ɑnd Α-Level victories.
Parents, competitive style fᥙll lah, elite primaries prepare fⲟr national assessments,
assuring smooth shifts tߋ secs.
Parents, worry aƅout the difference hor, mathematics groundwork proves vital ɗuring primary school іn understanding figures,
essential fߋr today’s digital economy.
Wah, math іs tһe groundwork stone іn primary schooling, assisting
kids ѡith dimensional reasoning tο building paths.
In addіtion to institution resources, focus սpon arithmetic foг аvoid common errors sᥙch as sloppy blunders at assessments.
Аpart bеyond institution facilities, concentrate ᴡith math in ordеr to avoid common mistakes including inattentive mistakes ɑt tests.
Listen սp, Singapore folks, math гemains рerhaps the moѕt crucial primary subject,
encouraging imagination іn prοblem-solving in innovative jobs.
Anderson Primary School ⲣrovides a stimulating environment tһаt supports intellectual аnd emotional development.
Witһ outstanding centers аnd dedicated teachers, іt inspires students to excel іn their studies.
Tanjong Katong Primary School ϲreates a cultural-rich environment.
Ꭲhe school inspires global thinking.
Mooms and dads value itѕ worldwide focus.
mʏ web paɡе; Kent Ridge Secondary School; Deangelo,
Deangelo
22 Aug 25 at 5:50 am
Mais alguém está usando o Delta Executor atualizado 2025?
Eu coimecei a usar hoje e achei bem rápido. Dá para rodar vários scripts semm
travar, e a nova interface ficou top.
Ache fácil pegar a chave, e até agora não tive problemas.
Também percebi que oss scripts carregam mais rápido.
Quem mais já aixou e acha que é confiável?
Recomendo demais para quem curte roblox scripts.
roblox scripts
22 Aug 25 at 5:51 am
Привет всем!
Долго обмозговывал как поднять сайт и свои проекты и нарастить CF cituation flow и узнал от друзей профессионалов,
топовых ребят, именно они разработали недорогой и главное буст прогон Xrumer – https://www.bing.com/search?q=bullet+%D0%BF%D1%80%D0%BE%D0%B3%D0%BE%D0%BD
Автоматический постинг форумов с Xrumer экономит время специалистов. Улучшение DR через Xrumer повышает позиции сайта. Программы для линкбилдинга делают продвижение системным. Повышение авторитетности сайта с помощью Xrumer заметно через месяц. Xrumer рассылка форумов расширяет охват ресурсов.
продвижение сайтов в могилеве, кз сео, линкбилдинг сайт
линкбилдинг это что, seo термины, продвижения сайтов способы
!!Удачи и роста в топах!!
Seofoumn
22 Aug 25 at 5:52 am
vps hosting server vps best hosting
vps-hosting-242
22 Aug 25 at 5:53 am
аттестат 11 класса купить цена [url=https://arus-diplom23.ru]аттестат 11 класса купить цена[/url] .
Diplomi_qlol
22 Aug 25 at 5:54 am
трансформаторная подстанция купить [url=http://transformatornye-podstancii-kupit1.ru]http://transformatornye-podstancii-kupit1.ru[/url] .
transformatornie podstancii kypit_bror
22 Aug 25 at 6:00 am
Каждая процедура проводится под контролем квалифицированного врача. При необходимости возможен экстренный выезд специалиста на дом, что позволяет оказать помощь пациенту в привычной и безопасной обстановке.
Разобраться лучше – [url=https://vyvod-iz-zapoya-odincovo6.ru/]вывести из запоя одинцово[/url]
Gregoryflony
22 Aug 25 at 6:02 am
If you are going for best contents like me, only visit this web page every day as it offers feature contents,
thanks
Feel free to surf to my blog: iPhone Schematic Diagram
iPhone Schematic Diagram
22 Aug 25 at 6:04 am
Hello, i read your blog occasionally and i own a similar one and i was
just wondering if you get a lot of spam feedback?
If so how do you protect against it, any plugin or anything you can recommend?
I get so much lately it’s driving me crazy so any help is very much appreciated.
My web page: A片
A片
22 Aug 25 at 6:05 am
https://3e96bf7a72aa90c3327716bbf0.doorkeeper.jp/
GroverPycle
22 Aug 25 at 6:10 am
трансформаторная будка цена [url=https://transformatornye-podstancii-kupit1.ru/]https://transformatornye-podstancii-kupit1.ru/[/url] .
transformatornie podstancii kypit_pjor
22 Aug 25 at 6:10 am
С момента основания клиники мы делаем ставку на сочетание передовых медицинских протоколов и внимания к каждому пациенту. Наши наркологи регулярно проходят обучение на базе ведущих российских и европейских центров, что позволяет внедрять в практику новые аппараты для аппаратной детоксикации, в том числе плазмаферез и молекулярное диализирование. Психологи и психотерапевты клиники работают по стандартам когнитивно-поведенческой терапии и мотивационного интервьюирования, а наши реабилитационные курсы аккредитованы в Международной ассоциации специалистов по алкоголизму и наркомании.
Выяснить больше – [url=https://narkologicheskaya-klinika-zhukovskij4.ru/]narkologicheskaya-klinika-zhukovskij4.ru/[/url]
Jamesmix
22 Aug 25 at 6:10 am
Dr. Jake Scott is on the front line of his second pandemic in five years and he is not getting much sleep.
Scott works full-time as an infectious disease physician at Stanford Health Care’s Tri-Valley hospital in Pleasanton, California. When he is done taking care of his patients and his two grade-school aged kids, he often stays up past midnight writing — furiously penning op-eds, collecting studies, leading evidence reviews and posting meaty threads on social media, most of them correcting the record on vaccines.
[url=https://trip-skan.cc]tripscan[/url]
Often, he’s reacting to the latest maneuvers by US Health and Human Services Secretary Robert F. Kennedy Jr.. A pinned post responding to one of Kennedy’s appearances on Fox News has been viewed almost 5 million times. Another post fact-checking Kennedy’s claims about potential harms from aluminum in vaccines had 1 million views in its first 48 hours. Scott’s followers on X have doubled since April.
https://trip-skan.cc
трипскан
“A million views for this long-winded, very detailed, kind of nerdy breakdown of the science,” Scott said, marveling at the attention it got. “I think that’s saying something, you know? People want that information, and they deserve it,” said Scott who is 48.
The Covid-19 pandemic turned many infectious disease specialists and virologists into household names. Scott’s was not one of them, perhaps because he was too busy treating patients. He didn’t stay out of the public discourse completely, however. He was one of the first doctors to tell people that Omicron didn’t seem to be as severe an infection as earlier strains of the virus, although some virologists were skeptical at the time.
In President Donald Trump’s second administration, however, Scott is taking on what he sees as a second pandemic — misinformation and disinformation about vaccines. He knows false information can be as harmful as any virus.
“When officials spread inaccurate information about vaccines, it does have real consequences, and families make decisions based on fear rather than on facts,” Scott said.
It’s already happening. The US Centers for Disease Control and Prevention recently reported data showing kindergarten vaccination rates continue to decline, as states make it easier to opt out of school vaccination requirements. Vaccine preventable diseases like measles and whooping cough are rising again, too.
Scott knows it could get much worse.
“In 2021, nearly every single patient I lost to Covid was unvaccinated by choice, and every colleague of mine has said the same thing.”
RobertArine
22 Aug 25 at 6:11 am
трансформаторные подстанции купить москва [url=http://transformatornye-podstancii-kupit1.ru]http://transformatornye-podstancii-kupit1.ru[/url] .
transformatornie podstancii kypit_npor
22 Aug 25 at 6:12 am
Хотите построить надежный и красивый загородный дом в Санкт-Петербурге или Ленинградской области? Мы предлагаем полный спектр строительных услуг: от разработки проекта и расчета сметы до сдачи объекта «под ключ». Используем кирпич, газобетонные блоки, пеноблоки и другие современные материалы. В прайсе подробно указаны расценки на кладку стен, перегородок, устройство перекрытий, штукатурку и отделочные работы. Стоимость фиксируется в договоре, чтобы каждый рубль был учтен. В нашей команде трудятся опытные подрядчики — https://builder-spb.ru/kamenschiki-kladka.html каменщики, штукатуры, сварщики, мастера по облицовке и внутренней отделке. Мы берем на себя все заботы о стройке, а заказчику остается только выбрать дизайн и дождаться завершения строительства. Построим дом вашей мечты с гарантией качества.
Benlog
22 Aug 25 at 6:14 am
http://steroidcarepharmacy.com/# SteroidCare Pharmacy
Davidrix
22 Aug 25 at 6:16 am
Этот интересный отчет представляет собой сборник полезных фактов, касающихся актуальных тем. Мы проанализируем данные, чтобы вы могли сделать обоснованные выводы. Читайте, чтобы узнать больше о последних трендах и значимых событиях!
Почему это важно? – https://rhfamlaw.com/hello-world
Mathewiceby
22 Aug 25 at 6:18 am
Good day! I know this is somewhat off topic but I was wondering which blog platform are
you using for this website? I’m getting tired of WordPress because I’ve had issues with hackers and I’m looking at options for another platform.
I would be awesome if you could point me in the direction of a good platform.
Fatvim Weight Loss Formula
22 Aug 25 at 6:19 am
Цитаты личность. Мир прекрасен цитаты. Красивые статусы про жизнь. Питер цитаты. Очень красивые стихи. Цитаты про людей которые обсуждают. Слова со смыслом. Успех в бизнесе цитаты. Странные слова и их значение.
citaty-top-937
22 Aug 25 at 6:19 am
mostbet bet [url=https://mostbet4147.ru]https://mostbet4147.ru[/url]
mostbet_xwMr
22 Aug 25 at 6:20 am
https://ivergrove.com/# ivermectin tablets for humans
Davidrix
22 Aug 25 at 6:21 am
I’m not sure why but this blog is loading extremely slow for me.
Is anyone else having this issue or is it a problem on my end?
I’ll check back later and see if the problem still exists.
Finance Legend App
22 Aug 25 at 6:22 am
Toronx.is is an advanced automated trading solution powered by artificial intelligence, offering AI-based tools in the
cryptocurrency and forex markets. With proprietary AI-driven algorithms, it enables investors to achieve consistent monthly profits while ensuring intelligent risk control.
Featuring quick transactions, auto trading, and a user-friendly interface,
Toronx.is is designed to attract both beginners and seasoned users.
trusted AI trading
22 Aug 25 at 6:24 am
FertiCare Online: FertiCare Online – can i order generic clomid price
WayneViemo
22 Aug 25 at 6:25 am
OMT’s blend ⲟf online and on-site alternatives սsеs flexibility, making
mathematics obtainable аnd lovable, while inspiring Singapore students fߋr examination success.
Ϲhange mathematics challenges іnto triumphs with OMT Math Tuition’ѕ blend of online and on-site
alternatives, Ƅacked ƅy a performance history ߋf trainee quality.
Ԝith trainees іn Singapore starting official mathematics education fгom daү one and facing high-stakes assessments,
math tuition рrovides the additional edge needed to achieve top performance in this crucial subject.
primary school tuition іѕ important for PSLE аs it provides remedial assistance fοr subjects like
wһole numbers and measurements, maкing sure no foundational
weaknesses continue.
Comprehensive coverage ߋf the wһole Ⲟ Level syllabus in tuition mɑkes certаin no topics, from sets t᧐ vectors, are ignored in a trainee’s revision.
Bу providing substantial exercise ᴡith paѕt A Level test papers, math tuition familiarizes pupils ԝith concern formats аnd noting schemes
f᧐r ideal efficiency.
OMT sets іtself аpart with аn educational program tһat enhances MOE curriculum
νia collective оn the internet discussion forums fߋr talking aЬоut exclusive math
obstacles.
Team discussion forums іn the platform let yoᥙ review ᴡith peers ѕia, clearing uρ
uncertainties and improving уour math performance.
Math tuition develops resilience іn dealing
ԝith hɑrd inquiries, a necessity fօr thriving in Singapore’ѕ
hіgh-pressure exam atmosphere.
Ꭺlso visit mу homеpaɡe: math tuition singapore
math tuition singapore
22 Aug 25 at 6:26 am
трансформаторная подстанция купить цена [url=https://www.transformatornye-podstancii-kupit1.ru]https://www.transformatornye-podstancii-kupit1.ru[/url] .
transformatornie podstancii kypit_lror
22 Aug 25 at 6:28 am
Посмотрите, что я нашел по этому поводу:
Для тех, кто ищет информацию по теме “travelmontenegro.ru”, есть отличная статья.
Вот, делюсь ссылкой:
[url=https://travelmontenegro.ru]https://travelmontenegro.ru[/url]
Поделитесь своими мыслями в комментариях.
rusPoito
22 Aug 25 at 6:28 am
Hey this is somewhat of off topic but I was wanting to know if blogs use WYSIWYG editors or
if you have to manually code with HTML. I’m starting a
blog soon but have no coding expertise so I wanted to get guidance from someone with experience.
Any help would be greatly appreciated!
tempat bermain arcade
22 Aug 25 at 6:28 am
https://community.wongcw.com/blogs/1133317/%D0%90%D0%B4%D0%B6%D0%BC%D0%B0%D0%BD-%D0%BA%D1%83%D0%BF%D0%B8%D1%82%D1%8C-%D0%BC%D0%B0%D1%80%D0%B8%D1%85%D1%83%D0%B0%D0%BD%D1%83-%D0%B3%D0%B0%D1%88%D0%B8%D1%88-%D0%B1%D0%BE%D1%88%D0%BA%D0%B8
GroverPycle
22 Aug 25 at 6:30 am
mostbet регистрация через официальный сайт [url=http://mostbet4146.ru/]http://mostbet4146.ru/[/url]
mostbet_wsKt
22 Aug 25 at 6:33 am
16 Coins Grand Gold Edition Game espanyol
Alfonzohut
22 Aug 25 at 6:36 am
силовые трансформаторные подстанции [url=https://www.transformatornye-podstancii-kupit1.ru]https://www.transformatornye-podstancii-kupit1.ru[/url] .
transformatornie podstancii kypit_wsor
22 Aug 25 at 6:37 am