Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add manual extension #401

Open
wants to merge 3 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
667 changes: 667 additions & 0 deletions wp-content/civi-extensions/civirazorpay/LICENSE.txt

Large diffs are not rendered by default.

12 changes: 12 additions & 0 deletions wp-content/civi-extensions/civirazorpay/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# civirazorpay
(*FIXME: In one or two paragraphs, describe what the extension does and why one would download it. *)

This is an [extension for CiviCRM](https://docs.civicrm.org/sysadmin/en/latest/customize/extensions/), licensed under [AGPL-3.0](LICENSE.txt).

## Getting Started

(* FIXME: Where would a new user navigate to get started? What changes would they see? *)

## Known Issues

(* FIXME *)
201 changes: 201 additions & 0 deletions wp-content/civi-extensions/civirazorpay/civirazorpay.civix.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,201 @@
<?php

// AUTO-GENERATED FILE -- Civix may overwrite any changes made to this file

/**
* The ExtensionUtil class provides small stubs for accessing resources of this
* extension.
*/
class CRM_Civirazorpay_ExtensionUtil {
const SHORT_NAME = 'civirazorpay';
const LONG_NAME = 'civirazorpay';
const CLASS_PREFIX = 'CRM_Civirazorpay';

/**
* Translate a string using the extension's domain.
*
* If the extension doesn't have a specific translation
* for the string, fallback to the default translations.
*
* @param string $text
* Canonical message text (generally en_US).
* @param array $params
* @return string
* Translated text.
* @see ts
*/
public static function ts($text, $params = []): string {
if (!array_key_exists('domain', $params)) {
$params['domain'] = [self::LONG_NAME, NULL];
}
return ts($text, $params);
}
Comment on lines +27 to +32
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Add null safety check for ts() function.

The ts() function is called without verifying its existence, which could cause issues if the CiviCRM framework isn't properly initialized.

  public static function ts($text, $params = []): string {
+   if (!function_exists('ts')) {
+     return $text;
+   }
    if (!array_key_exists('domain', $params)) {
      $params['domain'] = [self::LONG_NAME, NULL];
    }
    return ts($text, $params);
  }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
public static function ts($text, $params = []): string {
if (!array_key_exists('domain', $params)) {
$params['domain'] = [self::LONG_NAME, NULL];
}
return ts($text, $params);
}
public static function ts($text, $params = []): string {
if (!function_exists('ts')) {
return $text;
}
if (!array_key_exists('domain', $params)) {
$params['domain'] = [self::LONG_NAME, NULL];
}
return ts($text, $params);
}


/**
* Get the URL of a resource file (in this extension).
*
* @param string|NULL $file
* Ex: NULL.
* Ex: 'css/foo.css'.
* @return string
* Ex: 'http://example.org/sites/default/ext/org.example.foo'.
* Ex: 'http://example.org/sites/default/ext/org.example.foo/css/foo.css'.
*/
public static function url($file = NULL): string {
if ($file === NULL) {
return rtrim(CRM_Core_Resources::singleton()->getUrl(self::LONG_NAME), '/');
}
return CRM_Core_Resources::singleton()->getUrl(self::LONG_NAME, $file);
}

/**
* Get the path of a resource file (in this extension).
*
* @param string|NULL $file
* Ex: NULL.
* Ex: 'css/foo.css'.
* @return string
* Ex: '/var/www/example.org/sites/default/ext/org.example.foo'.
* Ex: '/var/www/example.org/sites/default/ext/org.example.foo/css/foo.css'.
*/
public static function path($file = NULL) {
// return CRM_Core_Resources::singleton()->getPath(self::LONG_NAME, $file);
return __DIR__ . ($file === NULL ? '' : (DIRECTORY_SEPARATOR . $file));
}

/**
* Get the name of a class within this extension.
*
* @param string $suffix
* Ex: 'Page_HelloWorld' or 'Page\\HelloWorld'.
* @return string
* Ex: 'CRM_Foo_Page_HelloWorld'.
*/
public static function findClass($suffix) {
return self::CLASS_PREFIX . '_' . str_replace('\\', '_', $suffix);
}


}

use CRM_Civirazorpay_ExtensionUtil as E;

/**
* (Delegated) Implements hook_civicrm_config().
*
* @link https://docs.civicrm.org/dev/en/latest/hooks/hook_civicrm_config
*/
function _civirazorpay_civix_civicrm_config($config = NULL) {
static $configured = FALSE;
if ($configured) {
return;
}
$configured = TRUE;

$extRoot = __DIR__ . DIRECTORY_SEPARATOR;
$include_path = $extRoot . PATH_SEPARATOR . get_include_path();
set_include_path($include_path);
// Based on <compatibility>, this does not currently require mixin/polyfill.php.
}
Comment on lines +88 to +99
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Add error handling for include path modification.

The configuration function modifies the PHP include path without proper error handling.

  function _civirazorpay_civix_civicrm_config($config = NULL) {
    static $configured = FALSE;
    if ($configured) {
      return;
    }
    $configured = TRUE;

    $extRoot = __DIR__ . DIRECTORY_SEPARATOR;
    $include_path = $extRoot . PATH_SEPARATOR . get_include_path();
-   set_include_path($include_path);
+   if (!set_include_path($include_path)) {
+     throw new CRM_Core_Exception('Failed to set include path for extension');
+   }
  }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
function _civirazorpay_civix_civicrm_config($config = NULL) {
static $configured = FALSE;
if ($configured) {
return;
}
$configured = TRUE;
$extRoot = __DIR__ . DIRECTORY_SEPARATOR;
$include_path = $extRoot . PATH_SEPARATOR . get_include_path();
set_include_path($include_path);
// Based on <compatibility>, this does not currently require mixin/polyfill.php.
}
function _civirazorpay_civix_civicrm_config($config = NULL) {
static $configured = FALSE;
if ($configured) {
return;
}
$configured = TRUE;
$extRoot = __DIR__ . DIRECTORY_SEPARATOR;
$include_path = $extRoot . PATH_SEPARATOR . get_include_path();
if (!set_include_path($include_path)) {
throw new CRM_Core_Exception('Failed to set include path for extension');
}
// Based on <compatibility>, this does not currently require mixin/polyfill.php.
}


/**
* Implements hook_civicrm_install().
*
* @link https://docs.civicrm.org/dev/en/latest/hooks/hook_civicrm_install
*/
function _civirazorpay_civix_civicrm_install() {
_civirazorpay_civix_civicrm_config();
// Based on <compatibility>, this does not currently require mixin/polyfill.php.
}

/**
* (Delegated) Implements hook_civicrm_enable().
*
* @link https://docs.civicrm.org/dev/en/latest/hooks/hook_civicrm_enable
*/
function _civirazorpay_civix_civicrm_enable(): void {
_civirazorpay_civix_civicrm_config();
// Based on <compatibility>, this does not currently require mixin/polyfill.php.
}

/**
* Inserts a navigation menu item at a given place in the hierarchy.
*
* @param array $menu - menu hierarchy
* @param string $path - path to parent of this item, e.g. 'my_extension/submenu'
* 'Mailing', or 'Administer/System Settings'
* @param array $item - the item to insert (parent/child attributes will be
* filled for you)
*
* @return bool
*/
function _civirazorpay_civix_insert_navigation_menu(&$menu, $path, $item) {
// If we are done going down the path, insert menu
if (empty($path)) {
$menu[] = [
'attributes' => array_merge([
'label' => $item['name'] ?? NULL,
'active' => 1,
], $item),
];
return TRUE;
}
else {
// Find an recurse into the next level down
$found = FALSE;
$path = explode('/', $path);
$first = array_shift($path);
foreach ($menu as $key => &$entry) {
if ($entry['attributes']['name'] == $first) {
if (!isset($entry['child'])) {
$entry['child'] = [];
}
$found = _civirazorpay_civix_insert_navigation_menu($entry['child'], implode('/', $path), $item);
}
}
return $found;
}
}
Comment on lines +132 to +158
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Refactor navigation menu insertion for better maintainability.

The navigation menu insertion logic is complex and could benefit from being split into smaller, more focused methods. Also, parameter type hints are missing.

- function _civirazorpay_civix_insert_navigation_menu(&$menu, $path, $item) {
+ function _civirazorpay_civix_insert_navigation_menu(array &$menu, string $path, array $item): bool {

Consider extracting the recursive logic into a separate method:

private function _insert_menu_item(array &$entry, array $path_parts, array $item): bool {
  if (!isset($entry['child'])) {
    $entry['child'] = [];
  }
  return _civirazorpay_civix_insert_navigation_menu(
    $entry['child'],
    implode('/', $path_parts),
    $item
  );
}


/**
* (Delegated) Implements hook_civicrm_navigationMenu().
*/
function _civirazorpay_civix_navigationMenu(&$nodes) {
if (!is_callable(['CRM_Core_BAO_Navigation', 'fixNavigationMenu'])) {
_civirazorpay_civix_fixNavigationMenu($nodes);
}
}

/**
* Given a navigation menu, generate navIDs for any items which are
* missing them.
*/
function _civirazorpay_civix_fixNavigationMenu(&$nodes) {
$maxNavID = 1;
array_walk_recursive($nodes, function($item, $key) use (&$maxNavID) {
if ($key === 'navID') {
$maxNavID = max($maxNavID, $item);
}
});
_civirazorpay_civix_fixNavigationMenuItems($nodes, $maxNavID, NULL);
}

function _civirazorpay_civix_fixNavigationMenuItems(&$nodes, &$maxNavID, $parentID) {
$origKeys = array_keys($nodes);
foreach ($origKeys as $origKey) {
if (!isset($nodes[$origKey]['attributes']['parentID']) && $parentID !== NULL) {
$nodes[$origKey]['attributes']['parentID'] = $parentID;
}
// If no navID, then assign navID and fix key.
if (!isset($nodes[$origKey]['attributes']['navID'])) {
$newKey = ++$maxNavID;
$nodes[$origKey]['attributes']['navID'] = $newKey;
$nodes[$newKey] = $nodes[$origKey];
unset($nodes[$origKey]);
$origKey = $newKey;
}
if (isset($nodes[$origKey]['child']) && is_array($nodes[$origKey]['child'])) {
_civirazorpay_civix_fixNavigationMenuItems($nodes[$origKey]['child'], $maxNavID, $nodes[$origKey]['attributes']['navID']);
}
}
}
32 changes: 32 additions & 0 deletions wp-content/civi-extensions/civirazorpay/civirazorpay.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<?php

require_once 'civirazorpay.civix.php';

use CRM_Civirazorpay_ExtensionUtil as E;

/**
* Implements hook_civicrm_config().
*
* @link https://docs.civicrm.org/dev/en/latest/hooks/hook_civicrm_config/
*/
function civirazorpay_civicrm_config(&$config): void {
_civirazorpay_civix_civicrm_config($config);
}

/**
* Implements hook_civicrm_install().
*
* @link https://docs.civicrm.org/dev/en/latest/hooks/hook_civicrm_install
*/
function civirazorpay_civicrm_install(): void {
_civirazorpay_civix_civicrm_install();
}

/**
* Implements hook_civicrm_enable().
*
* @link https://docs.civicrm.org/dev/en/latest/hooks/hook_civicrm_enable
*/
function civirazorpay_civicrm_enable(): void {
_civirazorpay_civix_civicrm_enable();
}
41 changes: 41 additions & 0 deletions wp-content/civi-extensions/civirazorpay/info.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
<?xml version="1.0"?>
<extension key="civirazorpay" type="module">
<file>civirazorpay</file>
<name>civirazorpay</name>
<description>FIXME</description>
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Replace the FIXME placeholder with a proper description.

The description should clearly explain the purpose and functionality of this Razorpay payment processor extension for CiviCRM.

Example description:

-  <description>FIXME</description>
+  <description>Integrates Razorpay payment gateway with CiviCRM to enable secure online payments and donations through Razorpay's payment processing services.</description>
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<description>FIXME</description>
<description>Integrates Razorpay payment gateway with CiviCRM to enable secure online payments and donations through Razorpay's payment processing services.</description>

<license>AGPL-3.0</license>
<authors>
<author>
<name>tarunnjoshi</name>
<email>[email protected]</email>
<role>Maintainer</role>
</author>
</authors>
<urls>
<url desc="Main Extension Page">https://FIXME</url>
<url desc="Documentation">https://FIXME</url>
<url desc="Support">https://FIXME</url>
Comment on lines +16 to +18
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Replace FIXME URLs with actual documentation and support links.

The extension's documentation and support URLs are crucial for users. Consider:

  • Main Extension Page: Link to the extension's page on CiviCRM's extension directory
  • Documentation: Link to detailed usage instructions and configuration guide
  • Support: Link to issue tracker or support forum

Example URLs:

-    <url desc="Main Extension Page">https://FIXME</url>
-    <url desc="Documentation">https://FIXME</url>
-    <url desc="Support">https://FIXME</url>
+    <url desc="Main Extension Page">https://civicrm.org/extensions/civirazorpay</url>
+    <url desc="Documentation">https://github.com/ColoredCow/goonj/wiki/CiviRazorpay-Extension</url>
+    <url desc="Support">https://github.com/ColoredCow/goonj/issues</url>

Committable suggestion was skipped due to low confidence.

<url desc="Licensing">https://www.gnu.org/licenses/agpl-3.0.html</url>
</urls>
<releaseDate>2024-10-29</releaseDate>
<version>1.0.0</version>
<develStage>alpha</develStage>
<compatibility>
<ver>5.77</ver>
</compatibility>
<comments>This is a new, undeveloped module</comments>
<classloader>
<psr0 prefix="CRM_" path="."/>
<psr4 prefix="Civi\" path="Civi"/>
</classloader>
<civix>
<namespace>CRM/Civirazorpay</namespace>
<format>24.09.1</format>
<angularModule>crmCivirazorpay</angularModule>
</civix>
<mixins>
<mixin>[email protected]</mixin>
<mixin>[email protected]</mixin>
<mixin>[email protected]</mixin>
</mixins>
</extension>
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
<?php
/**

* - user_name_label, password_label, signature_label, subject_label - these
* are generally about telling the plugin what to call these when they pass
* them to Omnipay. They are also shown to users so some reformatting is done
* to turn it into lower-first-letter camel case. Take a look at the gateway
* file for your gateway. This is directly under src. Some provide more than
* one and the 'getName' function distinguishes them. The getDefaultParameters
* will tell you what to pass. eg if you see
* 'apiKey' you should enter 'user_name' => 'Api Key' (you might ? be able to
* get away with 'API Key' - need to check). You can provide as many or as few
* as you want of these and it's irrelevant which field you put them in but
* note that the signature field is the longest and that in future versions of
* CiviCRM hashing may be done on password and signature on the screen.
*
* - 'class_name' => 'Payment_OmnipayMultiProcessor', (always)
*
* - 'url_site_default' - this is ignored. But, by giving one you make it
* easier for people adding processors
*
* - 'billing_mode' - 1 = onsite, 4 = redirect offsite (including transparent
* redirects).
*
* - payment_mode - 1 = credit card, 2 = debit card, 3 = transparent redirect.
* In practice 3 means that billing details are gathered on-site so it may also
* be used with automatic redirects where address fields need to be mandatory
* for the signature.
*
* The record will be automatically inserted, updated, or deleted from the
* database as appropriate. For more details, see "hook_civicrm_managed" at:
* http://wiki.civicrm.org/confluence/display/CRMDOC/Hook+Reference
*/
return [
[
'name' => 'MyProcessor',
'entity' => 'payment_processor_type',
Comment on lines +36 to +37
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Update processor name and description to match implementation

The configuration contains generic placeholders that should be updated:

  • 'name' is set to 'MyProcessor' but should be 'Razorpay'
  • 'description' is set to 'My processor' but should provide meaningful information about the Razorpay payment integration

Apply this diff to fix the inconsistencies:

-    'name' => 'MyProcessor',
+    'name' => 'Razorpay',
     'entity' => 'payment_processor_type',
     'params' => [
       'version' => 3,
       'title' => 'Razorpay',
       'name' => 'Razorpay',
-      'description' => 'My processor',
+      'description' => 'Razorpay Payment Gateway integration for CiviCRM',

Also applies to: 40-42

'params' => [
'version' => 3,
'title' => 'Razorpay',
'name' => 'Razorpay',
'description' => 'My processor',
// this will cause the user to be presented with a field,
// when adding this processor, labelled
// api key which will save to civicrm_payment_processor.user_name
// on save
'user_name_label' => 'apiKey',
// as per user_name_label, but saves to password
'password_label' => 'secret',
// as per user_name_label, but saves to signature
'signature_label' => 'signature',
// prefix of CRM_Core is implicit so the class ie CRM_Core_Payment_MyProcessor
'class_name' => 'Payment_MyProcessor',
// Any urls you might need stored for the user to be redirect to, for example.
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Update class name to match Razorpay implementation

The class name still contains the generic placeholder 'MyProcessor' instead of the actual Razorpay implementation.

Apply this diff:

-      'class_name' => 'Payment_MyProcessor',
+      'class_name' => 'Payment_Razorpay',
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
'class_name' => 'Payment_MyProcessor',
// Any urls you might need stored for the user to be redirect to, for example.
'class_name' => 'Payment_Razorpay',
// Any urls you might need stored for the user to be redirect to, for example.

// Note it is quite common these days to hard code the urls in the processors
// as they are not necessarily seen as configuration. But, if you enter
// something here it will be the default for data entry.
'url_site_default' => 'https://example.com',
'url_api_default' => 'https://example.com',
Comment on lines +58 to +59
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Replace example.com with actual Razorpay API endpoints

The URLs are currently set to example.com placeholders. These should be updated to the actual Razorpay endpoints.

Apply this diff:

-      'url_site_default' => 'https://example.com',
-      'url_api_default' => 'https://example.com',
+      'url_site_default' => 'https://api.razorpay.com',
+      'url_api_default' => 'https://api.razorpay.com/v1',
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
'url_site_default' => 'https://example.com',
'url_api_default' => 'https://example.com',
'url_site_default' => 'https://api.razorpay.com',
'url_api_default' => 'https://api.razorpay.com/v1',

// this is a deprecated concept and these docs recommend you override
// anything that references it. However, if you redirect the user offsite
// enter 4 and if not enter 1 here.
'billing_mode' => 4,
// Generally 1 for credit card & 2 for direct debit. This will ideally
// become an option group at some point but also note that it's mostly
// or possibly only used from functions that this documentation recommends
// you override (eg. `getPaymentTypeLabel`)
'payment_type' => 1,
],
],
];