<?php
/**
 * Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
 *
 * You are hereby granted a non-exclusive, worldwide, royalty-free license to
 * use, copy, modify, and distribute this software in source code or binary
 * form for use in connection with the web services and APIs provided by
 * Facebook.
 *
 * As with any software that integrates with the Facebook platform, your use
 * of this software is subject to the Facebook Developer Principles and
 * Policies [http://developers.facebook.com/policy/]. This copyright notice
 * shall be included in all copies or substantial portions of the software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 *
 */

namespace FacebookAdsTest\Object;

use FacebookAds\Object\AbstractCrudObject;
use FacebookAds\Object\AdAccount;
use FacebookAds\Object\AdsPixel;
use FacebookAds\Object\Business;
use FacebookAds\Object\Fields\AdsPixelsFields;
use FacebookAds\Object\Values\AdsPixelStatAggregations;

class AdsPixelTest extends AbstractCrudObjectTestCase {

  /**
   * AdsPixels can be created but only one per account can exist
   */
  public function testCreate() {
    // make sure there's at least one pixel
    $account = new AdAccount($this->getConfig()->accountId);
    $pixels = $account->getAdsPixels();
    $pixel = null;

    if (!$pixels->count()) {
      $pixel = new AdsPixel(null, $this->getConfig()->accountId);
      $pixel->{AdsPixelsFields::NAME} = 'WCA Pixel';
      $this->assertCanCreate($pixel);
    } else {
      $pixel = $pixels->current();
    }

    $pixel = new AdsPixel(null, $this->getConfig()->accountId);
    $pixel->{AdsPixelsFields::NAME} = $this->getConfig()->testRunId;
    $this->assertCannotCreate($pixel);
  }

  /**
   * @return AdsPixel
   */
  protected function getAccountPixel() {
    $cursor = (new AdAccount($this->getConfig()->accountId))->getAdsPixels();
    $this->assertGreaterThanOrEqual(1, $cursor->count());

    return $cursor->current();
  }

  /**
   * @depends testCreate
   */
  public function testCrud() {
    $pixel = $this->getAccountPixel();

    $this->assertCanRead($pixel, array(
      AdsPixelsFields::NAME,
    ));

    $name = $pixel->{AdsPixelsFields::NAME};

    $this->assertCanUpdate(
      $pixel,
      array(
        AdsPixelsFields::NAME => $this->getConfig()->testRunId.' updated',
      ));

    $pixel->{AdsPixelsFields::NAME} = $name;
    $pixel->update();

    $this->assertCanFetchConnection($pixel, 'getAdAccounts', array(), array(
      'business' => $this->getConfig()->businessId,
    ));
    $this->assertCanFetchConnection($pixel, 'getAgencies');
    $this->assertCanFetchConnection($pixel, 'getStats', array(), array(
      'aggregation' => AdsPixelStatAggregations::EVENT,
    ));

    $this->assertCannotDelete($pixel);
  }

  /**
   * @depends testCreate
   */
  public function testShareWithAdAccount() {
    $this->skipIf('no_business_manager');

    if (!$this->getConfig()->secondaryBusinessId) {
      $this->markTestSkipped('No secondary business provided in config');
    }

    if (!$this->getConfig()->secondaryAccountId) {
      $this->markTestSkipped('No secondary ad account provided in config');
    }

    $account_id_int = (int) substr($this->getConfig()->secondaryAccountId, 4);

    $pixel = $this->getAccountPixel();

    $pixel->sharePixelWithAdAccount(
      $this->getConfig()->secondaryBusinessId,
      $account_id_int);

    $pixel->unsharePixelWithAdAccount(
      $this->getConfig()->secondaryBusinessId,
      $account_id_int);

  }

  /**
   * @depends testCreate
   */
  public function testShareWithAgency() {
    $this->skipIf('no_business_manager');

    if (!$this->getConfig()->secondaryAccountId) {
      $this->markTestSkipped('No secondary business provided in config');
    }

    $pixel = $this->getAccountPixel();

    $business = new Business($this->getConfig()->businessId);
    $cursor = $business->getAgencies();
    $cursor->setUseImplicitFetch(true);

    $agency_id = null;
    foreach ($cursor as $agency) {
      if (
        $agency->{AbstractCrudObject::FIELD_ID}
        == $this->getConfig()->secondaryBusinessId
      ) {
        $agency_id = $agency->{AbstractCrudObject::FIELD_ID};
      }
    }

    if ($agency_id === null) {
      $this->markTestSkipped("Secondary business is not a valid agency");
    }

    $pixel->sharePixelWithAgency(
      $this->getConfig()->businessId,
      $this->getConfig()->secondaryBusinessId);

    $pixel->unsharePixelWithAgency(
      $this->getConfig()->businessId,
      $this->getConfig()->secondaryBusinessId);
  }
}


<?php
/**
 * Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
 *
 * You are hereby granted a non-exclusive, worldwide, royalty-free license to
 * use, copy, modify, and distribute this software in source code or binary
 * form for use in connection with the web services and APIs provided by
 * Facebook.
 *
 * As with any software that integrates with the Facebook platform, your use
 * of this software is subject to the Facebook Developer Principles and
 * Policies [http://developers.facebook.com/policy/]. This copyright notice
 * shall be included in all copies or substantial portions of the software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 *
 */

namespace FacebookAdsTest\Object;

use FacebookAds\Object\Campaign;
use FacebookAds\Object\AdCreative;
use FacebookAds\Object\Ad;
use FacebookAds\Object\AdImage;
use FacebookAds\Object\AdSet;
use FacebookAds\Object\Fields\CampaignFields;
use FacebookAds\Object\Fields\AdCreativeFields;
use FacebookAds\Object\Fields\AdFields;
use FacebookAds\Object\Fields\AdImageFields;
use FacebookAds\Object\Fields\AdSetFields;
use FacebookAds\Object\Fields\ObjectStory\LinkDataFields;
use FacebookAds\Object\Fields\ObjectStorySpecFields;
use FacebookAds\Object\ObjectStory\LinkData;
use FacebookAds\Object\ObjectStorySpec;
use FacebookAds\Object\TargetingSpecs;
use FacebookAds\Object\Fields\TargetingSpecsFields;
use FacebookAds\Object\Values\BillingEvents;
use FacebookAds\Object\Values\OptimizationGoals;
use FacebookAdsTest\Config\SkippableFeatureTestInterface;

class AdTest extends AbstractCrudObjectTestCase
  implements SkippableFeatureTestInterface {

  /**
   * @var Campaign
   */
  protected $campaign;

  /**
   * @var AdSet
   */
  protected $adSet;

  /**
   * @var AdCreative
   */
  protected $adCreative;

  /**
   * @var AdImage
   */
  protected $adImage;

  /**
   * @return array
   */
  public function skipIfAny() {
    return array('no_payment_method');
  }

  public function setup() {
    parent::setup();

    $targeting = new TargetingSpecs();
    $targeting->{TargetingSpecsFields::GEO_LOCATIONS} = array(
      'countries' => array('US'),
    );

    $this->campaign = new Campaign(null, $this->getConfig()->accountId);
    $this->campaign->{CampaignFields::NAME} = $this->getConfig()->testRunId;
    $this->campaign->create();

    $this->adSet = new AdSet(null, $this->getConfig()->accountId);
    $this->adSet->{AdSetFields::CAMPAIGN_ID}
      = (int) $this->campaign->{AdSetFields::ID};
    $this->adSet->{AdSetFields::NAME} = $this->getConfig()->testRunId;
    $this->adSet->{AdSetFields::DAILY_BUDGET} = '150';
    $this->adSet->{AdSetFields::START_TIME}
      = (new \DateTime("+1 week"))->format(\DateTime::ISO8601);
    $this->adSet->{AdSetFields::END_TIME}
      = (new \DateTime("+2 week"))->format(\DateTime::ISO8601);
    $this->adSet->{AdSetFields::TARGETING} = $targeting;
    $this->adSet->{AdSetFields::OPTIMIZATION_GOAL} = OptimizationGoals::REACH;
    $this->adSet->{AdSetFields::BILLING_EVENT} = BillingEvents::IMPRESSIONS;
    $this->adSet->{AdSetFields::BID_AMOUNT} = 2;
    $this->adSet->save(array(
      AdSet::STATUS_PARAM_NAME => AdSet::STATUS_PAUSED,
    ));

    $this->adImage = new AdImage(null, $this->getConfig()->accountId);
    $this->adImage->{AdImageFields::FILENAME}
      = $this->getConfig()->testImagePath;
    $this->adImage->save();

    $link = new LinkData();
    $link->{LinkDataFields::MESSAGE} = 'Message';
    $link->{LinkDataFields::IMAGE_HASH} = $this->adImage->{AdImageFields::HASH};
    $link->{LinkDataFields::LINK} = $this->getConfig()->appUrl;

    $story = new ObjectStorySpec();
    $story->{ObjectStorySpecFields::PAGE_ID} = $this->getConfig()->pageId;
    $story->{ObjectStorySpecFields::LINK_DATA} = $link;

    $this->adCreative = new AdCreative(null, $this->getConfig()->accountId);
    $this->adCreative->{AdCreativeFields::OBJECT_STORY_SPEC} = $story;
    $this->adCreative->create();
  }

  public function tearDown() {
    if ($this->adSet) {
      $this->adSet->deleteSelf();
      $this->adSet = null;
    }

    if ($this->campaign) {
      $this->campaign->deleteSelf();
      $this->campaign = null;
    }

    if ($this->adCreative) {
      $this->adCreative->deleteSelf();
      $this->adCreative = null;
    }

    if ($this->adImage) {
      $this->adImage->deleteSelf();
      $this->adImage = null;
    }

    parent::tearDown();
  }

  public function testCrudAccess() {

    $group = new Ad(null, $this->getConfig()->accountId);
    $group->{AdFields::NAME} = $this->getConfig()->testRunId;
    $group->{AdFields::ADSET_ID}
      = (int) $this->adSet->{AdSetFields::ID};
    $group->{AdFields::CREATIVE}
      = array('creative_id' => $this->adCreative->{AdCreativeFields::ID});

    $this->assertCanCreate($group, array(
      Ad::STATUS_PARAM_NAME => Ad::STATUS_PAUSED,
    ));
    $this->assertCanRead($group);
    $this->assertCanUpdate($group, array(
      AdFields::NAME => $this->getConfig()->testRunId.' updated',
    ));

    $this->assertCanFetchConnection($group, 'getAdCreatives');
    $this->assertCanFetchConnection($group, 'getLeads');
    $this->assertCanFetchConnection($group, 'getTargetingDescription');
    $this->assertCanFetchConnection($group, 'getAdPreviews',
      array(),
      array('ad_format' => 'RIGHT_COLUMN_STANDARD'));

    if (!$this->shouldSkipTest('no_reach_and_frequency')) {
      $this->assertCanFetchConnection($group, 'getReachEstimate');
    }
    $this->assertCanFetchConnection($group, 'getClickTrackingTag');
    $this->assertCanFetchConnection($group, 'getInsights');
    $this->assertCanFetchConnection($group, 'getInsightsAsync');

    $this->assertCanBeLabeled($group);
    $this->assertCanArchive($group);

    $this->assertCanDelete($group);
  }
}


