Sugarcrm支持产品指南糖开发人员糖开发人员指南11.0建筑学糖逻辑延长糖逻辑

# 延长糖逻辑

## 编写自定义公式功能

The most important feature of Sugar Logic is that it is simply and easily extendable. Both custom formula functions and custom actions can be added in an upgrade-safe manner to allow almost any custom logic to be added to Sugar. Custom functions will be stored in `./custom/include/Expressions/Expression/{Type}/{Function_Name}.php`.

The first step in writing a custom function is to decide what category the function falls under. Take, for example, a function for calculating the factorial of a number. In this case, we will be returning a number so we will create a file in `./custom/include/Expressions/Expression/Numeric/` called `FactorialExpression.php`. In the new PHP file we just created, we will define a class called `FactorialExpression` that will extend `NumericExpression`. All formula functions must follow the format `{functionName}Expression.php` and the class name must match the file name.

Next, we need to decide what parameters the function will accept. In this case, we need take in a single parameter, the number to return the factorial of. Since this class will be a sub-class of `NumericExpression`, it by default accepts only numeric types and we do not need to worry about specifying the type requirement.

Next, we must define the logic behind evaluating this expression. So we must override the abstract `evaluate()` function. The parameters can be accessed by calling an internal function `getParameters()` which returns the parameters passed into this object. So, with all this information, we can go ahead and write the code for the function.

``````<?php

require_once 'include/Expressions/Expression/Numeric/NumericExpression.php';

class FactorialExpression extends NumericExpression
{
function evaluate()
{
\$params = \$this->getParameters();
// params is an Expression object, so evaluate it
// to get its numerical value
\$number = \$params->evaluate();
// exception handling
if ( ! is_int( \$number ) )
{
throw new Exception("factorial: Only accepts integers");
}

if ( \$number < 0 )
{
throw new Exception("factorial: The number must be positive");
}

// special case 0! = 1
if ( \$number == 0 ) return 1;

// calculate the factorial
\$factorial = 1;
for ( \$i = 2 ; \$i <= \$number ; \$i ++ )
{
\$factorial = \$factorial * \$i;
}

return \$factorial;
}

// Define the javascript version of the function
static function getJSEvaluate()
{
return <<<EOQ
var params = this.getParameters();
var number = params.evaluate();
// reg-exp integer test
if ( ! /^\d*\$/.test(number) )
throw "factorial: Only accepts integers";

if ( number < 0 )
throw "factorial: The number must be postitive";
// special case, 0! = 1
if ( number == 0 ) return 1;
// compute factorial
var factorial = 1;

for ( var i = 2 ; i <= number ; i ++ )
factorial = factorial * i;

return factorial;
EOQ;
}

function getParameterCount()
{
return 1; // we only accept a single parameter
}

static function getOperationName()
{
return "factorial";
// our function can be called by 'factorial'
}
}

?>``````

One of the key features of Sugar Logic is that the functions should be defined in both PHP and JavaScript and have the same functionality under both circumstances. As you can see above, the `getJSEvaluate()` method should return the JavaScript equivalent of your `evaluate()` method. The JavaScript code is compiled and assembled for you after you run the "Rebuild Sugar Logic Functions" script through Admin > Schedulers.

### 写一个自定义行动

Using custom actions, you can easily create reusable custom logic or integrations that can include user-editable logic using the Sugar Formula Engine. Custom actions will be stored in `./custom/include/Expressions/Actions/{ActionName}.php`. Actions files must end in `Action.php` and the class defined in the file must match the file name and extend the `AbstractAction` class. The basic functions that must be defined are `fire`, `getDefinition`, `getActionName`, `getJavascriptClass`, and `getJavscriptFire`. Unlike functions, there is no requirement that an action works exactly the sameÂ for both server and client side as this is not always sensible or feasible.

A simple action could be "WarningAction" that shows an alert warning the user that something may be wrong and logs a message to the `./sugarcrm.log` file if triggered on the server side. It will take in a message as a formula so that the message can be customized at runtime. We would do this by creating a PHP file in `./custom/include/expressions/actions/warningaction.php.` as shown below:

./custom/include/expressions/actions/warningaction.php.

``````<?php

require_once("include/Expressions/Actions/AbstractAction.php");

class WarningAction extends AbstractAction    {

protected \$messageExp = "";

/**
* Returns the javascript class equavalent to this php class
* @return string javascript.
*/
static function getJavascriptClass()
{
return <<<EOQ

SUGAR.forms.WarningAction = function(message)
{
this.messageExp = message;
};

//Use the sugar extend function to extend AbstractAction
SUGAR.util.extend(SUGAR.forms.WarningAction, SUGAR.forms.AbstractAction,
{
//javascript exection code
exec : function()
{
//assume the message is a formula
var msg = SUGAR.forms.evalVariableExpression(this.messageExp);
alert(msg.evaluate());
}
});
EOQ;
}

/**
* Returns the javascript code to generate this actions equivalent.
* @return string javascript.
*/

function getJavascriptFire()
{
return "new SUGAR.forms.WarningAction('{\$this->messageExp}')";
}

/**
* Applies the Action to the target.
* @param SugarBean \$target
*/
function fire(&\$target)
{
//Parse the message formula and log it to fatal.
\$expr = Parser::replaceVariables(\$this->messageExp, \$target);
\$result = Parser::evaluate(\$expr)->evaluate();
\$GLOBALS['log']->warn(\$result);
}

/**
* Returns the definition of this action in array format.
*/
function getDefinition()
{
return array("message" => \$this->messageExp);
}

/**
* Returns the short name used when defining dependencies that use this action.
*/
static function getActionName()
{
return "Warn";
}
}

?>``````