opencart 4 extension | overriding home Controller proplem - opencart

hallow everyone , I'm trying to develop theme as extension in OpenCart 4 for my site but when i try to override the home controller it does not changed at all , other controller was changed normally
my startup controller
i need to develop a custume theme and i need to pass data from control panel to it.
`<?php
namespace Opencart\Catalog\Controller\Extension\Printinos\Startup;
class override extends \Opencart\System\Engine\Controller
{
public function index():void
{
if ($this->config->get('theme_printinos_status')) {
$this->event->register('controller/*/before', new \Opencart\System\Engine\Action('extension/printinos/startup/override|event'));
}
}
public function event(string &$route, array &$args): void
{
$override = [
'common/header',
'common/home',
'common/footer',
'common/column_left',
'common/column_right',
'common/column_bottom',
'common/column_top',
'common/currency',
'common/language',
'common/maintenance',
'common/menu',
'common/pagination',
'common/search',
];
if (in_array($route, $override)) {
$route = 'extension/printinos/' . $route;
}
}
}`
--------------------------------------------
my home controller
`<?php
namespace Opencart\Catalog\Controller\Extension\Printinos\Common;
class Home extends \Opencart\System\Engine\Controller {
public function index(): void {
$this->document->setTitle($this->config->get('config_meta_title'));
$this->document->setDescription($this->config->get('config_meta_description'));
$this->document->setKeywords($this->config->get('config_meta_keyword'));
$data['column_left'] = $this->load->controller('common/column_left');
$data['column_right'] = $this->load->controller('common/column_right');
$data['content_top'] = $this->load->controller('common/content_top');
$data['content_bottom'] = $this->load->controller('common/content_bottom');
$data['footer'] = $this->load->controller('common/footer');
$data['header'] = $this->load->controller('common/header');
var_dump($data);
$this->response->setOutput($this->load->view('common/home', $data));
}
}`

Related

Web Service doesn’t work when I try to update the android widget if the app is killed

