Zend Regex route reverse with paginator - regex

I have following regex route, which allows me to use pagination - to parse URL and also build it:
; route "product-{brand}"
product.type = "Zend_Controller_Router_Route_Regex"
product.route = "product-([a-z\-]+)(?:/page/(\d+)/?)?"
product.defaults.module = "default"
product.defaults.controller = "products"
product.defaults.action = "product"
product.defaults.page = "1"
product.map.1 = "brand"
product.map.2 = "page"
product.reverse = "product-%s/page/%d"
Everything is working fine, however, I need to get the rid of default page. Currently we are migrating old web to the Zend and we need to preserve old links because of current google positions, etc.
With default "page", I'm getting always /page/1, without it Zend "cannot assemble" URL.
How to not display page 1 in URL ?

Finally, I've managed to achieve this, but only by rewriting Regex assemble method.
I'm simply overriding two methods.
Class extension:
class Utils_Router_Regex extends Zend_Controller_Router_Route_Regex
{
// instantiate
public static function getInstance(Zend_Config $config)
{
$defs = ($config->defaults instanceof Zend_Config) ? $config->defaults->toArray() : array();
$map = ($config->map instanceof Zend_Config) ? $config->map->toArray() : array();
$reverse = (isset($config->reverse)) ? $config->reverse : null;
return new self($config->route, $defs, $map, $reverse);
}
// in this case, we are using $this->_reverse as array from config
public function assemble($data = array(), $reset = false, $encode = false, $partial = false)
{
//// EXTENSION PART !!!
if( !isset( $data[(string) $this->_reverse->pagemap]) ) { // if not set url helper
$reverse = $this->_reverse->base;
} else { // if set in url helper
$reverse = $this->_reverse->paginator;
}
/// end of extension part
if ($reverse === null) {
require_once 'Zend/Controller/Router/Exception.php';
throw new Zend_Controller_Router_Exception('Cannot assemble. Reversed route is not specified.');
}
$defaultValuesMapped = $this->_getMappedValues($this->_defaults, true, false);
$matchedValuesMapped = $this->_getMappedValues($this->_values, true, false);
$dataValuesMapped = $this->_getMappedValues($data, true, false);
// handle resets, if so requested (By null value) to do so
if (($resetKeys = array_search(null, $dataValuesMapped, true)) !== false) {
foreach ((array) $resetKeys as $resetKey) {
if (isset($matchedValuesMapped[$resetKey])) {
unset($matchedValuesMapped[$resetKey]);
unset($dataValuesMapped[$resetKey]);
}
}
}
// merge all the data together, first defaults, then values matched, then supplied
$mergedData = $defaultValuesMapped;
$mergedData = $this->_arrayMergeNumericKeys($mergedData, $matchedValuesMapped);
$mergedData = $this->_arrayMergeNumericKeys($mergedData, $dataValuesMapped);
if ($encode) {
foreach ($mergedData as $key => &$value) {
$value = urlencode($value);
}
}
ksort($mergedData);
$return = #vsprintf($reverse, $mergedData);
if ($return === false) {
require_once 'Zend/Controller/Router/Exception.php';
throw new Zend_Controller_Router_Exception('Cannot assemble. Too few arguments?');
}
return $return;
}
}
Then you can define which sprintf string to use:
hodinky.type = "Utils_Router_Regex"
hodinky.route = "hodinky-([a-z\-]+)(?:/page/(\d+)/?)?"
hodinky.defaults.module = "default"
hodinky.defaults.controller = "products"
hodinky.defaults.action = "hodinky"
hodinky.map.1 = "znacka"
hodinky.map.2 = "page"
hodinky.reverse.paginator = "hodinky-%s/page/%d" ; assebmly with paginator
hodinky.reverse.base = "hodinky-%s/" ; assebmly without paginator
hodinky.reverse.pagemap = "page" ; "page" map key
If you have better solution, please let me know.

Related

Hot to use variable in query in Drupal 8?

