تخطَّ إلى المستندات
PHP

جهات الاتصال

`contacts->list` و`get` و`create` و`save` و`update` و`setAudiences` و`delete` و`deleteMany` و`listPeople` و`setPhoto` و`removePhoto` و`block` و`unblock` و`listThreads` و`activity`.

كل الدوالّ

usage.php
$page = $client->contacts->list(limit: 100);$contact = $client->contacts->get('[email protected]'); $saved = $client->contacts->create([    'email' => '[email protected]',    'name' => 'Grace Hopper',    'notes' => 'Met at the compiler workshop',]); $client->contacts->update('[email protected]', ['notes' => null]);$client->contacts->setAudiences('[email protected]', ['audienceIds' => ['aud_4c1b8e2a7d9f05c36b4e8a71']]);$client->contacts->delete('[email protected]'); echo count($page), ' ', $page->hasMore ? 'more to come' : 'that is all', PHP_EOL;echo $contact['source'], ' ', $contact['lastSeenAt'] ?? 'never mailed', ' ', $saved['source'], PHP_EOL;

يعيد list جهات الاتصال الأحدث ظهورًا أولًا، وجهات الاتصال التي لم تُراسَل قط في الآخر. وتكون قيمة source هي auto حين كُتب السجل لأن عضوًا أرسل إلى ذلك العنوان رسالة من محرّر الرسائل في التطبيق، وهو ادعاء مختلف جوهريًا عن أن شخصًا قد حفظه. ووصول بريد من عنوان لا يكتب شيئًا، وكذلك الإرسال عبر هذه الواجهة.

دفتر العناوين ملك لمساحة العمل لا لشخص واحد، فجهة الاتصال التي يحفظها أي عضو هي نفسها التي يراها كل عضو وكل مفتاح. ويكتب create قيمة source بالقيمة manual ويضع جهة الاتصال في الجمهور الافتراضي فور كتابتها. اذكر قوائمك الخاصة في audienceIds لضمّها في الاستدعاء نفسه، وهو ما يتطلب أيضًا audiences:write، أو أضف جهة الاتصال لاحقًا عبر audiences->addContact، الذي تشرحه صفحة الجماهير. ويحدّد setAudiences بالضبط القوائم التي تنتمي إليها جهة اتصال، باستدعاء واحد.

تُخزَّن العناوين بأحرف صغيرة ويرمّز العميل العنوان الذي تمرّره، فيصل [email protected] إلى الصف الصحيح. والعنوان الفارغ يرمي InvalidArgumentException قبل إرسال أي شيء. والعنوان هو الهوية، فلا يستطيع update تغييره: فنقل جهة اتصال هو delete ثم create.

المعاملات: contacts->list

limitint
كم جهة اتصال تُعاد في كل صفحة: عدد صحيح من 1 إلى 200، والافتراضي 50. والقيمة خارج المدى تعطي 422 بدل أن تُقصّ. والوسيط من النوع `int`، فحوّل القيمة المقروءة من سلسلة استعلام بـ `(int)` أولًا.
cursorstring
`nextCursor` من الصفحة السابقة. لا تبنِه بنفسك أبدًا: فالمؤشر الذي يسمّي جهة اتصال لم تعد موجودة يعطي 400 `invalid_cursor`، يُرمى في صورة `InvalidRequestException`، وهذا يعني أن حالة الترقيم لديك قديمة وأن المرور يجب أن يبدأ من جديد دون مؤشر.
sourcestring
`manual` لجهات الاتصال التي حفظها شخص عمدًا، و`auto` لتلك التي سجّلها محرّر الرسائل في التطبيق. اتركه للحصول على دفتر العناوين كاملًا.
qstring
يبحث في الاسم والعنوان، حتى 200 حرف. وإن لم يطابق شيء تمامًا في الصفحة الأولى، تُعاد تهجئات قريبة بدلًا من ذلك، وتواصل الصفحات التالية المطابقة بالطريقة نفسها.

الاستجابة: جهة اتصال

يعيد contacts->list صفحة OpenEmail\Result\Page، فتكون الصفوف في $page->items ويتبع المرور $page->nextCursor ما دامت قيمة $page->hasMore هي true. ويعيد listAll كل الصفوف في مصفوفة واحدة، ويعيد iterate كائن Generator يسلّمها واحدًا تلو الآخر. ويعيد كلٌّ من get وcreate وupdate وsave وsetAudiences جهة اتصال واحدة في صورة مصفوفة مفاتيحها بصيغة camelCase، أي الصف نفسه مع audiences. ودفتر العناوين غير محدود، ولهذا يرقّم هذا المسار الصفحات بدل أن يعيد مصفوفة تتوقف بصمت عند 200.

