How to upload PDF files from femanager extension TYPO3 11.5 - file-upload

I am tryng to upload pdf files from the frontend with the user profile form (femanager), it only allows me to use the "Image" field, but for this case more pdf file fields are needed.
I have the following custom field for it
<f:form.upload
id="femanager_field_pdf"
property="pdf.0"
class="custom-file-input" />
In the extended User class
/**
* #var ObjectStorage<FileReference>
*/
protected $pdf;
/**
* Gets the pdf value
*
* #return ObjectStorage<FileReference>
*/
public function getPdf()
{
return $this->pdf;
}
/**
* Sets the pdf value
*
* #param ObjectStorage<FileReference> $pdf
*/
public function setpdf(ObjectStorage $pdf)
{
$this->pdf = $pdf;
}
I expected that when saving the user profile form the file would be saved in the "pdf" field but it generates an error
Exception while property mapping at property path "pdf.0": Property "name" was not found in target object of type "TYPO3\CMS\Extbase\Domain\Model\FileReference".

Related

error when sending a notification 'Call to undefined method App\Models\Role::routeNotificationFor()'

I am building a web app whereby after an admin(with the role of a manager) approves a booking, the booking passes to another admin(with the role of an accountant) who then starts working on it.I want the manager to send a notification to only the accountant after approving the booking.i tried this code below and it sends to all admins which is not what I want to achieve
$users=User::where('is_admin','1')->get();
Notification::send($users,new Newbookingrecieved($bookingstatus));
then i tried getting the email from the role model
$users=Role::where('Role_name','The Accountant')->get();
Notification::send($users,new Newbookingrecieved($bookingstatus));
but it responded with an error
BadMethodCallException
Call to undefined method App\Models\Role::routeNotificationFor()
here is my notification
<?php
namespace App\Notifications;
use App\Models\Bookings;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Notifications\Messages\MailMessage;
use Illuminate\Notifications\Notification;
class Newbookingrecieved extends Notification
{
use Queueable;
public $bookingstatus;
/**
* Create a new notification instance.
*
* #return void
*/
public function __construct($bookingstatus)
{
$this->bookingstatus = $bookingstatus;
}
/**
* Get the notification's delivery channels.
*
* #param mixed $notifiable
* #return array
*/
public function via($notifiable)
{
return ['mail'];
}
/**
* Get the mail representation of the notification.
*
* #param mixed $notifiable
* #return \Illuminate\Notifications\Messages\MailMessage
*/
public function toMail($notifiable)
{
return (new MailMessage)
->greeting('Hello there sir/madam')
->subject('New Booking by' .$this->bookingstatus->full_name)
->line('We have received a new Booking and approved it to you to request payment from the client' . $this->bookingstatus->email)
->action('Review This Booking', route('changestatus', $this->bookingstatus->id));
}
/**
* Get the array representation of the notification.
*
* #param mixed $notifiable
* #return array
*/
public function toArray($notifiable)
{
return [
//
];
}
}
here are all the roles
how can i achieve this such that i send the notification to the only adminand the notification wont be sent to other admins.
As I don't know the structure of your User model, I will assume that there is a role_id field.
Here is a piece of my code from one of my old projects that I will modify to your liking (it works for me) :
$users = User::where('role_id', 3)->get(); //3 is the id of The Accountant role
Notification::send($users, new Newbookingrecieved($bookingstatus));

GCP api key restrictions