I have this code:
function my_module_test($key_make = '') {
$db = new mysqli('xxx', 'xxx', 'xxx', "xxx");
mysqli_set_charset($db, "UTF8");
if ($key_make) {
$sql_model = "SELECT * FROM `car_model` WHERE `id_car_make` = ('$key_make')";
$res_model = $db->query($sql_model) or die(mysqli_error($db));
while ($row = mysqli_fetch_object($res_model)) {
$Key_model = $row->id_car_model;
$Model_value = $row->name;
$dropdown_model[$Key_model] = $Model_value;
}
}
return $dropdown_model;
}
How can I pass the value of the variable $key_make in WHERE clausole ?
The query function takes a second parameter with an array of replacement values, so you would do it like this:
$sql_model = "SELECT * FROM {car_model} WHERE id_car_make = :make";
$res_model = $db->query($sql_model, [':make' => $key_make]);
Static queries are documented here
You could also use a dynamic query (documented here):
$query = $db->select('car_model', 'cm');
$query->fields('cm');
$query->condition('cm.id_car_make', $key_make);
$res_model = $query->execute();
But...
if your "car_model"s are custom entities (which they should be as you will get many benefits like views integration), you should probably use an entityQuery
First you need to use the Drupal Database API to connect to a database. So my final code is the following and it works.
function car2db_model_dropdown_options($key_make) {
$connection = Database::getConnection('default', 'migrate');
$dropdown_model = ['_none'=>'Select'];
$key_make = (int)$key_make;
$sql_model = "SELECT * FROM car_model WHERE id_car_make = :make";
$query = $connection->query($sql_model, [':make' => $key_make]);
$result = $query->fetchAll();
foreach ($result as $row) {
$Key_model = $row->id_car_model;
$Model_value = $row->name;
$dropdown_model[$Key_model] = $Model_value;
}
return $dropdown_model;
}

Search in agresso Query Engine

Is it possible to search/filter on columns with Agresso's QueryEngineService? I've been playing around with SearchCriteria.SearchCriteriaPropertiesList and TemplateResultOptions.Filter but without any luck. I havn't been able to locate any documentation on this matter either.
QueryEngineService.TemplateList templateList = QueryEngineService.GetTemplateList(null, null, Credentials);
var template = templateList.TemplateHeaderList.FirstOrDefault(x => x.Name == strViewName);
if (template == null)
return null;
QueryEngineService.SearchCriteria searchProp = QueryEngineService.GetSearchCriteria(template.TemplateId, false, Credentials);
QueryEngineService.TemplateResultOptions options = QueryEngineService.GetTemplateResultOptions(Credentials);
options.RemoveHiddenColumns = true;
QueryEngineService.InputForTemplateResult input = new QueryEngineService.InputForTemplateResult();
input.TemplateResultOptions = options;
input.TemplateId = template.TemplateId;
input.SearchCriteriaPropertiesList = searchProp.SearchCriteriaPropertiesList;
QueryEngineService.TemplateResultAsDataSet result = QueryEngineService.GetTemplateResultAsDataSet(input, Credentials);
return result.TemplateResult;
You can try to start with this:
List<SearchCriteriaProperties> searchCriteriaProperties = searchCriteria.getSearchCriteriaPropertiesList().getSearchCriteriaProperties();
SearchCriteriaProperties columnFilter = null;
for (SearchCriteriaProperties criteria : searchCriteriaProperties) {
if(criteria.getColumnName().equalsIgnoreCase("ColumnNameHere")) {
columnFilter = criteria;
columnFilter.setRestrictionType("=");
columnFilter.setFromValue("valueToAssign");
}
}
Next is add the columnFilter variable to an instance of the ArrayOfSearchCriteriaProperties() object by using the getSearchCriteriaProperties().add()
ArrayOfSearchCriteriaProperties filter = new ArrayOfSearchCriteriaProperties();
filter.getSearchCriteriaProperties().add(columnFilter);
You can now add the filter object to an instance of the InputForTemplateResult() object.
Working solution (for me)
QueryEngineService.SearchCriteria searchProp = QueryEngineService.GetSearchCriteria(template.TemplateId, false, Credentials);
foreach (QueryEngineService.SearchCriteriaProperties criteria in searchProp.SearchCriteriaPropertiesList)
{
if(criteria.ColumnName.Equals("column_name", StringComparison.OrdinalIgnoreCase))
{
criteria.RestrictionType = "=";
criteria.FromValue = "value";
}
}
//Rest of the code from question above

