BxAdsModule.php 109 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789
  1. <?php defined('BX_DOL') or die('hack attempt');
  2. /**
  3. * Copyright (c) UNA, Inc - https://una.io
  4. * MIT License - https://opensource.org/licenses/MIT
  5. *
  6. * @defgroup Ads Ads
  7. * @ingroup UnaModules
  8. *
  9. * @{
  10. */
  11. define('BX_ADS_STATUS_OFFER', 'offer');
  12. define('BX_ADS_STATUS_SOLD', 'sold');
  13. define('BX_ADS_STATUS_ADMIN_UNPAID', 'unpaid');
  14. define('BX_ADS_COMMODITY_TYPE_PRODUCT', 'product');
  15. define('BX_ADS_COMMODITY_TYPE_PROMOTION', 'promotion');
  16. define('BX_ADS_OFFER_STATUS_ACCEPTED', 'accepted');
  17. define('BX_ADS_OFFER_STATUS_AWAITING', 'awaiting');
  18. define('BX_ADS_OFFER_STATUS_DECLINED', 'declined');
  19. define('BX_ADS_OFFER_STATUS_CANCELED', 'canceled');
  20. define('BX_ADS_OFFER_STATUS_PAID', 'paid');
  21. /**
  22. * Ads module
  23. */
  24. class BxAdsModule extends BxBaseModTextModule
  25. {
  26. protected $_aOfferStatuses;
  27. function __construct(&$aModule)
  28. {
  29. parent::__construct($aModule);
  30. $this->_oConfig->init($this->_oDb);
  31. $CNF = &$this->_oConfig->CNF;
  32. $this->_aSearchableNamesExcept = array_merge($this->_aSearchableNamesExcept, array(
  33. $CNF['FIELD_CATEGORY_VIEW'],
  34. $CNF['FIELD_CATEGORY_SELECT']
  35. ));
  36. $this->_aOfferStatuses = array(
  37. BX_ADS_OFFER_STATUS_ACCEPTED,
  38. BX_ADS_OFFER_STATUS_AWAITING,
  39. BX_ADS_OFFER_STATUS_DECLINED
  40. );
  41. }
  42. public function decodeDataApi ($aData, $bExtended = false)
  43. {
  44. $CNF = $this->_oConfig->CNF;
  45. $aResult = array_merge(parent::decodeDataApi($aData, $bExtended), [
  46. $CNF['FIELD_PRICE'] => $aData[$CNF['FIELD_PRICE']],
  47. $CNF['FIELD_QUANTITY'] => $aData[$CNF['FIELD_QUANTITY']],
  48. $CNF['FIELD_NOTES_PURCHASED'] => $aData[$CNF['FIELD_NOTES_PURCHASED']]
  49. ]);
  50. if($this->_oConfig->isSources() && !empty($aData[$CNF['FIELD_URL']]))
  51. $aResult[$CNF['FIELD_URL']] = $aData[$CNF['FIELD_URL']];
  52. return $aResult;
  53. }
  54. public function actionGetSource()
  55. {
  56. $aEntries = $this->serviceGetSourceData();
  57. header('Content-Type:text/javascript; charset=utf-8');
  58. echo(json_encode($aEntries));
  59. }
  60. public function serviceGetSourceData()
  61. {
  62. $sSourceType = bx_get('source_type');
  63. if(empty($sSourceType)) {
  64. $aSource = $this->serviceGetSource($this->_iProfileId);
  65. if(!empty($aSource) && is_array($aSource))
  66. $sSourceType = $aSource['name'];
  67. }
  68. $sTerm = bx_get('term');
  69. $aEntries = $this->serviceLoadEntriesFromSourceByTerm($sSourceType, $sTerm);
  70. return $aEntries;
  71. }
  72. public function actionLoadEntryFromSource()
  73. {
  74. $sSourceType = bx_process_url_param(bx_process_input(bx_get('source_type')));
  75. $sSource = bx_process_url_param(bx_process_input(bx_get('source')));
  76. if(empty($sSourceType) || empty($sSource))
  77. return echoJson(['code' => 1]);
  78. $aEntry = $this->serviceLoadEntryFromSource($sSourceType, $sSource);
  79. if(empty($aEntry) || !is_array($aEntry))
  80. return echoJson(['code' => 2]);
  81. return echoJson([
  82. 'code' => 0,
  83. 'fields' => $aEntry
  84. ]);
  85. }
  86. public function actionGetCategoryForm()
  87. {
  88. if(($iCategory = bx_get('category')) === false || (int)$iCategory == 0)
  89. return echoJson(['msg' => _t('_bx_ads_form_entry_input_category_select_err')]);
  90. return echoJson([
  91. 'eval' => $this->_oConfig->getJsObject('form') . '.onSelectCategory(oData)',
  92. 'content' => $this->serviceGetCreatePostForm([
  93. 'absolute_action_url' => true,
  94. 'dynamic_mode' => true,
  95. 'visibility_auto' => false,
  96. 'context_id' => ($iContextId = bx_get('context_id')) !== false ? (int)$iContextId : false,
  97. ])
  98. ]);
  99. }
  100. public function actionCheckName()
  101. {
  102. $CNF = &$this->_oConfig->CNF;
  103. $iId = (int)bx_get($CNF['FIELD_ID']);
  104. $sTitle = bx_process_input(bx_get($CNF['FIELD_TITLE']));
  105. echoJson($this->serviceCheckName($sTitle, $iId));
  106. }
  107. public function actionInterested()
  108. {
  109. $iContentId = bx_process_input(bx_get('id'), BX_DATA_INT);
  110. $aResult = $this->serviceInterested($iContentId);
  111. echoJson($aResult);
  112. }
  113. public function serviceInterested($iContentId, $iViewer = 0)
  114. {
  115. $CNF = &$this->_oConfig->CNF;
  116. $aContentInfo = $this->_oDb->getContentInfoById($iContentId);
  117. if(empty($aContentInfo) || !is_array($aContentInfo))
  118. return [];
  119. $iViewer = $iViewer ?: bx_get_logged_profile_id();
  120. $oViewer = BxDolProfile::getInstance($iViewer);
  121. if(!$oViewer)
  122. return [];
  123. $iContentAuthor = (int)$aContentInfo[$CNF['FIELD_AUTHOR']];
  124. if($iContentAuthor == $iViewer)
  125. return ['msg' => _t('_bx_ads_txt_err_your_own')];
  126. if($this->_oDb->isInterested($iContentId, $iViewer))
  127. return ['msg' => _t('_bx_ads_txt_err_duplicate')];
  128. $iInterestId = $this->_oDb->insertInterested(array('entry_id' => $iContentId, 'profile_id' => $iViewer));
  129. if(!$iInterestId)
  130. return ['msg' => _t('_bx_ads_txt_err_cannot_perform_action')];
  131. /**
  132. * @hooks
  133. * @hookdef hook-bx_ads-doInterest 'bx_ads', 'doInterest' - hook after 'interested' action was performed
  134. * - $unit_name - equals `bx_ads`
  135. * - $action - equals `doInterest`
  136. * - $object_id - content id
  137. * - $sender_id - profile id who performed the action
  138. * - $extra_params - array of additional params with the following array keys:
  139. * - `subobject_id` - [int] id of a database table record, created during the action
  140. * - `subobject_author_id` - [int] profile id who performed the action
  141. * - `object_author_id` - [int] content author profile id
  142. * @hook @ref hook-bx_ads-doInterest
  143. */
  144. bx_alert($this->getName(), 'doInterest', $iContentId, $iViewer, [
  145. 'subobject_id' => $iInterestId,
  146. 'subobject_author_id' => $iViewer,
  147. 'object_author_id' => $iContentAuthor
  148. ]);
  149. if(getParam($CNF['PARAM_USE_IIN']) == 'on')
  150. sendMailTemplate($CNF['ETEMPLATE_INTERESTED'], 0, $iContentAuthor, array(
  151. 'viewer_name' => $oViewer->getDisplayName(),
  152. 'viewer_url' => $oViewer->getUrl(),
  153. 'ad_name' => $aContentInfo[$CNF['FIELD_TITLE']],
  154. 'ad_url' => bx_absolute_url(BxDolPermalinks::getInstance()->permalink('page.php', array(
  155. 'i' => $CNF['URI_VIEW_ENTRY'],
  156. $CNF['FIELD_ID'] => $iContentId
  157. )))
  158. ));
  159. return ['msg' => _t('_bx_ads_txt_msg_author_notified')];
  160. }
  161. public function actionShow()
  162. {
  163. return echoJson($this->_actionChangeStatus(BX_BASE_MOD_TEXT_STATUS_ACTIVE));
  164. }
  165. public function actionHide()
  166. {
  167. return echoJson($this->_actionChangeStatus(BX_BASE_MOD_TEXT_STATUS_HIDDEN));
  168. }
  169. public function actionMakeOffer()
  170. {
  171. $CNF = &$this->_oConfig->CNF;
  172. $sJsObject = $this->_oConfig->getJsObject('entry');
  173. $iAuthorId = bx_get_logged_profile_id();
  174. $iContentId = bx_process_input(bx_get('content_id'), BX_DATA_INT);
  175. if(empty($iAuthorId))
  176. return echoJson(['code' => 1, 'eval' => 'window.open("' . BxDolPermalinks::getInstance()->permalink('page.php?i=login') . '", "_self");']);
  177. $aContentInfo = $this->_oDb->getContentInfoById($iContentId);
  178. if(empty($aContentInfo) || !is_array($aContentInfo))
  179. return echoJson([]);
  180. if(($mixedCheck = $this->checkAllowedMakeOffer($aContentInfo)) !== CHECK_ACTION_RESULT_ALLOWED)
  181. return echoJson(['code' => 2, 'msg' => $mixedCheck]);
  182. $aOffer = $this->_oDb->getOffersBy([
  183. 'type' => 'content_and_author_ids',
  184. 'content_id' => $iContentId,
  185. 'author_id' => $iAuthorId,
  186. 'status' => BX_ADS_OFFER_STATUS_AWAITING
  187. ]);
  188. if(!empty($aOffer) && is_array($aOffer))
  189. return echoJson(['code' => 3, 'msg' => _t('_bx_ads_txt_err_duplicate')]);
  190. $aOffer = $this->_oDb->getOffersBy([
  191. 'type' => 'content_and_author_ids',
  192. 'content_id' => $iContentId,
  193. 'author_id' => $iAuthorId,
  194. 'status' => BX_ADS_OFFER_STATUS_ACCEPTED
  195. ]);
  196. if(!empty($aOffer) && is_array($aOffer))
  197. return echoJson(['code' => 4, 'msg' => _t('_bx_ads_txt_err_offer_accepted')]);
  198. $oForm = BxDolForm::getObjectInstance($CNF['OBJECT_FORM_OFFER'], $CNF['OBJECT_FORM_OFFER_DISPLAY_ADD']);
  199. $oForm->aFormAttrs['action'] = BX_DOL_URL_ROOT . bx_append_url_params($this->_oConfig->getBaseUri() . 'make_offer', ['content_id' => $iContentId]);
  200. $oForm->initChecker();
  201. if($oForm->isSubmittedAndValid()) {
  202. $iQuantity = (int)$oForm->getCleanValue($CNF['FIELD_OFR_QUANTITY']);
  203. $iQuantityAvailable = $this->getAvailableQuantity($aContentInfo);
  204. if($iQuantity > $iQuantityAvailable)
  205. return echoJson(['code' => 5, 'msg' => _t('_bx_ads_txt_err_offer_wrong_quantity', $iQuantityAvailable)]);
  206. $aValToAdd = ['content_id' => $iContentId, 'author_id' => $iAuthorId];
  207. if(($iId = (int)$oForm->insert($aValToAdd)) != 0) {
  208. $this->checkAllowedMakeOffer($aContentInfo, true);
  209. $this->onOfferAdded($iId, $aResult);
  210. $aResult = ['code' => 0, 'msg' => _t('_bx_ads_txt_msg_offer_added'), 'eval' => $sJsObject . '.onMakeOffer(oData);', 'id' => $iId];
  211. }
  212. else
  213. $aResult = ['code' => 6, 'msg' => _t('_bx_ads_txt_err_cannot_perform_action')];
  214. return echoJson($aResult);
  215. }
  216. $sContent = BxTemplFunctions::getInstance()->transBox($this->_oConfig->getHtmlIds('offer_popup'), $this->_oTemplate->parseHtmlByName('offer_popup.html', array(
  217. 'form_id' => $oForm->getId(),
  218. 'form' => $oForm->getCode(true)
  219. )));
  220. return echoJson(array('popup' => array('html' => $sContent, 'options' => array('closeOnOuterClick' => false, 'removeOnClose' => true))));
  221. }
  222. public function actionViewOffer()
  223. {
  224. $CNF = &$this->_oConfig->CNF;
  225. $iAuthorId = bx_get_logged_profile_id();
  226. $iOfferId = bx_process_input(bx_get('id'), BX_DATA_INT);
  227. $aOffer = $this->_oDb->getOffersBy(array('type' => 'id', 'id' => $iOfferId));
  228. if(empty($aOffer) || !is_array($aOffer))
  229. return echoJson(array());
  230. $oForm = BxDolForm::getObjectInstance($CNF['OBJECT_FORM_OFFER'], $CNF['OBJECT_FORM_OFFER_DISPLAY_VIEW']);
  231. $oForm->initChecker($aOffer);
  232. $sContent = BxTemplFunctions::getInstance()->transBox($this->_oConfig->getHtmlIds('offer_popup'), $this->_oTemplate->parseHtmlByName('offer_popup.html', array(
  233. 'form_id' => $oForm->getId(),
  234. 'form' => $oForm->getCode(true)
  235. )));
  236. return echoJson(array('popup' => array('html' => $sContent, 'options' => array('closeOnOuterClick' => true, 'removeOnClose' => true))));
  237. }
  238. public function actionAcceptOffer()
  239. {
  240. $iId = bx_process_input(bx_get('id'), BX_DATA_INT);
  241. if(($mixedResult = $this->offerAccept($iId)) !== true)
  242. return echoJson(['msg' => $mixedResult !== false ? $mixedResult : _t('_bx_ads_txt_err_cannot_perform_action')]);
  243. return echoJson(['msg' => _t('_bx_ads_txt_msg_offer_accepted'), 'reload' => 1]);
  244. }
  245. public function actionDeclineOffer()
  246. {
  247. $iId = bx_process_input(bx_get('id'), BX_DATA_INT);
  248. if(!$this->offerDecline($iId))
  249. return echoJson(array('msg' => _t('_bx_ads_txt_err_cannot_perform_action')));
  250. return echoJson(array('msg' => _t('_bx_ads_txt_msg_offer_declined'), 'reload' => 1));
  251. }
  252. public function actionCancelOffer()
  253. {
  254. $iId = bx_process_input(bx_get('id'), BX_DATA_INT);
  255. if(!$this->offerCancel($iId))
  256. return echoJson(['msg' => _t('_bx_ads_txt_err_cannot_perform_action')]);
  257. return echoJson(['msg' => _t('_bx_ads_txt_msg_offer_canceled'), 'reload' => 1]);
  258. }
  259. public function actionPayOffer()
  260. {
  261. $iId = bx_process_input(bx_get('id'), BX_DATA_INT);
  262. if(($mixedResult = $this->offerPay($iId)) !== false)
  263. return echoJson($mixedResult);
  264. return echoJson(array('msg' => _t('_bx_ads_txt_err_cannot_perform_action')));
  265. }
  266. public function actionShipped()
  267. {
  268. return echoJson($this->_actionMarkAs('shipped'));
  269. }
  270. public function actionReceived()
  271. {
  272. return echoJson($this->_actionMarkAs('received'));
  273. }
  274. public function actionRegisterImpression($iId)
  275. {
  276. echoJson($this->serviceRegisterImpression($iId));
  277. }
  278. public function actionRegisterClick($iId)
  279. {
  280. echoJson($this->serviceRegisterClick($iId));
  281. }
  282. public function serviceGetSafeServices()
  283. {
  284. return array_merge(parent::serviceGetSafeServices(), [
  285. 'Interested' => '',
  286. 'IsSourcesAvaliable' => '',
  287. 'LoadEntryFromSource' => '',
  288. 'LoadEntriesFromSourceByTerm' => '',
  289. 'EntityReviews' => '',
  290. 'EntityReviewsRating' => '',
  291. 'CategoriesList' => '',
  292. 'BrowseCategory' => '',
  293. 'RegisterImpression' => '',
  294. 'RegisterClick' => '',
  295. 'BlockSourcesDetails' => '',
  296. 'GetSourceData' => '',
  297. ]);
  298. }
  299. public function serviceRegisterImpression($iId)
  300. {
  301. return ['code' => $this->_oDb->updatePromotionTracker($iId, 'impressions') ? 0 : 1];
  302. }
  303. public function serviceRegisterClick($iId)
  304. {
  305. $CNF = &$this->_oConfig->CNF;
  306. if(!$this->_oDb->updatePromotionTracker($iId, 'clicks'))
  307. return ['code' => 1];
  308. $sUrl = '';
  309. if($this->_oConfig->isSources()) {
  310. $aEntry = $this->_oDb->getContentInfoById($iId);
  311. if(!empty($aEntry) && is_array($aEntry) && !empty($aEntry[$CNF['FIELD_URL']]))
  312. $sUrl = $aEntry[$CNF['FIELD_URL']];
  313. }
  314. return [
  315. 'code' => 0,
  316. 'redirect' => !empty($sUrl) ? $sUrl : $this->_oConfig->getViewEntryUrl($iId)
  317. ];
  318. }
  319. public function serviceCheckName($sTitle, $iId = 0)
  320. {
  321. $CNF = &$this->_oConfig->CNF;
  322. if(empty($sTitle))
  323. return array();
  324. $sName = '';
  325. if(!empty($iId)) {
  326. $aEntry = $this->_oDb->getContentInfoById($iId);
  327. if(strcmp($sTitle, $aEntry[$CNF['FIELD_NAME']]) == 0)
  328. $sName = $sTitle;
  329. }
  330. return array(
  331. 'title' => $sTitle,
  332. 'name' => !empty($sName) ? $sName : $this->_oConfig->getEntryName($sTitle, $iId)
  333. );
  334. }
  335. public function serviceUpdateCategoriesStats($mixedContentInfo = false)
  336. {
  337. $aContentInfo = [];
  338. if(!empty($mixedContentInfo))
  339. $aContentInfo = !is_array($mixedContentInfo) ? $this->_oDb->getContentInfoById((int)$mixedContentInfo) : $mixedContentInfo;
  340. $iCategoryId = 0;
  341. if($aContentInfo && !empty($aContentInfo['category']))
  342. $iCategoryId = (int)$aContentInfo['category'];
  343. return $this->serviceUpdateCategoriesStatsByCategory($iCategoryId);
  344. }
  345. public function serviceUpdateCategoriesStatsByCategory($iCategoryId = 0)
  346. {
  347. $aParams = ['type' => 'collect_stats'];
  348. if($iCategoryId)
  349. $aParams['category_id'] = (int)$iCategoryId;
  350. $aStats = $this->_oDb->getCategories($aParams);
  351. if(empty($aStats) || !is_array($aStats))
  352. return true;
  353. $iUpdated = 0;
  354. foreach($aStats as $aStat)
  355. if($this->_oDb->updateCategory(array('items' => $aStat['count']), array('id' => $aStat['id'])))
  356. $iUpdated++;
  357. return count($aStats) == $iUpdated;
  358. }
  359. public function serviceGetCategoryOptions($iParentId, $bPleaseSelect = false)
  360. {
  361. $aValues = array();
  362. if($bPleaseSelect)
  363. $aValues[] = array('key' => '', 'value' => _t('_sys_please_select'));
  364. $this->_getCategoryOptions($iParentId, $aValues);
  365. return $aValues;
  366. }
  367. public function serviceGetSearchableFields($aInputsAdd = array())
  368. {
  369. $CNF = &$this->_oConfig->CNF;
  370. $aResult = parent::serviceGetSearchableFields(array_merge($aInputsAdd, $this->_getSearchableFields()));
  371. unset($aResult[$CNF['FIELD_NOTES_PURCHASED']]);
  372. unset($aResult[$CNF['FIELD_CATEGORY_VIEW']], $aResult[$CNF['FIELD_CATEGORY_SELECT']]);
  373. unset($aResult[$CNF['FIELD_PRICE']], $aResult[$CNF['FIELD_YEAR']]);
  374. return $aResult;
  375. }
  376. public function serviceGetSearchableFieldsExtended($aInputsAdd = array())
  377. {
  378. $CNF = &$this->_oConfig->CNF;
  379. $aInputsAdd = array_merge($aInputsAdd, $this->_getSearchableFields());
  380. if(isset($aInputsAdd[$CNF['FIELD_CATEGORY']])) {
  381. $aInputsAdd[$CNF['FIELD_CATEGORY']]['type'] = 'select';
  382. $aInputsAdd[$CNF['FIELD_CATEGORY']]['values_src'] = BxDolService::getSerializedService($this->_oConfig->getName(), 'get_category_options', array(0));
  383. }
  384. if(isset($aInputsAdd[$CNF['FIELD_PRICE']])) {
  385. $aInputsAdd[$CNF['FIELD_PRICE']]['search_type'] = 'text_range';
  386. $aInputsAdd[$CNF['FIELD_PRICE']]['search_operator'] = 'between';
  387. }
  388. if(isset($aInputsAdd[$CNF['FIELD_YEAR']])) {
  389. $aInputsAdd[$CNF['FIELD_YEAR']]['search_type'] = 'text_range';
  390. $aInputsAdd[$CNF['FIELD_YEAR']]['search_operator'] = 'between';
  391. }
  392. return parent::serviceGetSearchableFieldsExtended($aInputsAdd);
  393. }
  394. /**
  395. * Mark an ad as shipped/received by seller/bauer accordingly.
  396. * @param type $sAction - shipped/received action.
  397. * @param type $iContentId - an ad the action will be performed with.
  398. * @param integer $iProfileSrc - profile, who performed the action.
  399. * @param integer $iProfileDst - profile, the action is pointed on.
  400. * @return boolean - true or a string value with error message.
  401. */
  402. public function serviceMarkAs($sAction, $iContentId, $iProfileSrc = 0, $iProfileDst = 0)
  403. {
  404. $CNF = &$this->_oConfig->CNF;
  405. if(!$iProfileSrc)
  406. $iProfileSrc = bx_get_logged_profile_id();
  407. $sTxtError = '_bx_ads_txt_err_cannot_perform_action';
  408. $aContentInfo = $this->_oDb->getContentInfoById($iContentId);
  409. $sMethodCheck = 'checkAllowedMark' . bx_gen_method_name($sAction) . 'ForProfile';
  410. if(!method_exists($this, $sMethodCheck))
  411. return _t($sTxtError);
  412. if(($mixedCheckResult = $this->$sMethodCheck($aContentInfo, false, $iProfileSrc)) !== CHECK_ACTION_RESULT_ALLOWED)
  413. return $mixedCheckResult;
  414. if((int)$this->_oDb->updateEntriesBy(array($CNF['FIELD_' . strtoupper($sAction)] => time()), array($CNF['FIELD_ID'] => $iContentId)) == 0)
  415. return _t($sTxtError);
  416. $this->$sMethodCheck($aContentInfo, true, $iProfileSrc);
  417. $sMethodOnResult = 'on' . bx_gen_method_name($sAction);
  418. if(method_exists($this, $sMethodOnResult))
  419. $this->$sMethodOnResult($aContentInfo, $iProfileSrc, $iProfileDst);
  420. return true;
  421. }
  422. public function serviceEntityCreate ($sParams = false)
  423. {
  424. $iCategory = is_numeric($sParams) ? (int)$sParams : 0;
  425. if($this->_bIsApi && ($iCategory = bx_get('category_select')) !== false)
  426. $iCategory = (int)$iCategory;
  427. if(($sDisplay = $this->getCategoryDisplay('add', $iCategory)) !== false) {
  428. if(empty($sParams) || !is_array($sParams))
  429. $sParams = [];
  430. $sParams['display'] = $sDisplay;
  431. }
  432. if($iCategory)
  433. BxDolSession::getInstance()->setValue($sDisplay . '_category', $iCategory);
  434. return parent::serviceEntityCreate($sParams);
  435. }
  436. public function serviceEntityEditBudget ($iContentId = 0, $sDisplay = false)
  437. {
  438. $CNF = &$this->_oConfig->CNF;
  439. return parent::serviceEntityEdit($iContentId, $CNF['OBJECT_FORM_ENTRY_DISPLAY_EDIT_BUDGET']);
  440. }
  441. /**
  442. * @page service Service Calls
  443. * @section bx_ads Ads
  444. * @subsection bx_ads-page_blocks Page Blocks
  445. * @subsubsection bx_ads-entity_reviews entity_reviews
  446. *
  447. * @code bx_srv('bx_ads', 'entity_reviews', [...]); @endcode
  448. *
  449. * Get reviews for particular content
  450. * @param $iContentId content ID
  451. *
  452. * @see BxAdsModule::serviceEntityReviews
  453. */
  454. /**
  455. * @ref bx_ads-entity_reviews "entity_reviews"
  456. */
  457. public function serviceEntityReviews($iContentId = 0)
  458. {
  459. $CNF = &$this->_oConfig->CNF;
  460. if(empty($CNF['OBJECT_REVIEWS']))
  461. return false;
  462. return $this->_entityComments($CNF['OBJECT_REVIEWS'], $iContentId);
  463. }
  464. /**
  465. * @page service Service Calls
  466. * @section bx_ads Ads
  467. * @subsection bx_ads-page_blocks Page Blocks
  468. * @subsubsection bx_ads-entity_reviews_rating entity_reviews_rating
  469. *
  470. * @code bx_srv('bx_ads', 'entity_reviews_rating', [...]); @endcode
  471. *
  472. * Get reviews rating for particular content
  473. * @param $iContentId content ID
  474. *
  475. * @see BxAdsModule::serviceEntityReviewsRating
  476. */
  477. /**
  478. * @ref bx_ads-entity_reviews_rating "entity_reviews_rating"
  479. */
  480. public function serviceEntityReviewsRating($iContentId = 0)
  481. {
  482. $CNF = &$this->_oConfig->CNF;
  483. if(empty($CNF['OBJECT_REVIEWS']))
  484. return false;
  485. if(!$iContentId)
  486. $iContentId = bx_process_input(bx_get('id'), BX_DATA_INT);
  487. if(!$iContentId)
  488. return false;
  489. $oCmts = BxDolCmts::getObjectInstance($CNF['OBJECT_REVIEWS'], $iContentId);
  490. if (!$oCmts || !$oCmts->isEnabled())
  491. return false;
  492. return $oCmts->getRatingBlock(array('in_designbox' => false));
  493. }
  494. public function serviceEntityPromotionGrowth($iContentId = 0)
  495. {
  496. return $this->_serviceTemplateFunc('entryPromotionGrowth', $iContentId);
  497. }
  498. public function serviceEntityPromotionSummary($iContentId = 0)
  499. {
  500. return $this->_serviceTemplateFunc('entryPromotionSummary', $iContentId);
  501. }
  502. public function serviceEntityPromotionRoi($iContentId = 0)
  503. {
  504. return $this->_serviceTemplateFunc('entryPromotionRoi', $iContentId);
  505. }
  506. /**
  507. * @page service Service Calls
  508. * @section bx_ads Ads
  509. * @subsection bx_ads-page_blocks Page Blocks
  510. * @subsubsection bx_ads-categories_list categories_list
  511. *
  512. * @code bx_srv('bx_ads', 'categories_list', [...]); @endcode
  513. *
  514. * Get reviews rating for particular content
  515. * @param $aParams additional params array, such as 'show_empty'
  516. *
  517. * @see BxAdsModule::serviceCategoriesList
  518. */
  519. /**
  520. * @ref bx_ads-categories_list "categories_list"
  521. */
  522. public function serviceCategoriesList($aParams = array())
  523. {
  524. if(!isset($aParams['show_empty']))
  525. $aParams['show_empty'] = true;
  526. return $this->_oTemplate->categoriesList($aParams);
  527. }
  528. /**
  529. * @page service Service Calls
  530. * @section bx_ads Ads
  531. * @subsection bx_ads-browse Browse
  532. * @subsubsection bx_ads-browse_category browse_category
  533. *
  534. * @code bx_srv('bx_ads', 'browse_category', [...]); @endcode
  535. *
  536. * Get reviews rating for particular content
  537. * @param $iCategoryId category ID
  538. * @param $aParams additional params array, such as empty_message, ajax_paginate, etc
  539. *
  540. * @see BxAdsModule::serviceBrowseCategory
  541. */
  542. /**
  543. * @ref bx_ads-browse_category "browse_category"
  544. */
  545. public function serviceBrowseCategory($sUnitView = false, $bEmptyMessage = true, $bAjaxPaginate = true, $aParams = [])
  546. {
  547. $mixedResult = parent::serviceBrowseCategory($sUnitView, $bEmptyMessage, $bAjaxPaginate, $aParams);
  548. if(empty($mixedResult['content']))
  549. return $mixedResult;
  550. $aCategory = $this->_oDb->getCategories([
  551. 'type' => 'id',
  552. 'id' => !empty($aParams['category']) ? (int)$aParams['category'] : bx_process_input(bx_get('category'), BX_DATA_INT)
  553. ]);
  554. if(!empty($aCategory['title']))
  555. $mixedResult['title'] = _t('_bx_ads_page_block_title_entries_by_category_mask', _t($aCategory['title']));
  556. return $mixedResult;
  557. }
  558. public function serviceGetTimelinePost($aEvent, $aBrowseParams = [])
  559. {
  560. $CNF = &$this->_oConfig->CNF;
  561. $mixedResult = parent::serviceGetTimelinePost($aEvent, $aBrowseParams);
  562. if(!$mixedResult)
  563. return $mixedResult;
  564. $aContentInfo = $this->_oDb->getContentInfoById($aEvent['object_id']);
  565. if($this->_oConfig->isSources() && !empty($aContentInfo[$CNF['FIELD_URL']]))
  566. $mixedResult['url'] = $aContentInfo[$CNF['FIELD_URL']];
  567. return $mixedResult;
  568. }
  569. public function serviceGetNotificationsData()
  570. {
  571. $sModule = $this->_aModule['name'];
  572. $sEventPrivacy = $sModule . '_allow_view_event_to';
  573. if(BxDolPrivacy::getObjectInstance($sEventPrivacy) === false)
  574. $sEventPrivacy = '';
  575. $aResult = parent::serviceGetNotificationsData();
  576. $aResult['handlers'] = array_merge($aResult['handlers'], array(
  577. array('group' => $sModule . '_interest', 'type' => 'insert', 'alert_unit' => $sModule, 'alert_action' => 'doInterest', 'module_name' => $sModule, 'module_method' => 'get_notifications_interest', 'module_class' => 'Module', 'module_event_privacy' => $sEventPrivacy),
  578. array('group' => $sModule . '_paid', 'type' => 'insert', 'alert_unit' => $sModule, 'alert_action' => 'license_register', 'module_name' => $sModule, 'module_method' => 'get_notifications_license_register', 'module_class' => 'Module', 'module_event_privacy' => $sEventPrivacy),
  579. //---> To Buyer
  580. array('group' => $sModule . '_shipped', 'type' => 'insert', 'alert_unit' => $sModule, 'alert_action' => 'shipped', 'module_name' => $sModule, 'module_method' => 'get_notifications_shipped', 'module_class' => 'Module', 'module_event_privacy' => $sEventPrivacy),
  581. //<---
  582. array('group' => $sModule . '_received', 'type' => 'insert', 'alert_unit' => $sModule, 'alert_action' => 'received', 'module_name' => $sModule, 'module_method' => 'get_notifications_received', 'module_class' => 'Module', 'module_event_privacy' => $sEventPrivacy),
  583. array('group' => $sModule . '_offer_added', 'type' => 'insert', 'alert_unit' => $sModule, 'alert_action' => 'offer_added', 'module_name' => $sModule, 'module_method' => 'get_notifications_offer_added', 'module_class' => 'Module', 'module_event_privacy' => $sEventPrivacy),
  584. //---> To Offerer
  585. array('group' => $sModule . '_offer_accepted', 'type' => 'insert', 'alert_unit' => $sModule, 'alert_action' => 'offer_accepted', 'module_name' => $sModule, 'module_method' => 'get_notifications_offer_accepted', 'module_class' => 'Module', 'module_event_privacy' => $sEventPrivacy),
  586. array('group' => $sModule . '_offer_declined', 'type' => 'insert', 'alert_unit' => $sModule, 'alert_action' => 'offer_declined', 'module_name' => $sModule, 'module_method' => 'get_notifications_offer_declined', 'module_class' => 'Module', 'module_event_privacy' => $sEventPrivacy),
  587. //<---
  588. array('group' => $sModule . '_offer_canceled', 'type' => 'insert', 'alert_unit' => $sModule, 'alert_action' => 'offer_canceled', 'module_name' => $sModule, 'module_method' => 'get_notifications_offer_canceled', 'module_class' => 'Module', 'module_event_privacy' => $sEventPrivacy)
  589. ));
  590. $aResult['settings'] = array_merge($aResult['settings'], array(
  591. array('group' => 'interest', 'unit' => $sModule, 'action' => 'doInterest', 'types' => array('personal')),
  592. array('group' => 'usage', 'unit' => $sModule, 'action' => 'license_register', 'types' => array('personal')),
  593. array('group' => 'usage', 'unit' => $sModule, 'action' => 'shipped', 'types' => array('personal')),
  594. array('group' => 'usage', 'unit' => $sModule, 'action' => 'received', 'types' => array('personal')),
  595. array('group' => 'usage', 'unit' => $sModule, 'action' => 'offer_added', 'types' => array('personal')),
  596. array('group' => 'usage', 'unit' => $sModule, 'action' => 'offer_accepted', 'types' => array('personal')),
  597. array('group' => 'usage', 'unit' => $sModule, 'action' => 'offer_declined', 'types' => array('personal')),
  598. array('group' => 'usage', 'unit' => $sModule, 'action' => 'offer_canceled', 'types' => array('personal')),
  599. ));
  600. $aResult['alerts'] = array_merge($aResult['alerts'], array(
  601. array('unit' => $sModule, 'action' => 'doInterest'),
  602. array('unit' => $sModule, 'action' => 'license_register'),
  603. array('unit' => $sModule, 'action' => 'shipped'),
  604. array('unit' => $sModule, 'action' => 'received'),
  605. array('unit' => $sModule, 'action' => 'offer_added'),
  606. array('unit' => $sModule, 'action' => 'offer_accepted'),
  607. array('unit' => $sModule, 'action' => 'offer_declined'),
  608. array('unit' => $sModule, 'action' => 'offer_canceled'),
  609. ));
  610. return $aResult;
  611. }
  612. public function serviceGetNotificationsInsertData($oAlert, $aHandler, $aDataItems)
  613. {
  614. $CNF = &$this->_oConfig->CNF;
  615. $aResult = [];
  616. switch($oAlert->sAction) {
  617. case 'license_register':
  618. $aContentInfo = $this->_oDb->getContentInfoById($oAlert->aExtras['product_id']);
  619. if(empty($aContentInfo) || !is_array($aContentInfo)) {
  620. $aResult = $aDataItems;
  621. break;
  622. }
  623. foreach($aDataItems as $aDataItem) {
  624. $aDataItem = array_merge($aDataItem, [
  625. 'owner_id' => $oAlert->aExtras['profile_id'],
  626. 'object_id' => $aContentInfo[$CNF['FIELD_ID']],
  627. 'object_owner_id' => $aContentInfo[$CNF['FIELD_AUTHOR']],
  628. 'object_privacy_view' => BX_DOL_PG_ALL
  629. ]);
  630. $aResult[] = $aDataItem;
  631. }
  632. break;
  633. case 'shipped':
  634. foreach($aDataItems as $aDataItem) {
  635. $aLicense = $this->_oDb->getLicense(['type' => 'entry_id', 'entry_id' => $aDataItem['object_id'], 'newest' => true]);
  636. if(!empty($aLicense) && is_array($aLicense))
  637. $aDataItem['object_owner_id'] = $aLicense['profile_id'];
  638. $aResult[] = $aDataItem;
  639. }
  640. break;
  641. case 'offer_added':
  642. case 'offer_canceled':
  643. foreach($aDataItems as $aDataItem) {
  644. $aDataItem['object_owner_id'] = $oAlert->aExtras['object_author_id'];
  645. $aResult[] = $aDataItem;
  646. }
  647. break;
  648. case 'offer_accepted':
  649. case 'offer_declined':
  650. foreach($aDataItems as $aDataItem) {
  651. $aDataItem['object_owner_id'] = $oAlert->aExtras['offer_author_id'];
  652. $aResult[] = $aDataItem;
  653. }
  654. break;
  655. default:
  656. $aResult = $aDataItems;
  657. }
  658. return $aResult;
  659. }
  660. public function serviceGetNotificationsInterest($aEvent)
  661. {
  662. $CNF = &$this->_oConfig->CNF;
  663. $iContentId = (int)$aEvent['object_id'];
  664. $aContentInfo = $this->_oDb->getContentInfoById($iContentId);
  665. if(empty($aContentInfo) || !is_array($aContentInfo))
  666. return [];
  667. $iInterestedId = (int)$aEvent['subobject_id'];
  668. $aInterestedInfo = $this->_oDb->getInterested(['type' => 'id', 'id' => $iInterestedId]);
  669. if(empty($aInterestedInfo) || !is_array($aInterestedInfo))
  670. return [];
  671. if(($oInterestedProfile = BxDolProfile::getInstance($aInterestedInfo['profile_id'])) !== false)
  672. $sEntryUrl = $oInterestedProfile->getUrl();
  673. else
  674. $sEntryUrl = bx_absolute_url(BxDolPermalinks::getInstance()->permalink('page.php?i=' . $CNF['URI_VIEW_ENTRY'] . '&id=' . $iContentId), '{bx_url_root}');
  675. return [
  676. 'entry_sample' => $CNF['T']['txt_sample_single'],
  677. 'entry_url' => $sEntryUrl,
  678. 'entry_caption' => $aContentInfo[$CNF['FIELD_TITLE']],
  679. 'entry_author' => $aContentInfo[$CNF['FIELD_AUTHOR']],
  680. 'subentry_sample' => $CNF['T']['txt_sample_interest_single'],
  681. 'subentry_url' => '',
  682. 'lang_key' => '_bx_ads_txt_ntfs_subobject_interested', //may be empty or not specified. In this case the default one from Notification module will be used.
  683. ];
  684. }
  685. public function serviceGetNotificationsLicenseRegister($aEvent)
  686. {
  687. return $this->_serviceGetNotificationsByEntryAndAction($aEvent, 'license_register');
  688. }
  689. public function serviceGetNotificationsShipped($aEvent)
  690. {
  691. $aResult = $this->_serviceGetNotificationsByEntryAndAction($aEvent, 'shipped');
  692. $aResult['entry_author'] = $aEvent['object_owner_id'];
  693. return $aResult;
  694. }
  695. public function serviceGetNotificationsReceived($aEvent)
  696. {
  697. return $this->_serviceGetNotificationsByEntryAndAction($aEvent, 'received');
  698. }
  699. public function serviceGetNotificationsOfferAdded($aEvent)
  700. {
  701. return $this->_serviceGetNotificationsByOfferAndAction($aEvent, 'offer_added');
  702. }
  703. public function serviceGetNotificationsOfferAccepted($aEvent)
  704. {
  705. $aResult = $this->_serviceGetNotificationsByOfferAndAction($aEvent, 'offer_accepted');
  706. $aResult['entry_author'] = $aEvent['object_owner_id'];
  707. return $aResult;
  708. }
  709. public function serviceGetNotificationsOfferDeclined($aEvent)
  710. {
  711. $aResult = $this->_serviceGetNotificationsByOfferAndAction($aEvent, 'offer_declined');
  712. $aResult['entry_author'] = $aEvent['object_owner_id'];
  713. return $aResult;
  714. }
  715. public function serviceGetNotificationsOfferCanceled($aEvent)
  716. {
  717. return $this->_serviceGetNotificationsByOfferAndAction($aEvent, 'offer_canceled');
  718. }
  719. protected function _serviceGetNotificationsByEntryAndAction($aEvent, $sAction)
  720. {
  721. $CNF = &$this->_oConfig->CNF;
  722. $iContentId = (int)$aEvent['object_id'];
  723. $aContentInfo = $this->_oDb->getContentInfoById($iContentId);
  724. if(empty($aContentInfo) || !is_array($aContentInfo))
  725. return array();
  726. $sEntryUrl = bx_absolute_url(BxDolPermalinks::getInstance()->permalink('page.php?i=' . $CNF['URI_VIEW_ENTRY'] . '&id=' . $iContentId), '{bx_url_root}');
  727. return array(
  728. 'entry_sample' => $CNF['T']['txt_sample_single'],
  729. 'entry_url' => $sEntryUrl,
  730. 'entry_caption' => $aContentInfo[$CNF['FIELD_TITLE']],
  731. 'entry_author' => $aContentInfo[$CNF['FIELD_AUTHOR']],
  732. 'subentry_sample' => '',
  733. 'subentry_url' => '',
  734. 'lang_key' => '_bx_ads_txt_ntfs_object_' . $sAction, //may be empty or not specified. In this case the default one from Notification module will be used.
  735. );
  736. }
  737. protected function _serviceGetNotificationsByOfferAndAction($aEvent, $sAction)
  738. {
  739. $CNF = &$this->_oConfig->CNF;
  740. $iOfferId = (int)$aEvent['object_id'];
  741. $aOfferInfo = $this->_oDb->getOffersBy(['type' => 'id', 'id' => $iOfferId]);
  742. if(empty($aOfferInfo) || !is_array($aOfferInfo))
  743. return array();
  744. $iContentId = $aOfferInfo[$CNF['FIELD_OFR_CONTENT']];
  745. $aContentInfo = $this->_oDb->getContentInfoById($iContentId);
  746. if(empty($aContentInfo) || !is_array($aContentInfo))
  747. return array();
  748. $sEntryUrl = bx_absolute_url(BxDolPermalinks::getInstance()->permalink('page.php?i=' . $CNF['URI_VIEW_ENTRY'] . '&id=' . $iContentId), '{bx_url_root}');
  749. return array(
  750. 'object_id' => $iContentId,
  751. 'entry_sample' => $CNF['T']['txt_sample_single'],
  752. 'entry_url' => $sEntryUrl,
  753. 'entry_caption' => $aContentInfo[$CNF['FIELD_TITLE']],
  754. 'entry_author' => $aContentInfo[$CNF['FIELD_AUTHOR']],
  755. 'subentry_sample' => '',
  756. 'subentry_url' => '',
  757. 'lang_key' => '_bx_ads_txt_ntfs_' . $sAction, //may be empty or not specified. In this case the default one from Notification module will be used.
  758. );
  759. }
  760. /**
  761. * @page service Service Calls
  762. * @section bx_ads Ads
  763. * @subsection bx_ads-page_blocks Page Blocks
  764. * @subsubsection bx_ads-block_licenses block_licenses
  765. *
  766. * @code bx_srv('bx_ads', 'block_licenses', [...]); @endcode
  767. *
  768. * Get page block with a list of licenses purchased by currently logged member.
  769. *
  770. * @return an array describing a block to display on the site or false if there is no enough input data. All necessary CSS and JS files are automatically added to the HEAD section of the site HTML.
  771. *
  772. * @see BxAdsModule::serviceBlockLicenses
  773. */
  774. /**
  775. * @ref bx_ads-block_licenses "block_licenses"
  776. */
  777. public function serviceBlockLicenses()
  778. {
  779. return $this->_getBlockLicenses();
  780. }
  781. /**
  782. * @page service Service Calls
  783. * @section bx_ads Ads
  784. * @subsection bx_ads-page_blocks Page Blocks
  785. * @subsubsection bx_ads-block_licenses_administration block_licenses_administration
  786. *
  787. * @code bx_srv('bx_ads', 'block_licenses_administration', [...]); @endcode
  788. *
  789. * Get page block with a list of all licenses. It's needed for moderators/administrators.
  790. *
  791. * @return an array describing a block to display on the site or false if there is no enough input data. All necessary CSS and JS files are automatically added to the HEAD section of the site HTML.
  792. *
  793. * @see BxAdsModule::serviceBlockLicensesAdministration
  794. */
  795. /**
  796. * @ref bx_ads-block_licenses "block_licenses"
  797. */
  798. public function serviceBlockLicensesAdministration()
  799. {
  800. return $this->_getBlockLicenses('administration');
  801. }
  802. /**
  803. * @page service Service Calls
  804. * @section bx_ads Ads
  805. * @subsection bx_ads-page_blocks Page Blocks
  806. * @subsubsection bx_ads-block_licenses_note block_licenses_note
  807. *
  808. * @code bx_srv('bx_ads', 'block_licenses_note', [...]); @endcode
  809. *
  810. * Get page block with a notice for licenses usage.
  811. *
  812. * @return HTML string with block content to display on the site.
  813. *
  814. * @see BxAdsModule::serviceBlockLicensesNote
  815. */
  816. /**
  817. * @ref bx_ads-block_licenses_note "block_licenses_note"
  818. */
  819. public function serviceBlockLicensesNote()
  820. {
  821. return MsgBox(_t('_bx_ads_page_block_content_licenses_note'));
  822. }
  823. /**
  824. * @page service Service Calls
  825. * @section bx_ads Ads
  826. * @subsection bx_ads-payments Payments
  827. * @subsubsection bx_ads-get_payment_data get_payment_data
  828. *
  829. * @code bx_srv('bx_ads', 'get_payment_data', [...]); @endcode
  830. *
  831. * Get an array with module's description. Is needed for payments processing module.
  832. *
  833. * @return an array with module's description.
  834. *
  835. * @see BxAdsModule::serviceGetPaymentData
  836. */
  837. /**
  838. * @ref bx_ads-get_payment_data "get_payment_data"
  839. */
  840. public function serviceGetPaymentData()
  841. {
  842. $CNF = &$this->_oConfig->CNF;
  843. $oPermalink = BxDolPermalinks::getInstance();
  844. return array_merge($this->_aModule, [
  845. 'url_browse_order_common' => bx_absolute_url(bx_append_url_params($oPermalink->permalink($CNF['URL_LICENSES_COMMON']), ['filter' => '{order}'], false)),
  846. 'url_browse_order_administration' => bx_absolute_url(bx_append_url_params($oPermalink->permalink($CNF['URL_LICENSES_ADMINISTRATION']), ['filter' => '{order}'], false))
  847. ]);
  848. }
  849. /**
  850. * @page service Service Calls
  851. * @section bx_ads Ads
  852. * @subsection bx_ads-payments Payments
  853. * @subsubsection bx_ads-get_cart_item get_cart_item
  854. *
  855. * @code bx_srv('bx_ads', 'get_cart_item', [...]); @endcode
  856. *
  857. * Get an array with prodict's description. Is used in Shopping Cart in payments processing module.
  858. *
  859. * @param $mixedItemId product's ID or Unique Name.
  860. * @return an array with prodict's description. Empty array is returned if something is wrong.
  861. *
  862. * @see BxAdsModule::serviceGetCartItem
  863. */
  864. /**
  865. * @ref bx_ads-get_cart_item "get_cart_item"
  866. */
  867. public function serviceGetCartItem($mixedItemId, $iClientId = 0)
  868. {
  869. $CNF = &$this->_oConfig->CNF;
  870. if(!$mixedItemId || !is_numeric($mixedItemId))
  871. return [];
  872. $aCommodity = $this->_oDb->getCommodity(['sample' => 'id_with_entry', 'id' => (int)$mixedItemId]);
  873. if(empty($aCommodity) || !is_array($aCommodity))
  874. return [];
  875. $iItemId = (int)$aCommodity['id'];
  876. $sItemType = $aCommodity['type'];
  877. $iItemAuthor = 0;
  878. $fItemPrice = 0;
  879. switch($sItemType) {
  880. case BX_ADS_COMMODITY_TYPE_PRODUCT:
  881. $iItemAuthor = $aCommodity['entry_' . $CNF['FIELD_AUTHOR']];
  882. $fItemPrice = (float)$aCommodity['entry_' . $CNF['FIELD_PRICE']];
  883. if($this->_oConfig->isAuction() && (int)$aCommodity['entry_' . $CNF['FIELD_AUCTION']] != 0) {
  884. $aOffer = $this->_oDb->getOffersBy([
  885. 'type' => 'content_and_author_ids',
  886. 'content_id' => $iItemId,
  887. 'author_id' => $iClientId,
  888. 'status' => BX_ADS_OFFER_STATUS_ACCEPTED
  889. ]);
  890. if(!empty($aOffer) && is_array($aOffer))
  891. $fItemPrice = (float)$aOffer[$CNF['FIELD_OFR_AMOUNT']];
  892. }
  893. break;
  894. case BX_ADS_COMMODITY_TYPE_PROMOTION:
  895. $iItemAuthor = BxDolPayments::getInstance()->getOption('site_admin');
  896. $fItemPrice = (float)$aCommodity['amount'];
  897. break;
  898. }
  899. if(!$iClientId)
  900. $iClientId = bx_get_logged_profile_id();
  901. return [
  902. 'id' => $iItemId,
  903. 'author_id' => $iItemAuthor,
  904. 'name' => $aCommodity['entry_' . $CNF['FIELD_NAME']] . '-' . $sItemType,
  905. 'title' => $aCommodity['entry_' . $CNF['FIELD_TITLE']],
  906. 'description' => $sItemDescription = _t($CNF['T']['txt_cd_ct_' . $sItemType]),
  907. 'url' => bx_absolute_url(BxDolPermalinks::getInstance()->permalink('page.php?i=' . $CNF['URI_VIEW_ENTRY'], ['id' => $aCommodity['entry_' . $CNF['FIELD_ID']]])),
  908. 'price_single' => $fItemPrice,
  909. 'price_recurring' => '',
  910. 'period_recurring' => 0,
  911. 'period_unit_recurring' => '',
  912. 'trial_recurring' => ''
  913. ];
  914. }
  915. /**
  916. * @page service Service Calls
  917. * @section bx_ads Ads
  918. * @subsection bx_ads-payments Payments
  919. * @subsubsection bx_ads-get_cart_items get_cart_items
  920. *
  921. * @code bx_srv('bx_ads', 'get_cart_items', [...]); @endcode
  922. *
  923. * Get an array with prodicts' descriptions by seller. Is used in Manual Order Processing in payments processing module.
  924. *
  925. * @param $iSellerId seller ID.
  926. * @return an array with prodicts' descriptions. Empty array is returned if something is wrong or seller doesn't have any products.
  927. *
  928. * @see BxAdsModule::serviceGetCartItems
  929. */
  930. /**
  931. * @ref bx_ads-get_cart_items "get_cart_items"
  932. */
  933. public function serviceGetCartItems($iSellerId)
  934. {
  935. $CNF = &$this->_oConfig->CNF;
  936. $iSellerId = (int)$iSellerId;
  937. if(empty($iSellerId))
  938. return [];
  939. $aItems = $this->_oDb->getCommodity(['sample' => 'entry_author', 'author' => $iSellerId, 'type' => BX_ADS_COMMODITY_TYPE_PRODUCT]);
  940. $aResult = [];
  941. foreach($aItems as $aItem) {
  942. $aItemInfo = $this->_oDb->getContentInfoById((int)$aItem['entry_id']);
  943. if(empty($aItemInfo) || !is_array($aItemInfo) || $aItemInfo[$CNF['FIELD_STATUS']] != BX_BASE_MOD_TEXT_STATUS_ACTIVE || empty($aItemInfo[$CNF['FIELD_QUANTITY']]))
  944. continue;
  945. $aResult[] = $this->serviceGetCartItem($aItem['id']);
  946. }
  947. return $aResult;
  948. }
  949. /**
  950. * @page service Service Calls
  951. * @section bx_ads Ads
  952. * @subsection bx_ads-payments Payments
  953. * @subsubsection bx_ads-authorize_cart_item authorize_cart_item
  954. *
  955. * @code bx_srv('bx_ads', 'authorize_cart_item', [...]); @endcode
  956. *
  957. * Authorize the order to process a single time payment inside the Ads module in future. Is called with payment processing module after the order was authorized there.
  958. *
  959. * @param $iClientId client ID.
  960. * @param $iSellerId seller ID
  961. * @param $iItemId item ID.
  962. * @param $iItemCount the number of purchased items.
  963. * @param $sOrder order number received from payment provider (PayPal, Stripe, etc)
  964. * @return an array with authorize prodict's description. Empty array is returned if something is wrong.
  965. *
  966. * @see BxAdsModule::serviceAuthorizeCartItem
  967. */
  968. /**
  969. * @ref bx_ads-authorize_cart_item "authorize_cart_item"
  970. */
  971. public function serviceAuthorizeCartItem($iClientId, $iSellerId, $iItemId, $iItemCount, $sOrder)
  972. {
  973. $CNF = &$this->_oConfig->CNF;
  974. $aItem = $this->serviceGetCartItem($iItemId);
  975. if(empty($aItem) || !is_array($aItem))
  976. return [];
  977. $aCommodity = $this->_oDb->getCommodity(['sample' => 'id_with_entry', 'id' => (int)$iItemId]);
  978. if(empty($aCommodity) || !is_array($aCommodity))
  979. return [];
  980. /**
  981. * @hooks
  982. * @hookdef hook-bx_ads-order_authorize 'bx_ads', 'order_authorize' - hook after the order was authorized with payment processing module
  983. * - $unit_name - equals `bx_ads`
  984. * - $action - equals `order_authorize`
  985. * - $object_id - not used
  986. * - $sender_id - not used
  987. * - $extra_params - array of additional params with the following array keys:
  988. * - `id` - [int] commodity id
  989. * - `type` - [string] commodity type, 'product' or 'promotion'
  990. * - `product_id` - [int] ad (entry) id the commodity is associated with
  991. * - `order` - [string] order number provided with payment processing module
  992. * - `count` - [int] number of items in order
  993. * @hook @ref hook-bx_ads-order_authorize
  994. */
  995. bx_alert($this->getName(), 'order_authorize', 0, false, [
  996. 'id' => $aCommodity['id'],
  997. 'type' => $aCommodity['type'],
  998. 'product_id' => $aCommodity['entry_id'],
  999. 'profile_id' => $iClientId,
  1000. 'order' => $sOrder,
  1001. 'count' => $iItemCount
  1002. ]);
  1003. return $aItem;
  1004. }
  1005. /**
  1006. * @page service Service Calls
  1007. * @section bx_ads Ads
  1008. * @subsection bx_ads-payments Payments
  1009. * @subsubsection bx_ads-register_cart_item register_cart_item
  1010. *
  1011. * @code bx_srv('bx_ads', 'register_cart_item', [...]); @endcode
  1012. *
  1013. * Register a processed single time payment inside the Ads module. Is called with payment processing module after the payment was registered there.
  1014. *
  1015. * @param $iClientId client ID.
  1016. * @param $iSellerId seller ID
  1017. * @param $iItemId item ID.
  1018. * @param $iItemCount the number of purchased items.
  1019. * @param $sOrder order number received from payment provider (PayPal, Stripe, etc)
  1020. * @param $sLicense license number genereted with payment processing module for internal usage
  1021. * @return an array with purchased prodict's description. Empty array is returned if something is wrong.
  1022. *
  1023. * @see BxAdsModule::serviceRegisterCartItem
  1024. */
  1025. /**
  1026. * @ref bx_ads-register_cart_item "register_cart_item"
  1027. */
  1028. public function serviceRegisterCartItem($iClientId, $iSellerId, $iItemId, $iItemCount, $sOrder, $sLicense)
  1029. {
  1030. $aCommodity = $this->_oDb->getCommodity(['sample' => 'id', 'id' => (int)$iItemId]);
  1031. if(empty($aCommodity) || !is_array($aCommodity))
  1032. return [];
  1033. $sMethod = '_registerCartItem' . bx_gen_method_name($aCommodity['type']);
  1034. if(!method_exists($this, $sMethod))
  1035. return [];
  1036. return $this->$sMethod($iClientId, $iSellerId, $aCommodity, $iItemCount, $sOrder, $sLicense);
  1037. }
  1038. protected function _registerCartItemProduct($iClientId, $iSellerId, $aCommodity, $iItemCount, $sOrder, $sLicense)
  1039. {
  1040. $CNF = &$this->_oConfig->CNF;
  1041. $sModule = $this->getName();
  1042. $aItem = $this->serviceGetCartItem($aCommodity['id']);
  1043. if(empty($aItem) || !is_array($aItem))
  1044. return [];
  1045. $aEntry = $this->_oDb->getContentInfoById($aCommodity['entry_id']);
  1046. if(empty($aEntry) || !is_array($aEntry))
  1047. return [];
  1048. $iEntryId = (int)$aCommodity['entry_id'];
  1049. $iEntryQnt = (int)$aEntry[$CNF['FIELD_QUANTITY']];
  1050. if(($iEntryQnt - $iItemCount) < 0 || !$this->_oDb->registerLicense($iClientId, $iEntryId, $iItemCount, $sOrder, $sLicense))
  1051. return [];
  1052. $aOffer = $this->_oDb->getOffersBy([
  1053. 'type' => 'content_and_author_ids',
  1054. 'content_id' => $iEntryId,
  1055. 'author_id' => $iClientId,
  1056. 'status' => BX_ADS_OFFER_STATUS_ACCEPTED
  1057. ]);
  1058. if(!empty($aOffer) && is_array($aOffer))
  1059. $this->_oDb->updateOffer([$CNF['FIELD_OFR_STATUS'] => BX_ADS_OFFER_STATUS_PAID], [$CNF['FIELD_OFR_ID'] => $aOffer[$CNF['FIELD_OFR_ID']]]);
  1060. $iEntryQnt -= $iItemCount;
  1061. $bEntrySold = $iEntryQnt == 0;
  1062. $aUpdate = [
  1063. $CNF['FIELD_QUANTITY'] => $iEntryQnt
  1064. ];
  1065. if($bEntrySold)
  1066. $aUpdate = array_merge($aUpdate, [
  1067. $CNF['FIELD_STATUS'] => BX_ADS_STATUS_SOLD,
  1068. $CNF['FIELD_SOLD'] => time()
  1069. ]);
  1070. $this->_oDb->updateEntriesBy($aUpdate, [$CNF['FIELD_ID'] => $iEntryId]);
  1071. /**
  1072. * @hooks
  1073. * @hookdef hook-bx_ads-license_register 'bx_ads', 'license_register' - hook after the payment for an ad was processed with payment processing module
  1074. * - $unit_name - equals `bx_ads`
  1075. * - $action - equals `license_register`
  1076. * - $object_id - not used
  1077. * - $sender_id - not used
  1078. * - $extra_params - array of additional params with the following array keys:
  1079. * - `id` - [int] commodity id
  1080. * - `type` - [string] commodity type, 'product' or 'promotion'
  1081. * - `product_id` - [int] ad (entry) id the commodity is associated with
  1082. * - `profile_id` - [int] client (buyer) profile id
  1083. * - `order` - [string] order number provided with payment processing module
  1084. * - `license` - [string] license number generated for the order
  1085. * - `count` - [int] number of items in order
  1086. * @hook @ref hook-bx_ads-license_register
  1087. */
  1088. bx_alert($sModule, 'license_register', 0, false, [
  1089. 'id' => $aCommodity['id'],
  1090. 'type' => $aCommodity['type'],
  1091. 'product_id' => $iEntryId,
  1092. 'profile_id' => $iClientId,
  1093. 'order' => $sOrder,
  1094. 'license' => $sLicense,
  1095. 'count' => $iItemCount
  1096. ]);
  1097. if($bEntrySold) {
  1098. $aParams = $this->_alertParams($aEntry);
  1099. /**
  1100. * @hooks
  1101. * @hookdef hook-bx_ads-sold 'bx_ads', 'sold' - hook after the payment was processed with payment processing module and there is no the ad (entry) for selling anymore
  1102. * - $unit_name - equals `bx_ads`
  1103. * - $action - equals `sold`
  1104. * - $object_id - ad (entry) id
  1105. * - $sender_id - not used
  1106. * - $extra_params - array of additional params with the following array keys:
  1107. * - `status` - [string] content status
  1108. * - `status_admin` - [string] content admin status
  1109. * - `privacy_view` - [int] or [string] privacy for view content action, @see BxDolPrivacy
  1110. * - `cf` - [int] content's audience filter value
  1111. * @hook @ref hook-bx_ads-sold
  1112. */
  1113. bx_alert($sModule, 'sold', $iEntryId, false, $aParams);
  1114. }
  1115. $oAuthor = BxDolProfile::getInstanceMagic($aEntry[$CNF['FIELD_AUTHOR']]);
  1116. $oClient = BxDolProfile::getInstanceMagic($iClientId);
  1117. $oSeller = BxDolProfile::getInstanceMagic($iSellerId);
  1118. $sSellerUrl = $oSeller->getUrl();
  1119. $sSellerName = $oSeller->getDisplayName();
  1120. $sNote = $aEntry[$CNF['FIELD_NOTES_PURCHASED']];
  1121. if(empty($sNote))
  1122. $sNote = _t('_bx_ads_txt_purchased_note', $sSellerUrl, $sSellerName);
  1123. $sEmailTemplate = $CNF['ETEMPLATE_PURCHASED'];
  1124. $aEmailParams = [
  1125. 'client_name' => $oClient->getDisplayName(),
  1126. 'entry_name' => $aEntry[$CNF['FIELD_TITLE']],
  1127. 'entry_url' => bx_absolute_url(BxDolPermalinks::getInstance()->permalink('page.php?i=' . $CNF['URI_VIEW_ENTRY'], ['id' => $iEntryId])),
  1128. 'author_url' => $oAuthor->getUrl(),
  1129. 'author_name' => $oAuthor->getDisplayName(),
  1130. 'vendor_url' => $sSellerUrl,
  1131. 'vendor_name' => $sSellerName,
  1132. 'count' => (int)$iItemCount,
  1133. 'license' => $sLicense,
  1134. 'notes' => $sNote,
  1135. ];
  1136. $bCancel = false;
  1137. /**
  1138. * @hooks
  1139. * @hookdef hook-bx_ads-license_register_notif 'bx_ads', 'license_register_notif' - hook before sending a notification about new license. Allows to override a notification message or cancel the notification
  1140. * - $unit_name - equals `bx_ads`
  1141. * - $action - equals `license_register_notif`
  1142. * - $object_id - not used
  1143. * - $sender_id - not used
  1144. * - $extra_params - array of additional params with the following array keys:
  1145. * - `entry_id` - [int] ad (entry) id
  1146. * - `order` - [string] order number
  1147. * - `recipient_id` - [int] by ref, client (buyer) profile id, can be overridden in hook processing
  1148. * - `email_template` - [string] by ref, email template name, can be overridden in hook processing
  1149. * - `email_params` - [array] by ref, email params array as key&value pairs, which will be parsed in email subject/body, can be overridden in hook processing
  1150. * - `cancel` - [boolean] by ref, if email sending should be canceled or not, can be overridden in hook processing
  1151. * @hook @ref hook-bx_ads-license_register_notif
  1152. */
  1153. bx_alert($sModule, 'license_register_notif', 0, false, [
  1154. 'entry_id' => $iEntryId,
  1155. 'order' => $sOrder,
  1156. 'recipient_id' => &$iClientId,
  1157. 'email_template' => &$sEmailTemplate,
  1158. 'email_params' => &$aEmailParams,
  1159. 'cancel' => &$bCancel,
  1160. 'recipient_id_ref' => &$iClientId,
  1161. 'email_template_ref' => &$sEmailTemplate,
  1162. 'email_params_ref' => &$aEmailParams,
  1163. 'cancel_ref' => &$bCancel
  1164. ]);
  1165. if(!$bCancel)
  1166. sendMailTemplate($sEmailTemplate, 0, $iClientId, $aEmailParams);
  1167. return $aItem;
  1168. }
  1169. protected function _registerCartItemPromotion($iClientId, $iSellerId, $aCommodity, $iItemCount, $sOrder, $sLicense)
  1170. {
  1171. $CNF = &$this->_oConfig->CNF;
  1172. $aItem = $this->serviceGetCartItem($aCommodity['id']);
  1173. if(empty($aItem) || !is_array($aItem))
  1174. return [];
  1175. $aEntry = $this->_oDb->getContentInfoById($aCommodity['entry_id']);
  1176. if(empty($aEntry) || !is_array($aEntry))
  1177. return [];
  1178. $iEntryId = (int)$aCommodity['entry_id'];
  1179. if(!$this->_oDb->registerPromotion($aEntry[$CNF['FIELD_AUTHOR']], $aCommodity['id'], $iEntryId, $aCommodity['amount'], $sOrder, $sLicense))
  1180. return [];
  1181. if($aEntry[$CNF['FIELD_STATUS_ADMIN']] == BX_ADS_STATUS_ADMIN_UNPAID) {
  1182. $aUpdate[$CNF['FIELD_STATUS_ADMIN']] = BX_BASE_MOD_GENERAL_STATUS_ACTIVE;
  1183. if(!$this->_isModerator() && !$this->_oConfig->isAutoApproveEnabled())
  1184. $aUpdate[$CNF['FIELD_STATUS_ADMIN']] = BX_BASE_MOD_GENERAL_STATUS_PENDING;
  1185. $this->_oDb->updateEntriesBy($aUpdate, [$CNF['FIELD_ID'] => $iEntryId]);
  1186. }
  1187. /**
  1188. * @hooks
  1189. * @hookdef hook-bx_ads-promotion_register 'bx_ads', 'promotion_register' - hook after the payment for promotion was processed with payment processing module
  1190. * - $unit_name - equals `bx_ads`
  1191. * - $action - equals `promotion_register`
  1192. * - $object_id - not used
  1193. * - $sender_id - not used
  1194. * - $extra_params - array of additional params with the following array keys:
  1195. * - `id` - [int] commodity id
  1196. * - `type` - [string] commodity type, 'product' or 'promotion'
  1197. * - `product_id` - [int] ad (entry) id the commodity is associated with
  1198. * - `profile_id` - [int] client (buyer) profile id
  1199. * - `amount` - [float] amount paid for the promotion
  1200. * - `order` - [string] order number provided with payment processing module
  1201. * - `license` - [string] license number generated for the order
  1202. * @hook @ref hook-bx_ads-promotion_register
  1203. */
  1204. bx_alert($this->getName(), 'promotion_register', 0, false, [
  1205. 'id' => $aCommodity['id'],
  1206. 'type' => $aCommodity['type'],
  1207. 'product_id' => $iEntryId,
  1208. 'profile_id' => $iClientId,
  1209. 'amount' => $aCommodity['amount'],
  1210. 'order' => $sOrder,
  1211. 'license' => $sLicense,
  1212. ]);
  1213. return $aItem;
  1214. }
  1215. /**
  1216. * @page service Service Calls
  1217. * @section bx_ads Ads
  1218. * @subsection bx_ads-payments Payments
  1219. * @subsubsection bx_ads-authorize_subscription_item authorize_subscription_item
  1220. *
  1221. * @code bx_srv('bx_ads', 'authorize_subscription_item', [...]); @endcode
  1222. *
  1223. * Authorize the order to process a subscription (recurring payment) inside the Ads module in future. Is called with payment processing module after the order for subscription was authorized there.
  1224. *
  1225. * @param $iClientId client ID.
  1226. * @param $iSellerId seller ID
  1227. * @param $iItemId item ID.
  1228. * @param $iItemCount the number of purchased items.
  1229. * @param $sOrder order number received from payment provider (PayPal, Stripe, etc)
  1230. * @return an array with authorize prodict's description. Empty array is returned if something is wrong.
  1231. *
  1232. * @see BxAdsModule::serviceAuthorizeSubscriptionItem
  1233. */
  1234. /**
  1235. * @ref bx_ads-authorize_subscription_item "authorize_subscription_item"
  1236. */
  1237. public function serviceAuthorizeSubscriptionItem($iClientId, $iSellerId, $iItemId, $iItemCount, $sOrder)
  1238. {
  1239. return [];
  1240. }
  1241. /**
  1242. * @page service Service Calls
  1243. * @section bx_ads Ads
  1244. * @subsection bx_ads-payments Payments
  1245. * @subsubsection bx_ads-register_subscription_item register_subscription_item
  1246. *
  1247. * @code bx_srv('bx_ads', 'register_subscription_item', [...]); @endcode
  1248. *
  1249. * Register a processed subscription (recurring payment) inside the Ads module. Is called with payment processing module after the subscription was registered there.
  1250. *
  1251. * @param $iClientId client ID.
  1252. * @param $iSellerId seller ID
  1253. * @param $iItemId item ID.
  1254. * @param $iItemCount the number of purchased items.
  1255. * @param $sOrder order number received from payment provider (PayPal, Stripe, etc)
  1256. * @param $sLicense license number genereted with payment processing module for internal usage
  1257. * @return an array with subscribed prodict's description. Empty array is returned if something is wrong.
  1258. *
  1259. * @see BxAdsModule::serviceRegisterSubscriptionItem
  1260. */
  1261. /**
  1262. * @ref bx_ads-register_subscription_item "register_subscription_item"
  1263. */
  1264. public function serviceRegisterSubscriptionItem($iClientId, $iSellerId, $iItemId, $iItemCount, $sOrder, $sLicense)
  1265. {
  1266. return [];
  1267. }
  1268. /**
  1269. * @page service Service Calls
  1270. * @section bx_ads Ads
  1271. * @subsection bx_ads-payments Payments
  1272. * @subsubsection bx_ads-reregister_cart_item reregister_cart_item
  1273. *
  1274. * @code bx_srv('bx_ads', 'reregister_cart_item', [...]); @endcode
  1275. *
  1276. * Reregister a single time payment inside the Ads module. Is called with payment processing module after the payment was reregistered there.
  1277. *
  1278. * @param $iClientId client ID.
  1279. * @param $iSellerId seller ID
  1280. * @param $iItemIdOld old item ID.
  1281. * @param $iItemIdNew new item ID.
  1282. * @param $sOrder order number received from payment provider (PayPal, Stripe, etc)
  1283. * @return an array with purchased prodict's description. Empty array is returned if something is wrong.
  1284. *
  1285. * @see BxAdsModule::serviceReregisterCartItem
  1286. */
  1287. /**
  1288. * @ref bx_ads-reregister_cart_item "reregister_cart_item"
  1289. */
  1290. public function serviceReregisterCartItem($iClientId, $iSellerId, $iItemIdOld, $iItemIdNew, $sOrder)
  1291. {
  1292. return [];
  1293. }
  1294. /**
  1295. * @page service Service Calls
  1296. * @section bx_ads Ads
  1297. * @subsection bx_ads-payments Payments
  1298. * @subsubsection bx_ads-reregister_subscription_item reregister_subscription_item
  1299. *
  1300. * @code bx_srv('bx_ads', 'reregister_subscription_item', [...]); @endcode
  1301. *
  1302. * Reregister a subscription (recurring payment) inside the Ads module. Is called with payment processing module after the subscription was reregistered there.
  1303. *
  1304. * @param $iClientId client ID.
  1305. * @param $iSellerId seller ID
  1306. * @param $iItemIdOld old item ID.
  1307. * @param $iItemIdNew new item ID.
  1308. * @param $sOrder order number received from payment provider (PayPal, Stripe, etc)
  1309. * @return an array with subscribed prodict's description. Empty array is returned if something is wrong.
  1310. *
  1311. * @see BxAdsModule::serviceReregisterSubscriptionItem
  1312. */
  1313. /**
  1314. * @ref bx_ads-reregister_subscription_item "reregister_subscription_item"
  1315. */
  1316. public function serviceReregisterSubscriptionItem($iClientId, $iSellerId, $iItemIdOld, $iItemIdNew, $sOrder)
  1317. {
  1318. return [];
  1319. }
  1320. /**
  1321. * @page service Service Calls
  1322. * @section bx_ads Ads
  1323. * @subsection bx_ads-payments Payments
  1324. * @subsubsection bx_ads-unregister_cart_item unregister_cart_item
  1325. *
  1326. * @code bx_srv('bx_ads', 'unregister_cart_item', [...]); @endcode
  1327. *
  1328. * Unregister an earlier processed single time payment inside the Ads module. Is called with payment processing module after the payment was unregistered there.
  1329. *
  1330. * @param $iClientId client ID.
  1331. * @param $iSellerId seller ID
  1332. * @param $iItemId item ID.
  1333. * @param $iItemCount the number of purchased items.
  1334. * @param $sOrder order number received from payment provider (PayPal, Stripe, etc)
  1335. * @param $sLicense license number genereted with payment processing module for internal usage
  1336. * @return boolean value determining where the payment was unregistered or not.
  1337. *
  1338. * @see BxAdsModule::serviceUnregisterCartItem
  1339. */
  1340. /**
  1341. * @ref bx_ads-unregister_cart_item "unregister_cart_item"
  1342. */
  1343. public function serviceUnregisterCartItem($iClientId, $iSellerId, $iItemId, $iItemCount, $sOrder, $sLicense)
  1344. {
  1345. $aCommodity = $this->_oDb->getCommodity(['sample' => 'id', 'id' => (int)$iItemId]);
  1346. if(empty($aCommodity) || !is_array($aCommodity))
  1347. return [];
  1348. $sMethod = '_unregisterCartItem' . bx_gen_method_name($aCommodity['type']);
  1349. if(!method_exists($this, $sMethod))
  1350. return [];
  1351. return $this->$sMethod($iClientId, $iSellerId, $aCommodity, $iItemCount, $sOrder, $sLicense);
  1352. }
  1353. protected function _unregisterCartItemProduct($iClientId, $iSellerId, $aCommodity, $iItemCount, $sOrder, $sLicense)
  1354. {
  1355. $iEntryId = (int)$aCommodity['entry_id'];
  1356. if(!$this->_oDb->unregisterLicense($iClientId, $iEntryId, $sOrder, $sLicense))
  1357. return false;
  1358. /**
  1359. * @hooks
  1360. * @hookdef hook-bx_ads-license_unregister 'bx_ads', 'license_unregister' - hook after the payment for ad was refunded with payment processing module
  1361. * It's equivalent to @ref hook-bx_ads-license_register
  1362. * @hook @ref hook-bx_ads-license_unregister
  1363. */
  1364. bx_alert($this->getName(), 'license_unregister', 0, false, [
  1365. 'id' => $aCommodity['id'],
  1366. 'type' => $aCommodity['type'],
  1367. 'product_id' => $iEntryId,
  1368. 'profile_id' => $iClientId,
  1369. 'order' => $sOrder,
  1370. 'license' => $sLicense,
  1371. 'count' => $iItemCount
  1372. ]);
  1373. return true;
  1374. }
  1375. protected function _unregisterCartItemPromotion($iClientId, $iSellerId, $aCommodity, $iItemCount, $sOrder, $sLicense)
  1376. {
  1377. $CNF = &$this->_oConfig->CNF;
  1378. $aEntry = $this->_oDb->getContentInfoById($aCommodity['entry_id']);
  1379. if(empty($aEntry) || !is_array($aEntry))
  1380. return false;
  1381. $iEntryId = (int)$aCommodity['entry_id'];
  1382. if(!$this->_oDb->unregisterPromotion($aEntry[$CNF['FIELD_AUTHOR']], $aCommodity['id'], $iEntryId, $sOrder, $sLicense))
  1383. return false;
  1384. /**
  1385. * @hooks
  1386. * @hookdef hook-bx_ads-promotion_unregister 'bx_ads', 'promotion_unregister' - hook after the payment for promotion was refunded with payment processing module
  1387. * It's equivalent to @ref hook-bx_ads-promotion_register
  1388. * @hook @ref hook-bx_ads-promotion_unregister
  1389. */
  1390. bx_alert($this->getName(), 'promotion_unregister', 0, false, [
  1391. 'id' => $aCommodity['id'],
  1392. 'type' => $aCommodity['type'],
  1393. 'product_id' => $iEntryId,
  1394. 'profile_id' => $iClientId,
  1395. 'amount' => $aCommodity['amount'],
  1396. 'order' => $sOrder,
  1397. 'license' => $sLicense
  1398. ]);
  1399. return true;
  1400. }
  1401. /**
  1402. * @page service Service Calls
  1403. * @section bx_ads Ads
  1404. * @subsection bx_ads-payments Payments
  1405. * @subsubsection bx_ads-unregister_subscription_item unregister_subscription_item
  1406. *
  1407. * @code bx_srv('bx_ads', 'unregister_subscription_item', [...]); @endcode
  1408. *
  1409. * Unregister an earlier processed subscription (recurring payment) inside the Ads module. Is called with payment processing module after the subscription was unregistered there.
  1410. *
  1411. * @param $iClientId client ID.
  1412. * @param $iSellerId seller ID
  1413. * @param $iItemId item ID.
  1414. * @param $iItemCount the number of purchased items.
  1415. * @param $sOrder order number received from payment provider (PayPal, Stripe, etc)
  1416. * @param $sLicense license number genereted with payment processing module for internal usage
  1417. * @return boolean value determining where the subscription was unregistered or not.
  1418. *
  1419. * @see BxAdsModule::serviceUnregisterSubscriptionItem
  1420. */
  1421. /**
  1422. * @ref bx_ads-unregister_subscription_item "unregister_subscription_item"
  1423. */
  1424. public function serviceUnregisterSubscriptionItem($iClientId, $iSellerId, $iItemId, $iItemCount, $sOrder, $sLicense)
  1425. {
  1426. return true;
  1427. }
  1428. /**
  1429. * @page service Service Calls
  1430. * @section bx_ads Ads
  1431. * @subsection bx_ads-payments Payments
  1432. * @subsubsection bx_ads-cancel_subscription_item cancel_subscription_item
  1433. *
  1434. * @code bx_srv('bx_ads', 'cancel_subscription_item', [...]); @endcode
  1435. *
  1436. * Cancel an earlier processed subscription (recurring payment) inside the Ads module. Is called with payment processing module after the subscription was canceled there.
  1437. *
  1438. * @param $iClientId client ID.
  1439. * @param $iSellerId seller ID
  1440. * @param $iItemId item ID.
  1441. * @param $iItemCount the number of purchased items.
  1442. * @param $sOrder order number received from payment provider (PayPal, Stripe, etc)
  1443. * @return boolean value determining where the subscription was canceled or not.
  1444. *
  1445. * @see BxAdsModule::serviceCancelSubscriptionItem
  1446. */
  1447. /**
  1448. * @ref bx_ads-cancel_subscription_item "cancel_subscription_item"
  1449. */
  1450. public function serviceCancelSubscriptionItem($iClientId, $iSellerId, $iItemId, $iItemCount, $sOrder)
  1451. {
  1452. return true;
  1453. }
  1454. public function serviceGetOffersCount($sStatus = '')
  1455. {
  1456. if(!$this->_oConfig->isAuction())
  1457. return 0;
  1458. if(empty($sStatus) || !in_array($sStatus, $this->_aOfferStatuses))
  1459. $sStatus = BX_ADS_OFFER_STATUS_AWAITING;
  1460. $iUserId = bx_get_logged_profile_id();
  1461. return $this->_oDb->getOffersBy(array('type' => 'content_author_id', 'author_id' => $iUserId, 'status' => $sStatus, 'count' => true));
  1462. }
  1463. public function serviceGetLiveUpdates($sStatus, $aMenuItemParent, $aMenuItemChild, $iCount = 0)
  1464. {
  1465. if(!in_array($sStatus, $this->_aOfferStatuses))
  1466. return false;
  1467. $iUserId = bx_get_logged_profile_id();
  1468. $iCountNew = $this->_oDb->getOffersBy(array('type' => 'content_author_id', 'author_id' => $iUserId, 'status' => $sStatus, 'count' => true));
  1469. if($iCountNew == $iCount)
  1470. return false;
  1471. return array(
  1472. 'count' => $iCountNew, // required
  1473. 'method' => 'bx_menu_show_live_update(oData)', // required
  1474. 'data' => array(
  1475. 'code' => BxDolTemplate::getInstance()->parseHtmlByTemplateName('menu_item_addon', array(
  1476. 'content' => '{count}'
  1477. )),
  1478. 'mi_parent' => $aMenuItemParent,
  1479. 'mi_child' => $aMenuItemChild
  1480. ), // optional, may have some additional data to be passed in JS method provided using 'method' param above.
  1481. );
  1482. }
  1483. public function serviceOffers()
  1484. {
  1485. $CNF = &$this->_oConfig->CNF;
  1486. if(!$this->_oConfig->isAuction())
  1487. return '';
  1488. $oGrid = BxDolGrid::getObjectInstance($CNF['OBJECT_GRID_OFFERS_ALL']);
  1489. if(!$oGrid)
  1490. return '';
  1491. return $oGrid->getCode();
  1492. }
  1493. public function serviceEntityOffers($iContentId = 0)
  1494. {
  1495. $CNF = &$this->_oConfig->CNF;
  1496. if(!$this->_oConfig->isAuction())
  1497. return '';
  1498. $oGrid = BxDolGrid::getObjectInstance($CNF['OBJECT_GRID_OFFERS']);
  1499. if(!$oGrid)
  1500. return '';
  1501. if(empty($iContentId) && ($_iContentId = bx_get('id')) !== false)
  1502. $iContentId = (int)$_iContentId;
  1503. $oGrid->setContentId($iContentId);
  1504. return $oGrid->getCode();
  1505. }
  1506. public function serviceEntityOfferAccepted($iContentId = 0)
  1507. {
  1508. $CNF = &$this->_oConfig->CNF;
  1509. if(!$this->_oConfig->isAuction())
  1510. return '';
  1511. $iUserId = bx_get_logged_profile_id();
  1512. if(empty($iContentId) && ($_iContentId = bx_get('id')) !== false)
  1513. $iContentId = (int)$_iContentId;
  1514. $aContent = $this->_oDb->getContentInfoById($iContentId);
  1515. if(empty($aContent) || !is_array($aContent) || $aContent[$CNF['FIELD_QUANTITY']] <= 0)
  1516. return '';
  1517. $aOffer = $this->_oDb->getOffersBy(array(
  1518. 'type' => 'content_and_author_ids',
  1519. 'content_id' => $iContentId,
  1520. 'author_id' => $iUserId,
  1521. 'status' => BX_ADS_OFFER_STATUS_ACCEPTED
  1522. ));
  1523. if(empty($aOffer) || !is_array($aOffer))
  1524. return '';
  1525. return $this->_oTemplate->entryOfferAccepted($iUserId, $aContent, $aOffer);
  1526. }
  1527. public function serviceIsSourcesAvaliable()
  1528. {
  1529. return $this->_oConfig->isSources();
  1530. }
  1531. public function serviceGetSources($iAuthorId)
  1532. {
  1533. $aSources = $this->_oDb->getSources(['sample' => 'all']);
  1534. $aOptions = $this->_oDb->getSourcesOptions($iAuthorId);
  1535. $aResult = [];
  1536. foreach($aSources as $sSource => $aSource) {
  1537. if(!isset($aOptions[$aSource['option_prefix'] . 'active']) || (int)$aOptions[$aSource['option_prefix'] . 'active']['value'] != 1)
  1538. continue;
  1539. foreach($aOptions as $sName => $aOption)
  1540. if(strpos($sName, $aSource['option_prefix']) !== false)
  1541. $aSource['options'][$sName] = $aOption;
  1542. $aResult[$sSource] = $aSource;
  1543. }
  1544. return $aResult;
  1545. }
  1546. public function serviceGetSource($iAuthorId, $sAuthorSource = '')
  1547. {
  1548. $aSourcesOptions = $this->serviceGetSources($iAuthorId);
  1549. if(empty($aSourcesOptions) || !is_array($aSourcesOptions))
  1550. return false;
  1551. $mixedResult = false;
  1552. if(!empty($sAuthorSource)) {
  1553. if(!empty($aSourcesOptions[$sAuthorSource]) && is_array($aSourcesOptions[$sAuthorSource]))
  1554. $mixedResult = $aSourcesOptions[$sAuthorSource];
  1555. }
  1556. else
  1557. $mixedResult = array_shift($aSourcesOptions);
  1558. return $mixedResult;
  1559. }
  1560. public function serviceLoadEntriesFromSourceByTerm($sSourceType, $sTerm)
  1561. {
  1562. $CNF = &$this->_oConfig->CNF;
  1563. $oSource = $this->getObjectSource($sSourceType, $this->_iProfileId);
  1564. if(!$oSource)
  1565. return [];
  1566. $aEntries = $oSource->getEntries(['sample' => 'all_id_title_pairs']);
  1567. if(empty($aEntries) || !is_array($aEntries))
  1568. return [];
  1569. $aResults = [];
  1570. foreach($aEntries as $aEntry) {
  1571. if(stripos($aEntry[$CNF['FIELD_TITLE']], $sTerm) === false)
  1572. continue;
  1573. $aResults[] = [
  1574. 'label' => $aEntry[$CNF['FIELD_TITLE']],
  1575. 'value' => $aEntry[$CNF['FIELD_SOURCE']],
  1576. ];
  1577. }
  1578. return $aResults;
  1579. }
  1580. public function serviceLoadEntryFromSource($sSourceType, $sSource)
  1581. {
  1582. $CNF = &$this->_oConfig->CNF;
  1583. $aResult = [];
  1584. $oSource = $this->getObjectSource($sSourceType, $this->_iProfileId);
  1585. if(!$oSource)
  1586. return $aResult;
  1587. $aEntry = $oSource->getEntry($sSource);
  1588. if(empty($aEntry) || !is_array($aEntry))
  1589. return $aResult;
  1590. $aName = $this->serviceCheckName($aEntry[$CNF['FIELD_TITLE']]);
  1591. if(!empty($aName) && is_array($aName))
  1592. $aResult[$CNF['FIELD_NAME']] = ['type' => 'text', 'value' => $aName['name']];
  1593. $aKey2Type = [
  1594. $CNF['FIELD_TITLE'] => 'text',
  1595. $CNF['FIELD_URL'] => 'hidden',
  1596. $CNF['FIELD_TEXT'] => 'text_html',
  1597. $CNF['FIELD_TAGS'] => 'text',
  1598. $CNF['FIELD_PRICE'] => 'text',
  1599. $CNF['FIELD_QUANTITY'] => 'text'
  1600. ];
  1601. foreach($aEntry as $sKey => $sValue)
  1602. if(isset($aKey2Type[$sKey]))
  1603. $aResult[$sKey] = ['type' => $aKey2Type[$sKey], 'value' => $sValue];
  1604. return $aResult;
  1605. }
  1606. public function serviceBlockSourcesDetails($iProfileId = 0)
  1607. {
  1608. $CNF = &$this->_oConfig->CNF;
  1609. if(!isLogged())
  1610. return bx_is_api() ? [bx_api_get_msg(_t('_Access denied'))] : ['content' => MsgBox(_t('_Access denied'))];
  1611. $iProfileId = !empty($iProfileId) ? $iProfileId : bx_get_logged_profile_id();
  1612. $oForm = BxTemplFormView::getObjectInstance($CNF['OBJECT_FORM_SOURCES_DETAILS'], $CNF['OBJECT_FORM_SOURCES_DETAILS_DISPLAY_EDIT']);
  1613. $oForm->setProfileId($iProfileId);
  1614. $oForm->initChecker();
  1615. if($oForm->isSubmitted()) {
  1616. if($oForm->isValid()) {
  1617. $aOptions = $this->_oDb->getSourcesOptions();
  1618. foreach($aOptions as $aOption) {
  1619. $sValue = bx_get($aOption['name']) !== false ? bx_get($aOption['name']) : '';
  1620. $this->_oDb->updateSourceOption($iProfileId, $aOption['id'], bx_process_input($sValue));
  1621. }
  1622. if (bx_is_api()){
  1623. return [
  1624. bx_api_get_block('form', $oForm->getCodeAPI(), ['ext' => ['name' => $this->getName(), 'request' => ['url' => '/api.php?r=' . $this->getName() . '/block_sources_details', 'immutable' => true]]]),
  1625. bx_api_get_block('redirect', ['uri' => '/' . BxDolPermalinks::getInstance()->permalink($CNF['URL_SOURCES']), 'timeout' => 100])
  1626. ];
  1627. }
  1628. else{
  1629. header('Location: ' . bx_absolute_url(BxDolPermalinks::getInstance()->permalink($CNF['URL_SOURCES'])));
  1630. return;
  1631. }
  1632. }
  1633. else
  1634. foreach($oForm->aInputs as $aInput)
  1635. if(!empty($aInput['error']) && !empty($aInput['attrs']['bx-data-source'])) {
  1636. $sSourceBlock = 'source_' . (int)$aInput['attrs']['bx-data-source'] . '_begin';
  1637. if(!empty($oForm->aInputs[$sSourceBlock]))
  1638. $oForm->aInputs[$sSourceBlock]['collapsed'] = false;
  1639. }
  1640. }
  1641. return bx_is_api() ? [bx_api_get_block('form', $oForm->getCodeAPI(), ['ext' => ['name' => $this->getName(), 'request' => ['url' => '/api.php?r=' . $this->getName() . '/block_sources_details', 'immutable' => true]]])] : ['content' => $oForm->getCode()];
  1642. }
  1643. public function isEntryActive($aContentInfo)
  1644. {
  1645. $CNF = &$this->_oConfig->CNF;
  1646. $iViewer = bx_get_logged_profile_id();
  1647. $bModerator = $this->_isModerator();
  1648. $mixedResult = null;
  1649. /**
  1650. * @hooks
  1651. * @hookdef hook-bx_ads-is_entry_active 'bx_ads', 'is_entry_active' - hook to override whether an ad (entry) active or not
  1652. * It's equivalent to @ref hook-bx_base_general-is_entry_active
  1653. * @hook @ref hook-bx_ads-is_entry_active
  1654. */
  1655. bx_alert($this->getName(), 'is_entry_active', 0, 0, [
  1656. 'viewer_id' => $iViewer,
  1657. 'is_moderator' => $bModerator,
  1658. 'content_info' => $aContentInfo,
  1659. 'override_result' => &$mixedResult
  1660. ]);
  1661. if($mixedResult !== null)
  1662. return $mixedResult;
  1663. if($aContentInfo[$CNF['FIELD_AUTHOR']] == $iViewer || $bModerator)
  1664. return true;
  1665. if(isset($CNF['FIELD_STATUS']) && !in_array($aContentInfo[$CNF['FIELD_STATUS']], array(BX_BASE_MOD_TEXT_STATUS_ACTIVE, BX_ADS_STATUS_OFFER, BX_ADS_STATUS_SOLD)))
  1666. return false;
  1667. if(isset($CNF['FIELD_STATUS_ADMIN']) && $aContentInfo[$CNF['FIELD_STATUS_ADMIN']] != 'active')
  1668. return false;
  1669. return true;
  1670. }
  1671. public function isAuction($aContentInfo)
  1672. {
  1673. $CNF = &$this->_oConfig->CNF;
  1674. return $this->_oConfig->isAuction() && (int)$aContentInfo[$CNF['FIELD_AUCTION']] != 0;
  1675. }
  1676. public function isAllowedMakeOffer($mixedContent, $isPerformAction = false)
  1677. {
  1678. return $this->checkAllowedMakeOffer($mixedContent, $isPerformAction) === CHECK_ACTION_RESULT_ALLOWED;
  1679. }
  1680. public function checkAllowedMakeOffer($mixedContent, $isPerformAction = false)
  1681. {
  1682. $CNF = &$this->_oConfig->CNF;
  1683. $sTxtError = '_sys_txt_access_denied';
  1684. $iProfileId = bx_get_logged_profile_id();
  1685. if(!is_array($mixedContent))
  1686. $mixedContent = $this->_oDb->getContentInfoById((int)$mixedContent);
  1687. if(empty($mixedContent) || !is_array($mixedContent))
  1688. return _t($sTxtError);
  1689. if(!$this->isAuction($mixedContent) || (int)$mixedContent[$CNF['FIELD_QUANTITY']] <= 0)
  1690. return _t($sTxtError);
  1691. if($mixedContent[$CNF['FIELD_AUTHOR']] == $iProfileId)
  1692. return _t($sTxtError);
  1693. $aCheck = checkActionModule($iProfileId, 'make offer', $this->getName(), $isPerformAction);
  1694. if($aCheck[CHECK_ACTION_RESULT] !== CHECK_ACTION_RESULT_ALLOWED)
  1695. return $aCheck[CHECK_ACTION_MESSAGE];
  1696. return CHECK_ACTION_RESULT_ALLOWED;
  1697. }
  1698. public function isAllowedViewOffers($mixedContent, $isPerformAction = false)
  1699. {
  1700. return $this->checkAllowedViewOffers($mixedContent, $isPerformAction) === CHECK_ACTION_RESULT_ALLOWED;
  1701. }
  1702. public function checkAllowedViewOffers($mixedContent, $isPerformAction = false)
  1703. {
  1704. $CNF = &$this->_oConfig->CNF;
  1705. $sTxtError = '_sys_txt_access_denied';
  1706. if(!is_array($mixedContent))
  1707. $mixedContent = $this->_oDb->getContentInfoById((int)$mixedContent);
  1708. if(empty($mixedContent) || !is_array($mixedContent))
  1709. return _t($sTxtError);
  1710. if(!$this->isAuction($mixedContent))
  1711. return _t($sTxtError);
  1712. if($this->_isModerator())
  1713. return CHECK_ACTION_RESULT_ALLOWED;
  1714. if($mixedContent[$CNF['FIELD_AUTHOR']] == bx_get_logged_profile_id())
  1715. return CHECK_ACTION_RESULT_ALLOWED;
  1716. return _t($sTxtError);
  1717. }
  1718. public function isAllowedMarkShipped($mixedContent, $isPerformAction = false)
  1719. {
  1720. return $this->checkAllowedMarkShipped($mixedContent, $isPerformAction) === CHECK_ACTION_RESULT_ALLOWED;
  1721. }
  1722. public function checkAllowedMarkShipped($mixedContent, $isPerformAction = false)
  1723. {
  1724. return $this->checkAllowedMarkShippedForProfile($mixedContent, $isPerformAction);
  1725. }
  1726. public function checkAllowedMarkShippedForProfile($mixedContent, $isPerformAction = false, $iProfileId = false)
  1727. {
  1728. $CNF = &$this->_oConfig->CNF;
  1729. $sTxtError = '_sys_txt_access_denied';
  1730. if(!$iProfileId)
  1731. $iProfileId = bx_get_logged_profile_id();
  1732. if(!is_array($mixedContent))
  1733. $mixedContent = $this->_oDb->getContentInfoById((int)$mixedContent);
  1734. if(empty($mixedContent) || !is_array($mixedContent) || !$this->isSingle($mixedContent))
  1735. return _t($sTxtError);
  1736. if((int)$mixedContent[$CNF['FIELD_SHIPPED']] != 0 || $mixedContent[$CNF['FIELD_STATUS']] != BX_ADS_STATUS_SOLD || (!$this->isEntryAuthor($mixedContent, $iProfileId) && !$this->_isModerator() && !$this->_isAdministrator()))
  1737. return _t($sTxtError);
  1738. return CHECK_ACTION_RESULT_ALLOWED;
  1739. }
  1740. public function isAllowedMarkReceived($mixedContent, $isPerformAction = false)
  1741. {
  1742. return $this->checkAllowedMarkReceived($mixedContent, $isPerformAction) === CHECK_ACTION_RESULT_ALLOWED;
  1743. }
  1744. public function checkAllowedMarkReceived($mixedContent, $isPerformAction = false)
  1745. {
  1746. return $this->checkAllowedMarkReceivedForProfile($mixedContent, $isPerformAction);
  1747. }
  1748. public function checkAllowedMarkReceivedForProfile($mixedContent, $isPerformAction = false, $iProfileId = false)
  1749. {
  1750. $CNF = &$this->_oConfig->CNF;
  1751. $sTxtError = '_sys_txt_access_denied';
  1752. if(!$iProfileId)
  1753. $iProfileId = bx_get_logged_profile_id();
  1754. if(!is_array($mixedContent))
  1755. $mixedContent = $this->_oDb->getContentInfoById((int)$mixedContent);
  1756. if(empty($mixedContent) || !is_array($mixedContent) || !$this->isSingle($mixedContent))
  1757. return _t($sTxtError);
  1758. if((int)$mixedContent[$CNF['FIELD_RECEIVED']] != 0 || !$this->_oDb->hasLicense($iProfileId, $mixedContent[$CNF['FIELD_ID']]))
  1759. return _t($sTxtError);
  1760. return CHECK_ACTION_RESULT_ALLOWED;
  1761. }
  1762. public function onPublished($iContentId)
  1763. {
  1764. $this->serviceUpdateCategoriesStats($iContentId);
  1765. parent::onPublished($iContentId);
  1766. }
  1767. public function onOfferAdded($iOfferId, &$aResult)
  1768. {
  1769. $CNF = &$this->_oConfig->CNF;
  1770. $aOfferInfo = $this->_oDb->getOffersBy(array('type' => 'id', 'id' => $iOfferId));
  1771. if(empty($aOfferInfo) || !is_array($aOfferInfo))
  1772. return;
  1773. $iContentId = (int)$aOfferInfo[$CNF['FIELD_OFR_CONTENT']];
  1774. $aContentInfo = $this->_oDb->getContentInfoById($iContentId);
  1775. if(empty($aContentInfo) || !is_array($aContentInfo))
  1776. return;
  1777. $iViewer = bx_get_logged_profile_id();
  1778. $oViewer = BxDolProfile::getInstanceMagic($iViewer);
  1779. if(getParam($CNF['PARAM_USE_IIN']) == 'on')
  1780. sendMailTemplate($CNF['ETEMPLATE_OFFER_ADDED'], 0, $aContentInfo[$CNF['FIELD_AUTHOR']], array(
  1781. 'viewer_name' => $oViewer->getDisplayName(),
  1782. 'viewer_url' => $oViewer->getUrl(),
  1783. 'entry_name' => $aContentInfo[$CNF['FIELD_TITLE']],
  1784. 'entry_url' => bx_absolute_url(BxDolPermalinks::getInstance()->permalink('page.php', array(
  1785. 'i' => $CNF['URI_VIEW_ENTRY'],
  1786. $CNF['FIELD_ID'] => $iContentId
  1787. )))
  1788. ));
  1789. $aParams = $this->_alertParamsOffer($aContentInfo, $aOfferInfo);
  1790. $aParams['override_result'] = &$aResult;
  1791. /**
  1792. * @hooks
  1793. * @hookdef hook-bx_ads-offer_added 'bx_ads', 'offer_added' - hook after an offer was added. Allows to override action results.
  1794. * - $unit_name - equals `bx_ads`
  1795. * - $action - equals `offer_added`
  1796. * - $object_id - offer id
  1797. * - $sender_id - offer author profile id
  1798. * - $extra_params - array of additional params with the following array keys:
  1799. * - `object_id` - [int] content id
  1800. * - `object_author_id` - [int] content author profile id
  1801. * - `offer_id` - [int] offer id
  1802. * - `offer_author_id` - [int] offer author profile id
  1803. * - `privacy_view` - [int] privacy for view action, equals to BX_DOL_PG_ALL, @see BxDolPrivacy
  1804. * - `override_result` - [array] by ref, results array as key&value pairs, can be overridden in hook processing
  1805. * @hook @ref hook-bx_ads-offer_added
  1806. */
  1807. bx_alert($this->getName(), 'offer_added', $iOfferId, $aOfferInfo[$CNF['FIELD_OFR_AUTHOR']], $aParams);
  1808. }
  1809. public function onOfferAccepted($iOfferId)
  1810. {
  1811. $CNF = &$this->_oConfig->CNF;
  1812. $aOfferInfo = $this->_oDb->getOffersBy(array('type' => 'id', 'id' => $iOfferId));
  1813. if(empty($aOfferInfo) || !is_array($aOfferInfo))
  1814. return;
  1815. $iContentId = (int)$aOfferInfo[$CNF['FIELD_OFR_CONTENT']];
  1816. $aContentInfo = $this->_oDb->getContentInfoById($iContentId);
  1817. if(empty($aContentInfo) || !is_array($aContentInfo))
  1818. return;
  1819. if($aContentInfo[$CNF['FIELD_STATUS']] != BX_ADS_STATUS_OFFER && ($this->isSingle($aContentInfo) || $this->getAvailableQuantity($aContentInfo) <= 0))
  1820. if(!$this->_oDb->updateEntriesBy([$CNF['FIELD_STATUS'] => BX_ADS_STATUS_OFFER], [$CNF['FIELD_ID'] => $iContentId]))
  1821. return;
  1822. $this->serviceUpdateCategoriesStats($iContentId);
  1823. $iOfferer = (int)$aOfferInfo[$CNF['FIELD_OFR_AUTHOR']];
  1824. $oOfferer = BxDolProfile::getInstanceMagic($iOfferer);
  1825. if(getParam($CNF['PARAM_USE_IIN']) == 'on')
  1826. sendMailTemplate($CNF['ETEMPLATE_OFFER_ACCEPTED'], 0, $iOfferer, array(
  1827. 'offerer_name' => $oOfferer->getDisplayName(),
  1828. 'offerer_url' => $oOfferer->getUrl(),
  1829. 'entry_name' => $aContentInfo[$CNF['FIELD_TITLE']],
  1830. 'entry_url' => bx_absolute_url(BxDolPermalinks::getInstance()->permalink('page.php', array(
  1831. 'i' => $CNF['URI_VIEW_ENTRY'],
  1832. $CNF['FIELD_ID'] => $iContentId
  1833. )))
  1834. ));
  1835. $aParams = $this->_alertParamsOffer($aContentInfo, $aOfferInfo);
  1836. /**
  1837. * @hooks
  1838. * @hookdef hook-bx_ads-offer_accepted 'bx_ads', 'offer_accepted' - hook after an offer was accepted.
  1839. * It's equivalent to @ref hook-bx_ads-offer_added
  1840. * except content author profile id is passed to $sender_id and
  1841. * `override_result` parameter in $extra_params is missing
  1842. * @hook @ref hook-bx_ads-offer_accepted
  1843. */
  1844. bx_alert($this->getName(), 'offer_accepted', $iOfferId, $aContentInfo[$CNF['FIELD_AUTHOR']], $aParams);
  1845. }
  1846. public function onOfferDeclined($iOfferId)
  1847. {
  1848. $CNF = &$this->_oConfig->CNF;
  1849. $aOfferInfo = $this->_oDb->getOffersBy(array('type' => 'id', 'id' => $iOfferId));
  1850. if(empty($aOfferInfo) || !is_array($aOfferInfo))
  1851. return;
  1852. $iContentId = (int)$aOfferInfo[$CNF['FIELD_OFR_CONTENT']];
  1853. $aContentInfo = $this->_oDb->getContentInfoById($iContentId);
  1854. if(empty($aContentInfo) || !is_array($aContentInfo))
  1855. return;
  1856. $iOfferer = (int)$aOfferInfo[$CNF['FIELD_OFR_AUTHOR']];
  1857. $oOfferer = BxDolProfile::getInstanceMagic($iOfferer);
  1858. if(getParam($CNF['PARAM_USE_IIN']) == 'on')
  1859. sendMailTemplate($CNF['ETEMPLATE_OFFER_DECLINED'], 0, $iOfferer, array(
  1860. 'offerer_name' => $oOfferer->getDisplayName(),
  1861. 'offerer_url' => $oOfferer->getUrl(),
  1862. 'entry_name' => $aContentInfo[$CNF['FIELD_TITLE']],
  1863. 'entry_url' => bx_absolute_url(BxDolPermalinks::getInstance()->permalink('page.php', array(
  1864. 'i' => $CNF['URI_VIEW_ENTRY'],
  1865. $CNF['FIELD_ID'] => $iContentId
  1866. )))
  1867. ));
  1868. $aParams = $this->_alertParamsOffer($aContentInfo, $aOfferInfo);
  1869. /**
  1870. * @hooks
  1871. * @hookdef hook-bx_ads-offer_declined 'bx_ads', 'offer_declined' - hook after an offer was declined.
  1872. * It's equivalent to @ref hook-bx_ads-offer_accepted
  1873. * @hook @ref hook-bx_ads-offer_declined
  1874. */
  1875. bx_alert($this->getName(), 'offer_declined', $iOfferId, $aContentInfo[$CNF['FIELD_AUTHOR']], $aParams);
  1876. }
  1877. public function onOfferCanceled($iOfferId)
  1878. {
  1879. $CNF = &$this->_oConfig->CNF;
  1880. $aOfferInfo = $this->_oDb->getOffersBy(['type' => 'id', 'id' => $iOfferId]);
  1881. if(empty($aOfferInfo) || !is_array($aOfferInfo))
  1882. return;
  1883. $iContentId = (int)$aOfferInfo[$CNF['FIELD_OFR_CONTENT']];
  1884. $aContentInfo = $this->_oDb->getContentInfoById($iContentId);
  1885. if(empty($aContentInfo) || !is_array($aContentInfo))
  1886. return;
  1887. if(!$this->_oDb->updateEntriesBy([$CNF['FIELD_STATUS'] => BX_BASE_MOD_TEXT_STATUS_ACTIVE], [$CNF['FIELD_ID'] => $iContentId]))
  1888. return;
  1889. $this->serviceUpdateCategoriesStats($iContentId);
  1890. $iOfferer = (int)$aOfferInfo[$CNF['FIELD_OFR_AUTHOR']];
  1891. $oOfferer = BxDolProfile::getInstanceMagic($iOfferer);
  1892. if(getParam($CNF['PARAM_USE_IIN']) == 'on')
  1893. sendMailTemplate($CNF['ETEMPLATE_OFFER_CANCELED'], 0, (int)$aContentInfo[$CNF['FIELD_AUTHOR']], [
  1894. 'offerer_name' => $oOfferer->getDisplayName(),
  1895. 'offerer_url' => $oOfferer->getUrl(),
  1896. 'entry_name' => $aContentInfo[$CNF['FIELD_TITLE']],
  1897. 'entry_url' => bx_absolute_url(BxDolPermalinks::getInstance()->permalink('page.php', [
  1898. 'i' => $CNF['URI_VIEW_ENTRY'],
  1899. $CNF['FIELD_ID'] => $iContentId
  1900. ]))
  1901. ]);
  1902. $aParams = $this->_alertParamsOffer($aContentInfo, $aOfferInfo);
  1903. /**
  1904. * @hooks
  1905. * @hookdef hook-bx_ads-offer_canceled 'bx_ads', 'offer_canceled' - hook after an offer was declined.
  1906. * It's equivalent to @ref hook-bx_ads-offer_added
  1907. * except `override_result` parameter in $extra_params is missing
  1908. * @hook @ref hook-bx_ads-offer_canceled
  1909. */
  1910. bx_alert($this->getName(), 'offer_canceled', $iOfferId, $aOfferInfo[$CNF['FIELD_OFR_AUTHOR']], $aParams);
  1911. }
  1912. /**
  1913. * Common methods.
  1914. */
  1915. public function onShipped($mixedContent, $iProfileSrc = 0, $iProfileDst = 0)
  1916. {
  1917. $CNF = &$this->_oConfig->CNF;
  1918. if(!is_array($mixedContent))
  1919. $mixedContent = $this->_oDb->getContentInfoById((int)$mixedContent);
  1920. $iContentId = (int)$mixedContent[$CNF['FIELD_ID']];
  1921. if(empty($iProfileSrc))
  1922. $iProfileSrc = (int)$mixedContent[$CNF['FIELD_AUTHOR']];
  1923. $oProfileSrc = BxDolProfile::getInstanceMagic($iProfileSrc);
  1924. $aOffer = $this->_oDb->getOffersBy(array('type' => 'accepted', 'content_id' => $iContentId));
  1925. $bOffer = !empty($aOffer) && is_array($aOffer);
  1926. if(empty($iProfileDst) && $bOffer)
  1927. $iProfileDst = (int)$aOffer[$CNF['FIELD_OFR_AUTHOR']];
  1928. if(!empty($oProfileSrc) && !empty($iProfileDst) && getParam($CNF['PARAM_USE_IIN']) == 'on')
  1929. sendMailTemplate($CNF['ETEMPLATE_SHIPPED'], 0, $iProfileDst, array(
  1930. 'vendor_name' => $oProfileSrc->getDisplayName(),
  1931. 'vendor_url' => $oProfileSrc->getUrl(),
  1932. 'entry_name' => $mixedContent[$CNF['FIELD_TITLE']],
  1933. 'entry_url' => bx_absolute_url(BxDolPermalinks::getInstance()->permalink('page.php', array(
  1934. 'i' => $CNF['URI_VIEW_ENTRY'],
  1935. $CNF['FIELD_ID'] => $iContentId
  1936. )))
  1937. ));
  1938. $aParams = $this->_alertParams($mixedContent);
  1939. $aParams = array_merge($aParams, [
  1940. 'profile_src' => $iProfileSrc,
  1941. 'profile_dst' => $iProfileDst,
  1942. 'offer_id' => $bOffer ? (int)$aOffer[$CNF['FIELD_OFR_ID']] : 0,
  1943. ]);
  1944. /**
  1945. * @hooks
  1946. * @hookdef hook-bx_ads-shipped 'bx_ads', 'shipped' - hook after the ad (entry) was marked as shipped
  1947. * - $unit_name - equals `bx_ads`
  1948. * - $action - equals `shipped`
  1949. * - $object_id - ad (entry) id
  1950. * - $sender_id - not used
  1951. * - $extra_params - array of additional params with the following array keys:
  1952. * - `status` - [string] content status
  1953. * - `status_admin` - [string] content admin status
  1954. * - `privacy_view` - [int] or [string] privacy for view content action, @see BxDolPrivacy
  1955. * - `cf` - [int] content's audience filter value
  1956. * - `profile_src` - [int] sender profile id
  1957. * - `profile_dst` - [int] recipient profile id
  1958. * - `offer_id` - [int] offer id if the ad was sold by offer
  1959. * @hook @ref hook-bx_ads-shipped
  1960. */
  1961. bx_alert($this->getName(), 'shipped', $iContentId, false, $aParams);
  1962. }
  1963. public function onReceived($mixedContent, $iProfileSrc = 0, $iProfileDst = 0)
  1964. {
  1965. $CNF = &$this->_oConfig->CNF;
  1966. if(!is_array($mixedContent))
  1967. $mixedContent = $this->_oDb->getContentInfoById((int)$mixedContent);
  1968. $iContentId = (int)$mixedContent[$CNF['FIELD_ID']];
  1969. if(empty($iProfileDst))
  1970. $iProfileDst = (int)$mixedContent[$CNF['FIELD_AUTHOR']];
  1971. $aOffer = $this->_oDb->getOffersBy(array('type' => 'accepted', 'content_id' => $iContentId));
  1972. $bOffer = !empty($aOffer) && is_array($aOffer);
  1973. if(empty($iProfileSrc) && $bOffer)
  1974. $iProfileSrc = (int)$aOffer[$CNF['FIELD_OFR_AUTHOR']];
  1975. $oProfileSrc = BxDolProfile::getInstanceMagic($iProfileSrc);
  1976. if(!empty($iProfileSrc) && !empty($iProfileDst) && getParam($CNF['PARAM_USE_IIN']) == 'on')
  1977. sendMailTemplate($CNF['ETEMPLATE_RECEIVED'], 0, $iProfileDst, array(
  1978. 'client_name' => $oProfileSrc->getDisplayName(),
  1979. 'client_url' => $oProfileSrc->getUrl(),
  1980. 'entry_name' => $mixedContent[$CNF['FIELD_TITLE']],
  1981. 'entry_url' => bx_absolute_url(BxDolPermalinks::getInstance()->permalink('page.php', array(
  1982. 'i' => $CNF['URI_VIEW_ENTRY'],
  1983. $CNF['FIELD_ID'] => $iContentId
  1984. )))
  1985. ));
  1986. $aParams = $this->_alertParams($mixedContent);
  1987. $aParams = array_merge($aParams, [
  1988. 'profile_src' => $iProfileSrc,
  1989. 'profile_dst' => $iProfileDst,
  1990. 'offer_id' => $bOffer ? (int)$aOffer[$CNF['FIELD_OFR_ID']] : 0,
  1991. ]);
  1992. /**
  1993. * @hooks
  1994. * @hookdef hook-bx_ads-received 'bx_ads', 'received' - hook after the ad (entry) was marked as received
  1995. * It's equivalent to @ref hook-bx_ads-shipped
  1996. * @hook @ref hook-bx_ads-received
  1997. */
  1998. bx_alert($this->getName(), 'received', $iContentId, false, $aParams);
  1999. }
  2000. public function getObjectSource($sSource, $iProfileId = 0)
  2001. {
  2002. $aSource = $this->_oDb->getSources(array('sample' => 'by_name', 'name' => $sSource));
  2003. if(empty($aSource) || !is_array($aSource) || empty($aSource['class_name']))
  2004. return false;
  2005. if(!empty($iProfileId)) {
  2006. $aSource['author'] = (int)$iProfileId;
  2007. $aSource['options'] = $this->_oDb->getSourcesOptions((int)$iProfileId, $aSource['id']);
  2008. }
  2009. $sClassPath = !empty($aSource['class_file']) ? BX_DIRECTORY_PATH_ROOT . $aSource['class_file'] : $this->_oConfig->getClassPath() . $aSource['class_name'] . '.php';
  2010. if(!file_exists($sClassPath))
  2011. return false;
  2012. require_once($sClassPath);
  2013. return new $aSource['class_name']($this->_iProfileId, $aSource, $this);
  2014. }
  2015. public function offerAccept($iId)
  2016. {
  2017. $CNF = &$this->_oConfig->CNF;
  2018. $aOfferInfo = $this->_oDb->getOffersBy(['type' => 'id', 'id' => $iId]);
  2019. if(empty($aOfferInfo) || !is_array($aOfferInfo))
  2020. return false;
  2021. $iContentId = (int)$aOfferInfo[$CNF['FIELD_OFR_CONTENT']];
  2022. $aContentInfo = $this->_oDb->getContentInfoById($iContentId);
  2023. if(empty($aContentInfo) || !is_array($aContentInfo))
  2024. return false;
  2025. $iQuantity = (int)$aOfferInfo[$CNF['FIELD_OFR_QUANTITY']];
  2026. $iQuantityAvailable = $this->getAvailableQuantity($aContentInfo);
  2027. if($iQuantity > $iQuantityAvailable)
  2028. return _t('_bx_ads_txt_err_offer_wrong_quantity', $iQuantityAvailable);
  2029. if(!$this->_oDb->updateOffer([$CNF['FIELD_OFR_STATUS'] => BX_ADS_OFFER_STATUS_ACCEPTED], [$CNF['FIELD_OFR_ID'] => $iId]))
  2030. return false;
  2031. $this->onOfferAccepted($iId);
  2032. return true;
  2033. }
  2034. public function offerDecline($iId)
  2035. {
  2036. $CNF = &$this->_oConfig->CNF;
  2037. if(!$this->_oDb->updateOffer([$CNF['FIELD_OFR_STATUS'] => BX_ADS_OFFER_STATUS_DECLINED], [$CNF['FIELD_OFR_ID'] => $iId]))
  2038. return false;
  2039. $this->onOfferDeclined($iId);
  2040. return true;
  2041. }
  2042. public function offerCancel($iId)
  2043. {
  2044. $CNF = &$this->_oConfig->CNF;
  2045. if(!$this->_oDb->updateOffer([$CNF['FIELD_OFR_STATUS'] => BX_ADS_OFFER_STATUS_CANCELED], [$CNF['FIELD_OFR_ID'] => $iId]))
  2046. return false;
  2047. $this->onOfferCanceled($iId);
  2048. return true;
  2049. }
  2050. public function offerPay($iId)
  2051. {
  2052. $CNF = &$this->_oConfig->CNF;
  2053. $aOffer = $this->_oDb->getOffersBy(array('type' => 'id', 'id' => $iId));
  2054. if(empty($aOffer) || !is_array($aOffer))
  2055. return false;
  2056. $iContent = (int)$aOffer[$CNF['FIELD_OFR_CONTENT']];
  2057. $aContent = $this->_oDb->getContentInfoById($iContent);
  2058. $iContentAuthor = (int)$aContent[$CNF['FIELD_AUTHOR']];
  2059. $aReturn = array(
  2060. 'redirect' => bx_absolute_url(BxDolPermalinks::getInstance()->permalink('page.php', array(
  2061. 'i' => $CNF['URI_VIEW_ENTRY'],
  2062. $CNF['FIELD_ID'] => $aOffer[$CNF['FIELD_OFR_CONTENT']]
  2063. )))
  2064. );
  2065. $oPayments = BxDolPayments::getInstance();
  2066. $aResult = $oPayments->addToCart($iContentAuthor, $this->getName(), $iContent, $aOffer[$CNF['FIELD_OFR_QUANTITY']]);
  2067. if(!empty($aResult) && is_array($aResult)) {
  2068. if(!empty($aResult['message']))
  2069. $aReturn['msg'] = $aResult['message'];
  2070. if(isset($aResult['code']) && (int)$aResult['code'] == 0)
  2071. $aReturn['redirect'] = $oPayments->getCartUrl($iContentAuthor);
  2072. }
  2073. return $aReturn;
  2074. }
  2075. public function processMetasAdd($iContentId)
  2076. {
  2077. if(!parent::processMetasAdd($iContentId))
  2078. return false;
  2079. $CNF = &$this->_oConfig->CNF;
  2080. $oMetatags = BxDolMetatags::getObjectInstance($CNF['OBJECT_METATAGS']);
  2081. $aContentInfo = $this->_oDb->getContentInfoById($iContentId);
  2082. $aCategoryTypes = $this->_oDb->getCategoryTypes(array('type' => 'all'));
  2083. foreach($aCategoryTypes as $aCategoryType)
  2084. $oMetatags->metaAddAuto($iContentId, $aContentInfo, $CNF, $aCategoryType['display_add']);
  2085. return true;
  2086. }
  2087. public function processMetasEdit($iContentId, $oForm)
  2088. {
  2089. if(!parent::processMetasEdit($iContentId, $oForm))
  2090. return false;
  2091. $CNF = &$this->_oConfig->CNF;
  2092. $oMetatags = BxDolMetatags::getObjectInstance($CNF['OBJECT_METATAGS']);
  2093. $aContentInfo = $this->_oDb->getContentInfoById($iContentId);
  2094. $aCategoryTypes = $this->_oDb->getCategoryTypes(array('type' => 'all'));
  2095. foreach($aCategoryTypes as $aCategoryType)
  2096. $oMetatags->metaAddAuto($iContentId, $aContentInfo, $CNF, $aCategoryType['display_edit']);
  2097. return true;
  2098. }
  2099. public function getCategoryDisplay($sDisplayType, $iCategory = 0)
  2100. {
  2101. if(empty($iCategory) && bx_get('category') !== false)
  2102. $iCategory = (int)bx_get('category');
  2103. if(empty($iCategory))
  2104. return false;
  2105. $aCategory = $this->_oDb->getCategories(array('type' => 'id_full', 'id' => $iCategory));
  2106. $sKey = 'type_display_' . $sDisplayType;
  2107. if(empty($aCategory[$sKey]))
  2108. return false;
  2109. return $aCategory[$sKey];
  2110. }
  2111. public function isSingle($mixedContent)
  2112. {
  2113. $CNF = &$this->_oConfig->CNF;
  2114. if(!is_array($mixedContent))
  2115. $mixedContent = $this->_oDb->getContentInfoById((int)$mixedContent);
  2116. return (int)$mixedContent[$CNF['FIELD_SINGLE']] == 1;
  2117. }
  2118. public function getAvailableQuantity($mixedContent)
  2119. {
  2120. $CNF = &$this->_oConfig->CNF;
  2121. if(!is_array($mixedContent))
  2122. $mixedContent = $this->_oDb->getContentInfoById((int)$mixedContent);
  2123. if(!$this->_oConfig->isAuction() || (int)$mixedContent[$CNF['FIELD_AUCTION']] == 0)
  2124. return (int)$mixedContent[$CNF['FIELD_QUANTITY']];
  2125. $iQuantity = (int)$this->_oDb->getOffersBy([
  2126. 'type' => 'quantity_reserved',
  2127. 'content_id' => $mixedContent[$CNF['FIELD_ID']],
  2128. 'status' => BX_ADS_OFFER_STATUS_ACCEPTED
  2129. ]);
  2130. return (int)$mixedContent[$CNF['FIELD_QUANTITY']] - $iQuantity;
  2131. }
  2132. /**
  2133. * Internal methods.
  2134. */
  2135. protected function _actionMarkAs($sAction)
  2136. {
  2137. $iContentId = bx_process_input(bx_get('id'), BX_DATA_INT);
  2138. if(($mixedResult = $this->serviceMarkAs($sAction, $iContentId)) !== true)
  2139. return array('msg' => $mixedResult);
  2140. return array(
  2141. 'reload' => 1
  2142. );
  2143. }
  2144. protected function _actionChangeStatus($sStatus)
  2145. {
  2146. $CNF = &$this->_oConfig->CNF;
  2147. $iContentId = bx_process_input(bx_get('id'), BX_DATA_INT);
  2148. $aContentInfo = $this->_oDb->getContentInfoById($iContentId);
  2149. if(($mixedResult = $this->checkAllowedEdit($aContentInfo)) !== CHECK_ACTION_RESULT_ALLOWED)
  2150. return array('msg' => $mixedResult);
  2151. if(!$this->_oDb->updateEntriesBy(array($CNF['FIELD_STATUS'] => $sStatus), array($CNF['FIELD_ID'] => $iContentId)))
  2152. return array('msg' => _t('_bx_ads_txt_err_cannot_perform_action'));
  2153. $this->serviceUpdateCategoriesStats($aContentInfo);
  2154. return array(
  2155. 'reload' => 1
  2156. );
  2157. }
  2158. protected function _serviceEntityForm ($sFormMethod, $iContentId = 0, $sDisplay = false, $sCheckFunction = false, $bErrorMsg = true)
  2159. {
  2160. $CNF = &$this->_oConfig->CNF;
  2161. $mixedContent = $this->_getContent($iContentId, true);
  2162. if($mixedContent === false)
  2163. return false;
  2164. list($iContentId, $aContentInfo) = $mixedContent;
  2165. $sDisplayType = false;
  2166. switch($sFormMethod) {
  2167. case 'editDataForm':
  2168. if($sDisplay === false)
  2169. $sDisplayType = 'edit';
  2170. break;
  2171. case 'viewDataForm':
  2172. case 'viewDataEntry':
  2173. $sDisplayType = 'view';
  2174. break;
  2175. }
  2176. if($sDisplayType !== false && ($sDisplayNew = $this->getCategoryDisplay($sDisplayType, $aContentInfo[$CNF['FIELD_CATEGORY']])) !== false)
  2177. $sDisplay = $sDisplayNew;
  2178. return parent::_serviceEntityForm ($sFormMethod, $iContentId, $sDisplay, $sCheckFunction, $bErrorMsg);
  2179. }
  2180. protected function _getCategoryOptions($iParentId, &$aValues)
  2181. {
  2182. $aCategories = $this->_oDb->getCategories(array('type' => 'parent_id', 'parent_id' => $iParentId, 'active' => true));
  2183. foreach($aCategories as $aCategory) {
  2184. $aValues[] = array('key' => $aCategory['id'], 'value' => str_repeat('--', (int)$aCategory['level']) . ' ' . _t($aCategory['title']));
  2185. $this->_getCategoryOptions($aCategory['id'], $aValues);
  2186. }
  2187. }
  2188. protected function _getSearchableFields($mixedDisplayType = '')
  2189. {
  2190. $CNF = &$this->_oConfig->CNF;
  2191. if(empty($mixedDisplayType))
  2192. $mixedDisplayType = array('add', 'edit');
  2193. $aResult = array();
  2194. $aDisplays = $this->_oDb->getDisplays($this->_oConfig->getName() . '_entry', $mixedDisplayType);
  2195. foreach($aDisplays as $aDisplay) {
  2196. if($aDisplay['display_name'] == $CNF['OBJECT_FORM_ENTRY_DISPLAY_ADD'])
  2197. continue;
  2198. $oForm = BxDolForm::getObjectInstance($CNF['OBJECT_FORM_ENTRY'], $aDisplay['display_name'], $this->_oTemplate);
  2199. if(!$oForm)
  2200. continue;
  2201. $aResult = array_merge($aResult, $oForm->aInputs);
  2202. }
  2203. return $aResult;
  2204. }
  2205. protected function _getContentForTimelinePost($aEvent, $aContentInfo, $aBrowseParams = array())
  2206. {
  2207. $CNF = &$this->_oConfig->CNF;
  2208. $bDynamic = isset($aBrowseParams['dynamic_mode']) && (bool)$aBrowseParams['dynamic_mode'] === true;
  2209. $sCategory = '';
  2210. if(!empty($CNF['FIELD_CATEGORY']) && !empty($aContentInfo[$CNF['FIELD_CATEGORY']])) {
  2211. $iCategory = (int)$aContentInfo[$CNF['FIELD_CATEGORY']];
  2212. $aCategory = $this->_oDb->getCategories(array('type' => 'id', 'id' => $iCategory));
  2213. $sCategory = _t($aCategory['title']);
  2214. $sCategoryLink = bx_absolute_url(BxDolPermalinks::getInstance()->permalink($CNF['URL_CATEGORIES'], array($CNF['GET_PARAM_CATEGORY'] => $iCategory)));
  2215. }
  2216. $sPrice = _t('_bx_ads_txt_free');
  2217. if(!empty($CNF['FIELD_PRICE']) && !empty($aContentInfo[$CNF['FIELD_PRICE']]))
  2218. $sPrice = _t_format_currency_ext((float)$aContentInfo[$CNF['FIELD_PRICE']], [
  2219. 'sign' => BxDolPayments::getInstance()->getCurrencySign((int)$aContentInfo[$CNF['FIELD_AUTHOR']])
  2220. ]);
  2221. $aResult = parent::_getContentForTimelinePost($aEvent, $aContentInfo, $aBrowseParams);
  2222. if(!$this->_bIsApi) {
  2223. if(empty($aResult['raw']))
  2224. $aResult['raw'] = '';
  2225. $aResult['text'] = $this->_oTemplate->parseHtmlByName('timeline_post_text.html', [
  2226. 'category_link' => $sCategoryLink,
  2227. 'category_title' => $sCategory,
  2228. 'category_title_attr' => bx_html_attribute($sCategory),
  2229. 'price' => $sPrice,
  2230. 'text' => $aResult['text']
  2231. ]);
  2232. }
  2233. else
  2234. $aResult = array_merge($aResult, [
  2235. 'price' => $sPrice,
  2236. 'category_title' => $sCategory,
  2237. 'register_click' => $this->_oConfig->isPromotion() ? 'bx_ads/register_click&params[]=' . $aContentInfo[$CNF['FIELD_ID']] : false,
  2238. 'register_impression' => $this->_oConfig->isPromotion() ? 'bx_ads/register_impression&params[]=' . $aContentInfo[$CNF['FIELD_ID']] : false,
  2239. ]);
  2240. if($this->_oConfig->isSources() && !empty($aContentInfo[$CNF['FIELD_URL']]))
  2241. $aResult['url'] = $aContentInfo[$CNF['FIELD_URL']];
  2242. if($this->_bIsApi)
  2243. return $aResult;
  2244. if($this->_oConfig->isPromotion()) {
  2245. $sJsObject = $this->_oConfig->getJsObject('main');
  2246. $sHtmlId = $this->_oConfig->getHtmlIds('unit') . $aContentInfo[$CNF['FIELD_ID']] . '-' . time() . '-' . mt_rand(0, 100);
  2247. $aResult['onclick'] = 'return ' . $sJsObject . '.registerClick(this, ' . $aContentInfo[$CNF['FIELD_ID']] . ')';
  2248. $aResult['raw'] .= $this->_oTemplate->parseHtmlByName('timeline_post_promotion.html', [
  2249. 'html_id' => $sHtmlId,
  2250. 'js_code' => $this->_oTemplate->_wrapInTagJsCode($sJsObject . '.registerTrakerForTimeline(' . $aContentInfo[$CNF['FIELD_ID']] . ', \'' . $sHtmlId . '\');')
  2251. ]);
  2252. }
  2253. $sInclude = $this->_oTemplate->addCss(['timeline.css'], $bDynamic);
  2254. if($bDynamic)
  2255. $aResult['raw'] .= $sInclude;
  2256. return $aResult;
  2257. }
  2258. protected function _getBlockLicenses($sType = '')
  2259. {
  2260. $CNF = &$this->_oConfig->CNF;
  2261. $sGrid = $CNF['OBJECT_GRID_LICENSES' . (!empty($sType) ? '_' . strtoupper($sType) : '')];
  2262. $oGrid = BxDolGrid::getObjectInstance($sGrid);
  2263. if(!$oGrid)
  2264. return '';
  2265. $this->_oDb->updateLicense(array('new' => 0), array('profile_id' => bx_get_logged_profile_id(), 'new' => 1));
  2266. $this->_oTemplate->addJs(array('licenses.js'));
  2267. return array(
  2268. 'content' => $this->_oTemplate->getJsCode('licenses', array('sObjNameGrid' => $sGrid)) . $oGrid->getCode(),
  2269. 'menu' => $CNF['OBJECT_MENU_LICENSES']
  2270. );
  2271. }
  2272. protected function _alertParamsOffer($aContentInfo, $aOfferInfo)
  2273. {
  2274. $CNF = &$this->_oConfig->CNF;
  2275. $aParams = array(
  2276. 'object_id' => (int)$aContentInfo[$CNF['FIELD_ID']],
  2277. 'object_author_id' => (int)$aContentInfo[$CNF['FIELD_AUTHOR']],
  2278. 'offer_id' => (int)$aOfferInfo[$CNF['FIELD_OFR_ID']],
  2279. 'offer_author_id' => (int)$aOfferInfo[$CNF['FIELD_OFR_AUTHOR']],
  2280. );
  2281. if(isset($aContentInfo[$CNF['FIELD_ALLOW_VIEW_TO']]))
  2282. $aParams['privacy_view'] = $aContentInfo[$CNF['FIELD_ALLOW_VIEW_TO']];
  2283. return $aParams;
  2284. }
  2285. }
  2286. /** @} */