3 +--------------------------------------------------------------------+
4 | Copyright CiviCRM LLC. All rights reserved. |
6 | This work is published under the GNU AGPLv3 license with some |
7 | permitted exceptions and without any warranty. For full license |
8 | and copyright information, see https://civicrm.org/licensing |
9 +--------------------------------------------------------------------+
15 * @copyright CiviCRM LLC https://civicrm.org/licensing
19 * BAO object for crm_note table.
21 class CRM_Core_BAO_Note
extends CRM_Core_DAO_Note
{
22 use CRM_Core_DynamicFKAccessTrait
;
25 * Const the max number of notes we display at any given time.
31 * Given a note id, retrieve the note text.
34 * Id of the note to retrieve.
37 * the note text or NULL if note not found
39 * @throws \CRM_Core_Exception
43 public static function getNoteText($id) {
44 CRM_Core_Error
::deprecatedFunctionWarning('unused function');
45 return CRM_Core_DAO
::getFieldValue('CRM_Core_DAO_Note', $id, 'note');
49 * Given a note id, retrieve the note subject
52 * Id of the note to retrieve.
55 * the note subject or NULL if note not found
57 * @throws \CRM_Core_Exception
59 public static function getNoteSubject($id) {
60 return CRM_Core_DAO
::getFieldValue('CRM_Core_DAO_Note', $id, 'subject');
64 * Given a note id, decide if the note should be displayed based on privacy setting
67 * Either the id of the note to retrieve, or the CRM_Core_DAO_Note object itself.
70 * TRUE if the note should be displayed, otherwise FALSE
73 public static function getNotePrivacyHidden($note) {
74 if (CRM_Core_Permission
::check('view all notes')) {
79 if (is_object($note) && get_class($note) === 'CRM_Core_DAO_Note') {
80 CRM_Core_DAO
::storeValues($note, $noteValues);
83 $noteDAO = new CRM_Core_DAO_Note();
86 if ($noteDAO->fetch()) {
87 CRM_Core_DAO
::storeValues($noteDAO, $noteValues);
91 CRM_Utils_Hook
::notePrivacy($noteValues);
93 if (empty($noteValues['privacy'])) {
96 elseif (isset($noteValues['notePrivacy_hidden'])) {
97 // If the hook has set visibility, use that setting.
98 return $noteValues['notePrivacy_hidden'];
101 // Default behavior (if hook has not set visibility)
102 // is to hide privacy notes unless the note creator is the current user.
104 if ($noteValues['privacy']) {
105 $session = CRM_Core_Session
::singleton();
106 $userID = $session->get('userID');
107 return ($noteValues['contact_id'] != $userID);
116 * Takes an associative array and creates a note object.
118 * the function extract all the params it needs to initialize the create a
119 * note object. the params array could contain additional unused name/value
122 * @param array $params
123 * (reference) an assoc array of name/value pairs.
125 * (deprecated) associated array with note id - preferably set $params['id'].
126 * @return null|object
127 * $note CRM_Core_BAO_Note object
128 * @throws \CRM_Core_Exception
130 public static function add(&$params, $ids = []) {
131 $dataExists = self
::dataExists($params);
136 if (!empty($params['entity_table']) && $params['entity_table'] == 'civicrm_contact' && !empty($params['check_permissions'])) {
137 if (!CRM_Contact_BAO_Contact_Permission
::allow($params['entity_id'], CRM_Core_Permission
::EDIT
)) {
138 throw new CRM_Core_Exception('Permission denied to modify contact record');
142 $note = new CRM_Core_BAO_Note();
144 if (!isset($params['privacy'])) {
145 $params['privacy'] = 0;
148 $note->copyValues($params);
149 if (empty($params['contact_id'])) {
150 if (CRM_Utils_Array
::value('entity_table', $params) == 'civicrm_contact') {
151 $note->contact_id
= $params['entity_id'];
154 $id = $params['id'] ??
$ids['id'] ??
NULL;
161 // check and attach and files as needed
162 CRM_Core_BAO_File
::processAttachment($params, 'civicrm_note', $note->id
);
164 if ($note->entity_table
== 'civicrm_contact') {
165 CRM_Core_BAO_Log
::register($note->entity_id
,
169 $displayName = CRM_Contact_BAO_Contact
::displayName($note->entity_id
);
171 $noteActions = FALSE;
173 $loggedInContactID = CRM_Core_Session
::getLoggedInContactID();
174 if ($loggedInContactID) {
175 if ($loggedInContactID == $note->entity_id
) {
178 elseif (CRM_Contact_BAO_Contact_Permission
::allow($note->entity_id
, CRM_Core_Permission
::EDIT
)) {
185 $recentOther = array(
186 'editUrl' => CRM_Utils_System
::url('civicrm/contact/view/note',
187 "reset=1&action=update&cid={$note->entity_id}&id={$note->id}&context=home"
189 'deleteUrl' => CRM_Utils_System
::url('civicrm/contact/view/note',
190 "reset=1&action=delete&cid={$note->entity_id}&id={$note->id}&context=home"
195 // add the recently created Note
196 CRM_Utils_Recent
::add($displayName . ' - ' . $note->subject
,
197 CRM_Utils_System
::url('civicrm/contact/view/note',
198 "reset=1&action=view&cid={$note->entity_id}&id={$note->id}&context=home"
212 * Check if there is data to create the object.
214 * @param array $params
215 * (reference ) an assoc array of name/value pairs.
219 public static function dataExists(&$params) {
220 // return if no data present
221 if (empty($params['id']) && !strlen($params['note'])) {
228 * Given the list of params in the params array, fetch the object
229 * and store the values in the values array
231 * @param array $params
232 * Input parameters to find object.
233 * @param array $values
234 * Output values of the object.
235 * @param int $numNotes
236 * The maximum number of notes to return (0 if all).
240 public static function &getValues(&$params, &$values, $numNotes = self
::MAX_NOTES
) {
241 if (empty($params)) {
244 $note = new CRM_Core_BAO_Note();
245 $note->entity_id
= $params['contact_id'];
246 $note->entity_table
= 'civicrm_contact';
248 // get the total count of notes
249 $values['noteTotalCount'] = $note->count();
251 // get only 3 recent notes
252 $note->orderBy('modified_date desc');
253 $note->limit($numNotes);
258 while ($note->fetch()) {
259 $values['note'][$note->id
] = [];
260 CRM_Core_DAO
::storeValues($note, $values['note'][$note->id
]);
264 // if we have collected the number of notes, exit loop
265 if ($numNotes > 0 && $count >= $numNotes) {
278 * @param bool $showStatus
279 * Do we need to set status or not.
282 * no of deleted notes on success, null otherwise
284 public static function del($id, $showStatus = TRUE) {
286 $recent = array($id);
287 $note = new CRM_Core_DAO_Note();
291 if ($note->entity_table
== 'civicrm_note') {
292 $status = ts('Selected Comment has been deleted successfully.');
295 $status = ts('Selected Note has been deleted successfully.');
298 // Delete all descendents of this Note
299 foreach (self
::getDescendentIds($id) as $childId) {
300 $childNote = new CRM_Core_DAO_Note();
301 $childNote->id
= $childId;
302 $childNote->delete();
303 $recent[] = $childId;
306 $return = $note->delete();
308 CRM_Core_Session
::setStatus($status, ts('Deleted'), 'success');
311 // delete the recently created Note
312 foreach ($recent as $recentId) {
317 CRM_Utils_Recent
::del($noteRecent);
323 * Delete all records for this contact id.
326 * ID of the contact for which note needs to be deleted.
328 public static function deleteContact($id) {
329 // need to delete for both entity_id
330 $dao = new CRM_Core_DAO_Note();
331 $dao->entity_table
= 'civicrm_contact';
332 $dao->entity_id
= $id;
335 // and the creator contact id
336 $dao = new CRM_Core_DAO_Note();
337 $dao->contact_id
= $id;
342 * Retrieve all records for this entity-id
345 * ID of the relationship for which records needs to be retrieved.
347 * @param string $entityTable
350 * array of note properties
353 public static function &getNote($id, $entityTable = 'civicrm_relationship') {
360 WHERE entity_table=\"{$entityTable}\"
363 ORDER BY modified_date desc";
364 $params = array(1 => array($id, 'Integer'));
366 $dao = CRM_Core_DAO
::executeQuery($query, $params);
368 while ($dao->fetch()) {
369 $viewNote[$dao->id
] = $dao->note
;
376 * Get log record count for a Contact.
378 * @param int $contactID
381 * $count count of log records
384 public static function getContactNoteCount($contactID) {
385 $note = new CRM_Core_DAO_Note();
386 $note->entity_id
= $contactID;
387 $note->entity_table
= 'civicrm_contact';
390 while ($note->fetch()) {
391 if (!self
::getNotePrivacyHidden($note)) {
399 * Get all descendent notes of the note with given ID.
401 * @param int $parentId
402 * ID of the note to start from.
403 * @param int $maxDepth
404 * Maximum number of levels to descend into the tree; if not given, will include all descendents.
405 * @param bool $snippet
406 * If TRUE, returned values will be pre-formatted for display in a table of notes.
409 * Nested associative array beginning with direct children of given note.
412 public static function getNoteTree($parentId, $maxDepth = 0, $snippet = FALSE) {
413 return self
::buildNoteTree($parentId, $maxDepth, $snippet);
417 * Get total count of direct children visible to the current user.
423 * $count Number of notes having the give note as parent
426 public static function getChildCount($id) {
427 $note = new CRM_Core_DAO_Note();
428 $note->entity_table
= 'civicrm_note';
429 $note->entity_id
= $id;
432 while ($note->fetch()) {
433 if (!self
::getNotePrivacyHidden($note)) {
441 * Recursive function to get all descendent notes of the note with given ID.
443 * @param int $parentId
444 * ID of the note to start from.
445 * @param int $maxDepth
446 * Maximum number of levels to descend into the tree; if not given, will include all descendents.
447 * @param bool $snippet
448 * If TRUE, returned values will be pre-formatted for display in a table of notes.
450 * (Reference) Variable to store all found descendents.
452 * Depth of current iteration within the descendent tree (used for comparison against maxDepth).
455 * Nested associative array beginning with direct children of given note.
457 private static function buildNoteTree($parentId, $maxDepth = 0, $snippet = FALSE, &$tree = [], $depth = 0) {
458 if ($maxDepth && $depth > $maxDepth) {
462 // get direct children of given parentId note
463 $note = new CRM_Core_DAO_Note();
464 $note->entity_table
= 'civicrm_note';
465 $note->entity_id
= $parentId;
466 $note->orderBy('modified_date asc');
468 while ($note->fetch()) {
469 // foreach child, call this function, unless the child is private/hidden
470 if (!self
::getNotePrivacyHidden($note)) {
471 CRM_Core_DAO
::storeValues($note, $tree[$note->id
]);
473 // get name of user that created this note
474 $contact = new CRM_Contact_DAO_Contact();
475 $createdById = $note->contact_id
;
476 $contact->id
= $createdById;
479 $tree[$note->id
]['createdBy'] = $contact->display_name
;
480 $tree[$note->id
]['createdById'] = $createdById;
481 $tree[$note->id
]['note_date'] = CRM_Utils_Date
::customFormat($tree[$note->id
]['note_date']);
482 $tree[$note->id
]['modified_date'] = CRM_Utils_Date
::customFormat($tree[$note->id
]['modified_date']);
484 // paper icon view for attachments part
485 $paperIconAttachmentInfo = CRM_Core_BAO_File
::paperIconAttachment('civicrm_note', $note->id
);
486 $tree[$note->id
]['attachment'] = $paperIconAttachmentInfo ?
implode('', $paperIconAttachmentInfo) : '';
489 $tree[$note->id
]['note'] = nl2br($tree[$note->id
]['note']);
490 $tree[$note->id
]['note'] = smarty_modifier_mb_truncate(
491 $tree[$note->id
]['note'],
496 CRM_Utils_Date
::customFormat($tree[$note->id
]['modified_date']);
502 $tree[$note->id
]['child'],
512 * Given a note id, get a list of the ids of all notes that are descendents of that note
514 * @param int $parentId
515 * Id of the given note.
517 * (reference) one-dimensional array to store found descendent ids.
520 * One-dimensional array containing ids of all desendent notes
522 public static function getDescendentIds($parentId, &$ids = []) {
523 // get direct children of given parentId note
524 $note = new CRM_Core_DAO_Note();
525 $note->entity_table
= 'civicrm_note';
526 $note->entity_id
= $parentId;
528 while ($note->fetch()) {
529 // foreach child, add to ids list, and recurse
531 self
::getDescendentIds($note->id
, $ids);
537 * Delete all note related to contact when contact is deleted.
539 * @param int $contactID
540 * Contact id whose notes to be deleted.
542 public static function cleanContactNotes($contactID) {
543 $params = array(1 => array($contactID, 'Integer'));
545 // delete all notes related to contribution
546 $contributeQuery = "DELETE note.*
547 FROM civicrm_note note LEFT JOIN civicrm_contribution contribute ON note.entity_id = contribute.id
548 WHERE contribute.contact_id = %1 AND note.entity_table = 'civicrm_contribution'";
550 CRM_Core_DAO
::executeQuery($contributeQuery, $params);
552 // delete all notes related to participant
553 $participantQuery = "DELETE note.*
554 FROM civicrm_note note LEFT JOIN civicrm_participant participant ON note.entity_id = participant.id
555 WHERE participant.contact_id = %1 AND note.entity_table = 'civicrm_participant'";
557 CRM_Core_DAO
::executeQuery($participantQuery, $params);
559 // delete all contact notes
560 $contactQuery = "SELECT id FROM civicrm_note WHERE entity_id = %1 AND entity_table = 'civicrm_contact'";
562 $contactNoteId = CRM_Core_DAO
::executeQuery($contactQuery, $params);
563 while ($contactNoteId->fetch()) {
564 self
::del($contactNoteId->id
, FALSE);
569 * Whitelist of possible values for the entity_table field
572 public static function entityTables() {
574 'civicrm_relationship' => 'Relationship',
575 'civicrm_contact' => 'Contact',
576 'civicrm_participant' => 'Participant',
577 'civicrm_contribution' => 'Contribution',