How to add dynamic values to field injections list with custom trigger to camunda properties panel?

I have two questions here
Is it possible to add dynamic lists values to field injection list input ?
Can I create a trigger for this so this can be initiated from any other input selection say a class selection will populate all fields
I was just looking into FieldInjection.js whether that can be extented for the same
Can someone please provide a hint or direction for this ?
Thanks.
For anyone interested in the answer, I was able to achieve the above goal by changing the set function of the Java Class select input as folllowing
few imports
var extensionElementsHelper = require('../../../../helper/ExtensionElementsHelper'),
elementHelper = require('../../../../helper/ElementHelper')
var CAMUNDA_FIELD_EXTENSION_ELEMENT = 'camunda:Field';
function getExtensionFields(bo) {
return bo && extensionElementsHelper.getExtensionElements(bo, CAMUNDA_FIELD_EXTENSION_ELEMENT) || [];
}
then changing the set function to create extension element and push the field values as :
set: function(element, values, node) {
var bo = getBusinessObject(element);
var type = getImplementationType(element);
var attr = getAttribute(type);
var prop = {}
var commands = [];
prop[attr] = values.delegate || '';
var extensionElements = getExtensionFields(bo);
//remove any extension elements existing before
extensionElements.forEach(function(ele){
commands.push(extensionElementsHelper.removeEntry(getBusinessObject(element), element, ele));
});
if(prop[attr] !== ""){
var extensionElements = elementHelper.createElement('bpmn:ExtensionElements', { values: [] }, bo, bpmnFactory);
commands.push(cmdHelper.updateBusinessObject(element, bo, { extensionElements: extensionElements }));
var arrProperties = ["private org.camunda.bpm.engine.delegate.Expression com.cfe.extensions.SampleJavaDelegate.varOne","private org.camunda.bpm.engine.delegate.Expression com.cfe.extensions.SampleJavaDelegate.varTwo"]
var newFieldElem = "";
arrProperties.forEach(function(prop){
var eachProp = {
name:"",
string:"",
expression:""
}
var type = prop.split(" ")[1].split(".").reverse()[0];
var val = prop.split(" ")[2].split(".").reverse()[0];
eachProp.name = val;
if( type == "String"){
eachProp.string = "${" + val +" }"
}else if( type == "Expression"){
eachProp.expression = "${" + val +" }"
}
newFieldElem = elementHelper.createElement(CAMUNDA_FIELD_EXTENSION_ELEMENT, eachProp, extensionElements, bpmnFactory);
commands.push(cmdHelper.addElementsTolist(element, extensionElements, 'values', [ newFieldElem ]));
});
}
commands.push(cmdHelper.updateBusinessObject(element, bo, prop));
return commands;
}
Cheers !.

SPAlert.Filter not working

