Creating testcase

Correct

getBlink and any other methods just returns the result exactly as it is, in this case pure json. If you mean to get a stdClass object returned or a decoded json that is object, you can call $result->getResponseObject(); Please give more details and sample what you mean about HTTP and object.

No, not stdClass, actual objects with defined properties, like I’ve shown above.

The problem with the JSON array is that I can’t see in my code what’s in it. All I see is that it’s an array. I’d have to go to the documentation website in order to see what’s in there.

If instead of an array you return objects with named properties, like the Dto in my post above, I know what to expect, and it’s typed so tools like PHPStan etc can tell you when you’re using it incorrectly.

Also, I don’t want to do $result->isOk() when I call getBitlink. I just want to get a bitlink, I don’t want to have anything to do with HTTP. HTTP is an implentation details that is important to the Bitlink service, but not for classes that use of the Bitlink service. If a result is not ok, the getBitlink method should just throw an exception of some sort (preferable without any references to HTTP in the name).

So basically what I am proposing is to not return the Result object that is now being returned, but return a Dto instead.

I am unfamiliar with Dto objects, please give some links in documentations/guide.

It is basically just an object that only holds data to be moved from one spot in the code to another spot, without any methods on it (except for maybe a constructor).

The main difference between it and an array is that with a Dto I can know what to expect.

Like with the example I gave above:

class Bitlink
{
    /**
     * @var array<string, string>
     */
    public $references;

    /**
     * @var bool
     */
    public $archived;

    /**
     * @var string[]
     */
    public $tags;

     // etc
}

If I know I get an object of that type, I know that I can use $result->tags to get the tags of my bitlink, and I can see it’s an array of strings.

When a Result is returned (like now) I don’t know that. I just know it’s an array. But I can’t see from that definition where the tags are. I can’t even see that tags may be in there. I don’t know anything. It might be a completely empty array. Who knows?

How to convert json into Dto object, if this should not be stdClass object?

See their Auth service class constructor:

It uses flags to tell Api.php class that authorization is not bearer but basic and content of request is not json like other services. How to convert this to what you said?

  public function __construct (ApiInterface $api, $clientid_username, $clientsecret_password)
  {
        // what to do with this?
        parent::__construct(null, true);
         $this->url = 'https://api-ssl.bitly.com/oauth/access_token';    
         $key = base64_encode($clientid_username.":".$clientsecret_password);
         $this->setApiKey($key);
 }

I guess it should be called like:

$config['clientid_username'] = "";
$config['clientsecret_password'] = "";
$api = new Api(null, true);
$auth = new Auth($api, $config);

and change constructor too:

  public function __construct (ApiInterface $api, $config)
  {
         $this->api = $api;
         $this->url = 'https://api-ssl.bitly.com/oauth/access_token';    
         $key = base64_encode($config['clientid_username'].":".$config['clientsecret_password']);
         $api->setApiKey($key);
  }

But there it will give Too few arguments for testcase. How to fix?
Is there any better way to change this all?

Well, manually :smiley:

Since multiple methods return a Bitlink it would probably be easiest to tell a Bitlink how to construct itself from an array. So let’s say a Bitlink only has fields references, archived and tags, you could do this:

class Bitlink
{
    /**
     * @var array<string, string>
     */
    public $references;

    /**
     * @var bool
     */
    public $archived;

    /**
     * @var string[]
     */
    public $tags;

    public function __construct(array $references, bool $archived, array $tags)
    {
        $this->references = $references;
        $this->archived = $archived;
        $this->tags = $tags;
    }
    
    public static function fromArray(array $input): self
    {
        return new self(
            $input['references'] ?? [],
            $input['archived'] ?? false,
            $input['tags'] ?? []
        );
    }
}
$result = $this->api->get(...);

if (!$result->isOk()) {
    // might check multiple cases that could be wrong
    // so check things like isNotFound(), isClientError(), etc.
    // or just throw one exception for anything that goes wrong
    throw new BitlyException('Unable to fetch bitlink');
}

return Bitlink::fromArray($$result->getResponseArray());

Give more arguments in the testcase :stuck_out_tongue:

Define “better”

For travis should I care to add hhvm and nightly?

HHVM probably not. It’s not being used a lot anymore.

Nightly can be nice, but when you do add that allow it to fail. It’s fine if it fails, but it’s good to have it to know what you can expect for future versions.

how to set in yml to allow it to fail?

Read the documentation. It’s in there.

language: php
install: composer install
php:
  - '7.2'
  - '7.3'
  - nightly
allow_failures:
  - php: nightly  
notifications:
  email: false

But nightly always fail because it cannot find ApiInterface class, but 7.2. and 7.3 can find it! How to fix it?

phpunit is like this:

<phpunit bootstrap="vendor/autoload.php" colors="true">
<testsuites>
  <testsuite name="tests">
    <directory>lib/PHPLicengine/tests</directory>
  </testsuite>
</testsuites>
</phpunit>

Looking at shields.io website, I did not understand how to get a shields.io packagist version badge. How to generate it?

That sounds like a question for a new thread :wink:

1 Like

Please give more details about this structure

        $input['references'] ?? [],
        $input['archived'] ?? false,
        $input['tags'] ?? []

Whatever needs a value uses and whatever needs to be false or true uses false? What if a property has some sub-properties and one of them is emty?

And since all Bitlink methods results don’t have the same properties structur is it possible to use the fromArray for all of them if adding all possible properties to fromArray?

If a key was expected in the array but isn’t there and we know it should be an array we can safely use an empty array. If a key was expected in the array but isn’t there and we know it should be a boolean then 9 of 10 times false is a safe default value. Depends on your use case, of course.

For results with a different structure you use a different object.

For example the method getClicksSummaryForBitlink might return an object like BitlinkClicksSummary.

So fo each different result structure I have to have a separate class with different constructor and fromArray method?

That is correct