How to use WHMCS Local api (internal API) - api

How to use WHMCS LocalAPI (InternaAPI)
Hi
I have a problem to use WHMCS LocalAPI
WHMCS Documentation is very poor and unclear about this problem
when I run this code a blank page appear and any thing is happened
<?php
require('../init.php');
require('../includes/api.php');
$command = 'AddOrder';
$postData = array(
'clientid' => '1',
'domain' => array('domain1.com'),
'billingcycle' => array('annually'),
'domaintype' => array('register',),
'regperiod' => array(1),
'nameserver1' => 'ns1.demo.com',
'nameserver2' => 'ns2.demo.com',
'paymentmethod' => 'zarinpalgw',
);
$adminUsername = 'myadminname'; // Optional for WHMCS 7.2 and later
$results = localAPI($command, $postData, $adminUsername);
print_r($results);
?>
I expected to add order after run this code
External API is very slow and not suitable for me for some reason such as
I have a dynamic IP and External API work with static IP because IP must be recognize in WHMCS->General setting->Security

The Internal API code in your example looks like it should work. Temporarily enabling PHP errors can help narrow down the exact cause of this issue (Setup > General Settings > Other > Display Errors), although I believe it is due to the way you are initializing the WHMCS environment in your PHP file.
WHMCS provides specific guidelines on building custom pages, which appears to be what you were trying to do in the example provided. Custom PHP files must be located in the root WHMCS directory, however require('../init.php'); indicates that your script is currently inside a subdirectory. You also should not be requiring api.php, as that is already being handled by init.php. Moving your script to the WHMCS root directory and commenting out the require('../includes/api.php'); line should hopefully fix the blank page issue.
Please note: the example you provided does not display the normal WHMCS client interface and does not check to see if the user is logged in. If that is functionality you will be needing as well, you can create a page with the same interface and functionality as a native WHMCS client area page. The following is a slightly modified version of the example code WHMCS provides in their guide for creating client area pages:
<?php
// Define WHMCS namespaces
use WHMCS\ClientArea;
use WHMCS\Database\Capsule;
// Initialize WHMCS client area
define('CLIENTAREA', true);
require __DIR__ . '/init.php';
$ca = new ClientArea();
$ca->setPageTitle('Your Page Title Goes Here');
$ca->addToBreadCrumb('index.php', Lang::trans('globalsystemname'));
$ca->addToBreadCrumb('mypage.php', 'Your Custom Page Name');
$ca->initPage();
// Uncomment to require a login to access this page
//$ca->requireLogin();
// Uncomment to assign variables to the template system
//$ca->assign('variablename', $value);
// Code to run when the current user IS logged in
if ($ca->isLoggedIn()) {
$clientName = Capsule::table('tblclients')->where('id', '=', $ca->getUserID())->pluck('firstname');
$ca->assign('clientname', $clientName);
// Code to run when the current user is NOT logged in
} else {
$ca->assign('clientname', 'Random User');
}
// Setup the primary and secondary sidebars
Menu::addContext();
Menu::primarySidebar('announcementList');
Menu::secondarySidebar('announcementList');
// Define the template filename to be used (without the .tpl extension)
$ca->setTemplate('mypage');
// Display the contents of the page (generated by the Smarty template)
$ca->output();

Related

How to move Laravel Events into subdirectories and still have them work when broadcasting?

I've moved my Laravel Events into subdirectories, and now my broadcasted messages are not being received. Pusher shows them ok, and if I move them out of the subdirectories then they work as expected, so I believe this is a namespacing issue, but I cannot figure out how to make it work.
The Event I'm focusing on is called TeamInvitationEvent and is located in the Events->Company->Memberships directory.
Here is my Listener:
public function getListeners()
{
$user_id = Auth::id();
return [
'refresh-navigation-top-menu' => '$refresh',
"echo-private:user.{$user_id},TeamInvitationEvent" => 'notifyInvitation',
"echo-private:user.{$user_id},TeamInvitationCancelledEvent" => 'notifyInvitationCancelled',
"echo-private:user.{$user_id},TeamInvitationAcceptedEvent" => 'notifyInvitationAccepted',
"echo-private:user.{$user_id},TeamMemberRemovedEvent" => 'notifyMemberRemoved',
];
}
Here is a screenshot of my Pusher debug console, showing that the user is subscribed to the correct private channel, and that the API Message is being broadcast on that channel:
Here is a list of different ways I've tried to correct for the new namespace:
App.Events.Company.Memberships.TeamInvitationEvent
App\Events\Company\Memberships\TeamInvitationEvent
/App/Events/Company/Memberships/TeamInvitationEvent
.TeamInvitationEvent
There are no errors in the Laravel logs, or in the Pusher logs, and as I mentioned it works as expected if I don't move them into the subdirectory.
I'm running the following in my app:
Laravel v8
Livewire v2
Laravel Echo v1
Pusher
This was embarrassingly obvious, but here's what fixed it:
"echo-private:user.{$user_id},Company\Memberships\TeamInvitationEvent" => 'notifyInvitation'
The docs are very clear that "App\Events" is prepended to all events, so naturally I just needed to add the rest of the namespace to get it working. I looked back and I had actually tried this earlier, but I must have forgot to clear the cache. Big shout-out to #joshhanley on the Livewire Discord chat for getting me sorted on this.
Side Note: using broadcastAs() made this much cleaner:
public function broadcastAs()
{
return 'team.invitation';
}
But don't forget to add a '.' before this custom name in your view, like this:
"echo-private:user.{$user_id},.team.invitation" => 'notifyInvitation'

