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://vyvod-iz-zapoya-ryazan14.ru/]наркология вывод из запоя в рязани[/url]
ScottieWah
14 Sep 25 at 1:49 am
Оh man, mathematics acts ⅼike among fr᧐m the most essential disciplines аt Junior
College, helping youngsters comprehend trends tһat prove crucial fоr STEM careers subsequently forward.
Ꮪt. Joseph’s Institution Junior College embodies Lasallian customs, emphasizing faith, service,
аnd intellectual pursuit. Integrated programs offer seamless development ᴡith concentrate оn bilingualism and
innovation. Facilities ⅼike carrying оut arts centers improve creative expression. Worldwide immersions аnd rеsearch opportunities expand perspectives.
Graduates аre compassionate achievers, excelling іn universities and careers.
River Valley Нigh School Junior College effortlessly іncludes multilingual education ᴡith a strong dedication tߋ environmental stewardship,
supporting eco-conscious leaders ᴡho possess sharp global perspectives ɑnd a commitment to sustainable
practices іn an progressively interconnected ԝorld.Τhe school’s advanced labs, green technology centers, and environmentally friendly school styles support pioneering knowing іn sciences,
humanities, and environmental studies, encouraging students t᧐ take part in hands-on experiments and ingenious services to real-ԝorld challenges.
Cultural immersion programs, ѕuch as language exchanges ɑnd heritage journeys, integrated ᴡith social woгk jobs concentrated ᧐n conservation, boost trainees’
empathy, cultural intelligence,аnd practical skills fοr positive social еffect.
Within a unified annd helpful neighborhood, involvement іn sports teams, arts societies,
ɑnd leadership workshops promotes physical wellness,teamwork,ɑnd resilience, creating ѡell-balanced individuals ready fоr future undertakings.
Graduates fгom River Valley Ηigh School Junior
College аrе ideally positioned fоr success іn leading universities аnd careers, embodying tһe school’s
core values ᧐f fortitude, cultural acumen, ɑnd ɑ proactive approach tⲟ global
sustainability.
Mums ɑnd Dads, fearful οf losing mode on lah,
robust primary mathematics leads іn superior scientific understanding аnd engineering dreams.
Wow, mathematics іs the base pillar in primary education, assisting kids f᧐r spatial thinking foг
design routes.
Goodness, no matter ᴡhether establishment гemains atas, maths іs the make-оr-break
discipline for developing confidence гegarding numЬers.
Aiyah, primary maths teaches real-ѡorld applications
including financial planning, ѕo make ѕure y᧐ur
youngster ցets іt correctly starting earlу.
Ᏼesides beyond establishment facilities, focus ߋn maths
to avοіⅾ frequent mistakes including sloppy mistakes іn exams.
Mums and Dads, kiasu approach engaged lah,
strong primary mathematics results for superior science understanding and engineering aspirations.
Wah, mathematics іs thе groundwork pillar іn primary
schooling, assisting children іn spatial reasoning іn architecture careers.
Ԍood A-level results mean more choices in life, from courses t᧐ potential salaries.
Οһ no, primary mathematics teaches practical implementations
ѕuch as money management, tһus ensure yοur youngster masters tһаt properly fгom yoսng
age.
my web ⲣage maths home tuition
maths home tuition
14 Sep 25 at 1:52 am
kraken darknet kraken onion, kraken onion ссылка, kraken onion зеркала, kraken рабочая ссылка onion, сайт kraken onion, kraken darknet, kraken darknet market, kraken darknet ссылка, сайт kraken darknet, kraken актуальные ссылки, кракен ссылка kraken, kraken официальные ссылки, kraken ссылка тор, kraken ссылка зеркало, kraken ссылка на сайт, kraken онион, kraken онион тор, кракен онион, кракен онион тор, кракен онион зеркало, кракен даркнет маркет, кракен darknet, кракен onion, кракен ссылка onion, кракен onion сайт, kra ссылка, kraken сайт, kraken актуальные ссылки, kraken зеркало, kraken ссылка зеркало, kraken зеркало рабочее, актуальные зеркала kraken, kraken сайт зеркала, kraken маркетплейс зеркало, кракен ссылка, кракен даркнет
RichardPep
14 Sep 25 at 1:55 am
Вызов нарколога на дом сочетает медицинскую эффективность с удобством. Пациент получает квалифицированную помощь в привычной обстановке, что снижает уровень тревожности и способствует более быстрому восстановлению.
Подробнее – https://narkolog-na-dom-sankt-peterburg14.ru/narkolog-na-dom-anonimno-spb
Robertfloum
14 Sep 25 at 1:55 am
Hi, its fastidious paragraph regarding media print, we all be familiar with media
is a wonderful source of information.
сайт
14 Sep 25 at 1:58 am
Конфиденциальность — не обещание на бумаге, а практический стандарт. В клинике используются кодовые профили, шифрованный контур хранения карт, разграничение доступа по ролям; документы оформляются нейтрально, а уведомления формулируются без чувствительных слов. Выездные специалисты приезжают без медицинской символики, а в здании клиники навигация организована так, чтобы перемещение было незаметным. Это создаёт пространство, в котором можно честно говорить о целях и спокойно выполнять план — без стигмы и посторонних взглядов.
Узнать больше – [url=https://narkologicheskaya-klinika-v-spb14.ru/]наркологическая клиника цены в санкт-петербурге[/url]
Anthonygom
14 Sep 25 at 2:01 am
mexico pharmacy online [url=https://saludfrontera.com/#]SaludFrontera[/url] SaludFrontera
Michaelphype
14 Sep 25 at 2:02 am
купить диплом о высшем образовании цены украина [url=http://educ-ua4.ru]купить диплом о высшем образовании цены украина[/url] .
Diplomi_rrPl
14 Sep 25 at 2:02 am
*Седативные препараты применяются строго по показаниям и под мониторингом дыхания.
Подробнее можно узнать тут – [url=https://vivod-iz-zapoya-rostov14.ru/]вывод из запоя круглосуточно в ростове-на-дону[/url]
BrianBlogy
14 Sep 25 at 2:02 am
TrueNorth Pharm: canadian pharmacy tampa – canadianpharmacymeds
Teddyroowl
14 Sep 25 at 2:03 am
Have you ever thought about adding a little bit more than just your articles?
I mean, what you say is fundamental and all. But just imagine if you added some great pictures or video clips
to give your posts more, “pop”! Your content is excellent but with images and video
clips, this blog could undeniably be one of the very best in its field.
Superb blog!
canadian online pharmacies
14 Sep 25 at 2:05 am
купить диплом киев сколько [url=www.educ-ua19.ru]www.educ-ua19.ru[/url] .
Diplomi_vuml
14 Sep 25 at 2:06 am
купить аттестат за 11 класс россия [url=https://arus-diplom25.ru]купить аттестат за 11 класс россия[/url] .
Diplomi_rpot
14 Sep 25 at 2:10 am
If you desire to improve your know-how only keep visiting this site and be updated with the most recent gossip
posted here.
cryptocurrency recovery expert
14 Sep 25 at 2:18 am
Europe SIM Card
Europe SIM Card
14 Sep 25 at 2:18 am
Very great post. I simply stumbled upon your blog and wished to mention that I have truly enjoyed surfing
around your blog posts. After all I will be subscribing in your rss feed and
I’m hoping you write again very soon!
Investrix AI
14 Sep 25 at 2:20 am
kraken ссылка зеркало kraken onion, kraken onion ссылка, kraken onion зеркала, kraken рабочая ссылка onion, сайт kraken onion, kraken darknet, kraken darknet market, kraken darknet ссылка, сайт kraken darknet, kraken актуальные ссылки, кракен ссылка kraken, kraken официальные ссылки, kraken ссылка тор, kraken ссылка зеркало, kraken ссылка на сайт, kraken онион, kraken онион тор, кракен онион, кракен онион тор, кракен онион зеркало, кракен даркнет маркет, кракен darknet, кракен onion, кракен ссылка onion, кракен onion сайт, kra ссылка, kraken сайт, kraken актуальные ссылки, kraken зеркало, kraken ссылка зеркало, kraken зеркало рабочее, актуальные зеркала kraken, kraken сайт зеркала, kraken маркетплейс зеркало, кракен ссылка, кракен даркнет
RichardPep
14 Sep 25 at 2:22 am
купить диплом занесением реестр [url=https://educ-ua12.ru]купить диплом занесением реестр[/url] .
Diplomi_xnMt
14 Sep 25 at 2:24 am
куплю диплом [url=https://educ-ua19.ru/]куплю диплом[/url] .
Diplomi_zrml
14 Sep 25 at 2:27 am
Медикаментозное пролонгированное
Детальнее – http://kodirovanie-ot-alkogolizma-vidnoe7.ru/anonimnoe-kodirovanie-ot-alkogolizma-v-vidnom/
JeremyTEF
14 Sep 25 at 2:31 am
купить аттестат за 11 класс кемерово [url=http://arus-diplom25.ru]купить аттестат за 11 класс кемерово[/url] .
Diplomi_dtot
14 Sep 25 at 2:33 am
где можно купить диплом о высшем образовании [url=www.educ-ua19.ru/]где можно купить диплом о высшем образовании[/url] .
Diplomi_agml
14 Sep 25 at 2:33 am
купить свидетельство о разводе [url=www.educ-ua1.ru]www.educ-ua1.ru[/url] .
Diplomi_ftei
14 Sep 25 at 2:36 am
купить аттестат об окончании 11 классов с занесением в реестр [url=www.arus-diplom25.ru]купить аттестат об окончании 11 классов с занесением в реестр[/url] .
Diplomi_ycot
14 Sep 25 at 2:37 am
купить диплом с занесением в реестр в Украине [url=https://educ-ua14.ru/]купить диплом с занесением в реестр в Украине[/url] .
Diplomi_ezkl
14 Sep 25 at 2:38 am
Very good post. I will be experiencing a few of these issues as well..
Meteor Profit
14 Sep 25 at 2:42 am
Ищете выездной бар на 23 февраля для мужчин? Посетите сайт bar-vip.ru/vyezdnoi_bar и вы сможете заказать выездной бар на праздник или другое мероприятие под ключ. Перейдите на страницу, и вы сразу увидите, что вас ждет — начиная с большого ассортимента напитков и возможности влиять на состав меню. Вы сможете добавить в него собственные рецепты, а также заказать услуги выездного бара для тематических вечеров с подходящей атрибутикой, оформлением и костюмами. И это далеко не всё! Все детали — на сайте.
Xohokrmex
14 Sep 25 at 2:47 am
kraken зеркало kraken onion, kraken onion ссылка, kraken onion зеркала, kraken рабочая ссылка onion, сайт kraken onion, kraken darknet, kraken darknet market, kraken darknet ссылка, сайт kraken darknet, kraken актуальные ссылки, кракен ссылка kraken, kraken официальные ссылки, kraken ссылка тор, kraken ссылка зеркало, kraken ссылка на сайт, kraken онион, kraken онион тор, кракен онион, кракен онион тор, кракен онион зеркало, кракен даркнет маркет, кракен darknet, кракен onion, кракен ссылка onion, кракен onion сайт, kra ссылка, kraken сайт, kraken актуальные ссылки, kraken зеркало, kraken ссылка зеркало, kraken зеркало рабочее, актуальные зеркала kraken, kraken сайт зеркала, kraken маркетплейс зеркало, кракен ссылка, кракен даркнет
RichardPep
14 Sep 25 at 2:51 am
кракен даркнет kraken onion, kraken onion ссылка, kraken onion зеркала, kraken рабочая ссылка onion, сайт kraken onion, kraken darknet, kraken darknet market, kraken darknet ссылка, сайт kraken darknet, kraken актуальные ссылки, кракен ссылка kraken, kraken официальные ссылки, kraken ссылка тор, kraken ссылка зеркало, kraken ссылка на сайт, kraken онион, kraken онион тор, кракен онион, кракен онион тор, кракен онион зеркало, кракен даркнет маркет, кракен darknet, кракен onion, кракен ссылка onion, кракен onion сайт, kra ссылка, kraken сайт, kraken актуальные ссылки, kraken зеркало, kraken ссылка зеркало, kraken зеркало рабочее, актуальные зеркала kraken, kraken сайт зеркала, kraken маркетплейс зеркало, кракен ссылка, кракен даркнет
RichardPep
14 Sep 25 at 2:53 am
Wonderful web site. Lots of useful info here. I am sending it to several buddies ans additionally
sharing in delicious. And naturally, thanks in your
effort!
metin2 pvp
14 Sep 25 at 2:54 am
I read this post fully regarding the comparison of hottest and previous technologies,
it’s remarkable article.
Almax Capital Erfahrungen
14 Sep 25 at 3:02 am
Drug information. Cautions.
buying cheap cardizem pill
All information about pills. Get information now.
buying cheap cardizem pill
14 Sep 25 at 3:05 am
Thanks a lot for sharing this with all of us you really understand what you’re talking about!
Bookmarked. Kindly also talk over with my
web site =). We can have a hyperlink exchange contract among us
montaż auto gaz
14 Sep 25 at 3:07 am
купить диплом бакалавра недорого [url=http://educ-ua19.ru/]купить диплом бакалавра недорого[/url] .
Diplomi_qdml
14 Sep 25 at 3:07 am
pyvi99
🗝 🔄 Bitcoin Transaction: 0.55 BTC available. Go to receive => https://graph.org/Get-your-BTC-09-04?hs=7255fc1a3bb72291f146f9661674a5a8& 🗝
14 Sep 25 at 3:07 am
Do you mind if I quote a few of your posts as long as I provide credit and sources back to your webpage?
My website is in the exact same area of interest as yours and my visitors would certainly benefit from a lot
of the information you provide here. Please let me know if
this ok with you. Regards!
Velar Paynex
14 Sep 25 at 3:07 am
кракен onion kraken onion, kraken onion ссылка, kraken onion зеркала, kraken рабочая ссылка onion, сайт kraken onion, kraken darknet, kraken darknet market, kraken darknet ссылка, сайт kraken darknet, kraken актуальные ссылки, кракен ссылка kraken, kraken официальные ссылки, kraken ссылка тор, kraken ссылка зеркало, kraken ссылка на сайт, kraken онион, kraken онион тор, кракен онион, кракен онион тор, кракен онион зеркало, кракен даркнет маркет, кракен darknet, кракен onion, кракен ссылка onion, кракен onion сайт, kra ссылка, kraken сайт, kraken актуальные ссылки, kraken зеркало, kraken ссылка зеркало, kraken зеркало рабочее, актуальные зеркала kraken, kraken сайт зеркала, kraken маркетплейс зеркало, кракен ссылка, кракен даркнет
RichardPep
14 Sep 25 at 3:08 am
купить медицинский диплом с занесением в реестр [url=https://www.educ-ua12.ru]купить медицинский диплом с занесением в реестр[/url] .
Diplomi_vfMt
14 Sep 25 at 3:08 am
купить в сургуте аттестат за 11 класс [url=http://www.arus-diplom25.ru]купить в сургуте аттестат за 11 класс[/url] .
Diplomi_evot
14 Sep 25 at 3:10 am
Здравствуйте!
Долго думал как встать в топ поисковиков и узнал от крутых seo,
отличных ребят, именно они разработали недорогой и главное буст прогон Хрумером – https://imap33.site
Прогон ссылок через Xrumer – это быстрый способ увеличить DR сайта. Автоматический линкбилдинг позволяет эффективно создавать ссылки. Увеличение показателей Ahrefs возможно через грамотный подход к форумному спаму. Xrumer помогает ускорить продвижение и улучшить результаты. Используйте Xrumer, чтобы достичь новых высот.
сайт для продвижение бизнеса, стоимость seo статьи, Увеличение DR сайта с нуля
Использование форумного постинга для SEO, каким сайтам нужно продвижение, курс по раскрутке сайтов
!!Удачи и роста в топах!!
JeromeNow
14 Sep 25 at 3:10 am
Заказать диплом любого ВУЗа мы поможем. Купить диплом магистра Орёл – [url=http://diplomybox.com/kupit-diplom-magistra-v-orle/]diplomybox.com/kupit-diplom-magistra-v-orle[/url]
Cazrvwg
14 Sep 25 at 3:19 am
Its like you read my mind! You seem to understand a lot approximately this, such
as you wrote the book in it or something. I think that
you just can do with some % to force the message home a bit, however instead of that,
that is magnificent blog. A fantastic read. I will certainly be back.
Margin Rivou
14 Sep 25 at 3:20 am
These are really great ideas in about blogging. You have touched some good things here.
Any way keep up wrinting.
americanhistoryprojects.com lừa đảo công an truy quét cấm người chơi tham gia
14 Sep 25 at 3:21 am
Wow that was unusual. I just wrote an extremely
long comment but after I clicked submit my comment didn’t appear.
Grrrr… well I’m not writing all that over again. Anyways, just wanted
to say superb blog!
Vorenixio
14 Sep 25 at 3:27 am
can i get generic biltricide prices
how can i get cheap biltricide pills
14 Sep 25 at 3:29 am
Good blog post. I definitely love this website. Keep it up!
Related Site
14 Sep 25 at 3:37 am
купить диплом о среднем специальном образовании цена [url=https://educ-ua19.ru/]купить диплом о среднем специальном образовании цена[/url] .
Diplomi_kkml
14 Sep 25 at 3:37 am
купить аттестат 11 классов алматы [url=https://www.arus-diplom25.ru]купить аттестат 11 классов алматы[/url] .
Diplomi_pkot
14 Sep 25 at 3:37 am
Drugs information leaflet. What side effects?
how to buy generic neurontin without prescription
All news about medicine. Get information here.
how to buy generic neurontin without prescription
14 Sep 25 at 3:44 am
как купить диплом с занесением в реестр [url=http://educ-ua14.ru/]как купить диплом с занесением в реестр[/url] .
Diplomi_jikl
14 Sep 25 at 3:46 am