<?php
/**
 * Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
 *
 * You are hereby granted a non-exclusive, worldwide, royalty-free license to
 * use, copy, modify, and distribute this software in source code or binary
 * form for use in connection with the web services and APIs provided by
 * Facebook.
 *
 * As with any software that integrates with the Facebook platform, your use
 * of this software is subject to the Facebook Developer Principles and
 * Policies [http://developers.facebook.com/policy/]. This copyright notice
 * shall be included in all copies or substantial portions of the software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 *
 */

namespace FacebookAdsTest\Object;

use FacebookAds\Object\AdAccount;
use FacebookAds\Object\AdUser;
use FacebookAds\Object\Fields\AdUserFields;

class AdUserTest extends AbstractCrudObjectTestCase {

  public function testCrudAccess() {
    $ad_account = new AdAccount($this->getConfig()->accountId);
    $ad_users = $ad_account->getAdUsers();

    $this->assertGreaterThan(0, $ad_users->count());

    $uid = (new AdUser('me'))->read()->{AdUserFields::ID};
    $found = false;
    foreach ($ad_users as $ad_user) {
      if ($ad_user->id === $uid) {
        $this->assertCanFetchConnection($ad_user, 'getAdAccounts');
        $this->assertCanFetchConnection($ad_user, 'getAdAccountGroups');
        $found = true;
        break;
      }
    }

    $this->assertTrue($found);
  }
}


<?php
/**
 * Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
 *
 * You are hereby granted a non-exclusive, worldwide, royalty-free license to
 * use, copy, modify, and distribute this software in source code or binary
 * form for use in connection with the web services and APIs provided by
 * Facebook.
 *
 * As with any software that integrates with the Facebook platform, your use
 * of this software is subject to the Facebook Developer Principles and
 * Policies [http://developers.facebook.com/policy/]. This copyright notice
 * shall be included in all copies or substantial portions of the software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 *
 */

namespace FacebookAdsTest\Object;

use FacebookAds\Object\AdVideo;
use FacebookAds\Object\Fields\AdVideoFields;
use FacebookAdsTest\Config\SkippableFeatureTestInterface;

class AdVideoTest extends AbstractCrudObjectTestCase
  implements SkippableFeatureTestInterface {

  /**
   * @return array
   */
  public function skipIfAny() {
    return array('no_video_upload');
  }

  public function testCrud() {
    $video = new AdVideo(null, $this->getConfig()->accountId);
    $video->{AdVideoFields::NAME} = $this->getConfig()->testRunId;
    $video->{AdVideoFields::SOURCE} = $this->getConfig()->testVideoPath;
    $this->assertCanCreate($video);
    $this->assertCanRead($video);
    $this->assertCanUpdate($video, array(
      AdVideoFields::NAME => $this->getConfig()->testRunId.' updated',
    ));
    $this->assertCanDelete($video);
  }
}


<?php
/**
 * Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
 *
 * You are hereby granted a non-exclusive, worldwide, royalty-free license to
 * use, copy, modify, and distribute this software in source code or binary
 * form for use in connection with the web services and APIs provided by
 * Facebook.
 *
 * As with any software that integrates with the Facebook platform, your use
 * of this software is subject to the Facebook Developer Principles and
 * Policies [http://developers.facebook.com/policy/]. This copyright notice
 * shall be included in all copies or substantial portions of the software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 *
 */

 namespace FacebookAdsTest\Object;

 use FacebookAds\Object\AdAccount;
 use FacebookAds\Object\Fields\AdAccountFields;
 use FacebookAds\Object\AdReportRun;
 use FacebookAds\Object\Fields\AdsInsightsFields;
 use FacebookAds\Api;

 class AsyncJobInsightsTest extends AbstractAsyncJobTestCase {

   public function testCrud() {
     $account = new AdAccount($this->getConfig()->accountId);
     $job = $account->getInsightsAsync();
     $this->assertTrue($job instanceof AdReportRun);
     $this->waitTillJobComplete($job);
     $job->getInsights();
   }

   public function testFields() {
     $account = new AdAccount($this->getConfig()->accountId);
     $fields = array(AdAccountFields::ACCOUNT_ID);
     $account->{AdAccountFields::ACCOUNT_ID} = $account->getSelf($fields)->{AdAccountFields::ACCOUNT_ID};
     $fields = array(AdsInsightsFields::ACCOUNT_ID);
     $job = $account->getInsightsAsync($fields);
     $this->assertTrue($job instanceof AdReportRun);
     $this->waitTillJobComplete($job);
     $result = $job->getInsights();
     $this->assertEquals(
       $result[0]->{AdsInsightsFields::ACCOUNT_ID},
       $account->{AdAccountFields::ACCOUNT_ID});
   }
 }


<?php
/**
 * Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
 *
 * You are hereby granted a non-exclusive, worldwide, royalty-free license to
 * use, copy, modify, and distribute this software in source code or binary
 * form for use in connection with the web services and APIs provided by
 * Facebook.
 *
 * As with any software that integrates with the Facebook platform, your use
 * of this software is subject to the Facebook Developer Principles and
 * Policies [http://developers.facebook.com/policy/]. This copyright notice
 * shall be included in all copies or substantial portions of the software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 *
 */

namespace FacebookAdsTest\Object;

use FacebookAds\Object\AdUser;
use FacebookAds\Object\Business;
use FacebookAds\Object\Fields\AdUserFields;
use FacebookAds\Object\Fields\BusinessFields;
use FacebookAds\Object\Values\AdAccountRoles;
use FacebookAdsTest\Config\SkippableFeatureTestInterface;
use FacebookAds\Object\Values\BusinessRoles;

class BusinessTest extends AbstractCrudObjectTestCase
  implements SkippableFeatureTestInterface {

  /**
   * @return array
   */
  public function skipIfAny() {
    return array('no_business_manager');
  }

  public function testCrud() {
    $business = new Business($this->getConfig()->businessId);
    $this->assertCanRead($business);
    $this->assertCannotDelete($business);

    $name = $business->read(array(BusinessFields::NAME))
      ->{BusinessFields::NAME};

    $this->assertCanUpdate($business, array(
      BusinessFields::NAME => "My Awesome Business"
    ));

    $business->{BusinessFields::NAME} = $name;
    $business->save();

    if ($this->getConfig()->secondaryPageId) {
      $business->claimPage(
        $this->getConfig()->secondaryPageId,
        BusinessRoles::OWNER);
      $business->deletePage($this->getConfig()->secondaryPageId);
    }

    $business->inviteUserByEmail('test@example.com', BusinessRoles::EMPLOYEE);
    $business->deleteUserByEmail('test@example.com');

    $user = (new AdUser('me'))->read(array('id'));
    $business->addUserPermissionById(
      $user->{AdUserFields::ID},
      BusinessRoles::ADMIN);

    if ($this->getConfig()->secondaryAccountId) {
      $business->claimAdAccount(
        $this->getConfig()->secondaryAccountId,
        BusinessRoles::AGENCY,
        array(AdAccountRoles::ADMIN));
      $business->deleteAdAccount(
        $this->getConfig()->secondaryAccountId);
    }

    if ($this->getConfig()->secondaryAppId) {
      $business->claimApp(
        $this->getConfig()->secondaryAppId,
        BusinessRoles::OWNER);
      $business->deleteApp($this->getConfig()->secondaryAppId);
    }
  }

  public function testConnections() {
    $business = new Business($this->getConfig()->businessId);
    $this->assertCanFetchConnection($business, 'getAdAccounts');
    $this->assertCanFetchConnection($business, 'getUserPermissions');
    $this->assertCanFetchConnection($business, 'getProjects');
    $this->assertCanFetchConnection($business, 'getPages');
    $this->assertCanFetchConnection($business, 'getApps');
    $this->assertCanFetchConnection($business, 'getClients');
    $this->assertCanFetchConnection($business, 'getAgencies');
    $this->assertCanFetchConnection($business, 'getCreditCards');
    $this->assertCanFetchConnection($business, 'getExtendedCredits');
    $this->assertCanFetchConnection($business, 'getProductCatalogues');
    $this->assertCanFetchConnection($business, 'getSystemUsers');
    $this->assertCanFetchConnection($business, 'getAdsPixels');
  }
}


<?php
/**
 * Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
 *
 * You are hereby granted a non-exclusive, worldwide, royalty-free license to
 * use, copy, modify, and distribute this software in source code or binary
 * form for use in connection with the web services and APIs provided by
 * Facebook.
 *
 * As with any software that integrates with the Facebook platform, your use
 * of this software is subject to the Facebook Developer Principles and
 * Policies [http://developers.facebook.com/policy/]. This copyright notice
 * shall be included in all copies or substantial portions of the software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 *
 */

namespace FacebookAdsTest\Object;

use FacebookAds\Object\Campaign;
use FacebookAds\Object\Fields\CampaignFields;

class CampaignTest extends AbstractCrudObjectTestCase {

  public function testCrud() {
    $campaign = new Campaign(null, $this->getConfig()->accountId);
    $campaign->{CampaignFields::NAME} = $this->getConfig()->testRunId;

    $this->assertCanCreate($campaign);
    $this->assertCanRead($campaign);
    $this->assertCanUpdate(
      $campaign,
      array(
        CampaignFields::NAME => $this->getConfig()->testRunId.' updated',
      ));
    $this->assertCanFetchConnection($campaign, 'getAdSets');
    $this->assertCanFetchConnection($campaign, 'getAds');
    $this->assertCanFetchConnection($campaign, 'getInsights');
    $this->assertCanFetchConnection($campaign, 'getInsightsAsync');

    $this->assertCanBeLabeled($campaign);
    $this->assertCanArchive($campaign);

    $this->assertCanDelete($campaign);
  }
}