We are developing android widget for Xamarin.Forms application. The widget updates and gets data from the Web Service when the app is in Background, but stops working when the app is killed/closed. I have followed this article for developing this widget -
Xamarin: Android Widget with timer, stops when app killed
I want to Update the widget when the user clicks on Refresh button. If I add hardcoded data for textboxes and click Refresh it updates the time but doesn’t work if I assign web service result data for the textboxes. I have added internet permission in AndroidManifest.xml. Is there a way I can get the data from web service even when the app is closed? Or Probably I am missing some permission?
AppWidget.cs -
public static class WidgetConsts
{
public const string DebugTag = "com.myapp.WIDGET";
public const string ActionWakeup = "com.myapp.WIDGET_WAKEUP";
public const string ActionWidgetUpdate = "android.appwidget.action.APPWIDGET_UPDATE";
public const string ActionWidgetDisabled = "android.appwidget.action.APPWIDGET_DISABLED";
}
[BroadcastReceiver]
[IntentFilter(new string[] { WidgetConsts.ActionWakeup })]
public class AlarmReceiver : BroadcastReceiver
{
public override void OnReceive(Context context, Intent intent)
{
if (intent.Action.Equals(WidgetConsts.ActionWakeup))
{
Log.Debug(WidgetConsts.DebugTag, "Wakeup alarm called");
if (AppWidget.widgetTimer == null)
{
Log.Debug(WidgetConsts.DebugTag, "Widget updating does not run, enforcing update...");
AppWidget.UpdateAppWidget(context);
}
else
{
Log.Debug(WidgetConsts.DebugTag, "Widget updating runs, no action needed");
}
}
}
}
[BroadcastReceiver]
[IntentFilter(new string[] { WidgetConsts.ActionWidgetUpdate})]
[MetaData("android.appwidget.provider", Resource = "#xml/appwidget_provider")]
public class AppWidget : AppWidgetProvider
{
public static System.Timers.Timer widgetTimer = null;
public override void OnUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds)
{
RemoteViews views = BuildRemoteViews(context, appWidgetIds);
(AppWidgetManager.GetInstance(Android.App.Application.Context)).UpdateAppWidget(new ComponentName(Android.App.Application.Context, Java.Lang.Class.FromType(typeof(AppWidget))), views);
// appWidgetManager.UpdateAppWidget(appWidgetIds[0], views);
// set timer for updating the widget views each 5 sec
if (widgetTimer == null)
{
widgetTimer = new System.Timers.Timer();
widgetTimer.Interval = 5000;
widgetTimer.Elapsed += OnTimedEvent;
}
widgetTimer.Enabled = true;
// set alarm to wake up the app when killed, each 60 sec
// needs a fresh BroadcastReceiver because AppWidgetProvider.OnReceive is
// not virtual and overriden method in this class would not be called
AlarmManager am = (AlarmManager)context.GetSystemService(Context.AlarmService);
Intent ai = new Intent(context, typeof(AlarmReceiver));
ai.SetAction(WidgetConsts.ActionWakeup);
PendingIntent pi = PendingIntent.GetBroadcast(context, 0, ai, PendingIntentFlags.UpdateCurrent);
am.SetRepeating(AlarmType.ElapsedRealtime, 100, 1000 * 60, pi);
}
public override void OnEnabled(Context context)
{
AlarmManager am = (AlarmManager)context.GetSystemService(Context.AlarmService);
Intent ai = new Intent(context, typeof(AlarmReceiver));
ai.SetAction(WidgetConsts.ActionWakeup);
PendingIntent pi = PendingIntent.GetBroadcast(context, 0, ai, PendingIntentFlags.UpdateCurrent);
am.SetRepeating(AlarmType.ElapsedRealtime, 100, 1000 * 60, pi);
base.OnEnabled(context);
}
public override void OnDisabled(Context context)
{
Log.Debug(WidgetConsts.DebugTag, "Disabling the widget");
if (widgetTimer != null)
{
Log.Debug(WidgetConsts.DebugTag, "Stopping timer");
widgetTimer.Enabled = false;
}
else
Log.Debug(WidgetConsts.DebugTag, "Timer is null");
base.OnDisabled(context);
}
private void OnTimedEvent(object sender, ElapsedEventArgs e)
{
Log.Debug(WidgetConsts.DebugTag, "Updating status...");
new Handler(Looper.MainLooper).Post(() =>
{
//Run my code to periodically update the widget
RemoteViews views = new RemoteViews(Android.App.Application.Context.PackageName, Resource.Layout.SnapVertWidget);
AppWidgetManager manager = AppWidgetManager.GetInstance(Android.App.Application.Context);
ComponentName thisWidget = new ComponentName(Android.App.Application.Context, Java.Lang.Class.FromType(typeof(AppWidget)));
int[] appWidgetIds = manager.GetAppWidgetIds(thisWidget);
(AppWidgetManager.GetInstance(Android.App.Application.Context)).UpdateAppWidget(new ComponentName(Android.App.Application.Context, Java.Lang.Class.FromType(typeof(AppWidget))), views);
// manager.UpdateAppWidget(appWidgetIds[0], views);
});
}
static public void UpdateAppWidget(Context context)
{
Intent intent = new Intent(context, typeof(AppWidget));
intent.SetAction(WidgetConsts.ActionWidgetUpdate);
int[] ids = AppWidgetManager.GetInstance(context).GetAppWidgetIds(new ComponentName(context, Java.Lang.Class.FromType(typeof(AppWidget))));
intent.PutExtra(AppWidgetManager.ExtraAppwidgetIds, ids);
context.SendBroadcast(intent);
}
public RemoteViews BuildRemoteViews(Context context, int[] appWidgetIds)
{
xxx.Droid.Services.MyWidget myWidget = new xxx.Droid.Services.MyWidget();
var entry = myWidget.GetData();
// Build an update that holds the updated widget contents
var updateViews = new RemoteViews(context.PackageName, Resource.Layout.SnapVertWidget);
updateViews.SetTextViewText(Resource.Id.txtvwUpdate, Convert.ToString(DateTime.Now));
updateViews.SetTextViewText(Resource.Id.txtvwCityName, entry.Result.CityName);
updateViews.SetTextViewText(Resource.Id.txtvwTemp, entry.Result.TempValue);
//SetTextViewText(widgetView);
RegisterClicks(context, appWidgetIds, updateViews);
return updateViews;
}
private void RegisterClicks(Context context, int[] appWidgetIds, RemoteViews widgetView)
{
Intent intentUpdate = new Intent(context, typeof(AppWidget));
intentUpdate.SetAction(AppWidgetManager.ActionAppwidgetUpdate);
//Update the current widget instance only, by creating an array that contains the widget’s unique ID//
int[] idArray = new int[] { appWidgetIds[0] };
intentUpdate.PutExtra(AppWidgetManager.ExtraAppwidgetIds, idArray);
PendingIntent pendingUpdate = PendingIntent.GetBroadcast(
context, appWidgetIds[0], intentUpdate,
PendingIntentFlags.UpdateCurrent);
widgetView.SetOnClickPendingIntent(Resource.Id.btnRefresh, pendingUpdate);
Intent launchAppIntent = new Intent(context, typeof(MainActivity));
PendingIntent launchAppPendingIntent = PendingIntent.GetActivity(context, 0, launchAppIntent, PendingIntentFlags.UpdateCurrent);
widgetView.SetOnClickPendingIntent(Resource.Id.pnlWeather, launchAppPendingIntent);
}
}

