ES6 inherited function returns wrong type when invoked on subclass - static-analysis

When a function is inherited by a subclass, I want the return type to be as if the function were defined directly on the subclass.
To be clear, the code works fine at run-time. But I want to take advantage of static type-checking. I'm getting red squiggly lines in VScode and warnings from Google-Closure-Compiler. I'm not sure if this is an issue with my ES6 code or with my type annotations.
My trivial example ES6 classes:
// #ts-check
"use strict";
export class db_row {
/**
* #param {number} id
*/
constructor(id) {
/** #type {number} */
this.id = id;
}
clone() {
return new db_row(this.id);
}
}
export class Channel_row extends db_row {
/**
* Constructor
* #param {*=} init
* #param {string=} name
* #param {string=} value
*/
constructor(init, name, value = '') {
let id = -1;
if (typeof init == 'object') {
id = init.id;
name = init.name;
value = init.value;
} else if (typeof init == 'number') {
id = init;
}
super(id);
this.name = name;
this.value = value;
}
clone() {
return new Channel_row(this.id, this.name, this.value);
}
}
export class db_table {
/**
* Constructor
* #param {Array<db_row>} table
*/
constructor(table) {
/**#type {Array<db_row>} */
this.table = table;
}
/**
*/
get_table_copy() { return this.table.map(item => item.clone()) }
/**
* #param {?number=} id
*/
get_row_by_id(id) {
const row = this.table.filter(item => item.id === id)[0];
if (row) return row.clone();
return null;
}
}
export class Channel_table extends db_table {
constructor() {
/**#type {Array<Channel_row>} */
let table = [];
super(table);
}
}
// Test code below:
/**
*
* #param {Channel_row} chan_row
*/
function print_chan_row(chan_row) {
console.log(chan_row.name);
}
let channel_table = new Channel_table();
let channel_row = channel_table.get_row_by_id(0); // hover reports that the type of channel_row is db_row, when it should be type Channel_row
print_chan_row(channel_row); // Red squiggly line error: Argument of type 'db_row' is not assignable to parameter of type 'Channel_row'. Type 'db_row' is missing the following properties from type 'Channel_row': name, valuets(2345)
console.log(channel_row.name); // Red squiggly line error: Property 'name' does not exist on type 'db_row'.ts(2339)
let channel_table_2 = channel_table.get_table_copy(); // hover reports that the type of channel_row is db_row[], when it should be type Channel_row[]
print_chan_row(channel_table_2[0]); // Red squiggly line error: Argument of type 'db_row' is not assignable to parameter of type 'Channel_row'.ts(2345)
Now, if I move or copy the get_row_by_id() and get_table_copy() functions into the subclass, the type errors go away. But I don't want to duplicate code unnecessarily.
How can I declare the functions in the parent class so it can be reused in child classes, but maintain the static type checking?
As a bonus, can I also generalize the clone() function so it doesn't need to be over-ridden in subclasses of db_row?

Related

Hide header and footer in custom pdf Prestashop

