I am new to PHP and trying to a third party code namely Big blue button api
https://github.com/bigbluebutton/bigbluebutton/tree/master/labs/bbb-api-php
I try to call BigBlueButton->createMeeting() function which looks like this :
public function createMeeting($createMeetingParams, $xml = '')
{
$xml = $this->processXmlResponse($this
->getCreateMeetingURL($createMeetingParams), $xml);
//$xml is fine
return new CreateMeetingResponse($xml);
}
CreateMeetingResponse class
namespace BigBlueButton\Responses;
/**
* Class CreateMeetingResponse
* #package BigBlueButton\Responses
*/
class CreateMeetingResponse extends BaseResponse
{
/**
* #return string
*/
public function getMeetingId()
{
return $this->rawXml->meetingID->__toString();
}
/**
* #return string
*/
public function getAttendeePassword()
{
return $this->rawXml->attendeePW->__toString();
}
/**
* #return string
*/
public function getModeratorPassword()
{
return $this->rawXml->moderatorPW->__toString();
}
/**
* Creation timestamp.
*
* #return double
*/
public function getCreationTime()
{
return doubleval($this->rawXml->createTime);
}
/**
* #return int
*/
public function getVoiceBridge()
{
return intval($this->rawXml->voiceBridge);
}
/**
* #return string
*/
public function getDialNumber()
{
return $this->rawXml->dialNumber->__toString();
}
/**
* Creation date at the format "Sun Jan 17 18:20:07 EST 2016".
*
* #return string
*/
public function getCreationDate()
{
return $this->rawXml->createDate->__toString();
}
/**
* #return true
*/
public function hasUserJoined()
{
return $this->rawXml->hasUserJoined->__toString() == 'true';
}
/**
* #return int
*/
public function getDuration()
{
return intval($this->rawXml->duration);
}
/**
* #return bool
*/
public function hasBeenForciblyEnded()
{
return $this->rawXml->hasBeenForciblyEnded->__toString() == 'true';
}
/**
* #return string
*/
public function getMessageKey()
{
return $this->rawXml->messageKey->__toString();
}
/**
* #return string
*/
public function getMessage()
{
$this->rawXml->message->__toString();
}
}
BaseResponse class
namespace BigBlueButton\Parameters;
/**
* Class BaseParameters.
*/
abstract class BaseParameters
{
/**
* #param $array
*
* #return string
*/
protected function buildHTTPQuery($array)
{
return http_build_query(array_filter($array));
}
/**
* #return string
*/
abstract public function getHTTPQuery();
}
Now when I do call the BigBlueButton->createMeeting() function, I am expecting an object which I can encode to json ,But what I get is this (I have used print_r() here..):
BigBlueButton\Responses\CreateMeetingResponse Object
(
[rawXml:protected] => SimpleXMLElement Object
(
[returncode] => FAILED
[messageKey] => idNotUnique
[message] => A meeting already exists with that meeting ID. Please use a different meeting ID.
)
)
I am not sure what is happening but I think the prefixed namespace 'BigBlueButton\Responses\CreateMeetingResponse Object' is the problem. I want to parse the response I get to an json object in php but cannot
Here is where I try to parse it
function easymeet_create_meeting($id) {
// Create BBB object
$bbb = new BigBlueButton\BigBlueButton();
//creating meeting parameter
$meetingParas=new BigBlueButton\Parameters\CreateMeetingParameters('123456','sned');
//Creatign meeting
return json_encode($bbb->createMeeting($meetingParas));
///print_r($bbb->createMeeting($meetingParas)) give the xml response shown above
}
The return part looks right. The error you are getting is coming from BigBlueButton->createMeeting()
You already have created a meeting with the ID you used. Are you generating a new Meeting ID to pass in with the XML when you create a new meeting?
Edit:
To be able to json_encode the response you will need to use the getRawXml() function since $rawXml is a protected property of the base class and the rest of the class is just methods. So:
public function createMeeting($createMeetingParams, $xml = '')
{
$xml = $this->processXmlResponse($this
->getCreateMeetingURL($createMeetingParams), $xml);
//$xml is fine
$resp = new CreateMeetingResponse($xml);
return $resp->getRawXml();
}
Should return just the SimpleXMLElement which you can then json_encode.
Related
I am testing my model in isolation and keep getting this error. I thought perhaps it is my assert function but I want to check if what list I created a new instance with is the same as the list found.
Here is my model:
class ArchiveShoppingListModel
{
/**
* #var string
*/
private string $list;
/**
* ArchiveShoppingListModel constructor.
*
* #param string $list
*/
public function __construct(string $list)
{
$this->list = $list;
}
/**
* #return string
*/
public function getList(): string
{
return $this->list;
}
}
And here is my test:
class ArchiveShoppingListModelTest extends TestCase
{
/**
* #param string $list
* #return void
*/
public function test(string $list): void
{
$model = new ArchiveShoppingListModel('groceries');
$this->assertSame($list, $model->getList());
}
}
Why you make $list as a parameter in unit test? If you want to check by unit test you'd better use
public function test(): void
{
$list = ....; // the list you expect
$model = new ArchiveShoppingListModel('groceries');
$this->assertSame($list, $model->getList());
}
I am trying to use a package a link! and when after installation I tried to run this project it just failed and started giving me the error of Undefined Property.
So if anyone could help me out.
Its getting harder to complete my project with these errors
IPstack.php
namespace Voerro\Laravel\VisitorTracker\Geoip;
class Ipstack extends Driver
{
protected function getEndpoint($ip)
{
$key = config('visitortracker.ipstack_key');
return "http://api.ipstack.com/{$ip}?access_key={$key}";
}
public function latitude()
{
return $this->data->latitude;
}
public function longitude()
{
return $this->data->longitude;
}
public function country()
{
return $this->data->country_name;
}
public function countryCode()
{
return $this->data->country_code;
}
public function city()
{
return $this->data->city;
}
}
Driver.php
namespace Voerro\Laravel\VisitorTracker\Geoip;
use Voerro\Laravel\VisitorTracker\Models\Visit;
use GuzzleHttp\Client;
abstract class Driver
{
/**
* Holds data fetched from a remote geoapi service
*
* #var Object
*/
protected $data;
/**
* Fetch data from a remote geoapi service
*
* #param Voerro\Laravel\VisitorTracker\Models\Visit $visit
* #return $this
*/
public function getDataFor(Visit $visit)
{
$client = new Client();
$response = $client->get($this->getEndpoint($visit->ip));
if ($response->getStatusCode() == 200) {
$this->data = json_decode($response->getBody()->getContents());
return $this;
}
return null;
}
/**
* Returns an endpoint to fetch the data from
*
* #param string $ip IP address to fetch geolocation data for
* #return string
*/
abstract protected function getEndpoint($ip);
/**
* Returns latitude from the fetched data
*
* #return string
*/
abstract public function latitude();
/**
* Returns longitude from the fetched data
*
* #return string
*/
abstract public function longitude();
/**
* Returns country from the fetched data
*
* #return string
*/
abstract public function country();
/**
* Returns country code from the fetched data
*
* #return string
*/
abstract public function countryCode();
/**
* Returns city from the fetched data
*
* #return string
*/
abstract public function city();
}
So here is the driver.php if you could find the error.
I'm trying to "use" a vendor script to connect to feefo api (an online reviews service) but when I try and use the script it gives me this error:
Type error: Argument 1 passed to
BlueBayTravel\Feefo\Feefo::__construct() must be an instance of
GuzzleHttp\Client, null given, called in/Users/webuser1/Projects/_websites/domain.co.uk/plugins/gavinfoster/feefo/components/Feedback.php on line 47
Here is the vendor code I'm using:
/*
* This file is part of Feefo.
*
* (c) Blue Bay Travel <developers#bluebaytravel.co.uk>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace BlueBayTravel\Feefo;
use ArrayAccess;
use Countable;
use Exception;
use GuzzleHttp\Client;
use Illuminate\Contracts\Config\Repository;
use Illuminate\Contracts\Support\Arrayable;
use SimpleXMLElement;
/**
* This is the feefo class.
*
* #author James Brooks <james#bluebaytravel.co.uk>
*/
class Feefo implements Arrayable, ArrayAccess, Countable
{
/**
* The guzzle client.
*
* #var \GuzzleHttp\Client
*/
protected $client;
/**
* The config repository.
*
* #var \Illuminate\Contracts\Config\Repository
*/
protected $config;
/**
* The review items.
*
* #var array
*/
protected $data;
/**
* Create a new feefo instance.
*
* #param \GuzzleHttp\Client $client
* #param \Illuminate\Contracts\Config\Repository $config
*
* #return void
*/
public function __construct(Client $client, Repository $config)
{
$this->client = $client;
$this->config = $config;
}
/**
* Fetch feedback.
*
* #param array|null $params
*
* #return \BlueBayTravel\Feefo\Feefo
*/
public function fetch($params = null)
{
if ($params === null) {
$params['json'] = true;
$params['mode'] = 'both';
}
$params['logon'] = $this->config->get('feefo.logon');
$params['password'] = $this->config->get('feefo.password');
try {
$body = $this->client->get($this->getRequestUrl($params));
return $this->parse((string) $body->getBody());
} catch (Exception $e) {
throw $e; // Re-throw the exception
}
}
/**
* Parses the response.
*
* #param string $data
*
* #return \Illuminate\Support\Collection
*/
protected function parse($data)
{
$xml = new SimpleXMLElement($data);
foreach ((array) $xml as $items) {
if (isset($items->TOTALRESPONSES)) {
continue;
}
foreach ($items as $item) {
$this->data[] = new FeefoItem((array) $item);
}
}
return $this;
}
/**
* Assigns a value to the specified offset.
*
* #param mixed $offset
* #param mixed $value
*
* #return void
*/
public function offsetSet($offset, $value)
{
if (is_null($offset)) {
$this->data[] = $value;
} else {
$this->data[$offset] = $value;
}
}
/**
* Whether or not an offset exists.
*
* #param mixed $offset
*
* #return bool
*/
public function offsetExists($offset)
{
return isset($this->data[$offset]);
}
/**
* Unsets an offset.
*
* #param mixed $offset
*
* #return void
*/
public function offsetUnset($offset)
{
if ($this->offsetExists($offset)) {
unset($this->data[$offset]);
}
}
/**
* Returns the value at specified offset.
*
* #param mixed $offset
*
* #return mixed
*/
public function offsetGet($offset)
{
return $this->offsetExists($offset) ? $this->data[$offset] : null;
}
/**
* Count the number of items in the dataset.
*
* #return int
*/
public function count()
{
return count($this->data);
}
/**
* Get the instance as an array.
*
* #return array
*/
public function toArray()
{
return $this->data;
}
/**
* Returns the Feefo API endpoint.
*
* #param array $params
*
* #return string
*/
protected function getRequestUrl(array $params)
{
$query = http_build_query($params);
return sprintf('%s?%s', $this->config->get('feefo.baseuri'), $query);
}
}
And here is the code I'm using to try and use the fetch() method from the vendor class:
use Cms\Classes\ComponentBase;
use ArrayAccess;
use Countable;
use Exception;
use GuzzleHttp\Client;
use Illuminate\Contracts\Config\Repository;
use Illuminate\Contracts\Support\Arrayable;
use SimpleXMLElement;
use BlueBayTravel\Feefo\Feefo;
class Feedback extends ComponentBase
{
public $client;
public $config;
/**
* Container used for display
* #var BlueBayTravel\Feefo
*/
public $feedback;
public function componentDetails()
{
return [
'name' => 'Feedback Component',
'description' => 'Adds Feefo feedback to the website'
];
}
public function defineProperties()
{
return [];
}
public function onRun()
{
$this->feedback = $this->page['feedback'] = $this->loadFeedback($this->client, $this->config);
}
public function loadFeedback($client, $config)
{
$feefo = new Feefo($client, $config);
$feedback = $feefo->fetch();
return $feedback;
}
}
Won't allow me to call the Fetch() method statically so trying to instantiate and then use:
public function loadFeedback($client, $config)
{
$feefo = new Feefo($client, $config);
$feedback = $feefo->fetch();
return $feedback;
}
I've also tried type hinting the args like this:
public function loadFeedback(Client $client, Repository $config)
{
$feefo = new Feefo($client, $config);
$feedback = $feefo->fetch();
return $feedback;
}
But still I get the exception error above. I'm struggling to understand how to get past this. Any help for a newbie much appreciated :)
Just type hinting the function won't cast it to that object type. You need to properly pass the Guzzle\Client object to your function call.
// Make sure you 'use' the GuzzleClient on top of the class
// or use the Fully Qualified Class Name of the Client
$client = new Client();
$feedback = new Feedback();
// Now we passed the Client object to the function of the feedback class
// which will lead to the constructor of the Feefo class which is
// where your error is coming from.
$loadedFeedback = $feedback->loadFeedback($client);
Don't forget to do the same for the Repository $config from Laravel/Lumen
I have a class Version and I want to unittest the isValidVersionString() method.
use InvalidArgumentException;
class Version
{
/**
* dot separated representation of the version
* #var string
*/
protected $versionString;
public function __construct($value)
{
$this->setVersionString($value);
}
/**
* #return string
*/
public function getVersionString(): string
{
return $this->versionString;
}
/**
* #param string $versionString
*
* #return Version
*/
public function setVersionString(string $versionString)
{
if(!$this->isValidVersionString($versionString)) {
throw new InvalidArgumentException();
}
$this->versionString = $versionString;
return $this;
}
/**
* valid format is xxx.xxx.xxx.xxx, with xxx not larger than 255
* #param string $value
* #return bool
*/
public function isValidVersionString(string $value): bool
{
//todo: implementation
}
}
How can I build this unittest? Because this method is also called via the constructor.
You could use a partial mock of the class:
class VersionTest extends \PHPUnit_Framework_TestCase
{
/**
* #test
*/
public function itShouldTest()
{
/** #var Version|\PHPUnit_Framework_MockObject_MockObject $mock */
$mock = $this->getMockBuilder(Version::class)
->disableOriginalConstructor()
->setMethods(['setVersionString','getVersionString'])
->getMock();
$this->assertTrue($mock->isValidVersionString('a-string'));
}
}
IMHO you can simply define the method isValidVersionString as static and simply test as is.
Writing group of parsers that rely on one abstract class which implements shared methods and asks to implement addition method which contains per parser logic.
Abstract parser code:
<?
abstract class AbstractParser {
/*
* The only abstract method to implement. It contains unique logic of each feed passed to the function
*/
public abstract function parse($xmlObject);
/**
* #param $feed string
* #return SimpleXMLElement
* #throws Exception
*/
public function getFeedXml($feed) {
$xml = simplexml_load_file($feed);
return $xml;
}
/**
* #return array
*/
public function getParsedData() {
return $this->data;
}
/**
* #param SimpleXMLElement
* #return Array
*/
public function getAttributes($object) {
// implementation here
}
}
Concrete Parser class:
<?php
class FormulaDrivers extends AbstractParser {
private $data;
/**
* #param SimpleXMLElement object
* #return void
*/
public function parse($xmlObject) {
if (!$xmlObject) {
throw new \Exception('Unable to load remote XML feed');
}
foreach($xmlObject->drivers as $driver) {
$driverDetails = $this->getAttributes($driver);
var_dump($driver);
}
}
}
Instantiation:
$parser = new FormulaDrivers();
$parser->parse( $parser->getFeedXml('http://api.xmlfeeds.com/formula_drivers.xml') );
As you can see, I pass the result of getFeedXml method to parse method, basically delegating the validation of result of getFeedXml to parse method.
How can I avoid it, make sure it returns correct XML object before I pass it to parse method?
Increasing instantiation process and amount of called methods leads to the need of some factory method...
Anyway, how would you fix this small issue?
Thanks!
Make parse protected, so that only parse_xml_file calls it:
abstract class AbstractParser {
/*
* The only abstract method to implement. It contains unique logic of each feed passed to the function
*/
protected abstract function parse($xmlObject);
/**
* #param $feed string
* #return [whatever .parse returns]
* #throws Exception
*/
public function parseFile($feed) {
$xml = simplexml_load_file($feed);
if (!$xml) {
throw new \Exception('Unable to load remote XML feed');
}
return $this->parse($xml);
}
/**
* #return array
*/
public function getParsedData() {
return $this->data;
}
/**
* #param SimpleXMLElement
* #return Array
*/
public function getAttributes($object) {
// implementation here
}
}
$parser->parseFile('http://api.xmlfeeds.com/formula_drivers.xml');