Mocking OData service endpoint

I am trying to mock the OData service context using Moq to return a list of dummy entities so that I could base my unit test on that. I cannot expose my real model and application so I have created this simulated app and the portion, which I have exposed is similar.
MyOdataApplication consuming ODataEndpoint which I am testing.
public class MyApplication
{
private readonly IODataContext _odataContext;
public MyApplication(IODataContext odataContext){
_odataContext = odataContext;
}
public async Task<IEnumerable<Book>> GetBooks(string authorName)
{
IEnumerable<Book> books = null;
var query = (DataServiceQuery<Book>)_odataContext.Books.Where(x => x.Author = authorName);
books = await query.ExecuteAsync().ToList();
return books;
}
public bool async ValidateBooks(string authorName){
var books = await GetBooks(authorname);
//other code....
}
}
My Odata Service contract interface is
public interface IODataContext
{
global::Microsoft.OData.Client.DataServiceQuery<global::models.Book> Books { get; }
}
My Unit Test class is as follows.
[TestFixture]
public class MyTestClass
{
[Test]
public void TestOdataFunctionality()
{
var mockODataEndpoint = new Mock<IODataContext>();
//It fails here as its not able to convery IQueryable<Book> to DataServiceQuery<Book>
mockODataEndpoint.Setup(x => x.GetBooks(It.IsAny<string>)).Returns(GetDummyBooks());
var myApp = new MyApplication(mockODataEndpoint.Object);
//This is my main method which I need to test.
Task<bool> task = myApp.ValidateBooks("author name");
var isvalid = task.Result;
Assert.AreEqual(true, isvalid);
}
private DataServiceQuery<Book>GetDummyBooks()
{
var books = new List<Book>
{
new Book()
{
Name = "Book1",
Author = "author name",
//other properties...
}
};
//Not sure how to achieve this. The below line is giving error ???
return (DataServiceQuery<Book>)books.AsQueryable();
}
}
How do I mock the Odata Service endpoint so that I could test my ValidateBooks method?

Sitecore 8 MVC add Class to Image rendered as HtmlString