Can anybody help with SPAlert filters on Sharepoint 2013?
If I set Filter property on SPAlert instance the alert has not been sent
SPAlert newAlert = user.Alerts.Add();
SPAlertTemplateCollection alertTemplates = new SPAlertTemplateCollection(
(SPWebService)(SPContext.Current.Site.WebApplication.Parent));
newAlert.AlertType = SPAlertType.List;
newAlert.List = list;
newAlert.Title = alertTitle;
newAlert.DeliveryChannels = SPAlertDeliveryChannels.Email;
newAlert.EventType = eventType;
newAlert.AlertFrequency = SPAlertFrequency.Immediate;
newAlert.AlertTemplate = alertTemplates[Constants.AlertTemplates.GenericListCustom];
var wsm = new WorkflowServicesManager(web);
var wss = wsm.GetWorkflowSubscriptionService();
var subscriptions = wss.EnumerateSubscriptionsByList(list.ID);
bool assotiationExist = false;
var guid = Constants.Workflows.ApprovalWF.Guid;
foreach (var subs in subscriptions)
{
assotiationExist = subs.DefinitionId == guid;
if (assotiationExist)
{
newAlert.Filter = "<Query><Eq><FieldRef Name=\"ApprovalStatus\"/><Value type=\"string\">Approved</Value></Eq></Query>";
}
}
newAlert.Update(false);
If I set Filter property on SPAlert instance the alert has not been sent
What do you need exactly ?
If you just want to change the filter (alert condition), did you simply try :
newAlert.AlertType = SPAlertType.List;
newAlert.List = list;
newAlert.Title = alertTitle;
newAlert.DeliveryChannels = SPAlertDeliveryChannels.Email;
newAlert.EventType = eventType;
newAlert.AlertFrequency = SPAlertFrequency.Immediate;
newAlert.AlertTemplate = alertTemplates[Constants.AlertTemplates.GenericListCustom];
newAlert.Filter = "<Query><Eq><FieldRef Name=\"ApprovalStatus/New\"/><Value type=\"string\">Approved</Value></Eq></Query>";
newAlert.Update(false);
I have just added a /New in your filter query. Query filter in alert need to get a /New or a /Old in your field.
If your alert still doesn't work, it might be something else than the filter.
The problem was in line newAlert.EventType = eventType. eventType was SPEventType.Add. That was the reason of not sending alert after Workflow set the ApprovalStatus field to «Approved».
I’ve modified algourithm. Now eventType is SPEventType.Modify and I added new field "IsNewAlertSent" to list. When event fires the first time then I send email and set the "IsNewAlertSent" field
Final code is shown below.
class UserAlertManager:
..
newAlert.EventType = (eventType == SPEventType.Add? SPEventType.Modify: eventType);
newAlert.AlertFrequency = SPAlertFrequency.Immediate;
newAlert.AlertTemplate = alertTemplates[Constants.AlertTemplates.GenericListCustom];
..
if (assotiationExist)
{
newAlert.Filter = "<Query><Eq><FieldRef name=\"ApprovalStatus\"/><Value type=\"Text\">Approved</Value></Eq></Query>";
newAlert.Properties.Add("grcustomalert", "1");
}
..
newAlert.Update(false);
class GRCustomAlertHandler:
...
string subject = string.Empty;
string body = string.Empty;
bool grCustomAlert = Utils.IsSPAlertCustom(ahp.a);
if (ahp.eventData[0].eventType == (int)SPEventType.Modify && grCustomAlert)
{
SPListItem item = list.GetItemById(ahp.eventData[0].itemId);
var isNewAlertSentField = item.Fields.GetFieldByInternalName(Constants.Fields.IsNewAlertSent);
if (isNewAlertSentField != null && (item[Constants.Fields.IsNewAlertSent] == null || !(bool)item[Constants.Fields.IsNewAlertSent]))
{
...
Utils.SendMail(web, new List<string> { ahp.headers["to"].ToString() }, subject, body);
item[Constants.Fields.IsNewAlertSent] = true;
using (new DisabledItemEventScope())
{
item.SystemUpdate(false);
}
}
}
...

how to add product to cart in opencart

Below is add to product code . But I am not getting where the values are storing . Kindly help to find out solution for this . I want to know logic behind this code
public function add($product_id, $qty = 1, $option = array(), $recurring_id = 0) {
$this->data = array();
$product['product_id'] = (int)$product_id;
if ($option) {
$product['option'] = $option;
}
if ($recurring_id) {
$product['recurring_id'] = (int)$recurring_id;
}
$key = base64_encode(serialize($product));
if ((int)$qty && ((int)$qty > 0)) {
if (!isset($this->session->data['cart'][$key])) {
$this->session->data['cart'][$key] = (int)$qty;
} else {
$this->session->data['cart'][$key] += (int)$qty;
}
}
}
The product details with options are stored in $key = base64_encode(serialize($product));. Where $this->session->data['cart'][$key] contains the number of quantity added by the customer.
For more details check the getProducts() function on the same page. Where you can find
foreach ($this->session->data['cart'] as $key => $quantity) {
....
$product = unserialize(base64_decode($key));
....
}