<?php
/**
 * Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
 *
 * You are hereby granted a non-exclusive, worldwide, royalty-free license to
 * use, copy, modify, and distribute this software in source code or binary
 * form for use in connection with the web services and APIs provided by
 * Facebook.
 *
 * As with any software that integrates with the Facebook platform, your use
 * of this software is subject to the Facebook Developer Principles and
 * Policies [http://developers.facebook.com/policy/]. This copyright notice
 * shall be included in all copies or substantial portions of the software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 *
 */

namespace FacebookAdsTest\Object;

use FacebookAds\Object\CustomAudience;
use FacebookAds\Object\Fields\CustomAudienceFields;
use FacebookAds\Object\Fields\CustomAudienceMultikeySchemaFields;
use FacebookAds\Object\Values\CustomAudienceSubtypes;
use FacebookAds\Object\Values\CustomAudienceTypes;

class CustomAudienceMultikeyTest extends AbstractCrudObjectTestCase {

  /**
  * @var CustomAudience
  */
  protected $customaudience;

  public function setup() {
    parent::setup();
    $adaccount = new AdAccount($this->getConfig()->accountId);
    $params = array(
      CustomAudienceFields::NAME => $this->getConfig()->testRunId,
      CustomAudienceFields::SUBTYPE => CustomAudienceSubtypes::CUSTOM,
    );
    $this->customaudience = $adaccount->createCustomAudience(
      array(),
      $params
    );
  }

  public function tearDown() {
    if ($this->customaudience) {
      $this->customaudience->deleteSelf();
    }
  }

  private function checkServerResponse(
    CustomAudience $ca,
    array $users,
    array $schema,
    $is_hashed,
    $is_normalized) {
    $add = $ca->addUsersMultiKey($users, $schema, $is_hashed, $is_normalized);
    $this->assertClusterChangesResponse($ca, $users, $add);
    $remove = $ca->removeUsersMultiKey($users, $schema, $is_hashed, $is_normalized);
    $this->assertClusterChangesResponse($ca, $users, $remove);
  }

  protected function assertClusterChangesResponse(
    CustomAudience $ca, array $users, $response) {

    $this->assertTrue(is_array($response));

    $this->assertArrayHasKey('audience_id', $response);
    $this->assertEquals(
      $response['audience_id'], $ca->{CustomAudienceFields::ID});
    $this->assertArrayHasKey('num_received', $response);
    $this->assertEquals($response['num_received'], count($users));
    $this->assertArrayHasKey('num_invalid_entries', $response);
    $this->assertEquals($response['num_invalid_entries'], 0);
  }

  public function testMultikeyCustomAudiences() {
    $users = array(
      array('abc123def', 'fname', 'lname', 'someone@example.com'),
      array('abc234def', 'fname_new', 'lname_new', 'someone_new@example.com'),
    );
    $schema = array(
      CustomAudienceMultikeySchemaFields::EXTERN_ID,
      CustomAudienceMultikeySchemaFields::FIRST_NAME,
      CustomAudienceMultikeySchemaFields::LAST_NAME,
      CustomAudienceMultikeySchemaFields::EMAIL,
    );
    $is_hashed = false;
    $is_normalized = false;
    $this->checkServerResponse(
      $this->customaudience,
      $users,
      $schema,
      $is_hashed,
      $is_normalized);
  }

  public function testSinglekeyExternIDCustomAudiences() {
    $users = array(
      array('abc123def'),
      array('abc234def'),
      array('abc345def'),
      array('abc456def'),
    );
    $schema = array(
      CustomAudienceMultikeySchemaFields::EXTERN_ID,
    );
    $is_hashed = false;
    $is_normalized = false;
    $this->checkServerResponse(
      $this->customaudience,
      $users,
      $schema,
      $is_hashed,
      $is_normalized);
  }

}


<?php
/**
 * Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
 *
 * You are hereby granted a non-exclusive, worldwide, royalty-free license to
 * use, copy, modify, and distribute this software in source code or binary
 * form for use in connection with the web services and APIs provided by
 * Facebook.
 *
 * As with any software that integrates with the Facebook platform, your use
 * of this software is subject to the Facebook Developer Principles and
 * Policies [http://developers.facebook.com/policy/]. This copyright notice
 * shall be included in all copies or substantial portions of the software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 *
 */

namespace FacebookAdsTest\Object;

use FacebookAds\Object\CustomAudience;
use FacebookAds\Object\Fields\CustomAudienceFields;
use FacebookAds\Object\Values\CustomAudienceSubtypes;
use FacebookAds\Object\Values\CustomAudienceTypes;

class CustomAudienceTest extends AbstractCrudObjectTestCase {

  protected function assertClusterChangesResponse(
    CustomAudience $ca, array $users, $response) {

    $this->assertTrue(is_array($response));

    $this->assertArrayHasKey('audience_id', $response);
    $this->assertEquals(
      $response['audience_id'], $ca->{CustomAudienceFields::ID});
    $this->assertArrayHasKey('num_received', $response);
    $this->assertEquals($response['num_received'], count($users));
    $this->assertArrayHasKey('num_invalid_entries', $response);
    $this->assertEquals($response['num_invalid_entries'], 0);
  }

  public function testCustomAudiences() {
    $ca = new CustomAudience(null, $this->getConfig()->accountId);
    $ca->{CustomAudienceFields::NAME} = $this->getConfig()->testRunId;
    $ca->{CustomAudienceFields::SUBTYPE} = CustomAudienceSubtypes::CUSTOM;

    $this->assertCanCreate($ca);

    $this->assertCanRead($ca);
    $this->assertCanUpdate(
      $ca,
      array(
        CustomAudienceFields::NAME => $this->getConfig()->testRunId.' updated',
      ));

    $users = array('someone@example.com');

    $add = $ca->addUsers($users, CustomAudienceTypes::EMAIL);
    $this->assertClusterChangesResponse($ca, $users, $add);

    $remove = $ca->removeUsers($users, CustomAudienceTypes::EMAIL);
    $this->assertClusterChangesResponse($ca, $users, $remove);

    $optout = $ca->optOutUsers($users, CustomAudienceTypes::EMAIL);
    $this->assertSuccessResponse($optout);

    $this->assertCanDelete($ca);
  }

  /**
   * @depends testCustomAudiences
   */
  public function testAppIdsPayload() {
    $ca = new CustomAudience(null, $this->getConfig()->accountId);
    $ca->{CustomAudienceFields::NAME} = $this->getConfig()->testRunId;
    $ca->{CustomAudienceFields::SUBTYPE} = CustomAudienceSubtypes::CUSTOM;
    $ca->create();

    $users = array($this->getApi()->call('/me')->getContent()['id']);

    $add = $ca->addUsers(
      $users, CustomAudienceTypes::ID, array($this->getConfig()->appId));
    $this->assertClusterChangesResponse($ca, $users, $add);

    $remove = $ca->removeUsers(
      $users, CustomAudienceTypes::ID, array($this->getConfig()->appId));
    $this->assertClusterChangesResponse($ca, $users, $remove);

    $optout = $ca->optOutUsers(
      $users, CustomAudienceTypes::ID, array($this->getConfig()->appId));
    $this->assertSuccessResponse($optout);

    $ca->deleteSelf();
  }
}


<?php
/**
 * Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
 *
 * You are hereby granted a non-exclusive, worldwide, royalty-free license to
 * use, copy, modify, and distribute this software in source code or binary
 * form for use in connection with the web services and APIs provided by
 * Facebook.
 *
 * As with any software that integrates with the Facebook platform, your use
 * of this software is subject to the Facebook Developer Principles and
 * Policies [http://developers.facebook.com/policy/]. This copyright notice
 * shall be included in all copies or substantial portions of the software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 *
 */

namespace FacebookAdsTest\Object;

use FacebookAds\Object\AdAccount;
use FacebookAds\Object\Campaign;
use FacebookAds\Object\AdCreative;
use FacebookAds\Object\Ad;
use FacebookAds\Object\AdSet;
use FacebookAds\Object\AdsPixel;
use FacebookAds\Object\ObjectStorySpec;
use FacebookAds\Object\ProductAudience;
use FacebookAds\Object\ProductCatalog;
use FacebookAds\Object\ProductSet;
use FacebookAds\Object\TargetingSpecs;
use FacebookAds\Object\ObjectStory\TemplateData;
use FacebookAds\Object\Fields\CampaignFields;
use FacebookAds\Object\Fields\AdCreativeFields;
use FacebookAds\Object\Fields\AdFields;
use FacebookAds\Object\Fields\AdSetFields;
use FacebookAds\Object\Fields\AdsPixelsFields;
use FacebookAds\Object\Fields\ObjectStory\TemplateDataFields;
use FacebookAds\Object\Fields\ObjectStorySpecFields;
use FacebookAds\Object\Fields\ProductAudienceFields;
use FacebookAds\Object\Fields\ProductCatalogFields;
use FacebookAds\Object\Fields\ProductSetFields;
use FacebookAds\Object\Fields\TargetingSpecsFields;
use FacebookAds\Object\Values\AdObjectives;
use FacebookAds\Object\Values\BillingEvents;
use FacebookAds\Object\Values\CallToActionTypes;
use FacebookAds\Object\Values\OptimizationGoals;

class DynamicProductAdsAdvertTest extends AbstractCrudObjectTestCase {

  /**
   * @var ProductSet
   */
  protected $productSet;

  /**
   * @var ProductCatalog
   */
  protected $productCatalog;

  /**
   * @var AdsPixel
   */
  protected $adsPixel;

  /**
   * @var ProductAudience
   */
  protected $productAudience;

  /**
   * @var Campaign
   */
  protected $campaign;

  /**
   * @var AdSet
   */
  protected $adSet;

  /**
   * @var Ad
   */
  protected $ad;

  /**
   * @var AdCreative
   */
  protected $creative;