I made method to print custom pdf in my module in Prestashop 1.7.4.1. Everything works fine, but it print header with shop logo and footer with information about electronic invoice on every page. How can I hide them that my template take all size of the printed page?
I've tried to add to my pdf object code from tcpdf example but it seems I don't use TCPDF in presta:
$pdf->setPrintHeader(false);
$pdf->setPrintFooter(false);
This is my class:
class HTMLTemplateCustomPdf extends HTMLTemplate
{
public $custom_model;
public function __construct($custom_object, $smarty)
{
$this->custom_model = $custom_object;
$this->smarty = $smarty;
}
/**
* Returns the template's HTML content
* #return string HTML content
*/
public function getContent()
{
//here I get content
return $this->smarty->fetch(_PS_MODULE_DIR_ . 'ps_first_module/views/templates/hook/pdf.tpl');
}
/**
* Returns the template filename
* #return string filename
*/
public function getFilename()
{
return 'custom_pdf.pdf';
}
/**
* Returns the template filename when using bulk rendering
* #return string filename
*/
public function getBulkFilename()
{
return 'custom_pdf.pdf';
}
This is where I create pdf object:
if (Tools::isSubmit('print')) {
if (Shop::getContext() != Shop::CONTEXT_GROUP && Shop::getContext() != Shop::CONTEXT_ALL) {
require_once _PS_MODULE_DIR_ . 'ps_first_module/HTMLTemplateCustomPdf.php';
$orientation = 'L';
$pdf = new PDF($custom_object, 'CustomPdf', Context::getContext()->smarty, $orientation);
$pdf->render();
}
}
EDIT:
This is my PDFGenerator.php override. Should I put this in root/override/classes/pdf or my_module/override/classes/pdf?
<?php
class PDFGenerator extends PDFGeneratorCore
{
/**
* #param bool $use_cache
* #param string $orientation
*/
public function __construct($use_cache = false, $orientation = 'L')
{
parent::__construct($orientation, 'mm', 'A4', true, 'UTF-8', $use_cache, false);
$this->setRTL(Context::getContext()->language->is_rtl);
}
/**
* Write a PDF page
*/
public function writePage()
{
if(!$this->header){
$this->SetHeaderMargin(0);
}
else{
$this->SetHeaderMargin(5);
}
if(!$this->footer){
$this->SetFooterMargin(0);
}
else{
$this->SetFooterMargin(21);
}
$this->setMargins(10, 10, 10);
$this->AddPage();
$this->writeHTML($this->content, true, false, true, false, '');
}
}
I've tried in version 1.7.2 and file properties mention Producer: TCPDF 6.2.12 (http://www.tcpdf.org). Also, class Pdf in function render() as:
$this->pdf_renderer->createHeader($template->getHeader());
$this->pdf_renderer->createFooter($template->getFooter());
So, the best way would be your class HTMLTemplateCustomPdf to include the functions getHeader() and getFooter() to return false (or empty) otherwise it will use those from HTMLTemplateCore.
In the override for PDFGenerator, you can do something like:
public function writePage()
{
if(!$this->header){
$this->SetHeaderMargin(0);
}
else{
$this->SetHeaderMargin(5);
}
if(!$this->footer){
$this->SetFooterMargin(0);
}
else{
$this->SetFooterMargin(21);
}
$this->setMargins(10, 40, 10);
$this->AddPage();
$this->writeHTML($this->content, true, false, true, false, '');
}
You can also set different margins if needed in $this->setMargins(10, 40, 10);

visual studio 2017 goto method in file

I am trying to use VS 2017 on my typescript project. I am using the goto member and trying to navigate to methods in my current file. However, VS 2017 does not seem to filter the methods properly. In the goto I am using "m and currentfile" and for example, if I try to filter "extractData", it does not seem to filter properly.
My .ts file is as follows.
export class FooterLinksServiceSiteCore implements FooterLinksService {
/**
*
* #param {Http} private http [description]
*/
constructor(private http: Http) {
}
/**
* [LoadFooterLinks description]
* #return {Observable<FooterLink[]>} [description]
*/
get(footerValuesLink: string): Observable<FooterLink[]> {
}
/**
* [extractData description]
* #param {Response} res [description]
*/
private extractData(res: Response): Array<FooterLink> {
let mappedFooterLinks: Array<FooterLink> = new Array<FooterLink>();
let footerLinks = res.json();
footerLinks.forEach(footerLink => {
mappedFooterLinks.push(new FooterLink(footerLink.Title, footerLink.Url));
});
return mappedFooterLinks;
}
/**
* [handleError description]
* #param {Response | any} error [description]
*/
private handleError(error: Response | any) {
// In a real world app, we might use a remote logging infrastructure
let errMsg: string;
if (error instanceof Response) {
const body = error.json() || '';
const err = body.error || JSON.stringify(body);
errMsg = `${error.status} - ${error.statusText || ''} ${err}`;
} else {
errMsg = error.message ? error.message : error.toString();
}
console.error(errMsg);
return Observable.throw(errMsg);
}
}

ITextSharp - get image at a particular location

What I need to do is extract a 2D DataMatrix (bitmap) bar code and read it. I can make this work however, I have to loop through all the images on every page. This is taking a long time when I have 1000’s of pages, so I was wondering if it was possible to define a location(rectangle)of where the image(barcode) was and just extract that image?
The bar code is always i the same location.
note: I'm using Spire.Barcode from e-IceBlue
Thank you for any help.
CODE RenderFilter snippet:
public class MyRegionTextRenderFilter : RenderFilter {
/** the region to allow text from */
private RectangleJ filterRect;
public PdfImageObject image;
/**
* Constructs a filter
* #param filterRect the rectangle to filter text against. Note that this is a java.awt.Rectangle !
*/
public MyRegionTextRenderFilter(RectangleJ filterRect) {
this.filterRect = filterRect;
}
/**
* Constructs a filter
* #param filterRect the rectangle to filter text against.
*/
public MyRegionTextRenderFilter(iTextSharp.text.Rectangle filterRect)
{
this.filterRect = new RectangleJ(filterRect);
}
/**
* #see com.itextpdf.text.pdf.parser.RenderFilter#allowText(com.itextpdf.text.pdf.parser.TextRenderInfo)
*/
public override bool AllowImage(ImageRenderInfo renderInfo)
{
var matrix = renderInfo.GetImageCTM();
float left = matrix[6];
float top = matrix[7];
float width = matrix[0];
float height = matrix[4];
return filterRect.IntersectsLine(left, top, width, height);
}
}
Code calling :
RectangleJ rect = new RectangleJ(518.0f, 18.0f, 23.0f, 23.0f);
PdfReaderContentParser parser2 = new PdfReaderContentParser(pdfReader);
RenderFilter[] renderFilter = new RenderFilter[1];
renderFilter[0] = new MyRegionTextRenderFilter(rect);
FilteredTextRenderListener listener2 = new FilteredTextRenderListener(new LocationTextExtractionStrategy(), renderFilter);
parser2.ProcessContent(3, listener2);
The parser namespace of iText(Sharp) allows filtering of information digested by an IRenderListener implementation by using a RenderFilter:
public abstract class RenderFilter {
/**
* #param renderInfo
* #return true if the text render operation should be performed
*/
public virtual bool AllowText(TextRenderInfo renderInfo){
return true;
}
/**
*
* #param renderInfo
* #return true is the image render operation should be performed
*/
public virtual bool AllowImage(ImageRenderInfo renderInfo){
return true;
}
}
For filtering by area there already is a textual render filter, the RegionTextRenderFilter.
For your task simply copy it and add an AllowImage(ImageRenderInfo renderInfo) implementation similar to the existing AllowText(TextRenderInfo renderInfo) method.

Varien_Data_Collection pagination not working

I have been created a Varien_Data_Collection from scratch:
$myCollection = new Varien_Data_Collection();
after add some items into it, $myCollection->addItem($fooItem);, I tried to paginate it with:
$myCollection->setPageSize(3)->setCurPage(1);
but when I display the collection, it shows all items in the collection instead the first, second o N page.
$myItems = $myCollection->getItems();
foreach ($myItems as $item) {
echo $item->getData('bar');
}
The (non-abstract) base-class Varien_Data_Collection - although it does have the setPageSize and setCurPage methods, those are not reflected within the aggregation of the Iterator:
class Varien_Data_Collection implements IteratorAggregate, Countable
{
...
/**
* Implementation of IteratorAggregate::getIterator()
*/
public function getIterator()
{
$this->load();
return new ArrayIterator($this->_items);
}
...
It will in any case return an ArrayIteator that has all objects. The load method doesn't change a thing here btw:
...
/**
* Load data
*
* #return Varien_Data_Collection
*/
public function loadData($printQuery = false, $logQuery = false)
{
return $this;
}
...
/**
* Load data
*
* #return Varien_Data_Collection
*/
public function load($printQuery = false, $logQuery = false)
{
return $this->loadData($printQuery, $logQuery);
}
...
I'd say this qualifies as a bug, as the public interface makes one assume that the magent collection object Varien_Data_Collection provides pagination while it does not.
I have not searched for a bug-report regarding this issue. The solution is to use another iterator for pagination, for example like outlined in an answer to How to Paginate lines in a foreach loop with PHP with PHP's LimitIterator:
/**
* Class Varien_Data_Collection_Pagination
*
* Aggregates missing Pagination on Collection on getting the Iterator
*
* #author hakre <http://hakre.wordpress.com/>
*/
class Varien_Data_Collection_Pagination implements IteratorAggregate
{
/**
* #var Varien_Data_Collection
*/
private $collection;
public function __construct(Varien_Data_Collection $collection)
{
$this->collection = $collection;
}
public function getIterator()
{
$collection = $this->collection;
if (FALSE === $size = $collection->getPageSize()) {
return $collection;
}
$page = $collection->getCurPage();
if ($page < 1) {
return $collection;
}
$offset = $size * $page - $size;
return new LimitIterator(new IteratorIterator($collection), $offset, $size);
}
}
Usage Example:
$collection = new Varien_Data_Collection();
$collectionIterator = new Varien_Data_Collection_Pagination($collection);
# [...] fill collection
# set pagination:
$collection->setPageSize(3);
$collection->setCurPage(1);
echo iterator_count($collectionIterator); # 3 (int)
Keep in mind that this is mainly an example. IMHO this should be fixed upstream within the Magento codebase, so it's perhaps worth you do some search work in the Magento Bug-Tracker.
As explained in previous post Varien_Data_collection does not support pagination. One solution would be to extend this class and overwrite its loadData() method. Here is practical example of paginating array of stdClass objects. Can be used with any array of data
class YourNamespace_YourModule_Model_History_Collection extends Varien_Data_Collection{
//array of stdClass objects. Can be array of any objects/subarrays
protected $_history = array();
public function loadData($printQuery = false, $logQuery = false){
if ($this->isLoaded()) {
return $this;
}
$this->_totalRecords = count($this->_history);
$this->_setIsLoaded();
// paginate and add items
$from = ($this->getCurPage() - 1) * $this->getPageSize();
$to = $from + $this->getPageSize() ;
$isPaginated = $this->getPageSize() > 0;
$cnt = 0;
$sub_history = array_slice($this->_history, $from, $to-$from);
foreach ( $sub_history as $entry) {
$cnt++;
$item = new $this->_itemObjectClass();
//build here your Varien Object
$item->setDate($entry->Date);
//.......
$this->addItem($item);
if (!$item->hasId()) {
$item->setId($cnt);
}
}
return $this;
}
public function setRecords($records){
if(is_array($records)){
$this->_history = $records;
}
return;
}
}
//Your block class
class YourNamespace_YourModule_Block_History extends Mage_Core_Block_Template{
public function __construct(){
$collection_prepared = new YourNamespace_YourModule_Model_History_Collection();
//get your data here
//$records is array of stdClass objects
$collection_prepared->setRecords($records);
$this->setCollection($collection_prepared);
}
protected function _prepareLayout(){
parent::_prepareLayout();
$pager = $this->getLayout()->createBlock('page/html_pager', 'history.pager');
$pager->setAvailableLimit(array(20=>20,40=>40,80=>80,'all'=>'all'));
$pager->setCollection($this->getCollection());
$this->setChild('pager', $pager);
$this->getCollection()->load();
return $this;
}
public function getPagerHtml()
{
return $this->getChildHtml('pager');
}
}
Hope this helps!
class Pageable_Varien_Data_Collection extends Varien_Data_Collection
{
/**
* Load data
*
* #param bool $printQuery
* #param bool $logQuery
*
* #return Pageable_Varien_Data_Collection
*/
public function load($printQuery = false, $logQuery = false)
{
if ($this->isLoaded()) {
return $this;
}
$this->_renderLimit();
$this->_setIsLoaded();
return $this;
}
/**
* #return Pageable_Varien_Data_Collection
*/
protected function _renderLimit()
{
if ($this->_pageSize) {
$currentPage = $this->getCurPage();
$pageSize = $this->_pageSize;
$firstItem = (($currentPage - 1) * $pageSize + 1);
$lastItem = $firstItem + $pageSize;
$iterator = 1;
foreach ($this->getItems() as $key => $item) {
$pos = $iterator;
$iterator++;
if ($pos >= $firstItem && $pos <= $lastItem) {
continue;
}
$this->removeItemByKey($key);
}
}
return $this;
}
/**
* Retrieve collection all items count
*
* #return int
*/
public function getSize()
{
if (is_null($this->_totalRecords)) {
$this->_totalRecords = count($this->getItems());
}
return intval($this->_totalRecords);
}
/**
* Retrieve collection items
*
* #return array
*/
public function getItems()
{
return $this->_items;
}
}

I have a modal Window implemented in SmartGWT - how can I close it when someone clicks off of the window?

I've created a class that extends the Window SmartGWT class, and it is set to be modal. I am trying to make the Window close when a user clicks off the window. I have tried to link it up to a FocusChangedHandler with no luck. Has anyone done something like this before?
/**
* Sets up a modal Dialog box that lets the user edit attributes associated
* with the properties of the {#link LabElement} that are given.
*
* #author Therin Irwin
*/
public class EditorDialog extends Window {
final DynamicForm dyn = new DynamicForm();
final RichTextEditor richTextEditor = new RichTextEditor();
final List attrItems = new ArrayList();
/**
* Creates a new EditorDialog with a RichTextEditor and a list of
* attributes for the element.
*
* #param name the name of the element being edited.
* #param attr the List of String attributes of the element that can be
* edited.
* #param hasText true if the element supports text inside, false if not.
*/
public EditorDialog(String name, List attr, boolean hasText) {
super();
VLayout vert = new VLayout();
this.setShowMinimizeButton(false);
this.setIsModal(true);
this.setShowModalMask(true);
this.setTitle(name + " Editor");
richTextEditor.setWidth(550);
richTextEditor.setHeight(100);
richTextEditor.setPadding(5);
richTextEditor.setCanDragResize(true);
richTextEditor.setResizeFrom("B");
richTextEditor.setShowEdges(true);
if (attr == null || attr.size() == 0) {
richTextEditor.setHeight(300);
}
else {
int i = 0;
FormItem[] fi = new FormItem[attr.size()];
for (String at : attr) {
TextItem temp = new TextItem(at, at);
attrItems.add(temp);
fi[i++] = temp;
}
dyn.setFields(fi);
dyn.setPadding(5);
dyn.setTop(100);
}
if (hasText)
vert.addMember(richTextEditor);
if (!(attr == null || attr.size() == 0))
vert.addMember(dyn);
this.addItem(vert);
this.centerInPage();
this.setAutoSize(true);
}
/**
* Returns the text of the RichTextEditor.
*
* #return the text entered into the RichTextEditor.
*/
public String getRichText() {
return richTextEditor.getValue();
}
/**
* Sets the text in the RichTextEditor to String value.
*
* #param value the String to put as the contents of the RichTextEditor.
*/
public void setRichText(String value) {
richTextEditor.setValue(value);
}
/**
* Returns the List of TextItems that hold the user-entered values for
* attributes.
*
* #return the TextItems associated with each attribute, in order.
*/
public DynamicForm getFormItems() {
return dyn;
}
public TextItem getFormItem(int item) {
return (TextItem) dyn.getFields()[item];
}
}
#Therin
I guess according to your requirement, you need to implement this property of Window:
this.setDismissOnOutsideClick(true);

Resources