Where to save and how to call a custom OpenCart module - opencart

I'm trying to write a custom module for OpenCart 4.0.1.1. My module is as below:
<?php
class ControllerExtensionModuleProductList extends Controller {
public function index() {
$this->load->model('catalog/product');
$products = $this->model_catalog_product->getProducts();
$this->response->addHeader('Content-Type: application/json');
$this->response->setOutput(json_encode($products));
}
}
?>
Where should I save this file and what is the url to run this file?
Also is there any extension template for this version of OpenCart?

Related

How to use custom UI for swashbuckle

I am trying to use a custom swashbuckle index.html for our .net core project. I followed the doc and done this:
app.UseSwaggerUI(c =>
{
c.IndexStream = () => GetType().Assembly
.GetManifestResourceStream("CustomUIIndex.Swagger.index.html"); // requires file to be added as an embedded resource
});
The custom index page (based on the default index.html) is loaded, but I can see the html page outputted these:
%(HeadContent)
.....
window.onload = function () {
var configObject = JSON.parse('%(ConfigObject)');
var oauthConfigObject = JSON.parse('%(OAuthConfigObject)');
So looks like the contents %(ConfigObject) or %(HeadContent) are not replaced. What should I do to get the custom index page work properly?
thanks
i mark all codes in window.onload and
the image of html source code :
https://i.stack.imgur.com/haHWm.png

emberjs child component not re-rendering after property update

I have a page component (five-whys) with a number of inputs that the user can choose to finalize the input. When the user clicks finalize, all questions are made to be disabled.
Page component
five-whys.hbs:
{{#each this.whys as |why i|}}
<Generic::RichTextInput
#value={{why.content}}
#onChange={{action this.whyChanged i}}
#disabled={{this.isFinalized}} />
{{/each}}
<button {{on "click" this.finalizeWhy}}>Finalize</button>
five-whys.ts
interface AnalyzeFiveWhysArgs {
dataStory: DataStory;
}
export default class AnalyzeFiveWhys extends Component<AnalyzeFiveWhysArgs> {
#alias("args.dataStory.fiveWhysAnalysis") fiveWhysAnalysis
#tracked
isFinalized: boolean = this.fiveWhysAnalysis.isFinalized ?? false;
#tracked
whys: LocalWhy[] = this.fiveWhysAnalysis.whys;
#tracked
isFinalized: boolean = this.fiveWhysAnalysis.isFinalized ?? false;
#action
async finalizeWhy() {
this.isFinalized = true;
}
This works fine when my rich text component is just a regular text area. However, I am trying to implement tinymce which requires me to do stuff outside of Embers little safe space of magic.
My rich text component:
Template:
<textarea id={{this.id}} disabled={{this.templatePieceIsDisabled}}>{{#value}}</textarea>
Typescript:
interface GenericRichTextInputArgs {
value?: string;
onChange: (value: string) => void;
name: string;
disabled?: boolean;
}
export default class GenericRichTextInput extends Component<GenericRichTextInputArgs> {
constructor(owner: unknown, args: GenericRichTextInputArgs) {
super(owner, args);
this.initializeTinymce();
}
id = this.args.name;
get editor() {
return tinymce.get(this.id);
}
get settings() {
console.log(this.args.disabled);
const settings: TinyMCESettings = {
selector: `#${this.id}`,
setup: (editor: Editor) => this.setupEditor(this, editor),
readonly: this.args.disabled ? this.args.disabled : false
};
return settings;
}
initializeTinymce() {
Ember.run.schedule('afterRender', () => {
console.log("re-initializing"); // I expect to see this log every time the isFinalized property in the five-whys component changes. But I only see it on page load.
tinymce.init(this.settings);
});
}
setupEditor(self: GenericRichTextInput, editor: Editor) {
... // details of tinymce API
}
}
When I click the finalize button, The effect of the disabled flag in the rich text component does not change.
Note:
The tinymce library I'm using sets the text area display to none and the aria-hidden to true. This is because it wraps the textarea in a widget. So I have to use the library's api to set disabled.
I figured it out. Ember doesn't run the constructor for the update life-cycle event. So I need to tell Ember to re-run the initializer when the template gets re-rendered. I had to use https://github.com/emberjs/ember-render-modifiers to do this.
So my rich text editor template looks like:
<textarea
id={{this.id}}
{{did-update this.updateDisabled #disabled}}>
{{#value}}
</textarea>
And I added this action in the code behind of the rich text editor:
#action
updateDisabled(element: HTMLTextAreaElement, [disabled]: any[]) {
this.disabled = disabled;
this.editor.destroy();
this.initializeTinymce();
}

How do I directly add a controller in LoopBack 4?

EDIT: This was just a bug with loopback, I've put in a PR.
The following code does not work:
// BAD CODE
import {ApplicationConfig} from '#loopback/core';
import {RestApplication, RestServer, get} from '#loopback/rest';
export class HelloController {
#get('/hello')
hello(): string {
return 'Hello world!';
}
}
export class HelloWorldApplication extends RestApplication {
constructor(options: ApplicationConfig = {}) {
super(options);
this.controller(HelloController); // Error Here
}
async start() {
await super.start();
const rest = await this.getServer(RestServer);
console.log(
`REST server running on localhost:${await rest.get('rest.port')}`,
);
}
}
I get this error:
UnhandledPromiseRejectionWarning: TypeError: paramTypes is not iterable
at resolveControllerSpec (/Users/seph/Code/Project/api-loopback/node_modules/#loopback/openapi-v3/src/controller-spec.ts:312:21)
How can I directly add a controller in LoopBack 4?
No sure if this helps but you can inject another controller through the constructor of current controller. You should also generate your controller like using
lb4 controller then assuming you have 2 controllers created and want to access 1st of them inside of the second one you could do:
constructor(
// Inject other controller
#inject('controllers.SomeOtherController')
// Create localy
public otherCtrl: SomeOtherController,
and then
otherCtrl.SomeMethod()
Read more Loopback Controllers
Regards,

Drupal 8 custom module getting page not found

i'm trying to learn Drupal 8, i've been following the official guide to create a custom module (this tutorial), but when i go to the /hello route i get a page not found error, the module is active, maybe an error with the routing?
here's part of the code:
hello_world.routing.yml
hello_world.content:
path: '/hello'
defaults:
_controller: '\Drupal\hello_world\Controller\HelloController::content'
_title: 'Hello World'
requirements:
_permission: 'access content'
this is the HelloController.php
<?php
namespace Drupal\hello_world\Controller;
use Drupal\Core\Controller\ControllerBase;
/**
* Defines HelloController class.
*/
class HelloController extends ControllerBase {
/**
* Display the markup.
*
* #return array
* Return markup array.
*/
public function content() {
return [
'#type' => 'markup',
'#markup' => $this->t('Hello, World!'),
];
}
}
And this is the directory structure
I'm new with drupal so it is really posible that i made a rookie mistake, any help would be helpful, thanks
Your routing file says hello_worl, it is a typo. Correct that and clear caches.

Calling an action of another controller - Design consideration for File Uploader - MVC 4

I have a situation where I'm debating how to architect my controllers.
Consider the following controller:
public class FileSharingController : Controller
{
private readonly ICommandBus commandBus;
public FileSharingController(ICommandBus commandBus)
{
this.commandBus = commandBus;
}
[HttpPost]
public ActionResult PrepareMetadata(int blocksCount, string fileName, long fileSize)
{
...
}
[HttpPost]
public ActionResult ClearFileMetadata(string fileName){
...
}
[HttpPost] [ValidateInput(false)] //$.ajax({ data: html5FormDataFileChunk , processData: false ... })
public ActionResult UploadBlock(string fileName, int blockId){
var fileUploadCommand = (FileUploadCommand)ExtractFromSessionData(fileName);
var result = commandBus.Submit(fileUploadCommand);
...
}
public ActionResult CommitFileUploads(string[] filesToCommit){
var commitFileUploadCommand = (CommitFileUploadCommand)ExtractFromSessionData(fileName);
var result = commandBus.Submit(commitFileUploadCommand );
...
}
In this controller, I use the command pattern and pass a model to my commandBus which interfaces with my domain. The first three [HttpPost] methods on the controller are for handling jQuery ajax calls from a responsive file uploading UI.
Consider the situation where a user fills out a form (an interview) and uploads some files along with it. Although the user can upload the files before submitting the form, I don't want the uploaded files to be committed until AFTER they submit the form and it passes validation. That is why the last method on the controller is not an http endpoint. As such I have the following controller:
public class InterviewController : Controller
{
[HttpGet]
public ActionResult UserInterview()
{
InterviewViewModel viewModel = new InterviewViewModel ();
return PartialView(viewModel);
}
[HttpPost] [AllowAnonymous]
public ActionResult UserInterview(InterviewViewModel viewModel)
{
if(ModelState.IsValid)
{
var fileSharingController = new FileSharingController();
fileSharingController.CommitFileUploads(viewModel.Files);
}
return PartialView(viewModel);
}
}
The problem is I'm using IoC to inject a commandBus into the FileSharingController so I cannot just instantiate it with default constructor as I am doing.
My options to consider:
Create a custom controller factory to allow instantiating my controller anywhere in the code.
Turn my FileSharingController in a WebAPI controller and treat as a service
Which is the better design path for this situation? If the latter case, how can I keep the CommitFileUploads() method private? I don't want it to be exposed as an endpoint that can be triggered without first validating the rest of the form.
You can instantiate your controller like this:
ICommandBus commandBus = DependencyResolver.Current.GetService<ICommandBus>();
var fileShareController = new FileSharingController(commandBus);
Generic GetService() method is extension method, so make sure that you have "using System.Web.Mvc;" line in the cs file.
But then, it's better to have helper class that is responsible for keeping/storing already uploaded files, and call it from both controllers, instead instantiating controllers manually.
For example:
public class FileUploadManager
{
public FileUploadManager(ICommandBus commandBus, HttpSessionStateBase sessionState)
{
//....
}
}
and then you call it:
ICommandBus commandBus = DependencyResolver.Current.GetService<ICommandBus>();
var fileShareController = new FileUploadManager(commandBus, this.HttpContext.Session);
Or, if you don't want to use DependencyResolver, you pass ICommandBus to both controller's constructors, and use that reference to instantiate helper class.
simply just create the object of another conroller and use all its public methods.