  public function setup() {
    parent::setup();

    $account = new AdAccount($this->getConfig()->accountId);
    $this->adsPixel = $account->getAdsPixels()->current();
    if ($this->adsPixel === null) {
      throw new \Exception('Ads Pixel is null');
    }

    $this->productCatalog =
      new ProductCatalog(null, $this->getConfig()->businessId);
    $this->productCatalog->setData(array(
      ProductCatalogFields::NAME => $this->getConfig()->testRunId,
    ));
    $this->productCatalog->create();

    $this->productSet =
      new ProductSet(null, $this->productCatalog->{ProductCatalogFields::ID});
    $this->productSet->setData(array(
      ProductSetFields::NAME => $this->getConfig()->testRunId,
      ProductSetFields::FILTER => array(
        'retailer_id' => array(
          'is_any' => array('pid1', 'pid2')
        )
      )
    ));
    $this->productSet->create();

    $this->productAudience
      = new ProductAudience(null, $this->getConfig()->accountId);
    $this->productAudience->setData(array(
      ProductAudienceFields::NAME => $this->getConfig()->testRunId,
      ProductAudienceFields::PRODUCT_SET_ID =>
        $this->productSet->{ProductSetFields::ID},
      ProductAudienceFields::PIXEL_ID =>
        $this->adsPixel->{AdsPixelsFields::ID},
      ProductAudienceFields::INCLUSIONS => array(array(
        'retention_seconds' => 86400,
        'rule' => array(
          'and' => array(
            array('event' => array('eq'=>'ViewContent')),
            array('userAgent' => array('i_contains'=>'iPhone'))
          )
        )
      )),
    ));

    $this->productAudience->create();
  }

  public function tearDown() {
    if ($this->productSet) {
      $this->productSet->deleteSelf();
      $this->productSet = null;
    }

    if ($this->productCatalog) {
      $this->productCatalog->deleteSelf();
      $this->productCatalog = null;
    }

    if ($this->productAudience) {
      $this->productAudience->deleteSelf();
      $this->productAudience = null;
    }

    if ($this->campaign) {
      $this->campaign->deleteSelf();
      $this->campaign = null;
    }

    if ($this->adSet) {
      $this->adSet->deleteSelf();
      $this->adSet = null;
    }

    if ($this->ad) {
      $this->ad->deleteSelf();
      $this->ad = null;
    }

    if ($this->creative) {
      $this->creative->deleteSelf();
      $this->creative = null;
    }

    parent::tearDown();
  }

  public function testDynamicProductAdsCreation() {
    $this->campaign = new Campaign(null, $this->getConfig()->accountId);
    $this->campaign->setData(array(
      CampaignFields::NAME => $this->getConfig()->testRunId,
      CampaignFields::OBJECTIVE => AdObjectives::PRODUCT_CATALOG_SALES,
      CampaignFields::PROMOTED_OBJECT =>
        array('product_catalog_id' =>
          $this->productCatalog->{ProductCatalogFields::ID})
     ));
    $this->assertCanCreate($this->campaign);

    $targeting = new TargetingSpecs();
    $targeting->{TargetingSpecsFields::GEO_LOCATIONS} =
      array('countries' => array('US'));
    $targeting->{TargetingSpecsFields::DYNAMIC_AUDIENCE_IDS} =
      array($this->productAudience->{ProductAudienceFields::ID});

    $this->adSet = new AdSet(null, $this->getConfig()->accountId);
    $this->adSet->setData(array(
      AdSetFields::NAME => $this->getConfig()->testRunId,
      AdSetFields::OPTIMIZATION_GOAL => OptimizationGoals::LINK_CLICKS,
      AdSetFields::BILLING_EVENT => BillingEvents::IMPRESSIONS,
      AdSetFields::BID_AMOUNT => 2,
      AdSetFields::DAILY_BUDGET => 2000,
      AdSetFields::CAMPAIGN_ID =>
        $this->campaign->{CampaignFields::ID},
      AdSetFields::TARGETING => $targeting,
      AdsetFields::PROMOTED_OBJECT =>
        array(
          'product_set_id' => $this->productSet->{ProductSetFields::ID},
        ),
    ));
    $this->assertCanCreate($this->adSet);

    $template = new TemplateData();
    $template->setData(array(
      TemplateDataFields::DESCRIPTION => '{{product.description}}',
      TemplateDataFields::LINK => 'http://www.example.com/',
      TemplateDataFields::MESSAGE => 'Test DPA Ad Message',
      TemplateDataFields::NAME => '{{product.name | titleize}}',
      TemplateDataFields::CALL_TO_ACTION => array(
        'type' => CallToActionTypes::SHOP_NOW
      ),
    ));

    $story = new ObjectStorySpec();
    $story->setData(array(
      ObjectStorySpecFields::PAGE_ID => $this->getConfig()->pageId,
      ObjectStorySpecFields::TEMPLATE_DATA => $template,
    ));

    $this->creative = new AdCreative(null, $this->getConfig()->accountId);
    $this->creative->setData(array(
      AdCreativeFields::NAME => $this->getConfig()->testRunId,
      AdCreativeFields::OBJECT_STORY_SPEC => $story,
      AdCreativeFields::PRODUCT_SET_ID =>
        $this->productSet->{ProductSetFields::ID},
    ));
    $this->assertCanCreate($this->creative);

    $this->ad = new Ad(null, $this->getConfig()->accountId);
    $this->ad->setData(array(
      AdFields::NAME => 'DPA Test Ad 1 '.$this->getConfig()->testRunId,
      AdFields::ADSET_ID => $this->adSet->{AdSetFields::ID},
      AdFields::CREATIVE =>
        array('creative_id' => $this->creative->{AdCreativeFields::ID}),
    ));
    $this->assertCanCreate($this->ad);
  }
}


<?php
/**
 * Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
 *
 * You are hereby granted a non-exclusive, worldwide, royalty-free license to
 * use, copy, modify, and distribute this software in source code or binary
 * form for use in connection with the web services and APIs provided by
 * Facebook.
 *
 * As with any software that integrates with the Facebook platform, your use
 * of this software is subject to the Facebook Developer Principles and
 * Policies [http://developers.facebook.com/policy/]. This copyright notice
 * shall be included in all copies or substantial portions of the software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 *
 */

namespace FacebookAdsTest\Object;

use FacebookAds\Object\AbstractCrudObject;

class EmptyCrudObject extends AbstractCrudObject {
}


<?php
/**
 * Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
 *
 * You are hereby granted a non-exclusive, worldwide, royalty-free license to
 * use, copy, modify, and distribute this software in source code or binary
 * form for use in connection with the web services and APIs provided by
 * Facebook.
 *
 * As with any software that integrates with the Facebook platform, your use
 * of this software is subject to the Facebook Developer Principles and
 * Policies [http://developers.facebook.com/policy/]. This copyright notice
 * shall be included in all copies or substantial portions of the software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 *
 */

namespace FacebookAdsTest\Object;

use FacebookAds\Object\AbstractCrudObject;
use FacebookAds\Object\AbstractObject;

class EmptyObject extends AbstractObject {

  /**
   * @var array
   */
  protected static $fields = array(
    AbstractCrudObject::FIELD_ID,
  );
}


<?php
/**
 * Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
 *
 * You are hereby granted a non-exclusive, worldwide, royalty-free license to
 * use, copy, modify, and distribute this software in source code or binary
 * form for use in connection with the web services and APIs provided by
 * Facebook.
 *
 * As with any software that integrates with the Facebook platform, your use
 * of this software is subject to the Facebook Developer Principles and
 * Policies [http://developers.facebook.com/policy/]. This copyright notice
 * shall be included in all copies or substantial portions of the software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 *
 */

namespace FacebookAdsTest\Object;

use FacebookAds\Object\Fields\LeadgenFormFields;
use FacebookAds\Object\LeadgenForm;
use FacebookAds\Object\Page;

class LeadgenFormTest extends AbstractCrudObjectTestCase {

  /**
   * @var int
   */
  protected $leadgenFormId;

  public function setup() {
    parent::setup();

    $page = new Page($this->getConfig()->pageId);
    $forms = $page->getLeadgenForms();

    if ($forms->count() === 0) {
      $this->markTestSkipped(sprintf(
        'LeadgenForms can\'t be created through the API.'
          .' Page %s has no leadgen forms',
        (string)$this->getConfig()->pageId));
    }

    $this->leadgenFormId = $forms->current()->{LeadgenFormFields::ID};
  }

  public function tearDown() {
    $this->leadgenFormId = null;

    parent::tearDown();
  }

  public function testCrud() {
    $form = new LeadgenForm($this->leadgenFormId);

    $this->assertCannotCreate($form);
    $this->assertCanRead($form);
    $this->assertCannotUpdate($form);
    $this->assertCanFetchConnection($form, 'getLeads');
    $this->assertCannotDelete($form);
  }
}


<?php
/**
 * Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
 *
 * You are hereby granted a non-exclusive, worldwide, royalty-free license to
 * use, copy, modify, and distribute this software in source code or binary
 * form for use in connection with the web services and APIs provided by
 * Facebook.
 *
 * As with any software that integrates with the Facebook platform, your use
 * of this software is subject to the Facebook Developer Principles and
 * Policies [http://developers.facebook.com/policy/]. This copyright notice
 * shall be included in all copies or substantial portions of the software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 *
 */

namespace FacebookAdsTest\Object;

use FacebookAds\Object\Fields\LeadFields;
use FacebookAds\Object\Fields\LeadgenFormFields;
use FacebookAds\Object\Lead;
use FacebookAds\Object\LeadgenForm;
use FacebookAds\Object\Page;

class LeadTest extends AbstractCrudObjectTestCase {

  /**
   * @var int
   */
  protected $leadId;

  public function setup() {
    parent::setup();

    $limit = 25;
    $page = new Page($this->getConfig()->pageId);
    $forms = $page->getLeadgenForms(
      array(LeadgenFormFields::ID),
      array('limit' => $limit));

    $forms->setUseImplicitFetch(false); // Force-disable pagination

    /** @var LeadgenForm $form */
    foreach ($forms as $form) {
      $leads = $form->getLeads();
      if ($leads->count() > 0) {
        $this->leadId = $leads->current()->{LeadFields::ID};
        break;
      }
    }

    if ($this->leadId === null) {
      $this->markTestSkipped(sprintf(
        'Leads can\'t be created through the API.'
          .' The first %d leadgen forms of Page %s have no leads',
        $limit,
        (string)$this->getConfig()->pageId));
    }
  }

