Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • extensions/action-provider
  • noah/action-provider
  • BjoernE/action-provider
  • homotechsual/action-provider
  • JonGold/action-provider
  • j.vos/action-provider
  • ayduns/action-provider
  • artfulrobot/action-provider
  • FoadYousefi/action-provider
  • wintermoor/action-provider
  • JoeMurray/action-provider
  • ufundo/action-provider
  • fsnet/action-provider
  • cristinahart/action-provider
  • mattwire/action-provider
  • justinfreeman/action-provider
  • kainuk/action-provider
  • jmargraf/action-provider
  • Csar/action-provider
  • colemanw/action-provider
  • levi.k/action-provider
  • TheSmammy/action-provider
  • agilewarefj/action-provider
  • dotu/action-provider
  • semseysandor/action-provider
  • Janec/action-provider
  • wcha_michael/action-provider
  • partners/civicoop/nihr-bioresearch/action-provider
  • monish.deb/action-provider
  • partners/civicoop/freepressunlimited/action-provider
  • frankADsystopia.de/action-provider
  • partners/ixiam/action-provider
  • jaapjansma/action-provider
  • agileware-iris/action-provider
  • sebalis/action-provider
  • Detlev/action-provider
36 results
Show changes
Commits on Source (978)
Showing
with 1575 additions and 104 deletions
Version 1.50 (not yet released)
Version 1.167 (not yet released)
-------------
* Fix when updating exising phone numbers do not delete an existing when the parameter is not set. See !195
* Communication: Send e-mail action: pass contactId to hook alterMailContent. See !194
* New action. Contribution: Get by Membership ID. See !196
* Fix for Action Validate Checksum of case client. See !198
* Get State and Province ID - get by name OR abbreviation. See !199
Version 1.166
-------------
* Fix for Contact: Get list of subscribed groups.
Version 1.165
-------------
* Condition Contact is in Group works with dynamic groups as well. See !190
* Fixed issue with add contact to group and issue with permissions. See !191
* Fixed: Contribution: Create recurring contribution, two bugs causing next next scheduled contribution date to not be set. Strict type comparison causes failure and assumed date format incorrect. See !187
* Fixed: Membership: Get by Contact ID to actually support optional configurations. Add parameter mapping for membership type. See !185
* New Action to get Membership ID by custom field values. See !188
* Added validation for e-mail is valid.
* Add additional configurations to Membership: Get by Custom Field: added filtering by Membership Status and sort order. See !192
* Disable permission check for Event actions: isWaitListEnabled, GetParticipant, GetParticipantById. See !193
Version 1.164
-------------
* Fixed issue with create participant which creates line items (without a linked contribution).
* Added condition: Contact is (not) in Group(s). See !186
Version 1.163
-------------
* Fixed issue with array parameter contains
* Added action: Participant add role
Version 1.162
-------------
* Fixed: The action 'ContactDataById' does not offer output fields for custom fields that are defined for subtypes. (#61)
* Fixed: CreateUpdateIndividual does not process an update on a shared address correctly. (#62)
* Fixed bug in action Contact: Subscribe/Unsubscribe to groups.
Version 1.161
-------------
* Fixed issue with custom fields and multiple options.
* More refactoring of the Action: Create Relationship and Action: Create Relationship With Type Parameter. See !183 and !178
*
Version 1.160
-------------
* Refactor removal with backwards compatibility of the Action: Create Relationship With Type Parameter; by adding Type Parameter to Create Relationship Action. See !180
* Updated action Participant: Create Participant Contribution to make use of price set options.
* Removed obsolete explodes from GetMembershipByContactID action.
* Add Relationship Permissions options to Create Relationship and Create or Update Relationship actions. See !178
* Filter out null array values which may still exist in Parameter Bag arrays. See !181
* Fix for #60: link contribution recur to a membership. See !182
Version 1.159
-------------
* Fixed bug in Get Participant actions and multi value custom fields.
Version 1.158
-------------
* Fixed price field values processing with Create Line Item and calculate participant fee.
Version 1.157
-------------
* Add price field values processing with Create Line Item and calculate participant fee.
* Fixed issue with action map value.
Version 1.156
-------------
* Fixed issue with action: Stop Execution. Which did not behave correctly anymore.
* Added configuration of actions for custom fields.
Version 1.155
-------------
* Fixed issue with api verions 3 calls in actions and failure handling. See form-processor#84
* Added preferred_language on Contact: Create or Update Organization. See !175
* Fix for unintended custom field erasure. See #57
Version 1.154
-------------
* Fixed issue with the action Participant: send confirmation e-mail. An activity is also recordedd for the email.
Version 1.153
-------------
* Added action Contact: Create/update primary phone
* Added functionality to to set the phone to primary in the Contact create/update phone.
Version 1.152
-------------
* At registering on waitlist functionality to Create/Update Participant actions.
* Add the parameter Fee Level to the actions 'Participant: Create/Update event registration' and 'Participant: Register contact for an event'
* Add the parameter Register Date to the actions 'Participant: Create/Update event registration' and 'Participant: Register contact for an event'
* Enable the clearing of a custom value with a parameter that has the value NULL.
Version 1.151
-------------
* Contribution: Update made configuration parameters optional. See as well !104
* Communications: Create PDF fix issue with php 8.2
Version 1.150
-------------
* Fixed issue with update existing non-primary e-mail address.
Version 1.149
-------------
* Fixed issue with saving mappings of type collection. Used in condition Parameters are (not) empty.
* Added validation: CiviCase Contact does not have role on a case
Version 1.148
-------------
* Improved error handling.
* Implement next_sched_contribution_date field on Create contribution recur action. See !170
Version 1.147
-------------
* Fixed issue with Create or Update Relationship action.
Version 1.146
-------------
* Fixed issue with generating PDF from action provider (and Drupal 10).
Version 1.145
-------------
* Fixed issue with radio custom fields
* Let the Other::ModifyDateValue give better feedback.
* Added Contact Has Email condition. See !167
* Added conditions Parameters match (case-insensitive) and Parameters do not match (case-insensitive). See !166
* For option group configuration fields and parameters only active options are possible. See !168
Version 1.144
-------------
* Added action: Contribution Link to Contribution Page
* Fixed issue with Create Line Item Action. See !65
Version 1.143
-------------
* Fixed action: CiviCase has contact role on a case
* Added action: "Membership: Get by Contact ID". See !162
* Added action: "Other: Format date value". See !161
* Exclude deleted contacts when searching by Email. See !164
Version 1.142
-------------
* Added action: CiviCase has contact role on a case
* Added validation: CiviCase has contact role on a case
Version 1.141
-------------
* Fixed issue with CiviCRM 5.72
Version 1.140
-------------
* Fixed issue with CiviCRM 5.68 and newer.
Version 1.139
-------------
* Added Action: Relationship: Create with one or more contacts
* Added validators for Is Empty and Parameter Has Value.
* Added Action: Activities: Create activities and assign to members of a group.
* Added Action: Send email to a group.
* Update GetEmailAddress.php: is_active does not exist for e-mail addresses. See !159
* Add Action: Mailing Event: Get Contact ID from Mailing
Version 1.138
-------------
* New action: Validate a checksum for the case client of a provided case id.
* Handle zero values in CalculateValue and ConcatenateValues. see !155
* Added action: Other: Combine Lists
Version 1.137
-------------
* Fixed memory issue when downloading a large file.
* Add Membership to Create PDF action and Tokens. See !153
* New Action: ParticipantPayment: get by Participant Id or Contribution ID
Version 1.136
-------------
* Fix for 'TypeError: count():' error in the SearchActionDesigner.
Version 1.135
-------------
* New action, Stop Execution which can be used in combination with Conditions to cause the Form Processor to stop. See !150
* Fixed action: Contribution: Update recurring contribution
* Create PDF do not create zip when batch only consists of one item.
* Added action: Event: Get availability information
* PHP 8 in quick form templates
* Removed check on related deleted entities. See #43
* Added action: Participant: Calculate Participant Fee
* Added action: Participant: Create contribution for participant
* New action, Membership: Get type by ID. Required to get the details for a Membership Type. See !149
* New action: CiviCase: Create or update a role on the case. Allows to omit permission checks and ensures that each role is created only once.
Version 1.134
-------------
* CreateContribution now also takes Financial Type as parameter (For the configuration Financial Type is still required but will function as default).
* Subscribe to mailing list, improve error reporting and parameter checking, consistent parameter label. See !147
Version 1.133
-------------
* Fixed issue with action membership extend.
Version 1.132
-------------
* fix notice in parseRawAmount
* Added action: Membership: Extend or Create.
Version 1.131
-------------
* Reduce API calls for the FindExistingPhone... and add limit 1 to the civicrm_api3 getvalue API calls. See !143
* Add num_terms to CreateOrUpdateMembership actions. See !144
* Provide Action Contribution: Create recurring contribution - adds Payment Token ID parameter to allow saving of a Payment Token. See !145
* Provide Action Contribution: Update recurring contribution - to update details of an existing recurring contribution. See !145
* Provide Action Payment Token: Get by Payment Processor - to get a Payment Token for a given Payment Processor. See !145
* Provide Action Payment Token: Create or Update - creating or updating Payment Token. See !145
* Added action Campaign: Create
Version 1.130
-------------
* Add check for optional Organisation Name and Household Name to the CreateUpdateOrganisation and CreateUpdateHouseHold actions. See !139
* Small bug fix. Email is not valid as a parameter type. See !141
* Add "external_identifier" field to contact create/update actions. See !142
* Added Metadata to actions, conditions and validations
Version 1.129
-------------
* Added action 'Activity: Get Most Recent Activity By Custom Field'.
Version 1.128
-------------
* Added action 'Contact: Update Profile Photo'
* Reworked the action 'Campaign: Get by ID'. See !127
* Added action 'Other: Round Number'. See !136
* Changed Created or Update Membership actions: status should be optional configuration, not required. See !137
* Fixed issue with create and update address. See !138
Version 1.127
-------------
* Fixed issue with action Activity: Upload file to custom field.
* Add Action: Contact: Add to multiple Groups (with list of group IDs as parameter). See !135
Version 1.126
-------------
* Compatibility with CiviCRM 5.45
* Added CiviCase: addRole action
* Add support for custom field type EntityReference. See !119
* Add action to swap participant
* Add action to add notes to entities
* Add action to find event by custom field
* Add action to concatenate values
* Add action to sum up to 6 fields
* Reworked action: 'Other: Calculate value' does not rely on `eval` anymore.
* A generic approach to check the is_deleted flag see MR !125 and issue #38
* Bug fixed, Create Contribution With Parameters action the Is Pay Later parameter was incorrect, see MR !128
* Contribution: Create (with parameters), provide parameter to record the Contribution Page ID for the Contribution . See !130
* Create Update Membership and Create Update Membership Type, provide Membership Status configuration. See !132
Version 1.125
-------------
* Add: Action to get information about a file.
* Add: Action to export a file (or multiple files into one zip)
* Add: Contact: Find entry of a custom group with multi values
* Add: Contact: Edit or create entry for a custom group with multi values.
* Add 'Other: Increment integer value'
* Add 'Activities: Find similar activities'
Version 1.124
-------------
* Add "Campaign: Get by ID" action. See !115
* Add "Contribution: Send confirmation / receipt" action. See !116
* Changed configuration of Phone: Phone type to be not required anymore. See !114
Version 1.123
-------------
* Fix Other: Map Value action - when the result is a single value, do not return an array, just return the value. See !112 and #36
* Fix Action "Address: Get country or state/province from ID" crashes due to incorrect parameter usage. See !113
* Fixed issue with condition contact has tag.
Version 1.122
-------------
* Enable CiviCase:Update and CiviCase:Create to update case type.
* Contact: Create or update Organization expose fields: Legal Name, Nickname, SIC Code. See !103
* Contribution: Update, provide Configuration parameters for Financial Type, Payment Instrument, Contribution Status and Is Pay Later. See !104
* Contribution: Create Line Item, add financial items for the related Contribution. See !105
* Add Payment action to provide partial or complete payment for a Contribution. See !106
* Link Contribution to Membership action should set the Skip Line Items parameter, so that Line Item actions can be responsible for creating the Line Items correctly. See !107
* Two changes to the CreateLineItem action: 1) skip creating the Line Item if the Unit Price is zero and 2) provide the ability to set the Financial Type for a Line Item. See !108
* Contribution: Create, provide parameter to record the Contribution Page ID for the Contribution . See !109
* Fix of AbstractGetSingleAction to ensure, that for custom contact references the id instead of the contact name is returned.
* Replace deprecated `CRM_Core_OptionGroup::getValue` in the send e-mail functionality. See !111
* Added Phone Type to create/update contact actions.
* Added CC/BCC to parameters of Send e-mail and Send PDF by E-mail actions.
* Added action get message template by ID
* Use PDF Format when merging multiple pdf documents into one.
Version 1.121
-------------
* Create Contribution actions, provide option to create a "Pay Later" Contribution by !102
* Added framework for validator actions.
Version 1.120
-------------
* Sets the CiviCRM default Priceset for the line item, if not already set by !100
* Work on PHP 8 and PHP 7 compatibility.
Version 1.119
-------------
* Fixed regression bug from: optionValueToLabel action incorrectly returns an array when single parameter is provided by !91
Version 1.118
------------
* round amount in amount parser
Version 1.117
------------
* Added delete case action.
Version 1.116
------------
* Added configuration option to set bulk mail to Create contact actions.
Version 1.115
------------
* add help text to format individual name, parse raw date and parse raw amount
* add Contribution:Invoice action. To be used in combination with the action 'Communication: Create PDF and send by e-mail'.
Version 1.114
------------
* change format individual name with test results AIVL
* fix text label in action for country iso code
* format phone allows + in first character
Version 1.113
------------
* fix format individual name for more name parts
* output format phone to string so preceding 0 does not disappear
Version 1.112
------------
* add contact action to format individual name - fixes #32, funded by Amnesty International Vlaanderen
* add contact action to format phone string into numbers only - fixes #33, funded by Amnesty International Vlaanderen
Version 1.111
------------
* add generic action to parse raw amount, fixes #30, , funded by Amnesty International Vlaanderen
* Add parameter to Contact: Get e-mail address action to fallback to the active email address when the location type email address is not found.
Version 1.110
------------
*
* add generic action to parse raw data, fixes #29, funded by Amnesty International Vlaanderen
* Communication:Sendmail Enabled sending email for a contact with no email when an alternative email is provided.
* Add campaign parameter to Communication:Sendmail action. The email is added to the campaign.
* OptionValueToLabel action incorrectly returns an array when single parameter is provided by !91
* Custom field using option group returns incorrect values when option values are non-numeric by !90
* PHP 8.1 compatibility - set return types on iterator methods by !92
* Changes the Action: Contact: Get By Email* to search any email address instead of just primary email by !94 and !95
* Added the parameter Preferred Communication Method to the Action Contact: CreateUpdateIndividual
Version 1.109
------------
* Implemented the condition parameter configuration screen for the condition All are (not) empty in the search action designer.
Version 1.108
------------
* Fix for https://lab.civicrm.org/extensions/form-processor/issues/47
* !88 Activity: Create/Update does not expose Duration and Location fields
* !87 PHP 8.1 compatibility - jsonSerialize must have a return type
Version 1.107
------------
* Fixed regression bug. After performance update.
Version 1.106
------------
* Added location type to Send E-mail and Send PDF by Email actions. With a fall back to primary email address.
Version 1.105
------------
* Performance improvements.
Version 1.104
------------
* Added action CiviCase: Role Group Sync
* Added action CiviCase: Get Role Group
* Added action Other: Logged-in Contact Id
* Added parameter source to action Create Participant
Version 1.103
------------
* Added action GetRelationshipById.
* Added action GetEmployer (Retrieves the employer_id and name for a contact)
* Make subject optional in the Civi:Case Update Action.
* Added condition "Parameter is Not"
* Fixed issue with Send PDF By Email action and token replacements for participant tokens.
Version 1.102
------------
* Fixed issue with attachment and sending mails in batch mode.
Version 1.101
------------
* !83 Added Condition: Contact has Activity
* !84 CiviCase Create and CiviCase Update actions provides Case Subject as an input field, but should be provided as a parameter option field
* Added action CiviCase get most recent activity of a case
Version 1.100
------------
* !82 Add nick_name support to CreateUpdateIndividual
* Fix for #25: let mosaico alter the mail content and other extensions which use hook_alter_mailContent
Version 1.99
------------
* Fixed UpdateGroupSubscriptions action fails !24
* Use CiviCRM "standard" labels for address fields. Add missing Supplemental Address 2, 3 fields by !77
* Remove deprecated preferred_mail_format by !78
Version 1.98
------------
* Fixed issue with Create PDF action and CiviCRM and Drupal 9.
Version 1.97
------------
* Fixed issue in action Activity get most recent activity.
Version 1.96
------------
* Added action: Contact restore from trash.
* Added action: Contact: Block Communication (set all do not fields)
Version 1.95
------------
* Fixed issue with sending e-mails.
Version 1.94
------------
* Don't allow users to populate file custom fields
* Fixed regression bug #23
* Added action: Mailing Event Unsubscrive from Mailing list.
Version 1.93
------------
* Fixed #22: Typo in Activity: Get most Recent activity. And loading of configuration of an action when it contains multiple values. Such as activity type.
* Fixed bug with action Contact: add tags.
* Added is_opt_out parameter to CreateUpdateIndividual action see !73
* Added action Contact: Remove From Group see !74
Version 1.92
------------
* Added preferred language to action Create/Update Individual.
* Added action Other: Replace text.
* Error handling at the create activity action
Version 1.91
------------
* Convert tokens with the token processor (only if civicrm is newer then version 5.42).
Version 1.90
------------
* Added condition: 'Compare Parameter with an regular Expression'
* Added PDF Page Format to actions get message template by name and the create pdf and send pdf by email actions.
Version 1.89
------------
* The SendEmail action extended with from_email and from_name parameters
* Added action: Relationship Validate Checksums
Version 1.88
------------
* Fix for #21 Process mapping with customfields in the searchactiondesigner
* Added Action Update Campaign
Version 1.87
------------
* Added option to disable the sending of confirmation e-mails with the Contribution Repeat Transaction action
Version 1.86
------------
* Fixed issue action Contribution: repeat recurring contribution.
Version 1.85
------------
* Fixed issue action Contribution: repeat recurring contribution.
Version 1.84
------------
* Support nickname on create/update individual actions.
* Add action Contribution: Repeat recurring contribution.
Version 1.83
------------
* Added action Update Case status.
* Added action Update Case
* Added Case ID to create and update relationship actions
* Added extra fields to the action Create Case.
* Fix "Create or Update Relationships" to handle symmetric relationships.
* Refactoring SpecificationBag->getSpecificationByName. Processing remarks !55
* Support start/end dates on relationship create/update; related fixes by !62
* Address Component Lookup action by !63
Version 1.82
------------
* Added Action 'Activity: Assign'.
* Added Action 'Other: Replace entity tokens in HTML'.
* Fixed #18: activity contact not correctly returned for 1 record type only
Version 1.81
------------
* Changed action 'Contact: Edit communication styles' and made the communication style also available as a parameter.
* Action 'Activity: Create/Update' has now priority in the configuration (with default Normal).
Version 1.80
------------
* Added status to the create recurring contribution action.
Version 1.79
------------
* Added action 'Contribution: create recurring contribution'
* Added Contribution Recur ID as parameter to the Send E-mail, Create PDF and Send PDF by Email action.
Version 1.78
------------
* Added action 'Contact: Edit communication styles'.
* Fixed SpecificationBag->getSpecificationByName function to support custom fields.
* support note date on 'Create Note' by !53
Version 1.77
------------
* Regenerate auto-generated code (civix) for PHP7.4 compatibility.
* Use full class path in action_provider.php instead of a "use" statement as classloader has not always completed when this file is read (fixes failures on some Wordpress site when run via CRON).
* Added new action 'Other: Retrieve Geocoding (Latitude, Longitude)'. This action uses the CiviCRM geocoding settings.
Version 1.76
------------
* Added action Participant Get by Custom Field.
* Added condition all are equal.
Version 1.75
------------
* Fixed issue with Create and Update participant actions and custom fields.
Version 1.74
------------
* Add case_id to the GetActivity action.
* Extended Create/Update Individual with Is Deceased and Deceaded Date.
* Fixed issue with custom fields and Participant: register contact for event action.
Version 1.73
------------
* Fixed issue with action create contribution and non US locale.
Version 1.72
------------
* Fixed issue with Contact: Create/Update Individual when only an email address is provided.
Version 1.71
------------
* Added action: Contribution: get by custom field.
* Added possibility to give a group name at the Group: Add to Group action.
Version 1.70
------------
* Updated action Create/Update activity with looking activity type when none is given and an existing activity is updated.
Version 1.69
------------
* New Action: Create Line Item !47
* New action 'Other: Resolve/map input to option values' !46
* Fixed regression bug with output values from get entity by id actions. Such as Get Case By Id where the case type wasn't set correctly.
* Added alternative recipient email as a parameter to the Send E-mail and Send PDF by Email actions.
Version 1.68
------------
* Changed actions Send Email and Send pdf by email in such a way that one can set a custom from name and e-mail address. And also an alternative recipient.
Version 1.67
------------
* Regenerated action_provider.civix.php (removing curly braces PHP 7.4 problem)
* Fixed issue with Contact: Get contact by custom field #15
* Fixed issue with Contact: Create/Update Individual when only an email address is provided.
Version 1.66
------------
* Fixed issue with get participant actions.
* Fixed issues with Update Participant By ID action.
Version 1.65
------------
* Changed action Contact: get or create by email and names. So that it also accepts organization name and household name.
* Create action to send SMS by !142
Version 1.64
------------
* The checksum value is now also returned by ValidateChecksum
* Added action 'Contact: Get or create organization by name'
* Fixed bug when no organization is found at the action Contact: Get organization by name.
Version 1.63
------------
* Fixed compatibility issue with send pdf and civicrm version 5.35 and newer.
Version 1.62
------------
* Added action Implode List to the other actions.
* Ability to add schedule date for sending emails by !39
* New action to add multiple contacts to a group by !40
Version 1.61
------------
* Improved angular performance.
Version 1.60
------------
* Fixed regression issue with custom fields on a lot of actions.
Version 1.59
------------
* Fixed issue with custom fields with Create Event and Create Event From Template actions.
Version 1.58
------------
* Improved issue with action provider and CiviCRM version 5.14 whlist keeping the compatibility with civicrm version 5.34 and drupal 9.
* Add Event Full Text to Create Event and Create Event From Template actions.
Version 1.57
------------
* Fixed issue with action provider and CiviCRM version 5.14 whlist keeping the compatibility with civicrm version 5.34 and drupal 9.
Version 1.56
------------
* Improved performance of various actions by using the config container which caches the api calls of custom groups and custom fields.
* Add is_hidden as an option for Create Group action !38
* Add Max Participants and Waitlist Text to Create Event and Create Event From Template actions.
Version 1.55
------------
* Fixed issue with attachments and send e-mail action.
* Fixed issue with tokens generated by the Activity Token extension.
Version 1.54
------------
* Compatibility fix for Symfony ^3.4 ^4.0.
* Fixed issue with create pdf action and source contact id.
* Send PDF by E-mail action can also send additional attachments.
* The create note action does not require any extra permissions anymore.
Version 1.53
------------
* New action to create an event from a template !35
* Made plain text non required on the Send Email and Send PDF by email actions.
Version 1.52
------------
* Changed Add tags action so it could retrieve the tag list as a parameter.
Version 1.51
------------
* Added Formal Title to the action Contact: Create/Update Individual
* Added action Contact: Create Note
* Added action Contact: Add tags
* Added action Contact: Sync tags
Version 1.50
------------
* Create/Update group action also checks on the title. (#11)
* Added summary to create event action (!32 and #10)
Version 1.49
------------
......
......@@ -19,23 +19,28 @@ class CRM_ActionProvider_Page_DownloadFile extends CRM_Core_Page {
$path = $basePath.'/'.$fileName;
$mimeType = mime_content_type($path);
if (!$path) {
if (!$path || !file_exists($path)) {
CRM_Core_Error::statusBounce('Could not retrieve the file');
}
$buffer = file_get_contents($path);
if (!$buffer) {
CRM_Core_Error::statusBounce('The file is either empty or you do not have permission to retrieve the file');
$now = gmdate('D, d M Y H:i:s') . ' GMT';
CRM_Utils_System::setHttpHeader('Content-Type', $mimeType);
CRM_Utils_System::setHttpHeader('Expires', $now);
// lem9 & loic1: IE needs specific headers
$isIE = empty($_SERVER['HTTP_USER_AGENT']) ? FALSE : strstr($_SERVER['HTTP_USER_AGENT'], 'MSIE');
$fileString = "filename=\"{$downloadName}\"";
if ($isIE) {
CRM_Utils_System::setHttpHeader("Content-Disposition", "inline; $fileString");
CRM_Utils_System::setHttpHeader('Cache-Control', 'must-revalidate, post-check=0, pre-check=0');
CRM_Utils_System::setHttpHeader('Pragma', 'public');
}
else {
CRM_Utils_System::setHttpHeader("Content-Disposition", "download; $fileString");
CRM_Utils_System::setHttpHeader('Pragma', 'no-cache');
}
CRM_Utils_System::download(
$downloadName,
$mimeType,
$buffer,
NULL,
TRUE,
'download'
);
print readfile($path);
CRM_Utils_System::civiExit();
}
/**
......
<?php
namespace Civi\ActionProvider;
use Civi\API\Event\PrepareEvent;
/**
* API Wrapper class for intercepting API calls inside of Actions
*/
class APIWrapper {
/**
* Listener for civi.api.prepare event
* Adds callback wrapper to alter API calls
*
* @param \Civi\API\Event\PrepareEvent $event
*
* @return void
*/
public static function onApiPrepare (PrepareEvent $event): void {
$api_request = $event->getApiRequest();
if (is_array($api_request) && $api_request['version'] == 3) {
$action = strtolower($api_request['action']);
if($action == 'get' || $action == 'getsingle') {
// Only interested in APIv3 requests
$event->wrapAPI([self::class, 'wrapV3calls']);
}
if ($action == 'create' || $action == 'delete' || $action == 'submit') {
// Make sure that the Transaction is nested.
// So that an api failure will not cause the transaction not being
// committed.
$api_request['params']['is_transactional'] = 'nest';
$event->setApiRequest($api_request);
}
}
}
/**
* Wrapper callback. Executes mutators then calls the API function
*
* @param array $api_request
* @param array $forward
*
* @return mixed
*/
public static function wrapV3calls(array $api_request, array $forward) {
self::checkIsDeleted($api_request);
return $forward($api_request);
}
/**
* Mutator to avoid pulling deleted entities where behaviour is not specified.
*
* @param array $api_request
*
* @return void
*/
protected static function checkIsDeleted(array &$api_request): void{
// Contacts, Activities, and Cases can be marked as deleted, so check those directly
if (($api_request['entity'] === 'Contact'
|| $api_request['entity'] === 'Activity'
|| $api_request['entity'] === 'Case')
&& !array_key_exists('is_deleted', $api_request['params'])) {
$api_request['params']['is_deleted'] = 0;
}
}
}
......@@ -2,13 +2,18 @@
namespace Civi\ActionProvider\Action;
use Civi\ActionProvider\Exception\BreakException;
use Civi\ActionProvider\Exception\ExecutionException;
use Civi\ActionProvider\Parameter\SpecificationCollection;
use \Civi\ActionProvider\Provider;
use \Civi\ActionProvider\Condition\AbstractCondition;
use \Civi\ActionProvider\Parameter\ParameterBagInterface;
use \Civi\ActionProvider\Parameter\ParameterBag;
use \Civi\ActionProvider\Parameter\SpecificationBag;
use \Civi\ActionProvider\Parameter\InvalidParameterException;
use \Civi\ActionProvider\Exception\InvalidParameterException;
use \Civi\ActionProvider\Exception\InvalidConfigurationException;
use Civi\API\Events;
use Throwable;
/**
* This is the abstract class for an action.
......@@ -63,6 +68,9 @@ abstract class AbstractAction implements \JsonSerializable {
*/
private $condition;
// Reference counter for adding and removing API Wrapper when it's needed
protected static $wrapperLevel = 0;
public function __construct() {
}
......@@ -95,7 +103,7 @@ abstract class AbstractAction implements \JsonSerializable {
/**
* Returns the specification of the output parameters of this action.
*
* This function could be overriden by child classes.
* This function could be overridden by child classes.
*
* @return SpecificationBag
*/
......@@ -133,12 +141,44 @@ abstract class AbstractAction implements \JsonSerializable {
try {
$this->validateParameters($parameters);
} catch (InvalidParameterException $e) {
throw new InvalidParameterException("Found invalid parameters for the action: ".get_class($this).' '.$e->getMessage());
throw new \Civi\ActionProvider\Exception\InvalidParameterException("Found invalid parameters for the action: ".get_class($this).' '.$e->getMessage());
}
// Condition is valid or no condition class is set
$output = $this->createParameterBag();
$this->doAction($parameters, $output);
try {
// Install API wrapper at first level of action provider only
if (++self::$wrapperLevel == 1) {
\Civi::dispatcher()
->addListener('civi.api.prepare', [
'Civi\ActionProvider\APIWrapper',
'onApiPrepare'
], Events::W_EARLY +1);
}
// Wrap action in a transatcion.
$transaction = new \CRM_Core_Transaction();
try {
$this->doAction($parameters, $output);
} catch(BreakException $e) {
// Break exception should never roll back.
throw $e;
} catch (Throwable $e) {
$rollback = true;
if (method_exists($e, 'rollbackDBTransaction')) {
$rollback = $e->rollbackDBTransaction();
}
if ($rollback) {
$transaction->rollback();
}
throw new ExecutionException($e->getMessage() . '(in ' . $e->getFile() . ':' . $e->getLine() . ')' , $e->getCode(), $e, $rollback);
}
$transaction->commit();
} finally {
// Uninstall API wrapper, even if there was an exception
if (-- self::$wrapperLevel == 0) {
\Civi::dispatcher()->removeListener('civi.api.prepare', ['Civi\ActionProvider\APIWrapper', 'onApiPrepare']);
}
}
return $output;
}
......@@ -229,6 +269,26 @@ abstract class AbstractAction implements \JsonSerializable {
return $this;
}
/**
* @return \Civi\ActionProvider\Parameter\SpecificationBag|null
*/
protected function getMetadataSpecification(): SpecificationBag {
if ($this->provider) {
return $this->provider->getMetaData()->getSpecificationBag();
}
return new SpecificationBag();
}
/**
* @return \Civi\ActionProvider\Parameter\ParameterBag
*/
protected function getMetadata(): ParameterBag {
if ($this->provider) {
return $this->provider->getMetaData()->getMetaData();
}
return new ParameterBag();
}
/**
* Sets the default values of this action
*/
......@@ -236,11 +296,12 @@ abstract class AbstractAction implements \JsonSerializable {
$this->configuration = $this->createParameterBag();
$this->defaultConfiguration = $this->createParameterBag();
/**
* @var \Civi\ActionProvider\Parameter\SpecificationInterface
*/
foreach($this->getConfigurationSpecification() as $spec) {
if ($spec->getDefaultValue() !== null) {
$this->configuration->setParameter($spec->getName(), $spec->getDefaultValue());
$this->defaultConfiguration->setParameter($spec->getName(), $spec->getDefaultValue());
}
$spec->setDefaultInParameterBag($this->configuration);
$spec->setDefaultInParameterBag($this->defaultConfiguration);
}
}
......@@ -285,8 +346,9 @@ abstract class AbstractAction implements \JsonSerializable {
/**
* Returns the data structure to serialize it as a json
*/
public function jsonSerialize() {
public function jsonSerialize(): array {
// An empty array goes wrong with the default confifuration.
$return = [];
if (empty($return['default_configuration'])) {
$return['default_configuration'] = new \stdClass();;
}
......
......@@ -47,13 +47,13 @@ abstract class AbstractGetSingleAction extends AbstractAction {
/**
* Returns the specification of the output parameters of this action.
*
* This function could be overriden by child classes.
* This function could be overridden by child classes.
*
* @return SpecificationBag
*/
public function getOutputSpecification() {
$bag = new SpecificationBag();
Fields::getFieldsForEntity($bag,$this->getApiEntity(), 'get', $this->getSkippedFields());
Fields::getFieldsForEntity($bag, $this->getApiEntity(), 'get', $this->getSkippedFields(), $this->getEntityAlias());
return $bag;
}
......@@ -74,7 +74,8 @@ abstract class AbstractGetSingleAction extends AbstractAction {
if ($entity) {
$this->setOutputFromEntity($entity, $output);
}
} catch (\Exception $e) {
}
catch (\Exception $e) {
// Do nothing
}
}
......@@ -82,13 +83,17 @@ abstract class AbstractGetSingleAction extends AbstractAction {
protected function setOutputFromEntity($entity, ParameterBagInterface $output) {
$fieldsToSkip = $this->getSkippedFields();
$entity = $this->normalizeCustomValues($entity);
foreach($entity as $field => $value) {
foreach ($entity as $field => $value) {
if (in_array($field, $fieldsToSkip)) {
continue;
}
if (stripos($field, 'custom_') !== 0) {
if (stripos($field, $this->getEntityAlias() . '_') === 0) {
$output->setParameter(substr($field, strlen($this->getEntityAlias() . '_')), $value);
}
else if (stripos($field, 'custom_') !== 0) {
$output->setParameter($field, $value);
} else {
}
else {
$custom_id = substr($field, 7);
if (is_numeric($custom_id)) {
$fieldName = CustomField::getCustomFieldName($custom_id);
......@@ -107,50 +112,26 @@ abstract class AbstractGetSingleAction extends AbstractAction {
* @param $entity
*/
protected function normalizeCustomValues($entity) {
foreach($entity as $field => $value) {
$normalizedEntity = array();
foreach ($entity as $field => $value) {
if (stripos($field, 'custom_') !== 0) {
$normalizedEntity[$field] = $value;
// No a custom field
continue;
}
$custom_id = substr($field, 7);
if (substr($custom_id, -3) === '_id') {
$custom_id = substr($custom_id, 0, -3);
unset($entity[$field]);
if (is_array($value)) {
$entity['custom_' . $custom_id] = $this->convertCustomFieldWithMultipleValues($value);
} else {
$entity['custom_' . $custom_id] = $value;
}
} elseif (is_numeric($custom_id) && is_array($value)) {
$entity['custom_' . $custom_id] = $this->convertCustomFieldWithMultipleValues($value);
$normalizedEntity['custom_' . $custom_id] = $value;
}
}
return $entity;
}
/**
* Helper function, sometimes the civicrm api returns a multi value field
* as custom_xx => array(
* value 1 => 1,
* )
* and other times
* as custom_xx => array(
* value 1,
* )
*
* Not the difference between the value in the key or in the value bit of the array.
*
* @param $value
*
* @return array
*/
protected function convertCustomFieldWithMultipleValues($value) {
foreach($value as $k=>$v) {
if ($k == 0 && $v >= 1) {
return $value;
elseif (is_numeric($custom_id)) {
if (isset($normalizedEntity[$field])) {
continue;
}
$normalizedEntity['custom_' . $custom_id] = $value;
}
}
return array_keys($value);
return $normalizedEntity;
}
/**
......@@ -163,4 +144,13 @@ abstract class AbstractGetSingleAction extends AbstractAction {
return new SpecificationBag();
}
/**
* Returns the name of the entity.
*
* @return string
*/
protected function getEntityAlias() {
return strtolower($this->getApiEntity());
}
}
......@@ -18,11 +18,11 @@ class Actions {
* @param \Civi\ActionProvider\Provider $provider
*/
public static function loadActions(Provider $provider) {
$provider->addAction('CreateActivity', '\Civi\ActionProvider\Action\Activity\CreateActivity',E::ts('Activity: Create/Update') , array(
$provider->addAction('CreateActivity', '\Civi\ActionProvider\Action\Activity\CreateActivity', E::ts('Activity: Create/Update'), array(
AbstractAction::DATA_MANIPULATION_TAG,
AbstractAction::MULTIPLE_CONTACTS_ACTION_TAG
));
$provider->addAction('UpdateActivityStatus', '\Civi\ActionProvider\Action\Activity\UpdateActivityStatus',E::ts('Activity: Update status') , array(
$provider->addAction('UpdateActivityStatus', '\Civi\ActionProvider\Action\Activity\UpdateActivityStatus', E::ts('Activity: Update status'), array(
AbstractAction::DATA_MANIPULATION_TAG,
AbstractAction::WITHOUT_CONTACT_ACTION_TAG
));
......@@ -41,13 +41,26 @@ class Actions {
$provider->addAction('GetMostRecentActivity', '\Civi\ActionProvider\Action\Activity\GetMostRecentActivity', E::ts('Activity: Get most recent activity of a contact'), array(
AbstractAction::DATA_RETRIEVAL_TAG,
));
$provider->addAction('GetMostRecentActivityByCustomField', '\Civi\ActionProvider\Action\Activity\GetMostRecentActivityByCustomField', E::ts('Activity: Get most recent activity by custom field'), array(
AbstractAction::DATA_RETRIEVAL_TAG,
));
$provider->addAction('ActivityUploadAttachment', '\Civi\ActionProvider\Action\Activity\UploadAttachment', E::ts('Activity: Upload attachment'), array(
AbstractAction::DATA_RETRIEVAL_TAG,
));
$provider->addAction('ActivityUploadCustomFileField', '\Civi\ActionProvider\Action\Activity\UploadCustomFileField',E::ts('Activity: Upload file to a custom field'), array(
$provider->addAction('ActivityUploadCustomFileField', '\Civi\ActionProvider\Action\Activity\UploadCustomFileField', E::ts('Activity: Upload file to a custom field'), array(
AbstractAction::SINGLE_CONTACT_ACTION_TAG,
AbstractAction::DATA_MANIPULATION_TAG,
));
$provider->addAction('ActivityAssign', '\Civi\ActionProvider\Action\Activity\Assign', E::ts('Activity: Assign'), array(
AbstractAction::SINGLE_CONTACT_ACTION_TAG,
AbstractAction::DATA_MANIPULATION_TAG,
));
$provider->addAction('FindSimilarActivities', '\Civi\ActionProvider\Action\Activity\FindSimilarActivities', E::ts('Activity: Find similar activities'), array(
AbstractAction::DATA_RETRIEVAL_TAG,
));
$provider->addAction('CreateActivityForGroup', '\Civi\ActionProvider\Action\Activity\CreateActivityForGroup', E::ts('Activity: Create activities and assign to members of a group'), array(
AbstractAction::DATA_MANIPULATION_TAG,
));
}
......
<?php
/**
* @author Klaas Eikelboom <klaas.eikelboom@civicoop.org>
* @license AGPL-3.0
*/
namespace Civi\ActionProvider\Action\Activity;
use Civi\ActionProvider\Action\AbstractAction;
use Civi\ActionProvider\Parameter\ParameterBagInterface;
use Civi\ActionProvider\Parameter\Specification;
use Civi\ActionProvider\Parameter\SpecificationBag;
use CRM_ActionProvider_ExtensionUtil as E;
class Assign extends AbstractAction {
/**
* Returns the specification of the configuration options for the actual
* action.
*
* @return SpecificationBag
*/
public function getConfigurationSpecification() {
return new SpecificationBag([]);
}
/**
* Returns the specification of the parameters of the actual action.
*
* @return SpecificationBag
*/
public function getParameterSpecification() {
$bag = new SpecificationBag([
new Specification('id', 'Integer', E::ts('Activity ID'), true),
new Specification('assignee_id', 'Integer', E::ts('Assignee ID'), false),
]);
return $bag;
}
/**
* Returns the specification of the output parameters of this action.
*
* This function could be overridden by child classes.
*
* @return SpecificationBag
*/
public function getOutputSpecification() {
return new SpecificationBag(array());
}
/**
* Run the action
*
* @param ParameterBagInterface $parameters
* The parameters to this action.
* @param ParameterBagInterface $output
* The parameters this action can send back
* @return void
* @throws \Exception
*/
protected function doAction(ParameterBagInterface $parameters, ParameterBagInterface $output) {
// Get the contact and the event.
$activityParams['id'] = $parameters->getParameter('id');
$activityParams['assignee_id'] = $parameters->getParameter('assignee_id');
try {
$result = civicrm_api3('Activity', 'Create', $activityParams);
} catch (\Exception $e) {
}
}
}
......@@ -7,6 +7,7 @@
namespace Civi\ActionProvider\Action\Activity;
use Civi\ActionProvider\Action\AbstractAction;
use Civi\ActionProvider\ConfigContainer;
use Civi\ActionProvider\Parameter\OptionGroupByNameSpecification;
use Civi\ActionProvider\Parameter\ParameterBagInterface;
use Civi\ActionProvider\Parameter\Specification;
......@@ -31,6 +32,7 @@ class CreateActivity extends AbstractAction {
new OptionGroupByNameSpecification('activity_type', 'activity_type', E::ts('Activity Type'), FALSE),
new OptionGroupByNameSpecification('activity_status', 'activity_status', E::ts('Activity Status'), TRUE),
$subject,
new OptionGroupByNameSpecification('priority', 'priority', E::ts('Priority'), TRUE,'Normal'),
]);
}
......@@ -47,7 +49,9 @@ class CreateActivity extends AbstractAction {
new Specification('target_contact_id', 'Integer', E::ts('Target Contact ID'), TRUE,null, null, null, true),
new Specification('assignee_contact_id', 'Integer', E::ts('Assignee Contact ID'), FALSE, null, null, null, false),
new Specification('activity_type_id', 'Integer', E::ts('Activity Type'), FALSE, null, null, null, FALSE),
new Specification('location', 'String', E::ts('Location'), FALSE),
new Specification('activity_date', 'Timestamp', E::ts('Activity Date'), FALSE),
new Specification('duration', 'Integer', E::ts('Duration'), FALSE),
new Specification('id', 'Integer', E::ts('Activity ID'), false),
new Specification('campaign_id', 'Integer', E::ts('Campaign'), false),
$subject,
......@@ -55,13 +59,12 @@ class CreateActivity extends AbstractAction {
new Specification('case_id', 'Integer', E::ts('Case ID'), false),
]);
$customGroups = civicrm_api3('CustomGroup', 'get', [
'extends' => 'Activity',
'is_active' => 1,
'options' => ['limit' => 0],
]);
foreach ($customGroups['values'] as $customGroup) {
$bag->addSpecification(CustomField::getSpecForCustomGroup($customGroup['id'], $customGroup['name'], $customGroup['title']));
$config = ConfigContainer::getInstance();
$customGroups = $config->getCustomGroupsForEntity('Activity');
foreach ($customGroups as $customGroup) {
if (!empty($customGroup['is_active'])) {
$bag->addSpecification(CustomField::getSpecForCustomGroup($customGroup['id'], $customGroup['name'], $customGroup['title']));
}
}
return $bag;
......@@ -70,7 +73,7 @@ class CreateActivity extends AbstractAction {
/**
* Returns the specification of the output parameters of this action.
*
* This function could be overriden by child classes.
* This function could be overridden by child classes.
*
* @return SpecificationBag
*/
......@@ -94,6 +97,7 @@ class CreateActivity extends AbstractAction {
// Get the contact and the event.
$activityParams['status_id'] = $this->configuration->getParameter('activity_status');
$activityParams['priority_id'] = $this->configuration->getParameter('priority');
if ($parameters->doesParameterExists('subject')) {
$activityParams['subject'] = $parameters->getParameter('subject');
} elseif ($this->configuration->getParameter('subject')) {
......@@ -108,7 +112,11 @@ class CreateActivity extends AbstractAction {
if ($parameters->doesParameterExists('assignee_contact_id')) {
$activityParams['assignee_contact_id'] = $parameters->getParameter('assignee_contact_id');
}
$activityParams['location'] = $parameters->getParameter('location');
$activityParams['activity_date_time'] = $parameters->getParameter('activity_date');
$activityParams['duration'] = $parameters->getParameter('duration');
if ($parameters->doesParameterExists('campaign_id')) {
$activityParams['campaign_id'] = $parameters->getParameter('campaign_id');
}
......@@ -124,6 +132,10 @@ class CreateActivity extends AbstractAction {
$activityParams['case_id'] = $parameters->getParameter('case_id');
}
if (empty($activityParams['activity_type_id']) && !empty($activityParams['id'])) {
$activityParams['activity_type_id'] = civicrm_api3('Activity', 'getvalue', ['return' => 'activity_type_id', 'id' => $activityParams['id'],'options' => ['limit' => 1]]);
}
$activityParams = array_merge($activityParams, CustomField::getCustomFieldsApiParameter($parameters, $this->getParameterSpecification()));
try {
......@@ -131,7 +143,8 @@ class CreateActivity extends AbstractAction {
$result = civicrm_api3('Activity', 'Create', $activityParams);
$output->setParameter('id', $result['id']);
} catch (\Exception $e) {
// Do nothing.
\Civi::log()->error('ActionProvider CreateActivity Error: ' . $e->getMessage());
throw new \Civi\ActionProvider\Exception\ExecutionException(E::ts('Could not create activity.'));
}
}
......
<?php
namespace Civi\ActionProvider\Action\Activity;
use \Civi\ActionProvider\Action\AbstractAction;
use \Civi\ActionProvider\Parameter\ParameterBagInterface;
use \Civi\ActionProvider\Parameter\SpecificationBag;
use \Civi\ActionProvider\Parameter\Specification;
use Civi\ActionProvider\ConfigContainer;
use Civi\ActionProvider\Parameter\OptionGroupByNameSpecification;
use Civi\ActionProvider\Parameter\SpecificationGroup;
use Civi\ActionProvider\Utils\CustomField;
use CRM_ActionProvider_ExtensionUtil as E;
class CreateActivityForGroup extends AbstractAction {
/**
* Returns the specification of the configuration options for the actual action.
*
* @return SpecificationBag
*/
public function getConfigurationSpecification() {
$subject = new Specification('subject', 'String', E::ts('Default Subject'));
$subject->setDescription(E::ts('Subject when you don\'t get use a parameter for the subejct.'));
return new SpecificationBag([
new Specification('group_id', 'Integer', E::ts('Select group'), false, null, 'Group', null, FALSE),
new Specification('group_title', 'String', E::ts('Or group title'), false, null, null, null, FALSE),
new OptionGroupByNameSpecification('activity_type', 'activity_type', E::ts('Activity Type'), FALSE),
new OptionGroupByNameSpecification('activity_status', 'activity_status', E::ts('Activity Status'), TRUE),
$subject,
new OptionGroupByNameSpecification('priority', 'priority', E::ts('Priority'), TRUE, 'Normal'),
]);
return new SpecificationBag(array(
));
}
/**
* Returns the specification of the configuration options for the actual action.
*
* @return SpecificationBag
*/
public function getParameterSpecification() {
$subject = new Specification('subject', 'String', E::ts('Subject'));
$subject->setDescription(E::ts('Use this field when you want to set the subject from another field.'));
$bag = new SpecificationBag([
new Specification('group_id', 'Integer', E::ts('Group ID'), FALSE, null, null, null, false),
new Specification('source_contact_id', 'Integer', E::ts('Source Contact ID'), TRUE, null, null, null, false),
new Specification('target_contact_id', 'Integer', E::ts('Target Contact ID'), TRUE, null, null, null, true),
new Specification('activity_type_id', 'Integer', E::ts('Activity Type'), FALSE, null, null, null, FALSE),
new Specification('location', 'String', E::ts('Location'), FALSE),
new Specification('activity_date', 'Timestamp', E::ts('Activity Date'), FALSE),
new Specification('duration', 'Integer', E::ts('Duration'), FALSE),
new Specification('id', 'Integer', E::ts('Activity ID'), false),
new Specification('campaign_id', 'Integer', E::ts('Campaign'), false),
$subject,
new Specification('details', 'Text', E::ts('Details'), false),
new Specification('case_id', 'Integer', E::ts('Case ID'), false),
]);
$config = ConfigContainer::getInstance();
$customGroups = $config->getCustomGroupsForEntity('Activity');
foreach ($customGroups as $customGroup) {
if (!empty($customGroup['is_active'])) {
$bag->addSpecification(CustomField::getSpecForCustomGroup($customGroup['id'], $customGroup['name'], $customGroup['title']));
}
}
return $bag;
}
/**
* Returns the specification of the output parameters of this action.
*
* This function could be overridden by child classes.
*
* @return SpecificationBag
*/
public function getOutputSpecification() {
return new SpecificationBag();
}
/**
* Run the action
*
* @param ParameterInterface $parameters
* The parameters to this action.
* @param ParameterBagInterface $output
* The parameters this action can send back
* @return void
*/
protected function doAction(ParameterBagInterface $parameters, ParameterBagInterface $output) {
// Create and collect tthe activity configurations
$activityParams['status_id'] = $this->configuration->getParameter('activity_status');
$activityParams['priority_id'] = $this->configuration->getParameter('priority');
if ($parameters->doesParameterExists('subject')) {
$activityParams['subject'] = $parameters->getParameter('subject');
}
elseif ($this->configuration->getParameter('subject')) {
$activityParams['subject'] = $this->configuration->getParameter('subject');
}
if ($parameters->doesParameterExists('id')) {
$activityParams['id'] = $parameters->getParameter('id');
}
$activityParams['source_contact_id'] = $parameters->getParameter('source_contact_id');
$activityParams['target_contact_id'] = $parameters->getParameter('target_contact_id');
$activityParams['location'] = $parameters->getParameter('location');
$activityParams['activity_date_time'] = $parameters->getParameter('activity_date');
$activityParams['duration'] = $parameters->getParameter('duration');
if ($parameters->doesParameterExists('campaign_id')) {
$activityParams['campaign_id'] = $parameters->getParameter('campaign_id');
}
if ($parameters->doesParameterExists('details')) {
$activityParams['details'] = $parameters->getParameter('details');
}
if ($parameters->doesParameterExists('activity_type_id')) {
$activityParams['activity_type_id'] = $parameters->getParameter('activity_type_id');
}
elseif ($activityParams['activity_type_id'] = $this->configuration->doesParameterExists('activity_type')) {
$activityParams['activity_type_id'] = $this->configuration->getParameter('activity_type');
}
if ($parameters->doesParameterExists('case_id')) {
$activityParams['case_id'] = $parameters->getParameter('case_id');
}
if (empty($activityParams['activity_type_id']) && !empty($activityParams['id'])) {
$activityParams['activity_type_id'] = civicrm_api3('Activity', 'getvalue', ['return' => 'activity_type_id', 'id' => $activityParams['id'], 'options' => ['limit' => 1]]);
}
$activityParams = array_merge($activityParams, CustomField::getCustomFieldsApiParameter($parameters, $this->getParameterSpecification()));
// get list of contacts in the provided group
if ($parameters->doesParameterExists('group_id')) {
$groupId = $parameters->getParameter('group_id');
}
else if ($this->configuration->doesParameterExists('group_id')) {
$groupId = $this->configuration->getParameter('group_id');
}
else if ($this->configuration->doesParameterExists('group_title')) {
$groupTitle = $this->configuration->getParameter('group_title');
$groupId = civicrm_api4('Groups', 'get', [
'select' => ['id'],
'where' => [
['title', '=', $groupTitle]
]]
);
$groupId = $groupId[0]['id'];
}
else {
throw new \Civi\ActionProvider\Exception\ExecutionException(E::ts('Could not create activity. No group could be found.'));
}
$groupContacts = civicrm_api4('GroupContact', 'get', array(
'select' => array('contact_id'),
'where' => array(
array('group_id', '=', $groupId),
array('status', '=', 'Added')
)
));
foreach ($groupContacts as $contact) {
$activityParams['assignee_contact_id'] = $contact['contact_id'];
try {
// Do not use api as the api checks for an existing relationship.
$result = civicrm_api3('Activity', 'Create', $activityParams);
//$output->setParameter('id', $result['id']);
}
catch (\Exception $e) {
\Civi::log()->error('ActionProvider CreateActivity Error: ' . $e->getMessage());
throw new \Civi\ActionProvider\Exception\ExecutionException(E::ts('Could not create activity.'));
}
}
}
}
\ No newline at end of file
......@@ -42,7 +42,7 @@ class DeleteActivity extends AbstractAction {
/**
* Returns the specification of the output parameters of this action.
*
* This function could be overriden by child classes.
* This function could be overridden by child classes.
*
* @return SpecificationBag
*/
......
<?php
/**
* @author Simon Hermann <simon.hermann@civiservice.de>
* @license AGPL-3.0
*/
namespace Civi\ActionProvider\Action\Activity;
use Civi\ActionProvider\Action\AbstractAction;
use Civi\ActionProvider\ConfigContainer;
use Civi\ActionProvider\Parameter\ParameterBagInterface;
use Civi\ActionProvider\Parameter\OptionGroupSpecification;
use Civi\ActionProvider\Parameter\OptionGroupByNameSpecification;
use Civi\ActionProvider\Parameter\SpecificationBag;
use Civi\ActionProvider\Parameter\Specification;
use Civi\ActionProvider\Utils\CustomField;
use CRM_ActionProvider_ExtensionUtil as E;
class FindSimilarActivities extends AbstractAction {
/**
* Run the action
*
* @param ParameterInterface $parameters
* The parameters to this action.
* @param ParameterBagInterface $output
* The parameters this action can send back
* @return void
*/
protected function doAction(ParameterBagInterface $parameters, ParameterBagInterface $output) {
$parameterArray = $parameters->toArray();
$configurationArray = $this->configuration->toArray();
$apiParams = array();
$apiParams['return'] = array('id');
foreach ($parameterArray as $key => $value) {
if ($value !== '') {
$apiParams[$key] = $value;
}
}
foreach ($configurationArray as $key => $value) {
if (!isset($apiParams[$key]) && $value !== '') {
$apiParams[$key] = $value;
}
}
try {
$entity = civicrm_api3('Activity', 'get', $apiParams);
$output->setParameter('number_similar_activities', sizeof($entity['values']));
$activityIDs = array();
foreach ($entity['values'] as $entry) {
array_push($activityIDs, $entry['id']);
}
$output->setParameter('activity_Ids', $activityIDs);
$output->setParameter('apiCall', $apiParams);
}
catch (\Exception $e) {
throw new ExecutionException(E::ts('Could not find an activity'));
}
}
/**
* Returns the specification of the configuration options for the actual action.
*
* @return SpecificationBag
*/
public function getConfigurationSpecification() {
$specs = new SpecificationBag();
$specs->addSpecification(new OptionGroupByNameSpecification('activity_type_id', 'activity_type', E::ts('Activity Type'), FALSE));
$specs->addSpecification(new OptionGroupByNameSpecification('status_id', 'activity_status', E::ts('Activity Status'), FALSE));
return $specs;
}
/**
* Returns the specification of the parameters of the actual action.
*
* @return SpecificationBag
*/
public function getParameterSpecification() {
$specs = new SpecificationBag();
$specs->addSpecification(new Specification('activity_type_id', 'String', E::ts('Activity type ID'), false));
$specs->addSpecification(new Specification('status_id', 'String', E::ts('Activity status ID'), false));
$specs->addSpecification(new Specification('subject', 'String', E::ts('Activity subject'), false));
$specs->addSpecification(new Specification('target_contact_id', 'Integer', E::ts('Target contact ID'), false));
$config = ConfigContainer::getInstance();
$customGroups = $config->getCustomGroupsForEntity('Activity');
foreach ($customGroups as $customGroup) {
if (!empty($customGroup['is_active'])) {
$specs->addSpecification(CustomField::getSpecForCustomGroup($customGroup['id'], $customGroup['name'], $customGroup['title']));
}
}
return $specs;
}
/**
* Returns the specification of the output parameters of this action.
*
* This function could be overridden by child classes.
*
* @return SpecificationBag
*/
public function getOutputSpecification() {
$specs = new SpecificationBag();
$specs->addSpecification(new Specification('activity_Ids', 'String', E::ts('IDs of similar activities'), true));
$specs->addSpecification(new Specification('number_similar_activities', 'Integer', E::ts('Number of similar acitivities')));
$specs->addSpecification(new Specification('apiCall', 'Integer', E::ts('Call of the APIv3')));
return $specs;
}
}
\ No newline at end of file
......@@ -50,7 +50,7 @@ class GetActivity extends AbstractGetSingleAction {
/**
* Returns the specification of the output parameters of this action.
*
* This function could be overriden by child classes.
* This function could be overridden by child classes.
*
* @return SpecificationBag
*/
......@@ -78,10 +78,23 @@ class GetActivity extends AbstractGetSingleAction {
$target_contact_ids[] = $dao->contact_id;
}
}
$sql = "SELECT DISTINCT case_id from civicrm_case_activity WHERE activity_id = %1";
$sqlParams[1] = array($entity['id'], 'Integer');
$dao = \CRM_Core_DAO::executeQuery($sql, $sqlParams);
$case_id = array();
while($dao->fetch()) {
$case_id[] = $dao->case_id;
}
$output->setParameter('target_contact_id', $target_contact_ids);
if ($assignee_contact_id) {
$output->setParameter('assignee_contact_id', $assignee_contact_id);
}
if(!empty($case_id)){
if(count($case_id)){
$case_id = reset($case_id);
}
$output->setParameter('case_id', $case_id);
}
}
......
......@@ -43,7 +43,7 @@ class GetActivityContact extends AbstractAction {
/**
* Returns the specification of the output parameters of this action.
*
* This function could be overriden by child classes.
* This function could be overridden by child classes.
*
* @return SpecificationBag
*/
......@@ -69,8 +69,16 @@ class GetActivityContact extends AbstractAction {
$record_type_ids = $this->configuration->getParameter('record_type');
$sql = "SELECT DISTINCT contact_id FROM civicrm_activity_contact WHERE activity_id = %1";
$sqlParams[1] = array($id, 'Integer');
if ($record_type_ids && is_array($record_type_ids) && count($record_type_ids)) {
$sql .= " AND record_type_id IN (".implode(", ", $record_type_ids).")";
if ($record_type_ids) {
if (is_array($record_type_ids)) {
if (count($record_type_ids)) {
$sql .= " AND record_type_id IN (".implode(", ", $record_type_ids).")";
}
}
else {
$sql .= " AND record_type_id = %2";
$sqlParams[2] = [(int) $record_type_ids, 'Integer'];
}
}
$dao = \CRM_Core_DAO::executeQuery($sql, $sqlParams);
......@@ -85,4 +93,4 @@ class GetActivityContact extends AbstractAction {
}
\ No newline at end of file
}
......@@ -53,7 +53,7 @@ class GetMostRecentActivity extends AbstractAction {
/**
* Returns the specification of the output parameters of this action.
*
* This function could be overriden by child classes.
* This function could be overridden by child classes.
*
* @return SpecificationBag
*/
......@@ -77,7 +77,7 @@ class GetMostRecentActivity extends AbstractAction {
protected function doAction(ParameterBagInterface $parameters, ParameterBagInterface $output) {
$id = $parameters->getParameter('id');
$record_type_ids = $this->configuration->getParameter('record_type');
$activity_type_ids = $this->configuration->getParameter('activity_type');
$activity_type_ids = $this->configuration->getParameter('activity_type_id');
$status_ids = $this->configuration->getParameter('status_id');
$error = $this->configuration->getParameter('error');
$sql =<<< SQL
......@@ -89,12 +89,18 @@ SQL;
$sqlParams[1] = array($id, 'Integer');
if ($record_type_ids && is_array($record_type_ids) && count($record_type_ids)) {
$sql .= " AND record_type_id IN (".implode(", ", $record_type_ids).")";
} elseif ($record_type_ids && !is_array($record_type_ids)) {
$sql .= " AND record_type_id IN (".implode(", ", explode(",", $record_type_ids)).")";
}
if ($activity_type_ids && is_array($activity_type_ids) && count($activity_type_ids)) {
$sql .= " AND activity_type_id IN (".implode(", ", $activity_type_ids).")";
} elseif ($activity_type_ids && !is_array($activity_type_ids)) {
$sql .= " AND activity_type_id IN (".implode(", ", explode(",", $activity_type_ids)).")";
}
if ($status_ids && is_array($status_ids) && count($status_ids)) {
$sql .= " AND status_id IN (".implode(", ", $status_ids).")";
} elseif ($status_ids && !is_array($status_ids)) {
$sql .= " AND status_id IN (".implode(", ", explode(",", $status_ids)).")";
}
$sql .= " ORDER BY act.activity_date_time DESC limit 1";
$activity_id = \CRM_Core_DAO::singleValueQuery($sql,[
......
<?php
/**
* Gets the most recent activity of a contact. So the contact_id is the key, the
* activity id is returned.
*
* Returns the activity id and the contact id as well.
*
* @author Klaas Eikelboom <klaas.eikelboom@civicoop.org>
* @date 25-May-2020
* @license AGPL-3.0
*/
namespace Civi\ActionProvider\Action\Activity;
use Civi\ActionProvider\Action\AbstractAction;
use Civi\ActionProvider\ConfigContainer;
use Civi\ActionProvider\Exception\ExecutionException;
use Civi\ActionProvider\Parameter\OptionGroupSpecification;
use Civi\ActionProvider\Parameter\ParameterBagInterface;
use Civi\ActionProvider\Parameter\Specification;
use Civi\ActionProvider\Parameter\SpecificationBag;
use CRM_ActionProvider_ExtensionUtil as E;
use CRM_Core_Exception;
class GetMostRecentActivityByCustomField extends AbstractAction {
/**
* Returns the specification of the configuration options for the actual
* action.
*
* @return SpecificationBag
*/
public function getConfigurationSpecification() {
$fields = array();
$config = ConfigContainer::getInstance();
$customGroups = $config->getCustomGroupsForEntity('Activity');
foreach ($customGroups as $customGroup) {
if (!empty($customGroup['is_active'])) {
$customFields = $config->getCustomFieldsOfCustomGroup($customGroup['id']);
foreach($customFields as $customField) {
$fields[$customField['id']] = $customGroup['title']. ' :: '.$customField['label'];
}
}
}
$bag = new SpecificationBag();
$bag->addSpecification(new Specification('custom_field', 'Integer', E::ts('Custom field'), true, null, null, $fields, false));
$bag->addSpecification(new OptionGroupSpecification('activity_type_id', 'activity_type', E::ts('Activity Type'), false, null, true));
$bag->addSpecification(new OptionGroupSpecification('status_id', 'activity_status', E::ts('Activity Status'), false, null, true));
$bag->addSpecification(new Specification('error', 'Boolean', E::ts('Error on no activity found'), false, false));
return $bag;
}
/**
* Returns the specification of the parameters of the actual action.
*
* @return SpecificationBag
*/
public function getParameterSpecification() {
$bag = new SpecificationBag([
new Specification('value', 'String', E::ts('Custom Field Value'), true),
]);
return $bag;
}
/**
* Returns the specification of the output parameters of this action.
*
* This function could be overridden by child classes.
*
* @return SpecificationBag
*/
public function getOutputSpecification() {
$bag = new SpecificationBag();
$bag->addSpecification(new Specification('activity_id', 'Integer', E::ts('Activity ID')));
return $bag;
}
/**
* Run the action
*
* @param ParameterBagInterface $parameters
* The parameters to this action.
* @param ParameterBagInterface $output
* The parameters this action can send back
*
* @return void
* @throws \Civi\ActionProvider\Exception\ExecutionException
*/
protected function doAction(ParameterBagInterface $parameters, ParameterBagInterface $output) {
$customFieldId = $this->configuration->getParameter('custom_field');
$activity_type_ids = $this->configuration->getParameter('activity_type_id');
$status_ids = $this->configuration->getParameter('status_id');
$error = $this->configuration->getParameter('error');
$apiParams = [];
$apiParams['custom_'.$customFieldId] = $parameters->getParameter('value');
if ($activity_type_ids && is_array($activity_type_ids) && count($activity_type_ids)) {
$apiParams['activity_type_id']['IN'] = $activity_type_ids;
} elseif ($activity_type_ids && !is_array($activity_type_ids)) {
$apiParams['activity_type_id']['IN'] = explode(",", $activity_type_ids);
}
if ($status_ids && is_array($status_ids) && count($status_ids)) {
$apiParams['status_id']['IN'] = $status_ids;
} elseif ($status_ids && !is_array($status_ids)) {
$apiParams['status_id']['IN'] = explode(",", $status_ids);
}
$apiParams['options']['sort'] = 'activity_date_time DESC';
$apiParams['options']['limit'] = 1;
$apiParams['return'] = 'id';
try {
$activityId = civicrm_api3('Activity', 'getvalue', $apiParams);
$output->setParameter('activity_id', $activityId);
}
catch (CRM_Core_Exception $e) {
if ($error && empty($activity_id)) {
throw new ExecutionException(E::ts('Could not find an activity'));
}
}
}
}
......@@ -46,7 +46,7 @@ class UpdateActivityStatus extends AbstractAction {
/**
* Returns the specification of the output parameters of this action.
*
* This function could be overriden by child classes.
* This function could be overridden by child classes.
*
* @return SpecificationBag
*/
......
......@@ -86,7 +86,7 @@ class UploadAttachment extends AbstractAction {
/**
* Returns the specification of the output parameters of this action.
*
* This function could be overriden by child classes.
* This function could be overridden by child classes.
*
* @return SpecificationBag
*/
......
......@@ -3,6 +3,7 @@
namespace Civi\ActionProvider\Action\Activity;
use Civi\ActionProvider\Action\AbstractAction;
use Civi\ActionProvider\ConfigContainer;
use Civi\ActionProvider\Parameter\FileSpecification;
use Civi\ActionProvider\Parameter\ParameterBagInterface;
use Civi\ActionProvider\Parameter\SpecificationBag;
......@@ -41,13 +42,18 @@ class UploadCustomFileField extends AbstractAction {
$currentFile = civicrm_api3('Activity', 'getvalue', [
'id' => $activity_id,
'return' => 'custom_' . $customFieldId,
'options' => ['limit' => 1]
]);
if (isset($file['id']) && $currentFile && $file['id'] != $currentFile) {
$currentFileId = $currentFile;
if (is_array($currentFile) && isset($currentFile['fid'])) {
$currentFileId = $currentFile['fid'];
}
if (isset($file['id']) && $currentFileId && $file['id'] != $currentFileId) {
$deleteCurrentFile = true;
$updateCustomField = $file['id'];
}
if ($currentFile && $deleteCurrentFile) {
civicrm_api3('Attachment', 'delete', array('id' => $currentFile));
if (is_numeric($currentFileId) && $deleteCurrentFile) {
civicrm_api3('Attachment', 'delete', array('id' => $currentFileId));
}
} catch (\Exception $e) {
// Do nothing
......@@ -77,8 +83,8 @@ class UploadCustomFileField extends AbstractAction {
$updateCustomField = FALSE;
}
if ($updateCustomField) {
civicrm_api3('Event', 'create', [
'id' => $event_id,
civicrm_api3('Activity', 'create', [
'id' => $activity_id,
'custom_' . $customFieldId => $updateCustomField,
]);
}
......@@ -91,16 +97,16 @@ class UploadCustomFileField extends AbstractAction {
*/
public function getConfigurationSpecification() {
$fileFields = array();
$customGroups = civicrm_api3('CustomGroup', 'get', array('is_active' => 1, 'is_multiple' => 0, 'extends' => 'Activity', 'options' => array('limit' => 0)));
foreach($customGroups['values'] as $customGroup) {
$customFields = civicrm_api3('CustomField', 'get', [
'custom_group_id' => $customGroup['id'],
'is_active' => 1,
'data_type' => 'File',
'options' => ['limit' => 0],
]);
foreach ($customFields['values'] as $customField) {
$fileFields[$customField['id']] = $customGroup['title']. ' :: '.$customField['label'];
$config = ConfigContainer::getInstance();
$customGroups = $config->getCustomGroupsForEntity('Activity');
foreach ($customGroups as $customGroup) {
if (!empty($customGroup['is_active'])) {
$customFields = $config->getCustomFieldsOfCustomGroup($customGroup['id']);
foreach($customFields as $customField) {
if ($customField['data_type'] == 'File') {
$fileFields[$customField['id']] = $customGroup['title']. ' :: '.$customField['label'];
}
}
}
}
......@@ -124,7 +130,7 @@ class UploadCustomFileField extends AbstractAction {
/**
* Returns the specification of the output parameters of this action.
*
* This function could be overriden by child classes.
* This function could be overridden by child classes.
*
* @return SpecificationBag
*/
......
......@@ -54,6 +54,7 @@ class Send extends AbstractAction {
new Specification('from_name', 'String', E::ts('From name'), false, null, null, null, False),
new Specification('from_email', 'String', E::ts('From E-mail'), false, null, null, null, False),
new Specification('replyto_email', 'String', E::ts('Reply to'), false, null, null, null, False),
new Specification('scheduled_date', 'Timestamp', E::ts('Scheduled date'), false, null, null, null, False),
));
return $specs;
}
......@@ -61,7 +62,7 @@ class Send extends AbstractAction {
/**
* Returns the specification of the output parameters of this action.
*
* This function could be overriden by child classes.
* This function could be overridden by child classes.
*
* @return SpecificationBag
*/
......@@ -116,6 +117,9 @@ class Send extends AbstractAction {
if ($parameters->doesParameterExists('template_options')) {
$apiParams['template_options'] = $parameters->getParameter('template_options');
}
if ($parameters->doesParameterExists('scheduled_date')) {
$scheduled_date = $parameters->getParameter('scheduled_date');
}
$mailing = civicrm_api3('Mailing', 'Create', $apiParams);
foreach($groupIds as $groupId) {
......@@ -127,8 +131,13 @@ class Send extends AbstractAction {
}
// Now send the mailing
$now = new \DateTime();
$now->setTimezone(new \DateTimeZone('UTC'));
if(!empty($scheduled_date)) {
$now = new \DateTime($scheduled_date, new \DateTimeZone('UTC'));
}
else {
$now = new \DateTime();
$now->setTimezone(new \DateTimeZone('UTC'));
}
$mailingSendParams['id'] = $mailing['id'];
$mailingSendParams['scheduled_date'] = $now->format('Ymd His');
civicrm_api3('Mailing', 'submit', $mailingSendParams);
......
......@@ -18,7 +18,19 @@ class Actions {
* @param \Civi\ActionProvider\Provider $provider
*/
public static function loadActions(Provider $provider) {
$provider->addAction('FindOrCreateCampaign', '\Civi\ActionProvider\Action\Campaign\FindOrCreateCampaign',E::ts('Campaign: Get or create') , array(
$provider->addAction('FindOrCreateCampaign', '\Civi\ActionProvider\Action\Campaign\FindOrCreateCampaign', E::ts('Campaign: Get or create'), array(
AbstractAction::WITHOUT_CONTACT_ACTION_TAG,
AbstractAction::DATA_MANIPULATION_TAG,
));
$provider->addAction('UpdateCampaign', '\Civi\ActionProvider\Action\Campaign\UpdateCampaign', E::ts('Campaign: Update'), array(
AbstractAction::WITHOUT_CONTACT_ACTION_TAG,
AbstractAction::DATA_MANIPULATION_TAG,
));
$provider->addAction('CreateCampaign', '\Civi\ActionProvider\Action\Campaign\CreateCampaign', E::ts('Campaign: Create'), array(
AbstractAction::WITHOUT_CONTACT_ACTION_TAG,
AbstractAction::DATA_MANIPULATION_TAG,
));
$provider->addAction('GetCampaign', '\Civi\ActionProvider\Action\Campaign\GetCampaign', E::ts('Campaign: Get by ID'), array(
AbstractAction::WITHOUT_CONTACT_ACTION_TAG,
AbstractAction::DATA_MANIPULATION_TAG,
));
......