I made a helper which is meant to help me debug my app.
It firsts display a header.
Then it tries to run a block of code which returns a fews arguments (array of objects).
Those arguments are used in a string format which is displayed when the block ran fine.
If the block caused an exception, the exception gets displayed.
The problem is, nothing gets displayed at all when I call the helper (I'm very new to that feature).
What's wrong?
#{
Layout = "~/Views/Shared/_Layout.cshtml";
}
#using MygLogWeb.Classes.Fox
<span>test</span>
#helper TryMethod(
string header
, Func<object[]> act
, string successFormat
)
{
#Html.Raw(String.Format(
#"<h2>{0}</h2>"
, HttpUtility.HtmlEncode(header)
));
try
{
var args = act();
if (successFormat == null)
{
#Html.Raw(#"<span class='Success'>OK</span>");
}
else
{
#Html.Raw(String.Format(
#"<span class='Success'>{0}</span>"
, HttpUtility.HtmlEncode(String.Format(
successFormat
, args
))
));
}
}
catch (Exception exe)
{
#Html.Raw(String.Format(
#"<span class='Error'>{0}</span>"
, HttpUtility.HtmlEncode(exe.Message)
));
}
}
<span>test</span>
#{
TryMethod(
"Cust.Columns"
, () => {
return new object[]
{
Cust.Columns.Count
};
}
, "Count: {0}"
);
}
<span>test</span>
The problem is not with the helper method itself but with the execution.
When you execute like this:
#{
TryMethod(...);
}
the code is executed but it's a code block but not written to output.
Use this syntax instead:
#(TryMethod(...))
this should work.
Related
Can someone please clarify below issue.
Below validation throw NULL pointer error when pass null in myVar. It is because of !myVar.isEmpty()
if (myVar!= null || !myVar.isEmpty() ) {
some code///
}
Below works though as expected,
if (myVar!= null) {
if (!myVar.isEmpty()) {
some code///
}
Any other way of having both steps together.
If .isEmpty() is used on a string, then you can also just use Groovy
"truth" directly, as null and also empty strings are "false".
[null, "", "ok"].each{
if (it) {
println it
}
}
// -> ok
if ( myVar!= null && !myVar.isEmpty() ) {
//some code
}
the same as
if ( !( myVar== null || myVar.isEmpty() ) ) {
//some code
}
and to make it shorter - it's better to add method like hasValues
then check could be like this:
if( myVar?.hasValues() ){
//code
}
and finally to make it groovier - create a method boolean asBoolean()
class MyClass{
String s=""
boolean isEmpty(){
return s==null || s.length()==0
}
boolean asBoolean(){
return !isEmpty()
}
}
def myVar = new MyClass(s:"abc")
//in this case your check could be veeery short
//the following means myVar!=null && myVar.asBoolean()==true
if(myVar) {
//code
}
I'm working on a custom Twig filter which resizes your images to a set width (and auto height).
{# TWIG CODE #}
{% set imgpath = page.header.custom.bgimage|first.path %}
<div class="thumb" style="background-image: url({{ url(imgpath|resize(240)) }})"></div>
It works great so far, but I encountered some errors when the ordering of the pages is changed. I'd like to use the Grav Debug Bar for debugging, since it's very convenient and keeps the code clean.
Inside Twig, you can simply use {{ dump(message) }}.
Unfortunately the resizing process happens inside native PHP, so I need a way to output messages from PHP to the Grav Debug Bar.
As stated inside the Docs, you can use $grav['debugger']->addMessage($this).
This throws an error when calling the resize Twig filter:
Twig_Error_Runtime
An exception has been thrown during the rendering of a template ("Undefined variable: grav").
Why is the variable $grav undefined?
<?php namespace Grav\Common;
use \Grav\Common\Grav;
use \Grav\Common\Page\Page;
use \RocketTheme\Toolbox\ResourceLocator\UniformResourceLocator;
use \Eventviva\ImageResize;
include_once getcwd().'/user/plugins/resizer/lib/ImageResize.php';
class TwigResizerFilters extends \Twig_Extension
{
private $grav;
public function __construct() {
$this->grav = Grav::instance();
}
public function getName() {
return 'TwigResizeFilters';
}
public function getFilters() {
return [
new \Twig_SimpleFilter( 'resize', [$this, 'resizeImage'] )
];
}
public function resizeImage($mediapath, $maxWidth = 1920) {
if (file_exists($mediapath)) {
// if file exists
if ($currImg = getimagesize($mediapath)) {
// if is image
if (preg_match('(jpg|jpeg|png)', $currImg['mime'])) {
// if file format correct
$resizedFolder = 'images/resized/';
// calculate exact img dimensions for proper naming
$maxHeight = floor(($maxWidth/$currImg[0]) * $currImg[1]);
if (!file_exists($resizedFolder)) {
// create folder if it does not exist
mkdir($resizedFolder, 0777, true);
}
// create filename
$resizedExtension = '.'.pathinfo($mediapath, PATHINFO_EXTENSION);
$resizedFilename = basename($mediapath, $resizedExtension).'#'.$maxWidth.'x'.$maxHeight.$resizedExtension;
if (file_exists($resizedFolder.$resizedFilename)) {
// if file already has been cached, just potput
return $resizedFolder.$resizedFilename;
} else {
// if not cached, resize to desired size
$image = new ImageResize($mediapath);
$image->resize($maxWidth, $maxHeight);
$image->save($resizedFolder.$resizedFilename);
return $resizedFolder.$resizedFilename;
}
} else {
$grav['debugger']->addMessage("File type of ".$mediapath." is not supported.");
}
} else {
$grav['debugger']->addMessage($mediapath." is not an image.");
}
} else {
$grav['debugger']->addMessage("File ".$mediapath." does not exist.");
}
}
private function mergeConfig( Page $page ) {
$defaults = (array) $this->grav['config']->get('plugins.resizer');
if ( isset($page->header()->resizer) ) {
$this->grav['config']->set('plugins.resizer', array_merge($defaults, $page->header()->resizer));
}
}
}
I am currently trying to handle exceptions and errors in a NodeJS app which will be used for critical information. I need a clean error management !
I've been wondering if there is something similar to Java Exceptions encapsulation.
I'm explaning.
In Java you can do something like that :
try {
// something that throws Exception
} catch (Throwable t) {
throw new Exception("My message", t);
}
That allows you to decide when to log your exception and you get the whole stack trace and call path !
I would like to know if there is a way to do the same in NodeJS because logging at every step seems not to be the right way of doing things.
Thank you.
You should look at this module :
https://www.npmjs.com/package/verror
Joyent quote it on his error management best pratices : https://www.joyent.com/developers/node/design/errors
At Joyent, we use the verror module to wrap errors since it's
syntactically concise. As of this writing, it doesn't quite do all of
this yet, but it will be extended to do so.
It allow you to get details on error message. And tracking the step of the error.
And also hide details to the client with wrapped error : WError() who returns only the last error message.
I answer my own question to explain what i finaly did to have the wanted encapsulation.
I used https://www.npmjs.com/package/verror as Sachacr suggested.
Then I extended it that way :
my_error.js :
var VError = require('verror');
var _ = require('lodash');
function MyError() {
var args = [];
var httpErrorCode;
var cause;
if (arguments.length > 0) {
var lastArgumentIndex = [arguments.length];
cause = manageCause(lastArgumentIndex, arguments);
httpErrorCode = manageHttpCode(lastArgumentIndex, arguments);
for (var i = 0; i < lastArgumentIndex; i++) {
args[i] = arguments[i];
}
}
this.__proto__.__proto__.constructor.apply(this, args);
if (cause) {
if (this.stack) {
this.stack += '\n' + cause.stack;
} else {
this.stack = cause.stack;
}
}
this.httpErrorCode = httpErrorCode;
}
MyError.prototype.__proto__ = VError.prototype;
function manageCause(lastArgumentIndex, arguments) {
if (lastArgumentIndex[0] > 0
&& arguments[lastArgumentIndex[0] - 1] instanceof Error) {
lastArgumentIndex[0]--;
return arguments[lastArgumentIndex[0]];
}
}
function manageHttpCode(lastArgumentIndex, arguments) {
if (lastArgumentIndex[0] > 0
&& _.isNumber(arguments[lastArgumentIndex[0] - 1])) {
lastArgumentIndex[0]--;
return arguments[lastArgumentIndex[0]];
}
}
module.exports = MyError;
It allows me to use it easily in my code :
var MyError = require('./my_error.js');
function withErrors() {
try {
// something with errors
} catch (err) {
// This is the same pattern as VError
return new MyError("My message", err, 401);
}
}
function somethingToDo(req, res) {
var result = withErrors();
if (result instanceof MyError) {
logger.warn(result);
res.status(result.httpErrorCode).send(result.message).end();
return
}
}
That way, i hace a nice stack trace with call path and every line involved in error/exception.
Hope it will help people, cause i searched a looooong time :)
EDIT : I modified my MyError class to add HTTP Error codes and clean arguments management.
You should be able to do something like:
funtion exception(message, error) {
this.message = message;
this.stacktrace = error.stack;
}
try {
if(someData == false)
throw new exception("something went wrong!", new Error());
}
catch(ex) {
console.log(ex.message);
console.log(ex.stacktrace);
}
You can then throw your own custom exception instance containing whatever debugging info you need.
EDIT: added stack trace to exception object
I have a search() function in my model and I have messed around a bit with it in order to filter my results with some custom filters. So in my model I have this:
public function search()
{
// #todo Please modify the following code to remove attributes that should not be searched.
$startdate='';
$enddate='';
if ($this->year!=''){
$year=explode('-', $this->year);
$date=DateTime::createFromFormat('Y', $year[0])->format('d/m/Y');
$startdate = General::getSeasonStartDate($date);
$enddate = General::getSeasonEndDate($date);
}
$criteria=new CDbCriteria;
$criteria->with=array(
'contracts'=>array(
'select'=>'contracts.contractdate',
'together'=>true
),
'schoolstudents' => array(
'together' => true,
'select' => false,
),
'schoolstudents.school'
);
//$criteria->order='lastname, firstname, fathername, mothername';
if (Yii::app()->user->CompanyID){
$criteria->compare('school.companyid',Yii::app()->user->CompanyID);
}
if(Yii::app()->user->SchoolID){
$criteria->compare('schoolstudents.schoolid',Yii::app()->user->SchoolID);
}
$criteria->compare('schoolstudents.schoolid', $this->schoolid);
//$criteria->compare('studentid',$this->studentid);
$criteria->compare('lastname',$this->lastname,true);
$criteria->compare('firstname',$this->firstname,true);
$criteria->compare('fathername',$this->fathername,true);
$criteria->compare('telephone1',$this->telephone1,true);
$criteria->compare('telephone2',$this->telephone2,true);
$criteria->compare('cellphone1',$this->cellphone1,true);
$criteria->compare('cellphone2',$this->cellphone2,true);
$criteria->compare('email1',$this->email1,true);
$criteria->compare('email2',$this->email2,true);
if($this->year!=''){
if ($startdate && $enddate){
$from = DateTime::createFromFormat('d/m/Y', $startdate)->format('Y-m-d');
$to = DateTime::createFromFormat('d/m/Y', $enddate)->format('Y-m-d');
if ($this->filter=='R'){
$criteria->addBetweenCondition('contractdate',$from, $to, 'AND');
}
else {
$criteria->addBetweenCondition('schoolstudents.createddate',$from, $to, 'AND');
}
}
} else {
if ($this->filter=='R'){
$criteria->addCondition('contracts.studentid');
} else {
$criteria->addCondition('schoolstudents.studentid');
}
}
if(isset($this->birthdate))
{
if($this->birthdate!='') {
$criteria->addCondition('year(birthdate)=:birthdate');
$criteria->params=CMap::mergeArray($criteria->params,array(
':birthdate'=>$this->birthdate,
)
);
}
}
return new CActiveDataProvider($this, array(
'criteria'=>$criteria,
'sort'=>array(
'defaultOrder'=>'lastname asc',
),
'pagination'=>array(
'pageSize'=>50,
),
));
}
my controller looks like this:
public function actionAdmin()
{
$model=new Student('search');
$model->unsetAttributes();
$y=date('Y');
$y1=date('Y',strtotime($y.'+1 year'));
$test=$y.'-'.$y1;
$model->year=$test;
$model->filter='A';
if (isset($_GET['Student']['year'])){
$model->year=($_GET['Student']['year']);
}
if (isset($_GET['Student']['filter'])){
$model->filter=$_GET['Student']['filter'];
}
if(isset($_GET['Student']))
$model->attributes=$_GET['Student'];
$this->render('admin',array(
'model'=>$model,
));
}
and my problem is that when I use the search filters provided by Yii they don't work. I don't get an error. They don't return anything. If I remove from search() the extra conditions I've added then the filters work fine. But then I can't use my custom filters. Anybody has any idea how to solve this?Thanks in advance!
Never mind I solved it. I changed my controller to this:
public function actionAdmin()
{
$model=new Student('search');
$model->unsetAttributes();
$y=date('Y');
$y1=date('Y',strtotime($y.'+1 year'));
$test=$y.'-'.$y1;
if (isset($_GET['Student']['year'])){
$model->year=$_GET['Student']['year'];
}
if (isset($_GET['Student']['filter'])){
$model->filter=$_GET['Student']['filter'];
}
if(isset($_GET['Student'])){
$model->attributes=$_GET['Student'];
} else{
//for custom & ajax filters to work together
$model->year=$test;
$model->filter='A';
}
$this->render('admin',array(
'model'=>$model,
));
I am building a multilingual application and I am storing the value of the latest language used in a cookie.
When the user opens up the application, the sessionScope variable is not set and the code will look for the cookie value and reload the page if not in the proper Locale.
I am getting the "com.ibm.xsp.acl.RedirectSignal" warning each time the page is reloaded in the proper locale, and I'd lilke to avoid it.
My code is located in the beforeRenderResponse event of the ApplicationLayout control I am using in the application, and looks like this:
if(!sessionScope.lang) { //this only happens when the page is opened in browser for the first time
var lang = context.getUrlParameter("lang").toLowerCase();
if(!!lang) {
sessionScope.lang = lang.toUpperCase();
//set cookie for next time the site is opened by user
setCookie("lang", lang.toUpperCase(), 30);
context.setLocale(new Locale(lang.toLowerCase()));
} else {
//set language from cookie
var lang = getLangFromCookie();
if(!!lang) {
sessionScope.lang = lang;
context.setLocale(new Locale(lang.toLowerCase()));
} else {
sessionScope.lang = Appconfig.defaultLang;
context.setLocale(new Locale(Appconfig.defaultLang.toLowerCase()));
}
}
//need to trpa the redirect error thrown here, as it is just a warning - avoid filling log with this
//importPackage(com.ibm.xsp.acl.RedirectSignal);
importPackage(com.ibm.xsp.acl.RedirectSignal);
try {
//reload the page so Locale value kicks in
context.reloadPage();
} catch (RedirectSignal rs) {
//just ignore
}
}
Even though I added the importPackage line, I am still getting an error when saving the code (it is in a script Library):
Encountered " "rs"" at line...
How can I make this work?
Thanks :D
The catch is a Throwable, not a RedirectSignal. Here's the code I use in my handleException function
try {
try {
if (t instanceof RedirectSignal) {
return;
}
if ("javax.faces.el.EvaluationException".equals(t.getClass().getName())) {
if (t.getCause() instanceof RedirectSignal) {
return;
}
}
} catch (Throwable e) {
// Error checking cause, skip
}
// Now log the error
} catch (Throwable e) {
e.printStackTrace();
}
In SSJS you don't define the type/class of the exception in the catch block. Since you're not doing anything with the "exception", there's also no need to import the RedirectSignal class.
try {
context.reloadPage();
} catch ( redirectSignal ) {
// Ignore redirect signal "exception"
}