objectstring
دائمًا السلسلة `contact`، في سجلات القائمة كما في `get`.
emailstring
العنوان، ويُحوَّل إلى أحرف صغيرة عند الكتابة فيصبح `[email protected]` و`[email protected]` جهة اتصال واحدة، وهو المفتاح الذي تأخذه كل دوال contacts، إذ لا يُكشف أي معرّف لجهة الاتصال. والسجلات ملك لمساحة العمل لا للعضو أو المفتاح الذي كتبها، فكل عضو وكل مفتاح في مساحة العمل يقرأ ويكتب في دفتر عناوين واحد.
namestring or null
الاسم المعروض، أو null حين لم يُسجَّل أي اسم للعنوان قط. والكتابة التلقائية لا تحمل اسمًا إلا حين توفر الترويسة شيئًا غير العنوان نفسه، ولا يمكنها أبدًا الكتابة فوق اسم كتبه المستخدم.
sourcestring
تعني `auto` أن السجل كُتب لأن المستخدم أرسل بريدًا إلى ذلك العنوان. وتعني `manual` أن شخصًا أدخله بنفسه، وهو ادعاء مختلف جوهريًا، ولا تُنزل عملية الإدراج أو التحديث قيمة `manual` إلى `auto` أبدًا. ووصول بريد من عنوان لا يكتب أي سجل على الإطلاق، وهذا مقصود، فمن لم يفعل سوى مراسلتك ليس هنا. وعامل القيمة كسلسلة نصية مفتوحة، لأن العمود نص حر قيمته الافتراضية `manual`.
notesstring or null
نص حر كتبه شخص عن هذا الشخص، في التطبيق أو عبر `update`، ولا يُولَّد آليًا أبدًا. ويكون null حين لم يكتب أحد شيئًا، و`'notes' => null` في `update` يمسحه.
lastSeenAtstring or null
سلسلة ISO 8601 بتوقيت UTC، تُحدَّث في كل مرة يرسل فيها عضو إلى ذلك العنوان من محرّر الرسائل في التطبيق، لا عند وصول بريد منه، فذلك لا يكتب شيئًا. وتكون null لجهة اتصال حُفظت عبر `create` ولم تُراسَل قط، وتأتي هذه في الآخر في الترتيب التنازلي حسب `lastSeenAt` الذي يعيده هذا المسار.
audiencesarray
فقط في `get` و`create` و`update` و`save` و`setAudiences`، ولا يظهر أبدًا في صفوف القوائم. كل جمهور تنتمي إليه جهة الاتصال، بما فيه الجمهور الافتراضي، في صورة مصفوفة فيها `id` و`name` و`builtin`. وتكون قيمة `builtin` هي `default` في الجمهور الذي تنتمي إليه كل جهات الاتصال، وnull في جمهور أنشأه شخص، فتفرّع عليها لا على الاسم الذي يستطيع أي شخص تغييره.
photoUrlstring or null
مكان تقديم صورة جهة الاتصال، أو null حين لا تكون لها صورة. يعيّنها `setPhoto`، وكل رفع يحصل على URL جديد.

ضبط جماهير جهة اتصال

يحدّد setAudiences($email, ['audienceIds' => [...]]) بالضبط الجماهير التي تنتمي إليها جهة اتصال واحدة، بطلب واحد. تنضم جهة الاتصال إلى كل جمهور مذكور لم تكن فيه بعد، وتغادر كل جمهور آخر، ويعيد الاستدعاء جهة الاتصال بعد التغيير، مع audiences الخاصة بها. ويتطلب audiences:write، لأنه يكتب العضويات لا جهة الاتصال، وتكراره لا يغيّر شيئًا، فيعيد العميل محاولته بعد فشل في الشبكة.

يُحتفظ بالجمهور الافتراضي دائمًا، لذا فإن 'audienceIds' => [] يُبقي جهة الاتصال في الجمهور الافتراضي وحده. ويقبل حتى 100 معرّف. والمعرّف الذي لا يشير إلى أي جمهور في مساحة العمل هذه يعطي 404 audience_not_found ولا يتغير شيء، والعنوان الذي ليس جهة اتصال يعطي 404 contact_not_found. وكلاهما يرمي NotFoundException.

كل من في صفحة جهات الاتصال

يسرد listPeople الأشخاص الذين تعرضهم صفحة جهات الاتصال في التطبيق: جهات الاتصال المحفوظة وكل عنوان ظهر في البريد، ولكلٍّ منها saved وthreads وlastAt. أما list فجهات الاتصال المحفوظة وحدها. ويعيد OpenEmail\Result\PeoplePage، الذي يضيف seen إلى items وhasMore وnextCursor. ولا تأتي العناوين التي ظهرت في البريد إلا إذا كان المفتاح يحمل threads:read أيضًا، ويقول $page->seen هل أتت. وقيمة sort: هي recent أو name أو threads، ويسمّيها OpenEmail\Constants\PeopleSorts. ويبحث q: في الأسماء والعناوين والملاحظات، ويُبقي blocked: true الأشخاص الذين تحظرهم قائمة حظر مساحة العمل، بما في ذلك قواعد النطاق الكامل. ويسمّي blockedBy القاعدة في كل صف.