I have a very simple component, it just does consist of a single image.
The Controller:
public ActionResult Index()
{
ActionResult ret = null;
if (RenderingContext.Current.Rendering.Item != null)
{
IntroImageModel model =
CreateModel(RenderingContext.Current.Rendering.Item);
ret = View(model);
}
return ret;
}
private IntroImageModel CreateModel(Item item)
{
IntroImageModel introImage = new IntroImageModel();
introImage.IntroImage = new HtmlString(FieldRenderer.Render(item,
FieldNames.INTROIMAGE_INTROIMAGE));
return introImage;
}
The Model:
public class IntroImageModel
{
public IntroImageModel()
{
}
public HtmlString IntroImage { get; set; }
}
The View:
#model ON.LSX.FEATURE.CONTENT.Models.IntroImageModel
#{
Layout = null;
}
#Model.IntroImage
I need to add a specific class to the tag that is produced by this code, but I have absolutely no idea how to do it, anyone can help?
try this on the View, as you can see, you can add the class as a parameter
#Html.Sitecore().Field("IntroImage", new { mw = 1000, mh = 560, #class = "img-responsive" })
There are also some additional parameters that you can change

How to create custom Field type in Sitecore Web Form for Marketer 8.1

In one of my Sitecore Project, I have to create a Custom field in WFFM.
Field type must have Two Textbox and user can enter 5 digit in each text box (Example xxxxx xxxxx, as we enter credit card details in 4 text box).
As per the ref document “https://sdn.sitecore.net/upload/sitecore6/64/presentation_component_cookbook-a4.pdf” I have crated below code :-
Crated a .cs Class
using System;
using System.Web.UI;
using System.Web.UI.WebControls;
using Sitecore.Form.Web.UI.Controls;
using System.ComponentModel;
using System.ComponentModel.Design;
namespace Web.MySite.Fields
{
[Designer("System.Windows.Forms.Design.ParentControlDesigner, System.Design", typeof(IDesigner))]
public class SocialSecurityNumber : SingleLineText
{
private static readonly string baseCssClassName = "scfSingleLineTextBorder";
protected TextBox firstPart;protected TextBox lastPart;
public SocialSecurityNumber() : this(HtmlTextWriterTag.Div)
{
firstPart = new TextBox();
lastPart = new TextBox();
}
public SocialSecurityNumber(HtmlTextWriterTag tag) : base(tag)
{
this.CssClass = baseCssClassName;
}
protected override void OnInit(EventArgs e)
{
SetCssClasses();
SetTextBoxeWidths();
SetMaxLengths();
SetTextBoxModes();
AddChildControls();
base.OnInit(e);
}
private void SetCssClasses()
{
help.CssClass = "scfSingleLineTextUsefulInfo";
title.CssClass = "scfSingleLineTextLabel";
generalPanel.CssClass = "scfSingleLineGeneralPanel";
}
private void SetTextBoxeWidths()
{
firstPart.Style.Add("width", "40px");
lastPart.Style.Add("width", "50px");
}
private void SetMaxLengths()
{
firstPart.MaxLength = 3;
lastPart.MaxLength = 4;
}
private void SetTextBoxModes()
{
firstPart.TextMode = TextBoxMode.SingleLine;
lastPart.TextMode = TextBoxMode.SingleLine;
}
private void AddChildControls()
{
Controls.AddAt(0, generalPanel);
Controls.AddAt(0, title);
generalPanel.Controls.Add(firstPart);
generalPanel.Controls.Add(lastPart);
generalPanel.Controls.Add(help);
}
}
public class SocialSecurityNumberModel : Sitecore.Forms.Mvc.ViewModels.Fields.SingleLineTextField
{
}
}
Then I have Created a BootstrapEditorHtmlHelperExtension.CS and Crated a .CSHTML:-
using Sitecore.Forms.Mvc.Interfaces;
using Sitecore.Forms.Mvc.ViewModels.Fields;
using System.Web.Mvc;
using System.Web.Mvc.Html;
namespace Web.MySite.Extensions
{
public static class BootstrapEditorHtmlHelperExtension
{
public static MvcHtmlString ExtendedBootstrapEditor(this HtmlHelper helper, string expression, string placeholderText, string inlineStyle, string[] classes)
{
var str = string.Empty;
var viewModel = helper.ViewData.Model as IViewModel;
if (viewModel != null)
{
var styleSettings = viewModel as IStyleSettings;
if (styleSettings != null)
{
str = styleSettings.CssClass;
}
if (string.IsNullOrEmpty(placeholderText))
{
placeholderText = viewModel.Title;
}
}
return helper.TextBox(expression,null, new
{
#class = (string.Join(" ", classes) + " form-control col-lg-2" + (string.IsNullOrEmpty(str) ? string.Empty : " " + str) + (helper.ViewData.Model is SingleLineTextField ? " dangerousSymbolsCheck" : string.Empty)),
placeholder = placeholderText,
style = (inlineStyle ?? string.Empty)
});
}
}
}
SocialSecurityNumberModel.CSHTML
#using Sitecore.Forms.Mvc.Html
#using Web.MySite.Extensions
#model Web.MySite.Fields.SocialSecurityNumberModel
#using (Html.BeginField())
{
#Html.ExtendedBootstrapEditor("value", " ", "width:50%", new[] { "" })
#Html.ExtendedBootstrapEditor("value", " ", "width:40%", new[] { "" })
}
After it ,I have Crated a Custom Field in Sitecore and gave Below dll ref. in
Assembly
Sitecore.Forms.Custom.dll
Class
Sitecore.Form.Web.UI.Controls.SingleLineText
MVC Type
Web.MySite.Fields.SocialSecurityNumberModel,Web.MySite
I am getting both the text box but ID is same for Both.
ID=wffm1755f6ce241245b7a1183288954ce0e7_Sections_0__Fields_0__value
You don't have to create an ASCX file for creating a custom field for WFFM
First of all you need to create an item of type:
/sitecore/templates/Web Forms for Marketers/Field Type
If you are using WFFM with MVC you need to fill MVC Type field.
You can look with Dot Peek how other Sitecore Wffm field are build.
You need to create your own class like in this example:
https://sitecorecorner.com/tag/wffm-custom-field/
http://elenazlateva.blogspot.ro/2012/09/custom-field-type-for-sitecore-web.html
https://divamatrix.wordpress.com/2011/12/20/wffm-custom-field-type-made-easy/