Prestashop LOG: get DUMP of Object and Array

I am figuring out how Prestashop 1.7 works and I have some experience with Symfony.
In Symfony development mode [Symfony project url]/_profiler is useful, among other things, to check the dump($someVariable) of variables in a request.
With Prestashop 1.7 in the admin mode it is possible to do [Prestashop project url]/admin[some random chain of chars]/_profiler to display the Symfony _profiler and analyse what's going on in the requests concerning the admin mode.
But if outside the admin mode (in the virtual shop demo mode), [Prestashop project url]/_profiler or [Prestashop project url]/[language value]/_profiler does not display the Symfony _profiler.
I have tried Prestashop own profiler by activating define('_PS_DEBUG_PROFILING_', true); in [prestashop project]/config/defines.inc.php. It displays Prestashop profiler at the bottom of the "virtual shop demo mode" but this one does not include dump($someVariable) that could be used, for development and to understand Prestashop behaviour, in a hookAction[action name].
I've managed to get the Symfony dump($someVariable) with hookDisplay[display name] through the HTML generated but not in a hookAction[action name] which is what I am looking for.
UPDATE
Looking at Prestashop 1.7 code I almost have the feeling that Symfony is only used on the Admin side, because I can see:
$kernel = new AppKernel(_PS_MODE_DEV_?'dev':'prod', _PS_MODE_DEV_); in [Prestashop project url]/admin[some random chain of chars]/index.php but I don't see it in [Prestashop project url]/index.php.
Best solution I've found so far is to create a custom logger similar to the one explained here
I've created file: [Prestashop project]/modules/[my module]/classes/CustomLogger.php
<?php
class CustomLogger {
const DEFAULT_LOG_FILE ="prestashop_system.log";
public static function log($message, $level = 'debug', $fileName = null){
$fileDir = _PS_ROOT_DIR_ . '/log/';
$fileName=self::DEFAULT_LOG_FILE;
if(is_array($message) || is_object($message)){$message = print_r($message, true);}
$formatted_message=$level." -- ".date('Y/m/d - H:i:s').": ".$message."\r\n";
return file_put_contents($fileDir . $fileName, $formatted_message, FILE_APPEND);
}
}
?>
In '[Prestashop project]/modules/[my module]/[my module].php' it is declared at the top:
include_once dirname(__FILE__).'/classes/CustomLogger.php';
And use CustomLogger::log($[some variable]); in your code.

FPDM Merge Error extract_pdf_definition_value() does not support definition '/Type'

