PluginProbe
Fluent Booking – The Ultimate Appointments Scheduling, Events Booking, Events Calendar Solution / 2.5.0
Fluent Booking – The Ultimate Appointments Scheduling, Events Booking, Events Calendar Solution v2.5.0
2.5.0 2.4.0 2.3.0 2.2.5 2.2.0 2.1.2 2.1.1 trunk 1.10.0 1.10.01 1.10.02 1.5.0 1.5.01 1.5.02 1.5.1 1.5.10 1.5.20 1.5.21 1.5.22 1.5.23 1.5.24 1.5.25 1.6.0 1.7.0 1.7.1 All 34 releases
← All changes | app/Services/Integrations/FluentCRM/CrmContactService.php +110 -0 2.2.0 → 2.5.0 View file →
@@ -190,8 +190,118 @@
190 190 'list_ids' => self::taxonomyIds($contact, 'lists'),
191 191 ];
192 192 }
193 193
194 + /**
195 + * Create (or reuse) a tag/list definition in FluentCRM. Idempotent on
196 + * slug, so typing an existing name returns that existing tag/list.
197 + *
198 + * @param string $type 'tags' | 'lists'
199 + * @return array|null {id, title} or null when inactive / empty title.
200 + */
201 + public static function createTaxonomy($type, $title)
202 + {
203 + if (!self::isActive()) {
204 + return null;
205 + }
206 +
207 + $title = trim((string) $title);
208 + if ($title === '') {
209 + return null;
210 + }
211 +
212 + $model = self::taxonomyModel($type);
213 + $slug = sanitize_title($title);
214 +
215 + if ($slug === '') {
216 + return null;
217 + }
218 +
219 + $item = $model::firstOrCreate(['slug' => $slug], ['title' => $title]);
220 +
221 + if ($item->wasRecentlyCreated) {
222 + // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.DynamicHooknameFound -- FluentCRM's own hook names, fired so CRM listeners see parity with native tag/list creation
223 + do_action($type === 'tags' ? 'fluent_crm/tag_created' : 'fluent_crm/list_created', $item);
224 + }
225 +
226 + return [
227 + 'id' => (int) $item->id,
228 + 'title' => $item->title,
229 + ];
230 + }
231 +
232 + /**
233 + * The contact a note can be copied to, or null when FluentCRM is inactive,
234 + * the email has no contact, or the current user cannot manage contacts.
235 + *
236 + * @param string $email
237 + * @return array|null {contact_id, name, profile_url}
238 + */
239 + public static function getNoteTarget($email)
240 + {
241 + if (!self::canWriteNotes()) {
242 + return null;
243 + }
244 +
245 + $contact = self::getContact($email);
246 +
247 + if (!$contact) {
248 + return null;
249 + }
250 +
251 + return [
252 + 'contact_id' => (int) $contact->id,
253 + 'name' => trim((string) $contact->full_name) ?: (string) $contact->email,
254 + 'profile_url' => fluentcrm_menu_url_base() . 'subscribers/' . $contact->id,
255 + ];
256 + }
257 +
258 + /**
259 + * Add a note to the contact's FluentCRM profile, as FluentCRM's own
260 + * "Add note" does: same permission, same sanitizer, same hook.
261 + *
262 + * @param string $email
263 + * @param string $title Plain text.
264 + * @param string $description HTML. Passed through wp_kses_post.
265 + * @param string $type A FluentCRM activity type (fluentcrm_activity_types()).
266 + * @return int|\WP_Error The new note id.
267 + */
268 + public static function addContactNote($email, $title, $description, $type = 'note')
269 + {
270 + if (!self::canWriteNotes()) {
271 + return new \WP_Error('crm_permission', __('You do not have permission to add notes to CRM contacts.', 'fluent-booking'));
272 + }
273 +
274 + $contact = self::getContact($email);
275 +
276 + if (!$contact) {
277 + return new \WP_Error('crm_contact_not_found', __('No CRM contact found for this booking.', 'fluent-booking'));
278 + }
279 +
280 + $data = \FluentCrm\App\Services\Sanitize::contactNote([
281 + 'subscriber_id' => (int) $contact->id,
282 + 'title' => (string) $title,
283 + 'description' => (string) $description,
284 + 'type' => $type,
285 + 'created_at' => current_time('mysql'),
286 + ]);
287 +
288 + $data['created_by'] = get_current_user_id();
289 +
290 + $note = \FluentCrm\App\Models\SubscriberNote::create($data);
291 +
292 + // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound -- FluentCRM's own hook, fired so CRM automations see a note added from here like one added in the CRM
293 + do_action('fluent_crm/note_added', $note, $contact, $data);
294 +
295 + return (int) $note->id;
296 + }
297 +
298 + private static function canWriteNotes()
299 + {
300 + return self::isActive()
301 + && \FluentCrm\App\Services\PermissionManager::currentUserCan('fcrm_manage_contacts');
302 + }
303 +
194 304 private static function getContact($email)
195 305 {
196 306 if (!self::isActive() || !$email) {
197 307 return null;