  public function tearDown() {
    $this->leadId = null;

    parent::tearDown();
  }

  public function testCrud() {
    $lead = new Lead($this->leadId);

    $this->assertCannotCreate($lead);
    $this->assertCanRead($lead);
    $this->assertCannotUpdate($lead);
    $this->assertCannotDelete($lead);
  }
}


<?php
/**
 * Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
 *
 * You are hereby granted a non-exclusive, worldwide, royalty-free license to
 * use, copy, modify, and distribute this software in source code or binary
 * form for use in connection with the web services and APIs provided by
 * Facebook.
 *
 * As with any software that integrates with the Facebook platform, your use
 * of this software is subject to the Facebook Developer Principles and
 * Policies [http://developers.facebook.com/policy/]. This copyright notice
 * shall be included in all copies or substantial portions of the software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 *
 */

namespace FacebookAdsTest\Object;

use FacebookAds\Object\Page;

class PageTest extends AbstractCrudObjectTestCase {

  public function testConnections() {
    $page = new Page($this->getConfig()->pageId);

    $this->assertCannotCreate($page);
    $this->assertCanRead($page);
    $this->assertCanFetchConnection($page, 'getLeadgenForms');

    // Page editing is currently not supported in the SDK
  }
}


<?php
/**
 * Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
 *
 * You are hereby granted a non-exclusive, worldwide, royalty-free license to
 * use, copy, modify, and distribute this software in source code or binary
 * form for use in connection with the web services and APIs provided by
 * Facebook.
 *
 * As with any software that integrates with the Facebook platform, your use
 * of this software is subject to the Facebook Developer Principles and
 * Policies [http://developers.facebook.com/policy/]. This copyright notice
 * shall be included in all copies or substantial portions of the software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 *
 */

namespace FacebookAdsTest\Object;

use FacebookAds\Object\AbstractCrudObject;
use FacebookAds\Object\AdAccount;
use FacebookAds\Object\PartnerCategory;
use FacebookAdsTest\Config\SkippableFeatureTestInterface;

class PartnerCategoryTest extends AbstractCrudObjectTestCase
  implements SkippableFeatureTestInterface {

  /**
   * @return array
   */
  public function skipIfAny() {
    return array('no_partner_categories');
  }

  public function testCrudAccess() {
    $account = new AdAccount($this->getConfig()->accountId);
    $cursor = $account->getPartnerCategories();
    if (!$cursor->count()) {
      $this->markTestSkipped();
    }

    /* @var $category AbstractCrudObject */
    $category = $cursor->current();

    $this->assertTrue($category instanceof PartnerCategory);
    $this->assertCanRead($category);
    $this->assertCannotUpdate($category);
    $this->assertCannotDelete($category);
    $this->assertCannotCreate(
      new PartnerCategory(null, $this->getConfig()->accountId));
  }
}


<?php
/**
 * Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
 *
 * You are hereby granted a non-exclusive, worldwide, royalty-free license to
 * use, copy, modify, and distribute this software in source code or binary
 * form for use in connection with the web services and APIs provided by
 * Facebook.
 *
 * As with any software that integrates with the Facebook platform, your use
 * of this software is subject to the Facebook Developer Principles and
 * Policies [http://developers.facebook.com/policy/]. This copyright notice
 * shall be included in all copies or substantial portions of the software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 *
 */

namespace FacebookAdsTest\Object;

use FacebookAds\Object\AdAccount;
use FacebookAds\Object\AdsPixel;
use FacebookAds\Object\ProductAudience;
use FacebookAds\Object\ProductCatalog;
use FacebookAds\Object\ProductSet;
use FacebookAds\Object\Fields\AdsPixelsFields;
use FacebookAds\Object\Fields\ProductAudienceFields;
use FacebookAds\Object\Fields\ProductCatalogFields;
use FacebookAds\Object\Fields\ProductSetFields;

class ProductAudienceTest extends AbstractCrudObjectTestCase {

  /**
   * @var ProductSet
   */
  protected $productSet;

  /**
   * @var ProductCatalog
   */
  protected $productCatalog;

  /**
   * @var AdAccount
   */
  protected $account;

  /**
   * @var AdsPixel
   */
  protected $adsPixel;

  public function setup() {
    parent::setup();

    $this->account = new AdAccount($this->getConfig()->accountId);

    $cursor = $this->account->getAdsPixels();
    $this->adsPixel = $cursor->current();

    $this->productCatalog =
      new ProductCatalog(null, $this->getConfig()->businessId);
    $this->productCatalog->setData(array(
      ProductCatalogFields::NAME => $this->getConfig()->testRunId,
    ));
    $this->productCatalog->create();

    $this->productSet =
      new ProductSet(null, $this->productCatalog->{ProductCatalogFields::ID});
    $this->productSet->setData(array(
      ProductSetFields::NAME => $this->getConfig()->testRunId,
      ProductSetFields::FILTER => array(
        'retailer_id' => array(
          'is_any' => array('pid1', 'pid2')
        )
      )
    ));
    $this->productSet->create();
  }

  public function tearDown() {
    if ($this->productSet) {
      $this->productSet->deleteSelf();
      $this->productSet = null;
    }

    if ($this->productCatalog) {
      $this->productCatalog->deleteSelf();
      $this->productCatalog = null;
    }

    parent::tearDown();
  }

  public function testCrudAccess() {
    $audience_name = $this->getConfig()->testRunId;
    $this->adsPixel->{AdsPixelsFields::ID};

    $audience = new ProductAudience(null, $this->getConfig()->accountId);
    $audience->setData(array(
      ProductAudienceFields::NAME => $audience_name,
      ProductAudienceFields::PRODUCT_SET_ID =>
        $this->productSet->{ProductSetFields::ID},
      ProductAudienceFields::PIXEL_ID =>
        $this->adsPixel->{AdsPixelsFields::ID},
      ProductAudienceFields::INCLUSIONS => array(array(
        'retention_seconds' => 86400,
        'rule' => array(
          'and' => array(
            array('event' => array('eq'=>'ViewContent')),
            array('userAgent' => array('i_contains'=>'iPhone'))
          )
        )
      )),
    ));

    $this->assertCanCreate($audience);
    $this->assertCanRead($audience);
    $this->assertCanUpdate($audience, array(
      ProductAudienceFields::NAME => $audience_name.' updated',
    ));
    $this->assertCanDelete($audience);
  }
}


<?php
/**
 * Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
 *
 * You are hereby granted a non-exclusive, worldwide, royalty-free license to
 * use, copy, modify, and distribute this software in source code or binary
 * form for use in connection with the web services and APIs provided by
 * Facebook.
 *
 * As with any software that integrates with the Facebook platform, your use
 * of this software is subject to the Facebook Developer Principles and
 * Policies [http://developers.facebook.com/policy/]. This copyright notice
 * shall be included in all copies or substantial portions of the software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 *
 */

namespace FacebookAdsTest\Object;

use FacebookAds\Object\ProductCatalog;
use FacebookAds\Object\Fields\ProductCatalogFields;

class ProductCatalogTest extends AbstractCrudObjectTestCase {

  public function testCrud() {
    $catalog_name = $this->getConfig()->testRunId;
    $catalog = new ProductCatalog(null, $this->getConfig()->businessId);
    $catalog->setData(array(
      ProductCatalogFields::NAME => $catalog_name,
    ));

    $this->assertCanCreate($catalog);
    $this->assertCanRead($catalog);
    $this->assertCanUpdate($catalog, array(
      ProductCatalogFields::NAME => $catalog_name.' updated',
    ));
    $this->assertCanFetchConnectionAsArray($catalog, 'getExternalEventSources');
    $this->assertCanFetchConnection($catalog, 'getProductSets');
    $this->assertCanFetchConnection($catalog, 'getProductFeeds');
    $this->assertCanDelete($catalog);
  }
}


<?php
/**
 * Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
 *
 * You are hereby granted a non-exclusive, worldwide, royalty-free license to
 * use, copy, modify, and distribute this software in source code or binary
 * form for use in connection with the web services and APIs provided by
 * Facebook.
 *
 * As with any software that integrates with the Facebook platform, your use
 * of this software is subject to the Facebook Developer Principles and
 * Policies [http://developers.facebook.com/policy/]. This copyright notice
 * shall be included in all copies or substantial portions of the software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 *
 */

namespace FacebookAdsTest\Object;

use FacebookAds\Object\ProductCatalog;
use FacebookAds\Object\ProductFeed;
use FacebookAds\Object\Fields\ProductCatalogFields;
use FacebookAds\Object\Fields\ProductFeedFields;

class ProductFeedTest extends AbstractCrudObjectTestCase {

  /**
   * @var ProductCatalog
   */
  protected $productCatalog;

  public function setup() {
    parent::setup();

    $this->productCatalog
      = new ProductCatalog(null, $this->getConfig()->businessId);
    $this->productCatalog->setData(array(
      ProductCatalogFields::NAME => $this->getConfig()->testRunId,
    ));
    $this->productCatalog->create();
  }

  public function tearDown() {
    if ($this->productCatalog) {
      $this->productCatalog->deleteSelf();
      $this->productCatalog = null;
    }

    parent::tearDown();
  }

  public function testCrudAccess() {
    $feed_name = $this->getConfig()->testRunId;
    $feed = new ProductFeed(null, $this->productCatalog->id);
    $feed->setData(array(
      ProductFeedFields::FILE_NAME => 'my_product_feed.tsv',
      ProductFeedFields::NAME => $feed_name,
    ));

    $this->assertCanCreate($feed);
    $this->assertCanRead($feed);
    $this->assertCanUpdate($feed, array(
      ProductFeedFields::NAME => $feed_name.' updated',
    ));
    $this->assertCanFetchConnection($feed, 'getProducts');
    $this->assertCanFetchConnection($feed, 'getUploads');
    $this->assertCanDelete($feed);
  }
}


<?php
/**
 * Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
 *
 * You are hereby granted a non-exclusive, worldwide, royalty-free license to
 * use, copy, modify, and distribute this software in source code or binary
 * form for use in connection with the web services and APIs provided by
 * Facebook.
 *
 * As with any software that integrates with the Facebook platform, your use
 * of this software is subject to the Facebook Developer Principles and
 * Policies [http://developers.facebook.com/policy/]. This copyright notice
 * shall be included in all copies or substantial portions of the software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 *
 */