In my GCP project, I created a new api key. I restricted the key to IOS apps, and properly set my IOS application bundle id.
The api key is being used in an Ionic 5 app, which has been built in Xcode and is running on an IOS device.
The api key is being passed on a Google Maps static API request.
To test the api key restriction I crafted a url that looks like this:
https://maps.googleapis.com/maps/api/staticmap?center=290%20Bremner%20Blvd%2C%20Toronto%2C%20ON%20M5V%203L9&key=[restricted key here]&zoom=12&size=400x400
When I load this url from my laptop web browser a map is returned, but I expected this not to work, and instead that I would receive an http 403 error.
Any insight into what I'm missing here appreciated; how do I properly restrict my maps api key when using it in an Ionic 5 app?
I found the answer to my question: in addition to using a restricted API key, each Maps Static API request must be digitally signed when making the request.
Here's sample Node js code from Google on how to do this:
'use strict'
const crypto = require('crypto');
const url = require('url');
/**
* Convert from 'web safe' base64 to true base64.
*
* #param {string} safeEncodedString The code you want to translate
* from a web safe form.
* #return {string}
*/
function removeWebSafe(safeEncodedString) {
return safeEncodedString.replace(/-/g, '+').replace(/_/g, '/');
}
/**
* Convert from true base64 to 'web safe' base64
*
* #param {string} encodedString The code you want to translate to a
* web safe form.
* #return {string}
*/
function makeWebSafe(encodedString) {
return encodedString.replace(/\+/g, '-').replace(/\//g, '_');
}
/**
* Takes a base64 code and decodes it.
*
* #param {string} code The encoded data.
* #return {string}
*/
function decodeBase64Hash(code) {
// "new Buffer(...)" is deprecated. Use Buffer.from if it exists.
return Buffer.from ? Buffer.from(code, 'base64') : new Buffer(code, 'base64');
}
/**
* Takes a key and signs the data with it.
*
* #param {string} key Your unique secret key.
* #param {string} data The url to sign.
* #return {string}
*/
function encodeBase64Hash(key, data) {
return crypto.createHmac('sha1', key).update(data).digest('base64');
}
/**
* Sign a URL using a secret key.
*
* #param {string} path The url you want to sign.
* #param {string} secret Your unique secret key.
* #return {string}
*/
function sign(path, secret) {
const uri = url.parse(path);
const safeSecret = decodeBase64Hash(removeWebSafe(secret));
const hashedSignature = makeWebSafe(encodeBase64Hash(safeSecret, uri.path));
return url.format(uri) + '&signature=' + hashedSignature;
}
More information / documentation here:
https://developers.google.com/maps/documentation/maps-static/get-api-key#gen-sig

Selenium 1 - switch to iframe without ID

The page i crape have removed the ID from their iframe, so I have a problem switching to the iframe, and I can't find any documentation to help me, so maybe there is someone here on Stack?
The url of the page is: http://www.klappen.se/boka/onlinebokning/
I'm using Selenium 1 and my code looks like this:
$this->_driver->switchTo()->getFrameByName("mainframe");
In my TargetLocator.php i have these functions:
<?php
// Copyright 2012-present Nearsoft, Inc
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
namespace SeleniumClient;
require_once 'WebDriver.php';
class TargetLocator
{
private $_driver;
public function __construct(WebDriver $driver)
{
$this->_driver = $driver;
}
#region TargetLocator members
/**
* Move to a different frame using its index
* #param Integer $frameIndex
* #return current WebDriver
*/
public function getFrameByIndex($frameIndex)
{
$this->_driver->getFrame($frameIndex);
return $this->_driver;
}
/**
* Move to different frame using its name
* #param String $frameName
* #return current WebDriver
*/
public function getFrameByName($frameName)
{
//We should validate that frameName is string
/*
if ($frameName == null)
{
throw new ArgumentNullException("frameName", "Frame name cannot be null");
}
*/
$this->_driver->getFrame($frameName);
return $this->_driver;
}
/**
* Move to a frame element.
* #param WebElement $frameElement
* #return current WebDriver
*/
public function getFrameByWebElement(WebElement $frameElement)
{
//We should validate that frameElement is string
/*
if (frameElement == null)
{
throw new ArgumentNullException("frameElement", "Frame element cannot be null");
}
RemoteWebElement convertedElement = frameElement as RemoteWebElement;
if (convertedElement == null)
{
throw new ArgumentException("frameElement cannot be converted to RemoteWebElement", "frameElement");
}
*/
$frameId = $frameElement->getElementId();
$target = array('ELEMENT' => $frameId);
$this->_driver->getFrame($target);
return $this->_driver;
}
/**
* Change to the Window by passing in the name
* #param String $windowName
* #return current WebDriver
*/
public function getWindow($windowName)
{
$this->_driver->getWindow($windowName);
return $this->_driver;
}
/**
* Change the active frame to the default
* #return current WebDriver
*/
public function getDefaultFrame()
{
$this->_driver->getFrame(null);
return $this->_driver;
}
/**
* Finds the active element on the page and returns it
* #return WebElement
*/
public function getActiveElement()
{
$webElement = null;
$webElement = $this->_driver->getActiveElement();
return $webElement;
}
/**
* Switches to the currently active modal dialog for this particular driver instance.
* #return \SeleniumClient\Alert
*/
public function getAlert()
{
// N.B. We only execute the GetAlertText command to be able to throw
// a NoAlertPresentException if there is no alert found.
//$this->_driver->getAlertText();
return new Alert($this->_driver); //validate that the Alert object can be created, if not throw an exception, try to use a factory singleton o depency of injection to only use 1 instance
}
#endregion
}
I have tried them all, but can't get it to work. Is there anybody out there who can help:-)?
Thanks in advance.
As far as i see you are looking for this iFrame:
<iframe src="http://dlbookit3.dlsystems.se/dlbookitKSR/bmlogifilt/logifilt.aspx" style="height:700px; width:100%; border:0;"></iframe>
right? So you have a method like getFrameByWebElement(WebElement) which accepts a WebElement. I think you can use an xpath to find the webElement e.g.:
WebElement element = find(By.xpath("//iframe"));
getFrameByWebElement(element);
so far in theory this could work (this is Java, you have to adapt it for your php code). But if I analyze the HTML code of the page with chrome I cannot locate the webElement by using the xpath //iframe.
Still you can try... but it looks like that the page owner doesn't want its iFrame to be locateable anymore :-)
There is only 1 IFRAME on the page so you can just find it by tag name. The page loaded very slowly for me but I'm in the US so that may have something to do with it. You may have to wait for the IFRAME to become available and then get a handle to it.

Lack of response and typing info in API Explorer

I am using the latest version of Restler v3 (commit 0d79cd8) but I'm having some problems having my Swagger-based UI look the same as in the examples. The two problems I'm noticing are that variable typing and #return objects are not being displayed.
On the Restler site, here's a good example of both of these working:
example
Instead, in my Actions class I get this:
And yet as you can see from definition of the class both type information and a response object is specified:
class Actions {
/**
* LIST action types
*
* List all the action-types available
*
* #url GET /
*/
function list_actions() {
throw new RestException(501);
}
/**
* GET today's Actions
*
* Get the set of actions done today
*
* #url GET /{user_id}
* #param integer $user_id The user_id for whom the actions apply; you can insert the text "self" and it will resolve to the current/default user
* #param string $time_of_day {#from url} Allow's you to optionally set a time-of-day; if set then actions are only returned after that. Time should be in the format of HH:MM:SS
* #return ActionList
*/
public function action_today ($user_id, $time_of_day = false )
{
throw new RestException(501, "Today's actions for user '{$user_id}' not implemented.");
}
and my definition of ActionList class is:
class ActionList {
/**
* Unique identifier of action
*
* #var integer
*/
public $action_id;
/**
* String based unique identifier
*
* #var string
*/
public $action_slug;
}
If your class is versioned, e.g. in the namespace v1\Actions, you have to annotate the return type in the namespace too, e.g. #return v1\ActionList

render view in yii console application

I have an email template in a view and I want to write a process that is ConsoleApplication that prepares emails to be send. Becouse it is ConsoleApplication I have no access to controller. Is it any way to render a view?
Here is what I use:
private function render($template, array $data = array()){
$path = Yii::getPathOfAlias('application.views.email').'/'.$template.'.php';
if(!file_exists($path)) throw new Exception('Template '.$path.' does not exist.');
return $this->renderFile($path, $data, true);
}
It takes email template from views/email.
If all else fails (as in my case):
<?php
/**
* Renders a view file & returns result.
* #param string $_viewFile_ view file path
* #param array $_data_ optional data to be extracted as local view variables
* #param boolean $_return_ whether to return the rendering result instead of displaying it
* #return mixed the rendering result if required. Null otherwise.
*/
public function myRenderPartial($_viewFile_,$_data_=null,$_return_=true) {
if(is_array($_data_))
extract($_data_,EXTR_PREFIX_SAME,'data');
else
$data=$_data_;
if($_return_)
{
ob_start();
ob_implicit_flush(false);
require(YiiBase::getPathOfAlias("application.views").$_viewFile_.'.php');
return ob_get_clean();
}
else
{
require($_viewFile_);
}
}
?>