Zend Framework: How to unit test a model using Zend_Service_Twitter

I have been getting into Unit Testing with Zend Framework. I am getting used to the other things it provide but I am having a hard time understanding Mock Objects.
For this example, I am trying to use a Mock Object to test out my model.
<?php
class Twitter_Model_Twitter
{
private $_twitter;
/**
* Make the options injectable.
* __contruct($auth, $key)
*/
public function __construct()
{
$config = new Zend_Config_Ini(APPLICATION_INI, APPLICATION_ENV);
$key = $config->encryption->salt;
$iv_size = mcrypt_get_iv_size(MCRYPT_XTEA, MCRYPT_MODE_ECB);
$iv = mcrypt_create_iv($iv_size, MCRYPT_RAND);
$password = mcrypt_decrypt(MCRYPT_XTEA, $key, $password, MCRYPT_MODE_ECB, $iv);
$this->_twitter = new Zend_Service_Twitter($username, $password);
}
public function verifyCredentials()
{
return $this->_twitter->account->verifyCredentials();
}
public function friendsTimeline($params)
{
return $this->_twitter->status->friendsTimeline($params);
}
}
For my unit test:
require_once ('../application/models/Twitter.php');
class Model_TwitterTest extends ControllerTestCase
{
/**
* #var Model_Twitter
*/
protected $_twitter;
public function testfriendsTimeline()
{
$mockPosts = array('foo', 'bar');
//my understanding below is:
//get a mock of Zend_Service_Twitter with the friendsTimeline method
$twitterMock = $this->getMock('Zend_Service_Twitter', array('friendsTimeline'));
/*
line above will spit out an error:
1) testfriendsTimeline(Model_TwitterTest)
Missing argument 1 for Mock_Zend_Service_Twitter_9fe2aeaa::__construct(), called in
/Applications/MAMP/bin/php5/lib/php/PHPUnit/Framework/TestCase.php on line 672 and
defined /htdocs/twitter/tests/application/models/TwitterTest.php:38
*/
$twitterMock->expects($this->once())
->method('friendsTimeline')
->will($this->returnValue($mockPosts));
$model = new Twitter_Model_Twitter();
$model->setOption('twitter', $twitterMock);
$posts = $model->friendsTimeline(array('count'=>20));
$this->assertEquals($posts, $mockPosts);
}
}
How would you test the following?
1) verifyCredentials()
2) friendsTimeline()
Thanks,
Wenbert
I am going to answer this question. I think I have made this work thanks to zomg from #zftalk.
Here is my new Twitter Model:
<?php
//application/models/Twitter.php
class Twitter_Model_Twitter
{
private $_twitter;
private $_username;
private $_password;
public function __construct(array $options = null)
{
if (is_array($options)) {
$this->setOptions($options);
$this->_twitter = new Zend_Service_Twitter($this->_username, $this->_password);
} else {
$twitterAuth = new Zend_Session_Namespace('Twitter_Auth');
$config = new Zend_Config_Ini(APPLICATION_INI, APPLICATION_ENV);
$key = $config->encryption->salt;
$iv_size = mcrypt_get_iv_size(MCRYPT_XTEA, MCRYPT_MODE_ECB);
$iv = mcrypt_create_iv($iv_size, MCRYPT_RAND);
$password = mcrypt_decrypt(MCRYPT_XTEA, $key, $twitterAuth->password, MCRYPT_MODE_ECB, $iv);
$username = $twitterAuth->username;
$this->_twitter = new Zend_Service_Twitter($username, $password);
}
}
public function setOptions(array $options)
{
$methods = get_class_methods($this);
foreach ($options as $key => $value) {
$pieces = explode('_', $key);
foreach($pieces AS $piece_key => $piece_value) {
$pieces[$piece_key] = ucfirst($piece_value);
}
$name = implode('',$pieces);
$method = 'set' . $name;
//$method = 'set' . ucfirst($key);
if (in_array($method, $methods)) {
$this->$method($value);
}
}
return $this;
}
//I added this method. So that I could "inject"/set the $_twitter obj
public function setTwitter($obj)
{
$this->_twitter = $obj;
return $this;
}
public function verifyCredentials()
{
return $this->_twitter->account->verifyCredentials();
}
public function friendsTimeline($params)
{
return $this->_twitter->status->friendsTimeline($params);
}
//in the real code, more will go here...
}
And in my Unit Test, I have this:
<?php
// tests/application/models/TwitterTest.php
require_once ('../application/models/Twitter.php');
class Model_TwitterTest extends ControllerTestCase
{
public function testVerifyCredentials()
{
$stub = $this->getMock('Zend_Service_Twitter', array('verifyCredentials'),array(),'',FALSE);
//FALSE is actually the 5th parameter to flag getMock not to call the main class. See Docs for this.
//Now that I have set the $_twitter variable to use the mock, it will not call the main class - Zend_Rest_Client (i think)
$stub->expects($this->once())
->method('verifyCredentials');
$model = new Twitter_Model_Twitter();
//this is the part where i set the $_twitter variable in my model to use the $stub
$model->setOptions(array('twitter'=>$stub));
$model->verifyCredentials();
}
}
Anyways, I think I got it working.
1) The unit test no longer tried to connect to twitter.com:80
2) After I got the setOptions() working in the Twitter_Model, $model->verifyCredentials() in my unit test was successfully called.
I will wait for others in Stackoverflow to confirm that is the right answer. For the meantime, would like to hear from you guys.
Thanks!!!