people.php
use OpenEmail\Constants\PeopleSorts; $page = $client->contacts->listPeople(sort: PeopleSorts::THREADS, limit: 50); foreach ($page as $person) {    if (!$person['saved'] && $person['threads'] > 5) {        $client->contacts->save($person['email']);    }} $blocked = $client->contacts->listAllPeople(blocked: true);echo $page->seen ? 'saved and seen' : 'saved only', ', ', count($blocked), ' blocked', PHP_EOL;

يعيد listAllPeople كل الصفحات في مصفوفة واحدة، ويعيد iteratePeople كائن Generator يسلّم كل شخص. ولا يبلّغ أيٌّ منهما عن seen، فاقرأ صفحة واحدة عبر listPeople لتعرفه. والمؤشر معتم، فمرّر nextCursor مرة أخرى بوصفه cursor: كما جاء تمامًا، مع sort: وq: وblocked: نفسها.

الحفظ والحذف والصور

save($email)، مع مصفوفة اختيارية فيها name وnotes، هو إضافة إلى جهات الاتصال والإبقاء في جهات الاتصال: يحفظ عنوانًا ليس جهة اتصال بعد، ويُبقي عنوانًا سُجّل من إرسال محفوظًا يدويًا، ويعيد عنوانًا محذوفًا. وdelete هو حذف: يزيل جهة الاتصال المحفوظة ويُخفي العنوان، كي لا يسجّله محرّر الرسائل مجددًا، ويقبل كذلك عنوانًا لم يظهر إلا في البريد. ويقول wasSaved في المصفوفة التي يعيدها أيّهما كان. ويحذف deleteMany ما يصل إلى 200 في استدعاء واحد.

photo.php
$client->contacts->save('[email protected]', ['name' => 'Grace Hopper']); $contact = $client->contacts->setPhoto('[email protected]', file_get_contents('photo.jpg'), contentType: 'image/jpeg');echo $contact['photoUrl'], PHP_EOL; $client->contacts->setPhoto('[email protected]', new \SplFileInfo('avatar.png')); $client->contacts->removePhoto('[email protected]');$client->contacts->deleteMany(['[email protected]', '[email protected]']);

يرسل setPhoto بايتات الصورة كما هي: PNG أو JPEG أو WebP أو GIF حتى 5 ميغابايت، ملاءَمة داخل مربع 512 بكسل. والبايتات سلسلة نصية، أو مورد تدفق من fopen، أو SplFileInfo، أو تدفق PSR-7 أو ملف مرفوع. مرّر contentType:، أو بايتات تحمل نوعها بنفسها: ملف مرفوع بصيغة PSR-7، أو ملف مرفوع في Symfony أو Laravel، مع نوع وسائطه، أو ملف أو تدفق ينتهي اسمه بـ .png أو .jpg أو .jpeg أو .webp أو .gif. ودون نوع تُرسَل البايتات بوصفها application/octet-stream، ويرفضها الخادم بالخطأ 422 invalid_image. ويسمّي OpenEmail\Constants\ContactPhotoTypes الأنواع الأربعة. ويجب أن يكون العنوان جهة اتصال محفوظة أولًا.

الحظر

يضع block($email) العنوان في قائمة حظر مساحة العمل كي يُرفض بريده، مُسقطًا أي وسم زائد، ويزيل unblock($email) كل قاعدة تحظره. وكلاهما يحتاج settings:write، لأنهما يغيّران قائمة الحظر لا جهة الاتصال، ولا يحتاج أيٌّ منهما أن يكون العنوان جهة اتصال.

حين يرفع unblock قاعدة نطاق كامل، يسردها removed مع list مضبوطًا على blockedDomains، ويُلغى معها حظر كل من في ذلك النطاق. ويسمّي OpenEmail\Constants\ContactBlockLists القائمتين كلتيهما.

المحادثات والنشاط

يتصفح listThreads($email) صفحةً تلو صفحة المحادثاتِ التي كتبها العنوان أو كُتبت إليه، في كل المجلدات، ويمر listAllThreads وiterateThreads عليها كلها. ويعيد activity($email) الأرقام التي خلف تبويب النشاط لجهة اتصال: الوارد والصادر لكل فاصل زمني، والمحادثات التي تنتظر ردك، والزمن الوسيط للرد في كل اتجاه. وكلاهما يحتاج إلى threads:read.

activity.php
$threads = $client->contacts->listThreads('[email protected]', q: 'invoice'); $activity = $client->contacts->activity(    '[email protected]',    minutes: 30 * 24 * 60,    grain: 'day',    offsetMinutes: intdiv((int) date('Z'), 60),); echo count($threads), ' threads, ', $activity['totals']['waiting'], ' waiting on you', PHP_EOL;

يأخذ activity وسائط مسمّاة. ويضبط minutes: النافذة، وهي 90 يومًا إذا أُغفل. ويضبط grain: عرض الفاصل الزمني: minute أو hour أو day. ويضبط offsetMinutes: عدد الدقائق شرق UTC حيث تنقسم الأيام، وintdiv((int) date('Z'), 60) هو إزاحة المنطقة الزمنية المضبوطة في PHP.