namespace FacebookAdsTest\Object;

use FacebookAds\Object\ProductCatalog;
use FacebookAds\Object\ProductSet;
use FacebookAds\Object\Fields\ProductCatalogFields;
use FacebookAds\Object\Fields\ProductSetFields;

class ProductSetTest extends AbstractCrudObjectTestCase {

  /**
   * @var ProductCatalog
   */
  protected $productCatalog;

  public function setup() {
    parent::setup();

    $this->productCatalog
      = new ProductCatalog(null, $this->getConfig()->businessId);
    $this->productCatalog->setData(array(
      ProductCatalogFields::NAME => $this->getConfig()->testRunId,
    ));
    $this->productCatalog->create();
  }

  public function tearDown() {
    if ($this->productCatalog) {
      $this->productCatalog->deleteSelf();
      $this->productCatalog = null;
    }

    parent::tearDown();
  }

  public function testCrudAccess() {
    $feed_name = $this->getConfig()->testRunId;
    $product_set = new ProductSet(null, $this->productCatalog->id);
    $product_set->setData(array(
      ProductSetFields::NAME => $feed_name,
      ProductSetFields::FILTER => array(
        'retailer_id' => array(
          'is_any' => array('pid1', 'pid2')
        )
      )
    ));

    $this->assertCanCreate($product_set);
    $this->assertCanRead($product_set);
    $this->assertCanUpdate($product_set, array(
      ProductSetFields::NAME => $feed_name.' updated',
    ));
    $this->assertCanFetchConnection($product_set, 'getProductGroups');
    $this->assertCanDelete($product_set);
  }
}


<?php
/**
 * Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
 *
 * You are hereby granted a non-exclusive, worldwide, royalty-free license to
 * use, copy, modify, and distribute this software in source code or binary
 * form for use in connection with the web services and APIs provided by
 * Facebook.
 *
 * As with any software that integrates with the Facebook platform, your use
 * of this software is subject to the Facebook Developer Principles and
 * Policies [http://developers.facebook.com/policy/]. This copyright notice
 * shall be included in all copies or substantial portions of the software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 *
 */

namespace FacebookAdsTest\Object;

use FacebookAds\Object\Project;
use FacebookAds\Object\Fields\ProjectFields;
use FacebookAdsTest\Config\SkippableFeatureTestInterface;

class ProjectTest extends AbstractCrudObjectTestCase
  implements SkippableFeatureTestInterface {

  /**
   * @return array
   */
  public function skipIfAny() {
    return array('no_business_manager');
  }

  public function testCrud() {
    $project = new Project(null, $this->getConfig()->businessId);
    $project->{ProjectFields::NAME} = 'Test Project';

    $this->assertCanCreate($project);
    $this->assertCanRead($project);
    $this->assertCanUpdate($project, array(
      ProjectFields::NAME => 'Updated Test Project Name'
    ));

    $this->assertCanFetchConnection($project, 'getPages');
    $this->assertCanFetchConnection($project, 'getAdAccounts');
    $this->assertCanFetchConnection($project, 'getApps');

    $project->addPage($this->getConfig()->pageId);
    $project->deletePage($this->getConfig()->pageId);

    $project->adAdAccount($this->getConfig()->accountId);
    $project->deleteAdAccount($this->getConfig()->accountId);

    $project->addApp($this->getConfig()->appId);
    $project->deleteApp($this->getConfig()->appId);

    $this->assertCanDelete($project);
  }
}


<?php
/**
 * Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
 *
 * You are hereby granted a non-exclusive, worldwide, royalty-free license to
 * use, copy, modify, and distribute this software in source code or binary
 * form for use in connection with the web services and APIs provided by
 * Facebook.
 *
 * As with any software that integrates with the Facebook platform, your use
 * of this software is subject to the Facebook Developer Principles and
 * Policies [http://developers.facebook.com/policy/]. This copyright notice
 * shall be included in all copies or substantial portions of the software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 *
 */

namespace FacebookAdsTest\Object;

use FacebookAdsTest\AbstractTestCase;
use FacebookAds\Object\ReachEstimate;
use FacebookAds\Object\Fields\ReachEstimateFields;

class ReachEstimateTest extends AbstractTestCase {

  public function testOnlyInnerData() {
    $reach_estimate = new ReachEstimate();
    $reach_estimate->setData(array(
      'data' => array(
        ReachEstimateFields::ESTIMATE_READY => true,
      ),
    ));
    $this->assertTrue($reach_estimate->{ReachEstimateFields::ESTIMATE_READY});
  }

  public function testOnlyOuterData() {
    $reach_estimate = new ReachEstimate();
    $reach_estimate->setData(array(
      ReachEstimateFields::ESTIMATE_READY => true,
    ));
    $this->assertTrue($reach_estimate->{ReachEstimateFields::ESTIMATE_READY});
  }

  public function testInnerDataTakesPrecedenceOverOuterData() {
    $reach_estimate = new ReachEstimate();
    $reach_estimate->setData(array(
      ReachEstimateFields::ESTIMATE_READY => false,
      'data' => array(
        ReachEstimateFields::ESTIMATE_READY => true,
      ),
     ));
    $this->assertTrue($reach_estimate->{ReachEstimateFields::ESTIMATE_READY});
  }
}


<?php
/**
 * Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
 *
 * You are hereby granted a non-exclusive, worldwide, royalty-free license to
 * use, copy, modify, and distribute this software in source code or binary
 * form for use in connection with the web services and APIs provided by
 * Facebook.
 *
 * As with any software that integrates with the Facebook platform, your use
 * of this software is subject to the Facebook Developer Principles and
 * Policies [http://developers.facebook.com/policy/]. This copyright notice
 * shall be included in all copies or substantial portions of the software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 *
 */

namespace FacebookAdsTest\Object;

use FacebookAds\Object\Fields\TargetingFields;
use FacebookAds\Object\ReachFrequencyPrediction;
use FacebookAds\Object\Fields\ReachFrequencyPredictionFields as RF;
use FacebookAds\Object\TargetingSpecs;
use FacebookAds\Object\Values\AdObjectives;
use FacebookAdsTest\Config\SkippableFeatureTestInterface;

class ReachFrequencyPredictionTest extends AbstractCrudObjectTestCase
  implements SkippableFeatureTestInterface {

  /**
   * @return array
   */
  public function skipIfAny() {
    return array('no_reach_and_frequency');
  }

  public function testCrudAccess() {

    $prediction
      = new ReachFrequencyPrediction(null, $this->getConfig()->accountId);

    $targeting = new TargetingSpecs();
    $targeting->{TargetingSpecsFields::GEO_LOCATIONS}
      = array('countries' => array('US'));
    $targeting->{TargetingFields::AGE_MAX} = 35;
    $targeting->{TargetingFields::AGE_MIN} = 20;
    $targeting->{TargetingFields::GENDERS} = array(2);
    $targeting->{TargetingFields::PUBLISHER_PLATFORMS} = array('facebook');
    $targeting->{TargetingFields::DEVICE_PLATFORMS} = array('desktop');
    $targeting->{TargetingFields::FACEBOOK_POSITIONS} = array('feed');

    $prediction->setData(array(
      RF::BUDGET => 3000000,
      RF::TARGET_SPEC => $targeting,
      RF::START_TIME => strtotime('midnight + 2 weeks'),
      RF::END_TIME => strtotime('midnight + 3 weeks'),
      RF::FREQUENCY_CAP => 4,
      RF::DESTINATION_ID => $this->getConfig()->pageId,
      RF::PREDICTION_MODE => ReachFrequencyPrediction::PREDICTION_MODE_REACH,
      RF::OBJECTIVE => AdObjectives::POST_ENGAGEMENT,
      RF::STORY_EVENT_TYPE => 128,
    ));

    $this->assertCanCreate($prediction);
    $this->assertCanDelete($prediction);
  }

}


<?php
/**
 * Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
 *
 * You are hereby granted a non-exclusive, worldwide, royalty-free license to
 * use, copy, modify, and distribute this software in source code or binary
 * form for use in connection with the web services and APIs provided by
 * Facebook.
 *
 * As with any software that integrates with the Facebook platform, your use
 * of this software is subject to the Facebook Developer Principles and
 * Policies [http://developers.facebook.com/policy/]. This copyright notice
 * shall be included in all copies or substantial portions of the software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 *
 */

namespace FacebookAdsTest\Object;

use FacebookAds\Object\AbstractCrudObject;
use FacebookAds\Object\TargetingSearch;
use FacebookAds\Object\Search\TargetingSearchTypes;

class TargetingSearchTest extends AbstractCrudObjectTestCase {

  public function testCrudAccess() {
    $cursor = TargetingSearch::search(
      TargetingSearchTypes::GEOLOCATION, null, 'Lon');

    /* @var $category AbstractCrudObject */
    $result = $cursor->current();
    $this->assertTrue($result instanceof TargetingSearch);
    $this->assertNotEmpty($result->key);
  }
}


<?php
/**
 * Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
 *
 * You are hereby granted a non-exclusive, worldwide, royalty-free license to
 * use, copy, modify, and distribute this software in source code or binary
 * form for use in connection with the web services and APIs provided by
 * Facebook.
 *
 * As with any software that integrates with the Facebook platform, your use
 * of this software is subject to the Facebook Developer Principles and
 * Policies [http://developers.facebook.com/policy/]. This copyright notice
 * shall be included in all copies or substantial portions of the software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 *
 */

namespace FacebookAdsTest\Object\CustomAudienceNormalizers;

use FacebookAdsTest\AbstractUnitTestCase;
use FacebookAds\Object\CustomAudienceNormalizers\EmailNormalizer;

class EmailNormalizerTest extends AbstractUnitTestCase {

    /**
     * @var EmailNormalizer
     */
    protected $emailNormalizer;

    public function setUp() {
        $this->emailNormalizer = new EmailNormalizer();
    }

    public function testNormalizeData() {
        return array(
            array(
                "foo@fb.com\t\r\n\0\x0B.",
                'foo@fb.com',
            ),
        );
    }

    /**
     * @dataProvider testNormalizeData
     */
    public function testNormalize($input, $expected) {
        $this->assertEquals(
            $expected,
            $this->emailNormalizer->normalize('email', $input));
    }
}


#!/usr/bin/env php
<?php
/*
 * Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
 *
 * You are hereby granted a non-exclusive, worldwide, royalty-free license to
 * use, copy, modify, and distribute this software in source code or binary
 * form for use in connection with the web services and APIs provided by
 * Facebook.
 *
 * As with any software that integrates with the Facebook platform, your use
 * of this software is subject to the Facebook Developer Principles and
 * Policies [http://developers.facebook.com/policy/]. This copyright notice
 * shall be included in all copies or substantial portions of the software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 *
 */

use FacebookAds\Api;
use FacebookAds\Cursor;
use FacebookAds\Object\AbstractCrudObject;
use FacebookAds\Object\AdAccount;
use FacebookAds\Logger\CurlLogger;
use FacebookAdsTest\Bootstrap\IntegrationBootstrap;

chdir(__DIR__);

/** @var IntegrationBootstrap $bootstrap */
if (in_array('--docsmith-bootstrap', $_SERVER['argv'])) {
  $bootstrap = require_once __DIR__.'/../docsmith/init_integration.php';
} else {
  $bootstrap = require_once __DIR__.'/../test/init_integration.php';
}

$config = $bootstrap->getConfig();

Api::init($config->appId, $config->appSecret, $config->accessToken);

if (in_array('--dump', $_SERVER['argv'])) {
  Api::instance()->setLogger(new CurlLogger(STDERR));
}

$get_class_name = function($object) {
  return (new ReflectionClass($object))->getShortName();
};

$delete_object = function(AbstractCrudObject $object) use ($get_class_name) {
  echo sprintf(
    ' > Deleting %s %d',
    $get_class_name($object),
    $object->{AbstractCrudObject::FIELD_ID}).PHP_EOL;

  try {
    $object->deleteSelf();
  } catch (Exception $e) {
    echo sprintf(" > Deletion failed with %s: %s",
      $get_class_name($e),
      $e->getMessage()).PHP_EOL;
  }
};

$clean_edge = function($cursor_provider) use ($get_class_name, $delete_object) {
  try {
    $cursor = call_user_func($cursor_provider);
    if (!$cursor instanceof Cursor) {
      throw new ErrorException(sprintf(
        "Provider returned instance of %s",
        $get_class_name($cursor)));
    }
    $cursor->setUseImplicitFetch(true);
    foreach ($cursor as $object) {
      if (!$object instanceof AbstractCrudObject) {
        throw new ErrorException(sprintf(
          "Provider returned instance of %s, not a CRUD object",
          $get_class_name($object)));
      }

      $trait = 'FacebookAds\Object\Traits\CannotDelete';
      if (in_array($trait, (new ReflectionClass($object))->getTraitNames())) {
        break;
      }
      $delete_object($object);
    }
  } catch (Exception $e) {
    echo sprintf(" > Edge iteration failed with %s: %s",
      $get_class_name($e),
      $e->getMessage()).PHP_EOL;
  }
};

$account = new AdAccount($config->accountId);
$reflection = new ReflectionClass($account);

foreach ($reflection->getMethods(ReflectionMethod::IS_PUBLIC) as $method) {
  if (
    strncasecmp($method->getName(), 'get', 3) !== 0
    || preg_match('/@return\s+Cursor/', $method->getDocComment()) !== 1
  ) {
    continue;
  }

  echo sprintf(' > Fetching AdAccount::%s', $method->getName()).PHP_EOL;
  $clean_edge($method->getClosure($account));
}


<?php
/**
 * Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
 *
 * You are hereby granted a non-exclusive, worldwide, royalty-free license to
 * use, copy, modify, and distribute this software in source code or binary
 * form for use in connection with the web services and APIs provided by
 * Facebook.
 *
 * As with any software that integrates with the Facebook platform, your use
 * of this software is subject to the Facebook Developer Principles and
 * Policies [http://developers.facebook.com/policy/]. This copyright notice
 * shall be included in all copies or substantial portions of the software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 *
 */

namespace FacebookAdsBin;

use Symfony\Component\Finder\Finder;

chdir(__DIR__.DIRECTORY_SEPARATOR.'..'.DIRECTORY_SEPARATOR);

require_once 'vendor'.DIRECTORY_SEPARATOR.'autoload.php';

// Options
$include_autoloader = !in_array('--no-autoloader', $_SERVER['argv']);
$compress_gzip = !in_array('--no-gzip', $_SERVER['argv']);

$alias = 'facebook-php-ads-sdk.phar';
$build_dir = '.'.DIRECTORY_SEPARATOR.'builds'.DIRECTORY_SEPARATOR;
$out = $build_dir.$alias;

if (!is_dir($build_dir)) {
  mkdir($build_dir);
} else if (file_exists($out)) {
  unlink($out);
}

$phar = new \Phar($out, 0, $alias);
$phar->setSignatureAlgorithm(\Phar::SHA1);
if ($compress_gzip) {
  $phar->compressFiles(\Phar::GZ);
}
$phar->startBuffering();
$phar->addFile('LICENSE');

$finder = (new Finder())->files()
  ->ignoreVCS(true)
  ->name('*.php')
  ->in('src');

foreach ($finder->getIterator() as $file) {
  $phar->addFile($file);
}

$stub = <<<'EOF'
<?php
/**
 * Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
 *
 * You are hereby granted a non-exclusive, worldwide, royalty-free license to
 * use, copy, modify, and distribute this software in source code or binary
 * form for use in connection with the web services and APIs provided by
 * Facebook.
 *
 * As with any software that integrates with the Facebook platform, your use
 * of this software is subject to the Facebook Developer Principles and
 * Policies [http://developers.facebook.com/policy/]. This copyright notice
 * shall be included in all copies or substantial portions of the software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 *
 */
Phar::mapPhar('%s');

if (%d) {
  spl_autoload_register(function($class) {
    $prefix = 'FacebookAds\\';
    $base_dir = 'phar://%s/src/FacebookAds/';
    $len = strlen($prefix);
    if (strncmp($prefix, $class, $len) !== 0) {
      return;
    }
    $relative_class = substr($class, $len);
    $file = $base_dir.str_replace(
      '\\', DIRECTORY_SEPARATOR, $relative_class).'.php';
    if (file_exists($file)) {
      require $file;
    }
  });
}

__HALT_COMPILER();
EOF;

$phar->setStub(sprintf($stub, $alias, $include_autoloader ? 1 : 0, $alias));
$phar->stopBuffering();


#!/usr/bin/env php
<?php
/**
 * Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
 *
 * You are hereby granted a non-exclusive, worldwide, royalty-free license to
 * use, copy, modify, and distribute this software in source code or binary
 * form for use in connection with the web services and APIs provided by
 * Facebook.
 *
 * As with any software that integrates with the Facebook platform, your use
 * of this software is subject to the Facebook Developer Principles and
 * Policies [http://developers.facebook.com/policy/]. This copyright notice
 * shall be included in all copies or substantial portions of the software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 *
 */

use FacebookAdsTest\Bootstrap;
use FacebookAdsDocsmith\Runner;
use FacebookAdsDocsmith\Runner\ActionsEnum;
use FacebookAdsDocsmith\Runner\OptionsEnum;
use FacebookAdsTest\Bootstrap\IntegrationBootstrap;

$relative_path = getcwd();
chdir(__DIR__);

/** @var IntegrationBootstrap $bootstrap */
$bootstrap = require_once __DIR__.'/../docsmith/init_auto.php';

if ($argc < 3) {
  Runner::throwInvalidUsage("Insufficient number of arguments");
}

$action = $argv[1];
if (!ActionsEnum::getInstance()->isValidValue($action)) {
  Runner::throwInvalidUsage("Unknown action {$action}");
}

$doc_path = $argv[2][0] == '/'
  ? $argv[2]
  : realpath($relative_path.'/'.$argv[2]);

if (!file_exists($doc_path)) {
  Runner::throwInvalidUsage("Can't open {$doc_path} for reading");
}

$opts = array_splice($argv, 3);
$options = new ArrayObject(
  array_fill_keys(OptionsEnum::getInstance()->getValues(), false));

foreach ($opts as $opt) {
  $opt = substr($opt, 1);
  if (OptionsEnum::getInstance()->isValidValue($opt)) {
    $options->offsetSet($opt, true);
  }
}

$runner = new Runner($doc_path, $action, $options);

exit($runner->run());


#!/usr/bin/env php
<?php
/**
 * Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
 *
 * You are hereby granted a non-exclusive, worldwide, royalty-free license to
 * use, copy, modify, and distribute this software in source code or binary
 * form for use in connection with the web services and APIs provided by
 * Facebook.
 *
 * As with any software that integrates with the Facebook platform, your use
 * of this software is subject to the Facebook Developer Principles and
 * Policies [http://developers.facebook.com/policy/]. This copyright notice
 * shall be included in all copies or substantial portions of the software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 *
 */

use \FacebookAdsDocsmith\Bootstrap\IntegrationBootstrap;
use FacebookAds\Api;

chdir(__DIR__);

/** @var IntegrationBootstrap $bootstrap */
$bootstrap = require_once __DIR__.'/../docsmith/init_stub.php';

echo sprintf('v%s', Api::init('', '', '')->getDefaultGraphVersion()).PHP_EOL;


<?php
/**
 * Copyright (c) Meta Platforms, Inc. and affiliates.
 * All rights reserved.
 *
 * You are hereby granted a non-exclusive, worldwide, royalty-free license to
 * use, copy, modify, and distribute this software in source code or binary
 * form for use in connection with the web services and APIs provided by
 * Facebook.
 *
 * As with any software that integrates with the Facebook platform, your use
 * of this software is subject to the Facebook Developer Principles and
 * Policies [http://developers.facebook.com/policy/]. This copyright notice
 * shall be included in all copies or substantial portions of the software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 */

require __DIR__ . '/vendor/autoload.php';

use FacebookAds\Object\AdAccount;
use FacebookAds\Object\AdCreative;
use FacebookAds\Api;
use FacebookAds\Logger\CurlLogger;

$access_token = '<ACCESS_TOKEN>';
$app_secret = '<APP_SECRET>';
$app_id = '<APP_ID>';
$id = '<AD_ACCOUNT_ID>';

