Commit b9644f9d authored by Rich's avatar Rich

wip

parent 53550e19
<?php
use CRM_Actionlinks_ExtensionUtil as E;
class CRM_Actionlinks_BAO_ActionLink extends CRM_Actionlinks_DAO_ActionLink {
/**
* Create a new ActionLink based on array-data
*
* @param array $params key-value pairs
* @return CRM_Actionlinks_DAO_ActionLink|NULL
*
public static function create($params) {
$className = 'CRM_Actionlinks_DAO_ActionLink';
$entityName = 'ActionLink';
$hook = empty($params['id']) ? 'create' : 'edit';
CRM_Utils_Hook::pre($hook, $entityName, CRM_Utils_Array::value('id', $params), $params);
$instance = new $className();
$instance->copyValues($params);
$instance->save();
CRM_Utils_Hook::post($hook, $entityName, $instance->id, $instance);
return $instance;
} */
}
This diff is collapsed.
<?php
use CRM_Actionlinks_ExtensionUtil as E;
/**
* Collection of upgrade steps.
*/
class CRM_Actionlinks_Upgrader extends CRM_Actionlinks_Upgrader_Base {
// By convention, functions that look like "function upgrade_NNNN()" are
// upgrade tasks. They are executed in order (like Drupal's hook_update_N).
/**
* Example: Run an external SQL script when the module is installed.
*
public function install() {
$this->executeSqlFile('sql/myinstall.sql');
}
/**
* Example: Work with entities usually not available during the install step.
*
* This method can be used for any post-install tasks. For example, if a step
* of your installation depends on accessing an entity that is itself
* created during the installation (e.g., a setting or a managed entity), do
* so here to avoid order of operation problems.
*
public function postInstall() {
$customFieldId = civicrm_api3('CustomField', 'getvalue', array(
'return' => array("id"),
'name' => "customFieldCreatedViaManagedHook",
));
civicrm_api3('Setting', 'create', array(
'myWeirdFieldSetting' => array('id' => $customFieldId, 'weirdness' => 1),
));
}
/**
* Example: Run an external SQL script when the module is uninstalled.
*
public function uninstall() {
$this->executeSqlFile('sql/myuninstall.sql');
}
/**
* Example: Run a simple query when a module is enabled.
*
public function enable() {
CRM_Core_DAO::executeQuery('UPDATE foo SET is_active = 1 WHERE bar = "whiz"');
}
/**
* Example: Run a simple query when a module is disabled.
*
public function disable() {
CRM_Core_DAO::executeQuery('UPDATE foo SET is_active = 0 WHERE bar = "whiz"');
}
/**
* Example: Run a couple simple queries.
*
* @return TRUE on success
* @throws Exception
*
public function upgrade_4200() {
$this->ctx->log->info('Applying update 4200');
CRM_Core_DAO::executeQuery('UPDATE foo SET bar = "whiz"');
CRM_Core_DAO::executeQuery('DELETE FROM bang WHERE willy = wonka(2)');
return TRUE;
} // */
/**
* Example: Run an external SQL script.
*
* @return TRUE on success
* @throws Exception
public function upgrade_4201() {
$this->ctx->log->info('Applying update 4201');
// this path is relative to the extension base dir
$this->executeSqlFile('sql/upgrade_4201.sql');
return TRUE;
} // */
/**
* Example: Run a slow upgrade process by breaking it up into smaller chunk.
*
* @return TRUE on success
* @throws Exception
public function upgrade_4202() {
$this->ctx->log->info('Planning update 4202'); // PEAR Log interface
$this->addTask(E::ts('Process first step'), 'processPart1', $arg1, $arg2);
$this->addTask(E::ts('Process second step'), 'processPart2', $arg3, $arg4);
$this->addTask(E::ts('Process second step'), 'processPart3', $arg5);
return TRUE;
}
public function processPart1($arg1, $arg2) { sleep(10); return TRUE; }
public function processPart2($arg3, $arg4) { sleep(10); return TRUE; }
public function processPart3($arg5) { sleep(10); return TRUE; }
// */
/**
* Example: Run an upgrade with a query that touches many (potentially
* millions) of records by breaking it up into smaller chunks.
*
* @return TRUE on success
* @throws Exception
public function upgrade_4203() {
$this->ctx->log->info('Planning update 4203'); // PEAR Log interface
$minId = CRM_Core_DAO::singleValueQuery('SELECT coalesce(min(id),0) FROM civicrm_contribution');
$maxId = CRM_Core_DAO::singleValueQuery('SELECT coalesce(max(id),0) FROM civicrm_contribution');
for ($startId = $minId; $startId <= $maxId; $startId += self::BATCH_SIZE) {
$endId = $startId + self::BATCH_SIZE - 1;
$title = E::ts('Upgrade Batch (%1 => %2)', array(
1 => $startId,
2 => $endId,
));
$sql = '
UPDATE civicrm_contribution SET foobar = whiz(wonky()+wanker)
WHERE id BETWEEN %1 and %2
';
$params = array(
1 => array($startId, 'Integer'),
2 => array($endId, 'Integer'),
);
$this->addTask($title, 'executeSql', $sql, $params);
}
return TRUE;
} // */
}
This diff is collapsed.
<?php
namespace Civi\Api4;
/**
* ActionLink entity.
*
* Provided by the Action Links extension.
*
* @package Civi\Api4
*/
class ActionLink extends Generic\DAOEntity {
}
......@@ -473,5 +473,11 @@ function _actionlinks_civix_civicrm_alterSettingsFolders(&$metaDataFolders = NUL
function _actionlinks_civix_civicrm_entityTypes(&$entityTypes) {
$entityTypes = array_merge($entityTypes, array (
'CRM_Actionlinks_DAO_ActionLink' =>
array (
'name' => 'ActionLink',
'class' => 'CRM_Actionlinks_DAO_ActionLink',
'table' => 'civicrm_action_link',
),
));
}
<?php
// This file declares an Angular module which can be autoloaded
// in CiviCRM. See also:
// \https://docs.civicrm.org/dev/en/latest/hooks/hook_civicrm_angularModules/n
return array (
'js' =>
array (
0 => 'ang/actionlinksext.js',
1 => 'ang/actionlinksext/*.js',
2 => 'ang/actionlinksext/*/*.js',
),
'css' =>
array (
0 => 'ang/actionlinksext.css',
),
'partials' =>
array (
0 => 'ang/actionlinksext',
),
'requires' =>
array (
0 => 'crmUi',
1 => 'crmUtil',
2 => 'ngRoute',
),
'settings' =>
array (
),
);
/* Add any CSS rules for Angular module "actionlinksext" */
(function(angular, $, _) {
// Declare a list of dependencies.
angular.module('actionlinksext', CRM.angRequires('actionlinksext'));
})(angular, CRM.$, CRM._);
<div class="crm-container">
<h1 crm-page-title>{{ts('Action Links')}}</h1>
<div ng-if="!isLoaded">Loading...</div>
<div ng-if="isLoaded">
<div ng-if="view == 'list'">
<!-- Present a list of links -->
<table>
<thead>
<tr>
<th>Resource</th>
<th>Description</th>
<th>Active</th>
<th>Process</th>
<th>Use Count</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="row in actionLinks">
<td><a href="{{row.allowed_url}}" target="_blank" rel="noopener">{{row.allowed_url}}</a></td>
<td>{{row.description}}</td>
<td>{{row.is_active ? 'Active' : 'Inactive' }}</td>
<td>{{row.form_processor_name || '(None)'}}</td>
<td>{{row.use_count}}</td>
<td>
<a href ng-click="editRow(row)" >Edit</a>
<a href ng-click="deleteRow(row)" >Delete</a>
</td>
</tr>
</tbody>
</table>
<button class="btn" ng-click="editRow()" >Add Link</a>
</div>
<div ng-if="view == 'edit'">
<form name="editLinkForm" crm-ui-id-scope>
<div class="crm-block">
<div class="crm-group">
<div crm-ui-field="{name: 'editLinkForm.description', title: ts('Name')}">
<input
type="text"
crm-ui-id="editLinkForm.name"
name="name"
ng-model="editLinkForm.name"
class="crm-form-text"
/>
</div>
<div crm-ui-field="{name: 'myForm.description', title: ts('Description')}">
<textarea
crm-ui-id="myForm.description"
name="description"
ng-model="editData.description"
class="crm-form-text"
></textarea>
</div>
</div>
</div>
<div class="crm-block">
<button ng-click="saveRow()">{{ts('Save')}}</button>
</div>
</form>
</div>
</div>
</div>
(function(angular, $, _) {
angular.module('actionlinksext').config(function($routeProvider) {
$routeProvider.when('/actionlinks', {
controller: 'ActionLinksExtAdmin',
templateUrl: '~/actionlinksext/Admin.html',
// If you need to look up data when opening the page, list it out
// under "resolve".
// resolve: {}
});
}
);
// The controller uses *injection*. This default injects a few things:
// $scope -- This is the set of variables shared between JS and HTML.
// crmApi, crmStatus, crmUiHelp -- These are services provided by civicrm-core.
angular.module('actionlinksext').controller('ActionLinksExtAdmin', function($scope, crmApi, crmStatus, crmUiHelp) {
// The ts() and hs() functions help load strings for this module.
var ts = $scope.ts = CRM.ts('actionlinks');
//var hs = $scope.hs = crmUiHelp({file: 'CRM/actionlinksext/ActionLinksExtAdmin'}); // See: templates/CRM/actionlinksext/ActionLinksExtAdmin.hlp
$scope.isLoaded = false;
$scope.view = 'list';
$scope.actionLinks = [];
// We have myContact available in JS. We also want to reference it in HTML.
function resetEditData() {
$scope.editData = {
id: '',
description: '',
allowed_url: '',
name: '',
is_active: '',
use_limit: '',
contact_required: false,
use_by: '',
denied_url: '',
form_processor_name: '',
form_processor_params: '',
};
}
function reloadData() {
}
$scope.editRow = function editRow(row) {
resetEditData();
if (row !== undefined) {
$scope.editData = Object.assign($scope.editData, row);
}
$scope.view = 'edit';
};
$scope.deleteRow = function deleteRow(row) {
if (confirm("Delete " + row.name + "? This will break any links to this item that have been published.")) {
console.warn("deleteRow @todo");
}
};
$scope.saveRow = function saveRow() {
console.warn("saveRow @todo");
return;
return crmStatus(
// Status messages. For defaults, just use "{}"
{start: ts('Saving...'), success: ts('Saved')},
// The save action. Note that crmApi() returns a promise.
crmApi('Contact', 'create', {
id: myContact.id,
first_name: myContact.first_name,
last_name: myContact.last_name
})
);
};
resetEditData();
});
})(angular, CRM.$, CRM._);
{htxt id="full_name"}
{ts}The contact name should be divided in two parts, the first name and last name.{/ts}
{/htxt}
<?php
// This file declares a new entity type. For more details, see "hook_civicrm_entityTypes" at:
// https://docs.civicrm.org/dev/en/latest/hooks/hook_civicrm_entityTypes
return array (
0 =>
array (
'name' => 'ActionLink',
'class' => 'CRM_Actionlinks_DAO_ActionLink',
'table' => 'civicrm_action_link',
),
);
<?xml version="1.0" encoding="iso-8859-1" ?>
<table>
<base>CRM/Actionlinks</base>
<class>ActionLink</class>
<name>civicrm_action_link</name>
<comment>Holds action links from the Action Links Extension</comment>
<log>false</log>
<field>
<name>id</name>
<type>int unsigned</type>
<required>true</required>
<comment>Unique ActionLink ID</comment>
</field>
<primaryKey>
<name>id</name>
<autoincrement>true</autoincrement>
</primaryKey>
<field>
<name>name</name>
<type>varchar</type>
<length>255</length>
<comment>Administrative name</comment>
</field>
<field>
<name>description</name>
<type>text</type>
<comment>Description</comment>
<required>false</required>
</field>
<field>
<name>is_active</name>
<type>boolean</type>
<comment>Whether this link is active.</comment>
<default>0</default>
</field>
<field>
<name>allowed_url</name>
<type>varchar</type>
<length>255</length>
<comment>The URL you would normally redirect to</comment>
</field>
<field>
<name>denied_url</name>
<type>varchar</type>
<length>255</length>
<comment>The URL to redirect to if not allowed</comment>
</field>
<field>
<name>contact_required</name>
<type>boolean</type>
<comment>Must we be able to identify a valid contact</comment>
<default>1</default>
</field>
<field>
<name>form_processor_name</name>
<type>varchar</type>
<length>255</length>
<comment>The name of the form processor to trigger.</comment>
<required>false</required>
</field>
<field>
<name>form_processor_params</name>
<type>text</type>
<comment>JSON parameters (object of simple key:value pairs) for the form processor</comment>
<required>false</required>
<serialize>JSON</serialize>
</field>
<field>
<name>use_count</name>
<type>int unsigned</type>
<default>0</default>
</field>
<field>
<name>use_limit</name>
<type>int unsigned</type>
<required>false</required>
<comment>Access denied after this many uses</comment>
</field>
<field>
<name>use_by</name>
<type>datetime</type>
<required>false</required>
<comment>Access denied after this</comment>
</field>
</table>
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment