Skip to content

New module (BulkGate SMS) #4

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

Open
wants to merge 65 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
65 commits
Select commit Hold shift + click to select a range
340b737
gitignore
MartinKreizl Feb 4, 2025
7c0d4f9
initialize docker
MartinKreizl Feb 4, 2025
2a68424
initialize new module
MartinKreizl Feb 7, 2025
670dbf5
DI container
MartinKreizl Feb 7, 2025
8661bb3
DI...
MartinKreizl Feb 10, 2025
8b90a63
ajax - proxy
MartinKreizl Feb 11, 2025
ed54e59
debug page
MartinKreizl Feb 11, 2025
f2cf637
initialize events
MartinKreizl Feb 13, 2025
c8a3fac
events...
MartinKreizl Feb 13, 2025
c182a96
events...
MartinKreizl Feb 14, 2025
e276785
cartsms.hook.run + cartsms.hook.extension
MartinKreizl Feb 17, 2025
c04a035
rename event controllers
MartinKreizl Feb 17, 2025
22d3838
shop loader
MartinKreizl Feb 18, 2025
0ac486e
customer loader
MartinKreizl Feb 19, 2025
85c3302
order_status loader
MartinKreizl Feb 19, 2025
87cf9c4
order loader
MartinKreizl Feb 19, 2025
ecc0b73
product loader
MartinKreizl Feb 19, 2025
958f62e
employee (admin) loader
MartinKreizl Feb 20, 2025
f2f3da9
order_return loader
MartinKreizl Feb 20, 2025
d7dc5b5
loaders...
MartinKreizl Feb 20, 2025
f2d3af0
send-sms action
MartinKreizl Feb 20, 2025
e406819
menu
MartinKreizl Feb 20, 2025
7120ce2
send message
MartinKreizl Feb 23, 2025
ac0b233
fix variable
MartinKreizl Feb 23, 2025
98790a7
cron
MartinKreizl Feb 23, 2025
2157785
asynchronous asset
MartinKreizl Feb 23, 2025
8386ccc
permissions
MartinKreizl Feb 24, 2025
80df021
marketing message opt_in
MartinKreizl Feb 24, 2025
d0822c0
loaders
MartinKreizl Feb 26, 2025
36b1a61
distribution file
MartinKreizl Mar 3, 2025
1d19f16
hook pairs - state object
MartinKreizl Mar 4, 2025
8bc7b88
gate_url -> BulkGateWhiteLabelUrl
MartinKreizl Mar 4, 2025
b81ac79
customer loader tests
MartinKreizl Mar 7, 2025
9d5c0eb
add xdebug
MartinKreizl Mar 7, 2025
b35e8ec
phpstan
MartinKreizl Mar 7, 2025
336c4f8
customer loader tests
MartinKreizl Mar 10, 2025
ba1fd74
admin loader tests
MartinKreizl Mar 10, 2025
375fb88
extension loader tests
MartinKreizl Mar 10, 2025
1716afd
order status loader tests
MartinKreizl Mar 10, 2025
3f95558
return status loader tests
MartinKreizl Mar 10, 2025
259a828
shop loader tests
MartinKreizl Mar 10, 2025
1a5f122
order return loader tests
MartinKreizl Mar 10, 2025
fac1076
product loader tests
MartinKreizl Mar 10, 2025
f93a1f7
order loader tests
MartinKreizl Mar 10, 2025
8dda6ea
tests code refactor
MartinKreizl Mar 11, 2025
4bced0d
State test
MartinKreizl Mar 11, 2025
3640d2b
min. php version
MartinKreizl Mar 11, 2025
76ff864
Helpers test
MartinKreizl Mar 11, 2025
a124b24
eshop return status test
MartinKreizl Mar 11, 2025
0572607
eshop order status test
MartinKreizl Mar 11, 2025
7920922
eshop multistore test
MartinKreizl Mar 11, 2025
343f0ef
use clause
MartinKreizl Mar 11, 2025
35d5d20
eshop language test
MartinKreizl Mar 11, 2025
7af1fe2
eshop configuration test
MartinKreizl Mar 11, 2025
3f2b469
strict types
MartinKreizl Mar 11, 2025
d06bcb6
mixed type hint
MartinKreizl Mar 11, 2025
14b7bb3
refactor connection
MartinKreizl Mar 11, 2025
7cba5df
fix types
MartinKreizl Mar 11, 2025
ca046ed
fix order address
MartinKreizl Mar 12, 2025
e82b11c
comment
MartinKreizl Mar 12, 2025
eb22643
project image
MartinKreizl Mar 12, 2025
8d0b494
GH action
MartinKreizl Mar 12, 2025
7227069
install intl
MartinKreizl Mar 12, 2025
4d55964
docker image
MartinKreizl Mar 13, 2025
6b653c3
use image
MartinKreizl Mar 13, 2025
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
57 changes: 57 additions & 0 deletions .docker/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
FROM php:8.2-apache
ARG XDEBUG_VERSION=3.4.0
ARG OC_VERSION=4.1.0.0

LABEL org.opencontainers.image.source=https://github.com/bulkgate/cartsms
LABEL opencart_version=${OC_VERSION}

ENV OC_VERSION=${OC_VERSION}

RUN echo "Opencart version: ${OC_VERSION}"

WORKDIR /tmp

RUN curl -fL "https://github.com/opencart/opencart/archive/refs/tags/${OC_VERSION}.tar.gz" -o opencart.tar.gz && \
curl -sS https://raw.githubusercontent.com/composer/getcomposer.org/f3108f64b4e1c1ce6eb462b159956461592b3e3e/web/installer | php && \
mv composer.phar /usr/local/bin/composer

RUN tar -xzf opencart.tar.gz

RUN rm opencart.tar.gz

USER www-data:www-data

RUN cp -r opencart-*/upload/* /var/www/html

WORKDIR /var/www/html

RUN cp config-dist.php config.php && \
cp admin/config-dist.php admin/config.php

USER root

VOLUME /var/www/html

RUN apt-get update \
&& apt-get install -y \
wait-for-it \
unzip \
libicu-dev \
libfreetype6-dev \
libjpeg62-turbo-dev \
libpng-dev \
libzip-dev \
libcurl3-dev \
libwebp-dev \
&& pecl install xdebug-${XDEBUG_VERSION} \
&& docker-php-ext-enable xdebug \
&& docker-php-ext-configure gd --with-freetype --with-jpeg --with-webp \
&& docker-php-ext-install -j$(nproc) gd zip mysqli curl intl \
&& docker-php-ext-enable gd zip mysqli curl intl

RUN a2enmod rewrite

COPY --chmod=777 entrypoint.sh /usr/sbin
COPY install-extension.php /tmp

ENTRYPOINT ["entrypoint.sh"]
21 changes: 21 additions & 0 deletions .docker/entrypoint.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#!/bin/bash

if [ ! -f /var/www/html/install.lock ]; then
wait-for-it db:3306 -t 60 &&
php /var/www/html/install/cli_install.php install \
--username admin \
--password admin \
--email [email protected] \
--http_server http://localhost:8083/ \
--db_driver mysqli \
--db_hostname db \
--db_username root \
--db_password admin \
--db_database opencart \
--db_port 3306 \
--db_prefix oc_ &&
touch /var/www/html/install.lock &&
php /tmp/install-extension.php
fi

exec apache2-foreground
77 changes: 77 additions & 0 deletions .docker/install-extension.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
<?php

require_once '/var/www/html/admin/config.php';
require_once '/var/www/html/system/startup.php';

//sytem/framework.php
$autoloader = new \Opencart\System\Engine\Autoloader();
$autoloader->register('Opencart\\' . APPLICATION, DIR_APPLICATION);
$autoloader->register('Opencart\Extension', DIR_EXTENSION);
$autoloader->register('Opencart\System', DIR_SYSTEM);

require_once DIR_SYSTEM . 'vendor.php';

// Registry
$registry = new \Opencart\System\Engine\Registry();
$registry->set('autoloader', $autoloader);

// Config
$config = new \Opencart\System\Engine\Config();
$config->addPath(DIR_CONFIG);
// Load the default config
$config->load('default');
$config->load(strtolower(APPLICATION));
$registry->set('config', $config);

// Set the default application
$config->set('application', APPLICATION);

define('IS_4_1_x', class_exists('Opencart\System\Engine\Factory'));

// Factory - opencart 4.1.x
if (IS_4_1_x) {
$registry->set('factory', new \Opencart\System\Engine\Factory($registry));
}

// Loader
$loader = new \Opencart\System\Engine\Loader($registry);
$registry->set('load', $loader);

// Event
$event = new \Opencart\System\Engine\Event($registry);
$registry->set('event', $event);

// Cache
//$registry->set('cache', new \Opencart\System\Library\Cache($config->get('cache_engine'), $config->get('cache_expire')));

$db = new \Opencart\System\Library\DB($config->get('db_engine'), $config->get('db_hostname'), $config->get('db_username'), $config->get('db_password'), $config->get('db_database'), $config->get('db_port'), $config->get('db_ssl_key'), $config->get('db_ssl_cert'), $config->get('db_ssl_ca'));
$registry->set('db', $db);


$response = new \Opencart\System\Library\Response();
$response->addHeader('Content-Type: text/plain; charset=utf-8');
$registry->set('response', $response);

$registry->load->model('setting/extension');

/** @var \Opencart\Admin\Model\Setting\Extension $install*/
$install = $registry->get('model_setting_extension');
$install_info = json_decode(file_get_contents('/var/www/html/extension/oc_cartsms/install.json'), true);

$id = $install->addInstall([
'extension_id' => 0,
'extension_download_id' => 0,
'name' => $install_info['name'],
'code' => 'oc_cartsms',
'description' => $install_info['description'],
'version' => $install_info['version'],
'author' => $install_info['author'],
'link' => $install_info['link']
]);

$install->addPath($id, 'oc_cartsms/admin/controller/module/cartsms.php');
$install->editStatus($id, true);

$response->setOutput('Extension ' . $install_info['name'] . ' installed successfully.');

$response->output();
25 changes: 25 additions & 0 deletions .github/workflows/php.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
name: Run tests

on: [push]

jobs:
tests:
runs-on: ubuntu-latest

container: ghcr.io/bulkgate/cartsms:4.1.0.0

steps:
- uses: actions/checkout@v1

- run: composer install --prefer-dist --no-progress --no-suggest

- run: composer run tester

- run: composer run coverage

- uses: actions/upload-artifact@v4
with:
name: coverage-report
path: coverage.html

#- run: composer run phpstan
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
.env
.idea
vendor
opencart
tests/**/output/*
3 changes: 0 additions & 3 deletions .gitmodules

This file was deleted.

19 changes: 19 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,22 @@
<img src="https://portal.bulkgate.com/images/products/oc.svg" width="200" />

http://www.cart-sms.com/

# Development

https://webkul.com/blog/how-to-create-a-module-in-opencart/


## Category extension
URL: http://localhost:8083/admin/index.php?route=extension/opencart/module/category&user_token=886a6f6378b7a94cbccad4acd55abdf1
FILE: /extension/opencart/admin/controller/module/category.php
view: /extension/opencart/admin/view/template/module/category.twig
NAMESPACE: Opencart\Admin\Controller\Extension\Opencart\Module;
CLASS: Category

## Cartsms extension
URL: http://localhost:8083/admin/index.php?route=extension/cartsms/module/cartsms&user_token=886a6f6378b7a94cbccad4acd55abdf1
FILE: /extension/cartsms/admin/controller/module/cartsms.php
view: /extension/cartsms/admin/view/template/module/cartsms.twig
NAMESPACE: Opencart\Admin\Controller\Extension\Cartsms\Module;
CLASS: Cartsms
128 changes: 128 additions & 0 deletions admin/controller/event/hook.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
<?php

namespace Opencart\Admin\Controller\Extension\OcCartsms\Event;

use BulkGate\CartSms\Event\State;
use BulkGate\Plugin;

require_once DIR_EXTENSION . 'oc_cartsms/vendor/autoload.php';

class Hook extends \BulkGate\CartSms\Controller
{
private State $product_out_of_stock_state;
private State $return_status_state;

public function hookMenu(string $route, array &$data)
{
$this->language->load('extension/oc_cartsms/module/cartsms');

$data['menus'][] = [
'id' => 'menu-cartsms',
'icon' => 'fas fa-envelope',
'name' => $this->language->get('extension_name_menu'),
'href' => $this->url->link('extension/oc_cartsms/module/cartsms', 'user_token=' . $this->session->data['user_token']),
'children' => []
];
}

public function hookRenderSendMessageBox(string $route, array &$data)
{
$order_id = (int) $data['order_id'];

if ($order_id === 0 || !$this->di_container->getByClass(Plugin\Settings\Settings::class)->load('static:application_token')) {
return;
}

$data['extensions'][] = $this->load->controller('extension/oc_cartsms/module/send_message', $order_id);
}

public function hookSendSms(array $params)
{
$number = $params['number'] ?? null;
$template = $params['template'] ?? null;
$variables = $params['variables'] ?? [];
$settings = $params['settings'] ?? [];

$hook = $this->di_container->getByClass(Plugin\Event\Hook::class);

$hook->send('/api/2.0/advanced/transactional', [
'number' => $number,
'application_product' => 'oc',
'tag' => 'module_custom',
'variables' => $variables,
'country' => $settings['country'] ?? null,
'channel' => [
'sms' => [
'sender_id' => $settings['senderType'] ?? 'gSystem',
'sender_id_value' => $settings['senderValue'] ?? '',
'unicode' => $settings['unicode'] ?? false,
'text' => $template,
],
],
]);
}

//OK
public function hookAddCustomer(string $route, array $params, int $id_customer)
{
$this->runHook('customer', 'new', new Plugin\Event\Variables([
'customer_id' => $id_customer,
//'data' => $params,
]));
}

public function hookProductOutOfStockBefore(string $route, array $params)
{
[$id_product] = $params;
$this->load->model('catalog/product');

$this->product_out_of_stock_state = (new State(fn() => (int) $this->model_catalog_product->getProduct($id_product)['quantity']))
->captureInitial()
->setExpected(0);
}

//OK
public function hookProductOutOfStockAfter(string $route, array $params)
{
[$id_product, $data] = $params;

$this->product_out_of_stock_state->captureActual();

if (!$this->product_out_of_stock_state->shouldRunHook()) {
return;
}

$this->runHook('product', 'out-of-stock', new Plugin\Event\Variables([
'product_id' => $id_product,
'shop_id' => $data['product_store'][0],
//'data' => $params,
]));
}

public function hookChangeReturnStatusBefore(string $route, array $params)
{
[$id_return, $id_return_status] = $params;

$this->load->model('sale/returns');

$this->return_status_state = (new State(fn() => (int) $this->model_sale_returns->getReturn($id_return)['return_status_id']))
->captureInitial()
->setExpected((int) $id_return_status);
}

public function hookChangeReturnStatusAfter(string $route, array $params)
{
[$id_return, $id_return_status] = $params;

$this->return_status_state->captureActual();

if (!$this->return_status_state->shouldRunHook()) {
return;
}

$this->runHook('return', 'change-status', new Plugin\Event\Variables([
'return_id' => $id_return,
'return_status_id' => $id_return_status,
]));
}
}
Loading