1<?php 2/** 3 * Copyright 2017 Facebook, Inc. 4 * 5 * You are hereby granted a non-exclusive, worldwide, royalty-free license to 6 * use, copy, modify, and distribute this software in source code or binary 7 * form for use in connection with the web services and APIs provided by 8 * Facebook. 9 * 10 * As with any software that integrates with the Facebook platform, your use 11 * of this software is subject to the Facebook Developer Principles and 12 * Policies [http://developers.facebook.com/policy/]. This copyright notice 13 * shall be included in all copies or substantial portions of the software. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21 * DEALINGS IN THE SOFTWARE. 22 * 23 */ 24namespace Facebook\GraphNodes; 25 26use Facebook\FacebookRequest; 27use Facebook\Url\FacebookUrlManipulator; 28use Facebook\Exceptions\FacebookSDKException; 29 30/** 31 * Class GraphEdge 32 * 33 * @package Facebook 34 */ 35class GraphEdge extends Collection 36{ 37 /** 38 * @var FacebookRequest The original request that generated this data. 39 */ 40 protected $request; 41 42 /** 43 * @var array An array of Graph meta data like pagination, etc. 44 */ 45 protected $metaData = []; 46 47 /** 48 * @var string|null The parent Graph edge endpoint that generated the list. 49 */ 50 protected $parentEdgeEndpoint; 51 52 /** 53 * @var string|null The subclass of the child GraphNode's. 54 */ 55 protected $subclassName; 56 57 /** 58 * Init this collection of GraphNode's. 59 * 60 * @param FacebookRequest $request The original request that generated this data. 61 * @param array $data An array of GraphNode's. 62 * @param array $metaData An array of Graph meta data like pagination, etc. 63 * @param string|null $parentEdgeEndpoint The parent Graph edge endpoint that generated the list. 64 * @param string|null $subclassName The subclass of the child GraphNode's. 65 */ 66 public function __construct(FacebookRequest $request, array $data = [], array $metaData = [], $parentEdgeEndpoint = null, $subclassName = null) 67 { 68 $this->request = $request; 69 $this->metaData = $metaData; 70 $this->parentEdgeEndpoint = $parentEdgeEndpoint; 71 $this->subclassName = $subclassName; 72 73 parent::__construct($data); 74 } 75 76 /** 77 * Gets the parent Graph edge endpoint that generated the list. 78 * 79 * @return string|null 80 */ 81 public function getParentGraphEdge() 82 { 83 return $this->parentEdgeEndpoint; 84 } 85 86 /** 87 * Gets the subclass name that the child GraphNode's are cast as. 88 * 89 * @return string|null 90 */ 91 public function getSubClassName() 92 { 93 return $this->subclassName; 94 } 95 96 /** 97 * Returns the raw meta data associated with this GraphEdge. 98 * 99 * @return array 100 */ 101 public function getMetaData() 102 { 103 return $this->metaData; 104 } 105 106 /** 107 * Returns the next cursor if it exists. 108 * 109 * @return string|null 110 */ 111 public function getNextCursor() 112 { 113 return $this->getCursor('after'); 114 } 115 116 /** 117 * Returns the previous cursor if it exists. 118 * 119 * @return string|null 120 */ 121 public function getPreviousCursor() 122 { 123 return $this->getCursor('before'); 124 } 125 126 /** 127 * Returns the cursor for a specific direction if it exists. 128 * 129 * @param string $direction The direction of the page: after|before 130 * 131 * @return string|null 132 */ 133 public function getCursor($direction) 134 { 135 if (isset($this->metaData['paging']['cursors'][$direction])) { 136 return $this->metaData['paging']['cursors'][$direction]; 137 } 138 139 return null; 140 } 141 142 /** 143 * Generates a pagination URL based on a cursor. 144 * 145 * @param string $direction The direction of the page: next|previous 146 * 147 * @return string|null 148 * 149 * @throws FacebookSDKException 150 */ 151 public function getPaginationUrl($direction) 152 { 153 $this->validateForPagination(); 154 155 // Do we have a paging URL? 156 if (!isset($this->metaData['paging'][$direction])) { 157 return null; 158 } 159 160 $pageUrl = $this->metaData['paging'][$direction]; 161 162 return FacebookUrlManipulator::baseGraphUrlEndpoint($pageUrl); 163 } 164 165 /** 166 * Validates whether or not we can paginate on this request. 167 * 168 * @throws FacebookSDKException 169 */ 170 public function validateForPagination() 171 { 172 if ($this->request->getMethod() !== 'GET') { 173 throw new FacebookSDKException('You can only paginate on a GET request.', 720); 174 } 175 } 176 177 /** 178 * Gets the request object needed to make a next|previous page request. 179 * 180 * @param string $direction The direction of the page: next|previous 181 * 182 * @return FacebookRequest|null 183 * 184 * @throws FacebookSDKException 185 */ 186 public function getPaginationRequest($direction) 187 { 188 $pageUrl = $this->getPaginationUrl($direction); 189 if (!$pageUrl) { 190 return null; 191 } 192 193 $newRequest = clone $this->request; 194 $newRequest->setEndpoint($pageUrl); 195 196 return $newRequest; 197 } 198 199 /** 200 * Gets the request object needed to make a "next" page request. 201 * 202 * @return FacebookRequest|null 203 * 204 * @throws FacebookSDKException 205 */ 206 public function getNextPageRequest() 207 { 208 return $this->getPaginationRequest('next'); 209 } 210 211 /** 212 * Gets the request object needed to make a "previous" page request. 213 * 214 * @return FacebookRequest|null 215 * 216 * @throws FacebookSDKException 217 */ 218 public function getPreviousPageRequest() 219 { 220 return $this->getPaginationRequest('previous'); 221 } 222 223 /** 224 * The total number of results according to Graph if it exists. 225 * 226 * This will be returned if the summary=true modifier is present in the request. 227 * 228 * @return int|null 229 */ 230 public function getTotalCount() 231 { 232 if (isset($this->metaData['summary']['total_count'])) { 233 return $this->metaData['summary']['total_count']; 234 } 235 236 return null; 237 } 238 239 /** 240 * @inheritDoc 241 */ 242 public function map(\Closure $callback) 243 { 244 return new static( 245 $this->request, 246 array_map($callback, $this->items, array_keys($this->items)), 247 $this->metaData, 248 $this->parentEdgeEndpoint, 249 $this->subclassName 250 ); 251 } 252} 253