$api = Api::init($app_id, $app_secret, $access_token);
$api->setLogger(new CurlLogger());

$fields = array(
  'name',
);
$params = array(
);
echo json_encode((new AdAccount($id))->getAdCreatives(
  $fields,
  $params
)->getResponse()->getContent(), JSON_PRETTY_PRINT);


<?php
/**
 * Copyright (c) Meta Platforms, Inc. and affiliates.
 * All rights reserved.
 *
 * You are hereby granted a non-exclusive, worldwide, royalty-free license to
 * use, copy, modify, and distribute this software in source code or binary
 * form for use in connection with the web services and APIs provided by
 * Facebook.
 *
 * As with any software that integrates with the Facebook platform, your use
 * of this software is subject to the Facebook Developer Principles and
 * Policies [http://developers.facebook.com/policy/]. This copyright notice
 * shall be included in all copies or substantial portions of the software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 */

require __DIR__ . '/vendor/autoload.php';

use FacebookAds\Object\AdAccount;
use FacebookAds\Object\AdCreative;
use FacebookAds\Api;
use FacebookAds\Logger\CurlLogger;

$access_token = '<ACCESS_TOKEN>';
$app_secret = '<APP_SECRET>';
$app_id = '<APP_ID>';
$id = '<AD_ACCOUNT_ID>';

$api = Api::init($app_id, $app_secret, $access_token);
$api->setLogger(new CurlLogger());

$fields = array(
);
$params = array(
  'name' => 'Sample Promoted Post',
  'object_story_id' => '<pageID>_<postID>',
);
echo json_encode((new AdAccount($id))->createAdCreative(
  $fields,
  $params
)->exportAllData(), JSON_PRETTY_PRINT);


<?php
/**
 * Copyright (c) Meta Platforms, Inc. and affiliates.
 * All rights reserved.
 *
 * You are hereby granted a non-exclusive, worldwide, royalty-free license to
 * use, copy, modify, and distribute this software in source code or binary
 * form for use in connection with the web services and APIs provided by
 * Facebook.
 *
 * As with any software that integrates with the Facebook platform, your use
 * of this software is subject to the Facebook Developer Principles and
 * Policies [http://developers.facebook.com/policy/]. This copyright notice
 * shall be included in all copies or substantial portions of the software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 */

require __DIR__ . '/vendor/autoload.php';

use FacebookAds\Object\AdAccount;
use FacebookAds\Object\AdCreative;
use FacebookAds\Api;
use FacebookAds\Logger\CurlLogger;

$access_token = '<ACCESS_TOKEN>';
$app_secret = '<APP_SECRET>';
$app_id = '<APP_ID>';
$id = '<AD_ACCOUNT_ID>';

$api = Api::init($app_id, $app_secret, $access_token);
$api->setLogger(new CurlLogger());

$fields = array(
);
$params = array(
  'object_story_id' => '<pageID>_<postID>',
);
echo json_encode((new AdAccount($id))->createAdCreative(
  $fields,
  $params
)->exportAllData(), JSON_PRETTY_PRINT);


<?php
/**
 * Copyright (c) Meta Platforms, Inc. and affiliates.
 * All rights reserved.
 *
 * You are hereby granted a non-exclusive, worldwide, royalty-free license to
 * use, copy, modify, and distribute this software in source code or binary
 * form for use in connection with the web services and APIs provided by
 * Facebook.
 *
 * As with any software that integrates with the Facebook platform, your use
 * of this software is subject to the Facebook Developer Principles and
 * Policies [http://developers.facebook.com/policy/]. This copyright notice
 * shall be included in all copies or substantial portions of the software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 */

require __DIR__ . '/vendor/autoload.php';

use FacebookAds\Object\AdAccount;
use FacebookAds\Object\AdCreative;
use FacebookAds\Api;
use FacebookAds\Logger\CurlLogger;

$access_token = '<ACCESS_TOKEN>';
$app_secret = '<APP_SECRET>';
$app_id = '<APP_ID>';
$id = '<AD_ACCOUNT_ID>';

$api = Api::init($app_id, $app_secret, $access_token);
$api->setLogger(new CurlLogger());

$fields = array(
);
$params = array(
  'image_hash' => '<imageHash>',
  'object_story_spec' => array('page_id' => '<pageID>','link_data' => array('image_hash' => '<imageHash>','link' => '<canvasURI>','name' => 'Creative message','call_to_action' => array('type' => 'LEARN_MORE'))),
);
echo json_encode((new AdAccount($id))->createAdCreative(
  $fields,
  $params
)->exportAllData(), JSON_PRETTY_PRINT);


<?php
/**
 * Copyright (c) Meta Platforms, Inc. and affiliates.
 * All rights reserved.
 *
 * You are hereby granted a non-exclusive, worldwide, royalty-free license to
 * use, copy, modify, and distribute this software in source code or binary
 * form for use in connection with the web services and APIs provided by
 * Facebook.
 *
 * As with any software that integrates with the Facebook platform, your use
 * of this software is subject to the Facebook Developer Principles and
 * Policies [http://developers.facebook.com/policy/]. This copyright notice
 * shall be included in all copies or substantial portions of the software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 */

require __DIR__ . '/vendor/autoload.php';

use FacebookAds\Object\AdAccount;
use FacebookAds\Object\AdCreative;
use FacebookAds\Api;
use FacebookAds\Logger\CurlLogger;

$access_token = '<ACCESS_TOKEN>';
$app_secret = '<APP_SECRET>';
$app_id = '<APP_ID>';
$id = '<AD_ACCOUNT_ID>';

$api = Api::init($app_id, $app_secret, $access_token);
$api->setLogger(new CurlLogger());

$fields = array(
);
$params = array(
  'object_story_spec' => array('page_id' => '<pageID>','template_data' => array('format_option' => 'collection_video','link' => '<canvasURI>','name' => 'English Creative title','message' => 'English Creative message','call_to_action' => array('type' => 'LEARN_MORE'),'retailer_item_ids' => array(0,0,0,0),'customization_rules_spec' => array(array('customization_spec' => array('language' => 'en_XX')),array('customization_spec' => array('language' => 'fr_XX'),'link' => '<canvasURIFR>','name' => 'French Creative title','message' => 'French Creative message')))),
  'product_set_id' => '<productSetID>',
);
echo json_encode((new AdAccount($id))->createAdCreative(
  $fields,
  $params
)->exportAllData(), JSON_PRETTY_PRINT);


<?php
/**
 * Copyright (c) Meta Platforms, Inc. and affiliates.
 * All rights reserved.
 *
 * You are hereby granted a non-exclusive, worldwide, royalty-free license to
 * use, copy, modify, and distribute this software in source code or binary
 * form for use in connection with the web services and APIs provided by
 * Facebook.
 *
 * As with any software that integrates with the Facebook platform, your use
 * of this software is subject to the Facebook Developer Principles and
 * Policies [http://developers.facebook.com/policy/]. This copyright notice
 * shall be included in all copies or substantial portions of the software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 */

require __DIR__ . '/vendor/autoload.php';

use FacebookAds\Object\AdAccount;
use FacebookAds\Object\AdCreative;
use FacebookAds\Api;
use FacebookAds\Logger\CurlLogger;

$access_token = '<ACCESS_TOKEN>';
$app_secret = '<APP_SECRET>';
$app_id = '<APP_ID>';
$id = '<AD_ACCOUNT_ID>';

$api = Api::init($app_id, $app_secret, $access_token);
$api->setLogger(new CurlLogger());

$fields = array(
);
$params = array(
  'object_story_spec' => array('page_id' => '<pageID>','link_data' => array('picture' => '<imageURL>','link' => '<canvasURI>','name' => 'English Creative title','message' => 'English Creative message','call_to_action' => array('type' => 'LEARN_MORE'),'retailer_item_ids' => array(0,0,0,0),'customization_rules_spec' => array(array('customization_spec' => array('language' => 'en_XX')),array('customization_spec' => array('language' => 'fr_XX'),'picture' => '<imageURLFR>','link' => '<canvasURIFR>','name' => 'French Creative title','message' => 'French Creative message')))),
  'product_set_id' => '<productSetID>',
);
echo json_encode((new AdAccount($id))->createAdCreative(
  $fields,
  $params
)->exportAllData(), JSON_PRETTY_PRINT);


<?php
/**
 * Copyright (c) Meta Platforms, Inc. and affiliates.
 * All rights reserved.
 *
 * You are hereby granted a non-exclusive, worldwide, royalty-free license to
 * use, copy, modify, and distribute this software in source code or binary
 * form for use in connection with the web services and APIs provided by
 * Facebook.
 *
 * As with any software that integrates with the Facebook platform, your use
 * of this software is subject to the Facebook Developer Principles and
 * Policies [http://developers.facebook.com/policy/]. This copyright notice
 * shall be included in all copies or substantial portions of the software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 */

require __DIR__ . '/vendor/autoload.php';

use FacebookAds\Object\AdAccount;
use FacebookAds\Object\AdCreative;
use FacebookAds\Api;
use FacebookAds\Logger\CurlLogger;

$access_token = '<ACCESS_TOKEN>';
$app_secret = '<APP_SECRET>';
$app_id = '<APP_ID>';
$id = '<AD_ACCOUNT_ID>';

$api = Api::init($app_id, $app_secret, $access_token);
$api->setLogger(new CurlLogger());

$fields = array(
);
$params = array(
  'object_story_spec' => array('page_id' => '<pageID>','video_data' => array('video_id' => '<videoID>','image_url' => '<imageURL>','title' => 'English Creative title','message' => 'English Creative message','call_to_action' => array('type' => 'LEARN_MORE','value' => array('link' => '<canvasURI>')),'retailer_item_ids' => array(0,0,0,0),'customization_rules_spec' => array(array('customization_spec' => array('language' => 'en_XX')),array('customization_spec' => array('language' => 'fr_XX'),'video_id' => '<videoIDFR>','picture' => '<imageURLFR>','link' => '<canvasURIFR>','name' => 'French Creative title','message' => 'French Creative message')))),
  'product_set_id' => '<productSetID>',
);
echo json_encode((new AdAccount($id))->createAdCreative(
  $fields,
  $params
)->exportAllData(), JSON_PRETTY_PRINT);