I'm trying to fill out my PDF document using FPDM with a script I found here:
http://www.fpdf.org/en/script/script93.php
First, keep in mind that I don't want to install any additional libraries on the shared hosting setup I am using. I would have to switch hosts to do this.
Here's what I've tried:
Downgrading my PDF template to Acrobat 5.x (v1.4)
Disabling compression and fast web mode
Using the paid version of PDFTK and the Advanced output params "%PDFTK% %PDFIN% output %PDFOUT%" to modify the template I'm using (this prevents the weird error about object streams)
Used variations of FDF files with a different method.
Successfully wrote out an HTML version of my PDF, but it didn't look like my template exactly
My code:
require('/libs/fpdm/fpdm.php');
$fields = array(
'dealer_name' => 'My name',
'dealer_address' => 'My address',
'dealer_phone' => 'My city',
);
$pdf = new FPDM('/some/pdf/filename.pdf');
$pdf->Load($fields, false);
$pdf->Merge();
$pdf->Output('someoutput.pdf', 'F');
The Error
The error that I cannot seem to find anywhere is the following:
<b>FPDF-Merge Error:</b> extract_pdf_definition_value() does not support definition '/Type'
The Question
Are there any other things I can do to my PDF or any other methods to make this work?
fpdm.php is quite old but can be fixed up. The problem is the global variables can't be accessed from within the class FPDM.
To resolve the issue, the global variables need to be moved inside the class as protected properties.
Step 1
Remove the following lines:
$FPDM_FILTERS=array(); //holds all supported filters
$FPDM_REGEXPS= array(
"/Type"=>"/\/Type\s+\/(\w+)$/",
"/Subtype" =>"/^\/Subtype\s+\/(\w+)$/"
);
Step 2
Put the following immediately after "class FPDM {", around line 65:
protected $FPDM_FILTERS = array(); //holds all supported filters
protected $FPDM_REGEXPS = array(
"/Type"=>"/\/Type\s+\/(\w+)$/",
"/Subtype" =>"/^\/Subtype\s+\/(\w+)$/"
);
Step 3
Delete all instances of global $FPDM_FILTERS; and global $FPDM_REGEXPS;.
Step 4
Update the remaining references (except the property declarations).
Change $FPDM_FILTERS to $this->FPDM_FILTERS
Change $FPDM_REGEXPS to $this->FPDM_REGEXPS
Step 5
To properly include filters from the filters/ directory, we need to move the includes into the class. Remove the require_once()s from the beginning of the file then add the following at the beginning of the constructor FPDM()
$FPDM_FILTERS = array();
//Major stream filters come from FPDI's stuff but I've added some :)
require_once("filters/FilterASCIIHex.php");
require_once("filters/FilterASCII85.php");
require_once("filters/FilterFlate.php");
require_once("filters/FilterLZW.php");
require_once("filters/FilterStandard.php");
$this->FPDM_FILTERS = $FPDM_FILTERS;

How can I get the Register form on the front page in Drupal 8?

I've been trying to get the create account form (register form) in a pop-up on the front page, without any success.
Can anybody here help me out with an example that works?
I've tried adapting examples from Drupal 7 but couldn't get them to work, I've tried to make a custom form but it didn't work, I've tried installing modules that could handle this but they also didn't work.
The last attempt I've made to resolve this problem was:
<?php
/**
* #file
* Functions to support theming in the themename theme.
*/
use Drupal\Core\Form\FormBase;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Component\Utility\UrlHelper;
/**
* Implements hook_preprocess_HOOK() for HTML document templates.
*/
function themename_preprocess_html(&$variables) {
$form = \Drupal::formBuilder()->getForm('Drupal\user\register');
return $form;
}
Any help would be greatly appreciated.
Thank you!
you can use this module: https://www.drupal.org/project/formblock which exposes some additional forms as blocks (like the user registration, new password, contact, etc..). So after you install it you can just configure the block to appear only on the front page. The registration block will not be available for authenticated users or if the anonymous users are not allowed to create new accounts.
However, you will also have to apply this patch https://www.drupal.org/node/2570221 (if it will not be already committed by the time you check it) if you use the latest Drupal8 stable version, otherwise you will get a fatal error.
This link explains how it can be used to programmatically render the login and registration forms.
http://web-tricks.org/content/how-render-user-login-form-and-user-register-form-drupal-8
For the login form
$form = Drupal::formBuilder()->getForm(Drupal\user\Form\UserLoginForm::class) ;
$render = Drupal::service('renderer');
$variables['login_form'] = $render->renderPlain($form);
and for register form
$entity = \Drupal::entityTypeManager()->getStorage('user')->create(array());
$formObject = \Drupal::entityTypeManager()
->getFormObject('user', 'register')->setEntity($entity);
$form = \Drupal::formBuilder()->getForm($formObject);
$variables['register_form'] = \Drupal::service('renderer')->render($form);

Is it possible to init AdminController from outside Prestashop?

I am trying to initiate the AdminController module from outside the Prestashop. Basically, I am creating an external program which uses Prestashop to get current employee for which I should instantiate the AdminController, but its throwing error.
Many modules init the FrontController but I cannot find any example for AdminController like :
include(dirname(__FILE__).'/../../config/config.inc.php');
include(dirname(__FILE__).'/../../init.php');
Please advice.
I found the solution after all. Simply define _PS_ADMIN_DIR_ and init the config.inc.php, Prestashop will automatically load the admin environment. However, if you are loading this from a module, its tricky to find the admin directory as its not defined anywhere, so I have written this small script.
$admindir = '';
foreach (glob("../../*/ajaxfilemanager", GLOB_ONLYDIR) as $filename) {
$admindir = str_replace('../../', '', $filename);
$admindir = str_replace('/ajaxfilemanager', '', $admindir);
}
define('_PS_ADMIN_DIR_', getcwd().'/../../'.$admindir);
require(_PS_ADMIN_DIR_.'/../config/config.inc.php');
Enjoy!