host = rtrim($host, '/'); if ($key !== false && $key !== '') { $this->key = (string)$key; } } /** * Ellenőrzi, hogy az API gazdagép és kulcs be van-e állítva. */ public function check(): bool { return !empty($this->host) && !empty($this->key); } /** * POST kérést küld az API adott végpontjára. * * @param string $f A gyár/végpont neve (pl. 'subscribe') * @param array $data POST mezők tömbje * @return object A dekódolt JSON válasz objektumként * @throws RuntimeException Ha hiányoznak a hitelesítési adatok, cURL hiba * esetén, vagy ha a válasz nem érvényes JSON */ public function process(string $f, array $data): object { if (!$this->check()) { throw new RuntimeException('ninjaMail: hiányzó gazdagép vagy API kulcs.'); } $url = $this->host . '/a/' . rawurlencode($f) . '/?key=' . urlencode($this->key); $ch = curl_init($url); if ($ch === false) { throw new RuntimeException('ninjaMail: nem sikerült inicializálni a cURL munkamenetet.'); } curl_setopt_array($ch, [ CURLOPT_ENCODING => 'UTF-8', CURLOPT_RETURNTRANSFER => true, CURLOPT_POST => true, CURLOPT_POSTFIELDS => $data, CURLOPT_TIMEOUT => $this->timeout, CURLOPT_CONNECTTIMEOUT => 10, CURLOPT_SSL_VERIFYPEER => true, CURLOPT_SSL_VERIFYHOST => 2, CURLOPT_FOLLOWLOCATION => false, CURLOPT_MAXREDIRS => 0, CURLOPT_HTTPHEADER => ['Accept: application/json'], ]); $response = curl_exec($ch); $errno = curl_errno($ch); $error = curl_error($ch); curl_close($ch); if ($response === false) { throw new RuntimeException( sprintf('ninjaMail: cURL hiba (%d): %s', $errno, $error) ); } $decoded = json_decode((string)$response); if (json_last_error() !== JSON_ERROR_NONE) { throw new RuntimeException( 'ninjaMail: érvénytelen JSON válasz: ' . json_last_error_msg() ); } $result = (object)$decoded; $this->data = $result; return $result; } /** * Véletlenszerű kulccsal indít távoli belépési munkamenetet. * * @return object API válasz (tartalmaz 'token' mezőt siker esetén) * @throws RuntimeException Lásd: process() */ public function login(): object { return $this->process('login', [ 'rkey' => bin2hex(random_bytes(16)), ]); } } // --------------------------------------------------------------------------- // Levélküldés // --------------------------------------------------------------------------- /** * Egyszeri e-mail küldése megadott címzettnek. */ class ninjaMailSend extends ninjaMail { private string $to = ''; private string $subject = ''; private string $message = ''; private string $message_text = ''; /** * @param string $to Feliratkozó azonosítója vagy e-mail cím */ public function to(string $to): true { $this->to = trim($to); return true; } /** * @param string $s Az e-mail tárgya */ public function subject(string $s): true { $this->subject = $s; return true; } /** * @param string $m HTML tartalom * @param string|bool $t Opcionális egyszerű szöveges változat; * ha nincs megadva, a HTML-ből kerül levezetésre */ public function message(string $m, string|bool $t = false): true { $this->message = $m; $this->message_text = ($t !== false && $t !== '') ? (string)$t : trim(strip_tags($m)); return true; } /** * Elküldi az e-mailt. * * @return bool true ha a levél sikeresen sorba állt * @throws InvalidArgumentException Ha kötelező mező hiányzik * @throws RuntimeException Lásd: process() */ public function send(): bool { if (empty($this->to) || empty($this->subject) || empty($this->message)) { throw new InvalidArgumentException( 'ninjaMailSend: a to, subject és message mezők kötelezők.' ); } $post = [ 'to' => $this->to, 'subject' => $this->subject, 'message' => $this->message, 'message_text' => $this->message_text, ]; return $this->process('send', $post)->status === 'message_queued'; } } // --------------------------------------------------------------------------- // Feliratkozások // --------------------------------------------------------------------------- /** * Feliratkozók hozzáadása és eltávolítása levelezőlistákból. */ class ninjaMailSubscription extends ninjaMail { private int $list = 0; private int $activated = 0; private int $forcenamechange = 0; /** * @param int $id Lista azonosítója * @return bool false ha az azonosító nem pozitív egész szám */ public function list(int $id): bool { if ($id <= 0) { return false; } $this->list = $id; return true; } /** * @param bool $s true = azonnal megerősített; false = megerősítő e-mail küldése */ public function activated(bool $s): true { $this->activated = $s ? 1 : 0; return true; } /** * @param bool $s true = névfrissítés engedélyezése meglévő feliratkozóknál */ public function namechange(bool $s): true { $this->forcenamechange = $s ? 1 : 0; return true; } /** * Feliratkozó hozzáadása a listához. * * @param string $email A feliratkozó e-mail címe * @param string $name A feliratkozó neve (opcionális) * @return bool true sikeres feliratkozás esetén * @throws InvalidArgumentException Ha a lista nincs beállítva * @throws RuntimeException Lásd: process() */ public function subscribe(string $email, string $name = ''): bool { if ($this->list <= 0) { throw new InvalidArgumentException( 'ninjaMailSubscription: lista azonosítója nincs beállítva.' ); } $post = [ 'list' => $this->list, 'name' => $name, 'email' => $email, 'activated' => $this->activated, 'forcenamechange' => $this->forcenamechange, ]; return $this->process('subscribe', $post)->status === 'success'; } /** * Feliratkozó eltávolítása a listából. * * @param string $email A leiratkozó e-mail címe * @return bool true sikeres leiratkozás esetén * @throws InvalidArgumentException Ha a lista nincs beállítva * @throws RuntimeException Lásd: process() */ public function unsubscribe(string $email): bool { if ($this->list <= 0) { throw new InvalidArgumentException( 'ninjaMailSubscription: lista azonosítója nincs beállítva.' ); } $post = [ 'list' => $this->list, 'email' => $email, ]; return $this->process('unsubscribe', $post)->status === 'success'; } } // --------------------------------------------------------------------------- // Hírlevél // --------------------------------------------------------------------------- /** * Hírlevelek létrehozása, frissítése és küldése. */ class ninjaMailNewsletter extends ninjaMail { private int $newsletter = 0; private string $subject = ''; private string $message = ''; private string $message_text = ''; /** * Lekérdezi vagy beállítja az aktuális hírlevél azonosítóját. * * @param int|false $id Hírlevél azonosítója a beállításhoz; false = lekérdezés * @return int|bool Lekérdezési módban az aktuális azonosítót adja vissza; * beállítási módban true/false */ public function newsletter(int|false $id = false): int|bool { if ($id !== false) { if ($id > 0) { $this->newsletter = $id; return true; } return false; } return $this->newsletter; } /** * @param string $s A hírlevél tárgya */ public function subject(string $s): true { $this->subject = $s; return true; } /** * @param string $m HTML tartalom * @param string|bool $t Opcionális egyszerű szöveges változat */ public function message(string $m, string|bool $t = false): true { $this->message = $m; $this->message_text = ($t !== false && $t !== '') ? (string)$t : trim(strip_tags($m)); return true; } /** * @param bool $update true = meglévő frissítése; false = új létrehozása * @return int|false Az új/frissített hírlevél azonosítója, vagy false hiba esetén * @throws InvalidArgumentException Ha nincs üzenet beállítva * @throws RuntimeException Lásd: process() */ private function query(bool $update = false): int|false { if (empty($this->message)) { throw new InvalidArgumentException( 'ninjaMailNewsletter: az üzenet tartalma kötelező.' ); } $post = [ 'new' => true, 'id' => $update ? $this->newsletter : false, 'subject' => $this->subject, 'message' => $this->message, 'message_text' => $this->message_text, ]; $data = $this->process('newsletter', $post); if ($data->status === 'success' && isset($data->id) && is_numeric($data->id)) { $this->newsletter = (int)$data->id; return $this->newsletter; } return false; } /** * Új hírlevelet hoz létre. * * @return int|false Az új hírlevél azonosítója, vagy false hiba esetén */ public function create(): int|false { return $this->query(false); } /** * Meglévő hírlevelet frissít. * * @return int|false A hírlevél azonosítója, vagy false hiba esetén * @throws InvalidArgumentException Ha nincs hírlevél kiválasztva */ public function update(): int|false { if ($this->newsletter <= 0) { throw new InvalidArgumentException( 'ninjaMailNewsletter: hírlevél azonosítója nincs beállítva a frissítéshez.' ); } return $this->query(true); } /** * Hírlevelet küld azonnali vagy ütemezett időpontban. * * @param int|false $time Unix időbélyeg a küldés időpontjához; false vagy 0 = azonnali * @return bool true sikeres sorbaállítás esetén * @throws InvalidArgumentException Ha nincs hírlevél kiválasztva * @throws RuntimeException Lásd: process() */ public function send(int|false $time = false): bool { if ($this->newsletter <= 0) { throw new InvalidArgumentException( 'ninjaMailNewsletter: hírlevél azonosítója nincs beállítva a küldéshez.' ); } $post = [ 'send' => true, 'id' => $this->newsletter, 'start' => ($time && $time > 0) ? $time : 0, ]; $data = $this->process('newsletter', $post); return in_array($data->status ?? '', ['success', 'already_queued'], true); } /** * Listázza az elérhető híreveleket. * * @return object API válasz tömbbel * @throws RuntimeException Lásd: process() */ public function get(): object { return $this->process('newsletter', ['get' => true]); } } // --------------------------------------------------------------------------- // Kampány // --------------------------------------------------------------------------- /** * Kampányok létrehozása, törlése és konfigurálása. */ class ninjaMailCampaign extends ninjaMail { private int $campaign = 0; /** * Lekérdezi vagy beállítja az aktuális kampány azonosítóját. * * @param int|false $id Kampány azonosítója beállításhoz; false = lekérdezés * @return int|bool Lekérdezési módban az aktuális azonosítót adja vissza; * beállítási módban true/false */ public function campaign(int|false $id = false): int|bool { if ($id === false) { return $this->campaign; } if ($id > 0) { $this->campaign = $id; return true; } return false; } /** * Új kampányt hoz létre. * * @param string $name A kampány neve * @return int|false Az új kampány azonosítója, vagy false hiba esetén * @throws InvalidArgumentException Ha a név üres * @throws RuntimeException Lásd: process() */ public function create(string $name): int|false { if (trim($name) === '') { throw new InvalidArgumentException( 'ninjaMailCampaign: a kampány neve nem lehet üres.' ); } $post = [ 'new' => true, 'name' => $name, ]; $data = $this->process('campaign', $post); if ($data->status === 'success' && isset($data->id) && is_numeric($data->id)) { $this->campaign = (int)$data->id; return $this->campaign; } return false; } /** * Törli az aktuális kampányt. * * @return bool true sikeres törlés esetén * @throws InvalidArgumentException Ha nincs kampány kiválasztva * @throws RuntimeException Lásd: process() */ public function remove(): bool { if ($this->campaign <= 0) { throw new InvalidArgumentException( 'ninjaMailCampaign: kampány azonosítója nincs beállítva a törléshez.' ); } $post = [ 'remove' => true, 'id' => $this->campaign, ]; return $this->process('campaign', $post)->status === 'success'; } /** * Listákat rendel a kampányhoz. * * @param int[] $lists Lista azonosítók tömbje * @return bool true sikeres frissítés esetén * @throws InvalidArgumentException Ha a $lists üres vagy nincs kampány beállítva * @throws RuntimeException Lásd: process() */ public function update(array $lists): bool { if (empty($lists)) { throw new InvalidArgumentException( 'ninjaMailCampaign: legalább egy lista azonosítója szükséges.' ); } if ($this->campaign <= 0) { throw new InvalidArgumentException( 'ninjaMailCampaign: kampány azonosítója nincs beállítva a frissítéshez.' ); } $post = [ 'update' => true, 'id' => $this->campaign, 'lists' => $lists, ]; return $this->process('campaign', $post)->status === 'success'; } /** * Hírlevelet csatol a kampányhoz. * * @param int $newsletter A csatolni kívánt hírlevél azonosítója * @return bool true sikeres csatolás esetén * @throws InvalidArgumentException Ha az azonosító érvénytelen vagy nincs kampány beállítva * @throws RuntimeException Lásd: process() */ public function attach(int $newsletter): bool { if ($newsletter <= 0) { throw new InvalidArgumentException( 'ninjaMailCampaign: érvénytelen hírlevél azonosító.' ); } if ($this->campaign <= 0) { throw new InvalidArgumentException( 'ninjaMailCampaign: kampány azonosítója nincs beállítva a csatoláshoz.' ); } $post = [ 'relations' => true, 'id' => $this->campaign, 'newsletter' => $newsletter, ]; return $this->process('campaign', $post)->status === 'success'; } } // --------------------------------------------------------------------------- // Statisztika // --------------------------------------------------------------------------- /** * Hírlevél-statisztikák lekérdezése. */ class ninjaMailStatistics extends ninjaMail { /** * Statisztikát kér le egy adott hírlevélről. * * @param int $id A hírlevél azonosítója * @return object Az API statisztikai válasza * @throws InvalidArgumentException Ha az azonosító érvénytelen * @throws RuntimeException Lásd: process() */ public function get(int $id): object { if ($id <= 0) { throw new InvalidArgumentException( 'ninjaMailStatistics: érvénytelen hírlevél azonosító.' ); } $post = [ 'newsletter' => $id, 'type' => 1, ]; return $this->process('statistics', $post); } }