siteBuilder.php 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137
  1. <?php
  2. /**
  3. * WHMCS siteBuilder Provisioning Module
  4. *
  5. * Provisioning User Accounts & manage Websites on the siteBuilder Server
  6. *
  7. * @see https://centos-webpanel.com/
  8. * @copyright Copyright (c) Thurdata GmbH 2022
  9. * @license GPL
  10. */
  11. use WHMCS\Database\Capsule;
  12. require_once 'Net/DNS2.php';
  13. require_once(__DIR__ . '/api/sitebuilder.php');
  14. require_once(__DIR__ . '/api/SiteProApiClient.php');
  15. if (!defined('WHMCS')) {
  16. die('This file cannot be accessed directly');
  17. }
  18. /**
  19. * Define siteBuilder product metadata parameters.
  20. *
  21. * @see https://developers.whmcs.com/provisioning-modules/meta-data-params/
  22. *
  23. * @return array
  24. */
  25. function siteBuilder_MetaData() {
  26. return array(
  27. 'DisplayName' => 'ThurData SiteBuilder Provisioning',
  28. 'APIVersion' => '1.2',
  29. 'DefaultNonSSLPort' => '80',
  30. 'DefaultSSLPort' => '443',
  31. 'RequiresServer' => true,
  32. 'ServiceSingleSignOnLabel' => 'Login to siteBuilder',
  33. 'AdminSingleSignOnLabel' => 'Login to siteBuilder Admin'
  34. );
  35. }
  36. function siteBuilder_ConfigOptions() {
  37. siteBuilderCreateTables();
  38. return ["BuilderURL" => [
  39. "FriendlyName" => "Builder URL", # Full Builder URL (prefix//hostname:port/)
  40. "Type" => "text", # Text Box
  41. "Size" => "25", # Defines the Field Width
  42. "Description" => "Full Builder URL (prefix//hostname:port/)",
  43. "Default" => "https://builder.thurdata.ch/",
  44. ], [
  45. "FriendlyName" => "Hosting Plan ID",
  46. "Type" => "text", # Text Box
  47. "Size" => "25", # Defines the Field Width
  48. "Description" => "Set the hostingPlan ID for this Product",
  49. "Default" => "Free",
  50. ], [
  51. "FriendlyName" => "Quota in MB",
  52. "Type" => "text", # Text Box
  53. "Size" => "25", # Defines the Field Width
  54. "Description" => "Set the Quoat matching Your HostingPlan (MB)",
  55. "Default" => "512",
  56. ]
  57. ];
  58. }
  59. /**
  60. * Test connection to a siteBuilder server with the given server parameters.
  61. *
  62. * Allows an admin user to verify that an API connection can be
  63. * successfully made with the given configuration parameters for a
  64. * server.
  65. *
  66. * When defined in a module, a test connection button will appear
  67. * alongside the server type dropdown when adding or editing an
  68. * existing server.
  69. *
  70. * @param array $params common module parameters
  71. *
  72. * @see https://developers.whmcs.com/provisioning-modules/module-parameters/
  73. *
  74. * @return array
  75. */
  76. function siteBuilder_Testconnection($params) {
  77. $siteBuilder = new ApiClient(getSiteBuilderApiURL($params), $params['serveraccesshash']);
  78. $response = $siteBuilder->ping($params['serverusername'], $params['serverpassword']);
  79. if($response['response']['answer'] == 'pong') {
  80. return array(
  81. 'success' => true,
  82. 'error' => '',
  83. );
  84. }
  85. return array(
  86. 'success' => false,
  87. 'error' => $response,
  88. );
  89. }
  90. /**
  91. * Provision a new account of a siteBuilder server.
  92. *
  93. * Attempt to provision a new siteBuilder account. This is
  94. * called any time provisioning is requested inside of WHMCS. Depending upon the
  95. * configuration, this can be any of:
  96. * * When a new order is placed
  97. * * When an invoice for a new order is paid
  98. * * Upon manual request by an admin user
  99. *
  100. * @param array $params common module parameters
  101. *
  102. * @see https://developers.whmcs.com/provisioning-modules/supported-functions/
  103. *
  104. * @return string 'success' or an error message
  105. */
  106. function siteBuilder_CreateAccount($params) {
  107. $username = strtolower(substr($params['clientsdetails']['firstname'],0,2) . substr($params['clientsdetails']['lastname'],0,3)) . $params['serviceid'];
  108. $userdomain = $params['domain'];
  109. // set DNS
  110. $response = siteBuildersetDNS($params, $userdomain);
  111. if($response != 'success') {
  112. return $response;
  113. }
  114. try {
  115. Capsule::table('tblhosting')
  116. ->where('id', '=', $params['serviceid'])
  117. ->update(
  118. array(
  119. 'username' => $username,
  120. 'domain' => $userdomain,
  121. )
  122. );
  123. } catch (\Exception $e) {
  124. logModuleCall(
  125. 'siteBuilder',
  126. __FUNCTION__,
  127. $params,
  128. 'Error: could save username & domain in database',
  129. $e->getMessage()
  130. );
  131. return 'Error: could save username & password in database';
  132. }
  133. try {
  134. Capsule::table('sitePro_acc')
  135. ->insert(
  136. array(
  137. 'account' => $username,
  138. 'pid' => $params['serviceid'],
  139. 'enabled' => true,
  140. )
  141. );
  142. } catch (\Exception $e) {
  143. logModuleCall(
  144. 'siteBuilder',
  145. __FUNCTION__,
  146. $params,
  147. 'Error: could save username & serviceid in database',
  148. $e->getMessage()
  149. );
  150. return 'Error: could save username & serviceid in database';
  151. }
  152. $siteBuilder = new ApiClient(getSiteBuilderApiURL($params), $params['serveraccesshash']);
  153. $response = $siteBuilder->create($params['username'], $params['domain'], $params['serverusername'], $params['serverpassword']);
  154. if($response['status'] != '200') {
  155. return 'Error: ' . $response['response']['error'];
  156. }
  157. $response = $siteBuilder->init($params['username'], $params['domain'], $params['serverusername'], $params['serverpassword']);
  158. if($response['status'] != '200') {
  159. return 'Error: ' . $response['response']['error'];
  160. }
  161. $response = $siteBuilder->setQuota($params['username'], $params['configoption3'], $params['serverusername'], $params['serverpassword']);
  162. if($response['status'] != '200') {
  163. return 'Error: ' . $response['response']['error'];
  164. }
  165. return 'success';
  166. }
  167. /**
  168. * Removes a siteBuilder account.
  169. *
  170. * Called when a termination is requested. This can be invoked automatically for
  171. * overdue products if enabled, or requested manually by an admin user.
  172. *
  173. * @param array $params common module parameters
  174. *
  175. * @see https://developers.whmcs.com/provisioning-modules/supported-functions/
  176. *
  177. * @return string 'success' or an error message
  178. */
  179. function siteBuilder_TerminateAccount($params) {
  180. try {
  181. $active = Capsule::table('sitePro_acc')
  182. ->where('account',$params['username'])
  183. ->value('enabled');
  184. } catch (\Exception $e) {
  185. logModuleCall(
  186. 'siteBuilder',
  187. __FUNCTION__,
  188. $params,
  189. 'Error: could fetch account from database',
  190. $e->getMessage()
  191. );
  192. return 'Error: could fetch account from database';
  193. }
  194. if($active == true) {
  195. return 'Error: Account is active, please suspend account first';
  196. }
  197. // undeploy all related sites
  198. $sites = getSites($params['serviceid']);
  199. $siteBuilder = new ApiClient(getSiteBuilderApiURL($params), $params['serveraccesshash']);
  200. if(!empty($sites)) {
  201. foreach($sites as $site) {
  202. /* $response = $siteBuilder->undeploy($params['username'], $site, $params['serverusername'], $params['serverpassword']);
  203. if($response['status'] != '200') {
  204. return 'Error: ' . $response['response'];
  205. } */
  206. logModuleCall(
  207. 'siteBuilder',
  208. __FUNCTION__,
  209. $params,
  210. 'debug',
  211. $site
  212. );
  213. }
  214. try {
  215. Capsule::table('sitePro_site')
  216. ->where('relid',$params['serviceid'])
  217. ->delete();
  218. } catch (\Exception $e) {
  219. logModuleCall(
  220. 'siteBuilder',
  221. __FUNCTION__,
  222. $params,
  223. 'Error: could remove domains from database',
  224. $e->getMessage()
  225. );
  226. return 'Error: could remove domains from database';
  227. }
  228. }
  229. // terminate account
  230. $response = $siteBuilder->terminate($params['username'], $params['domain']);
  231. if($response['status'] != '200') {
  232. return 'Error: ' . $response['response']['error'];
  233. }
  234. try {
  235. Capsule::table('sitePro_acc')
  236. ->where('account',$params['username'])
  237. ->delete();
  238. } catch (\Exception $e) {
  239. logModuleCall(
  240. 'siteBuilder',
  241. __FUNCTION__,
  242. $params,
  243. 'Error: could remove account from database',
  244. $e->getMessage()
  245. );
  246. return 'Error: could remove account from database';
  247. }
  248. return 'success';
  249. }
  250. /**
  251. * Set a siteBuilder account to status inactive.
  252. *
  253. * Called when a suspension is requested. This is invoked automatically by WHMCS
  254. * when a product becomes overdue on payment or can be called manually by admin
  255. * user.
  256. *
  257. * @param array $params common module parameters
  258. *
  259. * @see https://developers.whmcs.com/provisioning-modules/supported-functions/
  260. *
  261. * @return string 'success' or an error message
  262. */
  263. function siteBuilder_SuspendAccount($params) {
  264. $siteBuilder = new ApiClient(getSiteBuilderApiURL($params), $params['serveraccesshash']);
  265. $status = $siteBuilder->isenabled($params['username'],$params['domain']);
  266. if($status['status'] != '200') {
  267. return 'Error: ' . $status['response']['error'];
  268. }
  269. if($response['response']['isenabled'] == 'YES'){
  270. $response = $siteBuilder->disable($params['username'],$params['domain']);
  271. if($response['status'] != '200') {
  272. return 'Error: ' . $response['response']['error'];
  273. }
  274. }
  275. try {
  276. Capsule::table('sitePro_acc')
  277. ->where('account',$params['username'])
  278. ->update(array(
  279. 'enabled' => false,
  280. ));
  281. } catch (\Exception $e) {
  282. logModuleCall(
  283. 'siteBuilder',
  284. __FUNCTION__,
  285. $params,
  286. 'Error: could not disable account in database',
  287. $e->getMessage()
  288. );
  289. return 'Error: could not disable account in database';
  290. }
  291. // disable all sites but not change status in DB for unsuspend restoring
  292. $sites = getSites($params['serviceid']);
  293. if(!empty($sites)) {
  294. $siteBuilder = new ApiClient(getSiteBuilderApiURL($params), $params['serveraccesshash']);
  295. foreach($sites as $site) {
  296. $response = $siteBuilder->disable($params['username'], $site, $params['serverusername'], $params['serverpassword']);
  297. if($response['status'] != '200') {
  298. return 'Error: ' . $response['response']['error'];
  299. }
  300. }
  301. }
  302. return 'success';
  303. }
  304. /**
  305. * Set a siteBuilder account to status active.
  306. *
  307. * Called when an un-suspension is requested. This is invoked
  308. * automatically upon payment of an overdue invoice for a product, or
  309. * can be called manually by admin user.
  310. *
  311. * @param array $params common module parameters
  312. *
  313. * @see https://developers.whmcs.com/provisioning-modules/supported-functions/
  314. *
  315. * @return string 'success' or an error message
  316. */
  317. function siteBuilder_UnsuspendAccount($params) {
  318. try {
  319. Capsule::table('sitePro_acc')
  320. ->where('account',$params['username'])
  321. ->update(array(
  322. 'enabled' => true,
  323. ));
  324. } catch (\Exception $e) {
  325. logModuleCall(
  326. 'siteBuilder',
  327. __FUNCTION__,
  328. $params,
  329. 'Error: could update account in database',
  330. $e->getMessage()
  331. );
  332. return 'Error: could update account in database';
  333. }
  334. // enable active sites
  335. $sites = getSitesEnabled($params['serviceid']);
  336. if(!empty($sites)) {
  337. $siteBuilder = new ApiClient(getSiteBuilderApiURL($params), $params['serveraccesshash']);
  338. foreach($sites as $site) {
  339. $response = $siteBuilder->enable($params['username'], $site, $params['serverusername'], $params['serverpassword']);
  340. if($response['status'] != '200') {
  341. return 'Error: ' . $response['response']['error'];
  342. }
  343. }
  344. }
  345. return 'success';
  346. }
  347. /**
  348. * Client area output logic handling.
  349. *
  350. * This function is used to define module specific client area output. It should
  351. * return an array consisting of a template file and optional additional
  352. * template variables to make available to that template.
  353. *
  354. * @param array $params common module parameters
  355. *
  356. * @see https://developers.whmcs.com/provisioning-modules/client-area-output/
  357. *
  358. * @return array
  359. */
  360. function siteBuilder_ClientArea($params) {
  361. $siteBuilder = new ApiClient(getSiteBuilderApiURL($params), $params['serveraccesshash']);
  362. $clientInfo = array('moduleclientarea' => '1');
  363. $clientInfo['domain'] = $params['domain'];
  364. $accEnabled = Capsule::table('sitePro_acc')
  365. ->where('pid', $params['serviceid'])
  366. ->value('enabled');
  367. $sitesObj = Capsule::table('sitePro_site')
  368. ->where('relid', $params['serviceid'])
  369. ->get();
  370. $clientInfo['account'] = ['enabled' => $accEnabled];
  371. $clientInfo['sites'] = [];
  372. foreach($sitesObj as $site){
  373. $response = $siteBuilder->getSSLDays($params['username'], $site->name);
  374. if($response['status'] == '200') {
  375. $sslSite = $response['response']['ssl_remaining'];
  376. }
  377. array_push($clientInfo['sites'],['name' => $site->name, 'sslSite' => $sslSite, 'enabled' => $site->enabled]);
  378. }
  379. $response = $siteBuilder->getQuota($params['username']);
  380. if($response['status'] != '200') {
  381. logModuleCall(
  382. 'siteBuilder',
  383. __FUNCTION__,
  384. $params,
  385. 'Error getting Quota',
  386. $response
  387. );
  388. }
  389. $clientInfo['quota'] = round($response['response']['quota'][0]['blocks']/1024);
  390. $clientInfo['limit'] = round($response['response']['quota'][0]['hard']/1024);
  391. return array(
  392. 'tabOverviewReplacementTemplate' => 'clientarea',
  393. 'vars' => $clientInfo,
  394. );
  395. }
  396. /**
  397. * Upgrade or downgrade a siteBuilder account by package.
  398. *
  399. * Called to apply any change in product assignment or parameters. It
  400. * is called to provision upgrade or downgrade orders, as well as being
  401. * able to be invoked manually by an admin user.
  402. *
  403. * This same function is called for upgrades and downgrades of both
  404. * products and configurable options.
  405. *
  406. * @param array $params common module parameters
  407. *
  408. * @see https://developers.whmcs.com/provisioning-modules/supported-functions/
  409. *
  410. * @return string "success" or an error message
  411. */
  412. function siteBuilder_ChangePackage($params) {
  413. $siteBuilder = new ApiClient(getSiteBuilderApiURL($params), $params['serveraccesshash']);
  414. $response = $siteBuilder->setQuota($params['username'], $params['configoption3'], $params['serverusername'], $params['serverpassword']);
  415. if($response['status'] != '200') {
  416. return 'Error: ' . $response['response']['error'];
  417. }
  418. return 'success';
  419. }
  420. /**
  421. * Usage Update
  422. *
  423. * Important: Runs daily per server not per product
  424. * Run Manually: /admin/reports.php?report=disk_usage_summary&action=updatestats
  425. * @param array $params common module parameters
  426. *
  427. * @see https://developers.whmcs.com/provisioning-modules/usage-update/
  428. */
  429. function siteBuilder_UsageUpdate($params) {
  430. $siteBuilder = new ApiClient(getSiteBuilderApiURL($params), $params['serveraccesshash']);
  431. $response = $siteBuilder->getStats();
  432. if($response['status'] != '200') {
  433. logActivity('ERROR: Unable to update sitebuilder server usage: ' . implode('#',[$response]));
  434. }
  435. $stats = $response['response']['quota'];
  436. foreach($stats as $stat){
  437. try {
  438. Capsule::table('tblhosting')
  439. ->where('server', $params['serverid'])
  440. ->where('username', $stat['user'])
  441. ->update([
  442. 'diskusage' => $stat['used']/1024,
  443. 'disklimit' => $stat['hard']/1024,
  444. 'lastupdate' => Capsule::raw('now()'),
  445. ]);
  446. } catch (\Exception $e) {
  447. logActivity('ERROR: Unable to update sitebuilder server usage: ' . $e->getMessage());
  448. }
  449. logModuleCall(
  450. 'siteBuilder',
  451. __FUNCTION__,
  452. $stat,
  453. 'debug',
  454. $params
  455. );
  456. }
  457. }
  458. /**
  459. * Additional actions a client user can invoke.
  460. *
  461. * Define additional actions a client user can perform for an instance of a
  462. * product/service.
  463. *
  464. * Any actions you define here will be automatically displayed in the available
  465. * list of actions within the client area.
  466. *
  467. * @return array
  468. */
  469. function siteBuilder_ClientAreaCustomButtonArray ($params) {
  470. return array(
  471. 'Neue Webseite' => 'newSite',
  472. );
  473. }
  474. /**
  475. * Additional actions a client user can invoke.
  476. *
  477. * Define additional actions a client user is allowed to perform for an instance of a
  478. * product/service.
  479. *
  480. * @see https://developers.whmcs.com/provisioning-modules/supported-functions/
  481. *
  482. * @return array
  483. */
  484. function siteBuilder_ClientAreaAllowedFunctions() {
  485. return array(
  486. 'Add Site' => 'addSite',
  487. 'New Site' => 'newSite',
  488. 'Confirm Delete Site' => 'delSiteConfirm',
  489. 'Delete Site' => 'delSite',
  490. 'Edit Site' => 'editSite',
  491. 'Conform Revert Site' => 'revSiteConfirm',
  492. 'Revert Site' => 'revSite',
  493. 'Disable Site' => 'disableSite',
  494. 'Enable Site' => 'enableSite'
  495. );
  496. }
  497. /**
  498. * Opens a form to add a new domain.
  499. *
  500. * @param array $params common module parameters
  501. *
  502. * @see https://developers.whmcs.com/provisioning-modules/supported-functions/
  503. *
  504. * @return array template information
  505. */
  506. function siteBuilder_newSite($params) {
  507. return array(
  508. 'breadcrumb' => array(
  509. 'clientarea.php?action=productdetails&id=' . $params['serviceid'] . '&modop=custom&a=newSite' => 'Neue Webseite',
  510. ),
  511. 'templatefile' => 'siteBuilder_new_site',
  512. );
  513. }
  514. /**
  515. * Adds a new domain to a siteBuilder account.
  516. *
  517. * @param array $params common module parameters
  518. *
  519. * @see https://developers.whmcs.com/provisioning-modules/supported-functions/
  520. *
  521. * @return string "success" or an error message
  522. */
  523. function siteBuilder_addSite($params) {
  524. if(empty($_POST['d'])) {
  525. $site = $params['domain'];
  526. } else {
  527. if(!filter_var($_POST['d'], FILTER_VALIDATE_DOMAIN, FILTER_FLAG_HOSTNAME)){
  528. return 'Error: invalid site name';
  529. }
  530. $site = $_POST['d'] . '.' . $params['domain'];
  531. }
  532. // set DNS
  533. $response = siteBuildersetDNS($params, $site);
  534. if($response != 'success') {
  535. return $response;
  536. }
  537. $siteBuilder = new ApiClient(getSiteBuilderApiURL($params), $params['serveraccesshash']);
  538. // init prod
  539. $response = $siteBuilder->init($params['username'], $site, $params['serverusername'], $params['serverpassword']);
  540. if($response['status'] != '200') {
  541. return 'Error: ' . $response['response']['error'];
  542. }
  543. // update DB
  544. try {
  545. Capsule::table('sitePro_site')
  546. ->insert(
  547. array(
  548. 'relid' => $params['serviceid'],
  549. 'name' => $site,
  550. 'enabled' => true,
  551. )
  552. );
  553. } catch (\Exception $e) {
  554. logModuleCall(
  555. 'siteBuilder',
  556. __FUNCTION__,
  557. $params,
  558. 'Error: could save site & serviceid in database',
  559. $e->getMessage()
  560. );
  561. return 'Error: could save site & serviceid in database';
  562. }
  563. return 'success';
  564. }
  565. function siteBuilder_editSite($params) {
  566. if(!filter_var($_POST['s'], FILTER_VALIDATE_DOMAIN, FILTER_FLAG_HOSTNAME)){
  567. return 'Error: invalid site name';
  568. }
  569. $site = $_POST['s'];
  570. $api = new SiteProApiClient('https://builder.thurdata.ch/api/', 'apikey0', '993yVHwC05TLsx2JI2XFlAhkkPUxR6JbQUYbI.a5HiRtmNV9');
  571. // use this for enterprise licenses and change 'your-bulder-domain.com' to your builder domain
  572. //$api = new SiteProApiClient('http://your-bulder-domain.com/api/', 'your_api_username', 'your_api_password');
  573. try {
  574. // this call is used to open builder, so you need to set correct parameters to represent users website you want to open
  575. // this data usually comes from your user/hosting manager system
  576. $res = $api->remoteCall('requestLogin', array(
  577. 'type' => 'internal', // (required) 'internal'
  578. 'domain' => $site, // (required) domain of the user website you want to edit
  579. 'lang' => 'de', // (optional) 2-letter language code, set language code you whant builder to open in
  580. 'apiUrl' => getSiteBuilderApiURL($params) . 'deploy/' . $params['username'] . '/' . $site, // (required) API endpoint URL
  581. 'resellerClientAccountId' => $params['serviceid'], // (required) ID of website/user in your system
  582. 'username' => $params['serverusername'], // (optional) authorization username to be used with API endpoint
  583. 'password' => 'your-secure-password', // (optional) authorization password to be used with API endpoint
  584. 'hostingPlan' => $params['configoption2'],
  585. ));
  586. if (!$res || !is_object($res)) {
  587. logModuleCall(
  588. 'siteBuilder',
  589. __FUNCTION__,
  590. $params,
  591. 'Error: Response format error',
  592. $res
  593. );
  594. return 'Error: Response format error';
  595. } else if (isset($res->url) && $res->url) {
  596. logModuleCall(
  597. 'siteBuilder',
  598. __FUNCTION__,
  599. $params,
  600. 'Debug',
  601. $res
  602. );
  603. // on success redirect to builder URL
  604. header('Location: '.$res->url, true);
  605. exit();
  606. } else {
  607. logModuleCall(
  608. 'siteBuilder',
  609. __FUNCTION__,
  610. $params,
  611. 'Error: Unknown error',
  612. $res
  613. );
  614. return 'Error: Unknown error';
  615. }
  616. } catch (\Exception $e) {
  617. logModuleCall(
  618. 'siteBuilder',
  619. __FUNCTION__,
  620. $params,
  621. 'Error: Request error',
  622. $e->getMessage()
  623. );
  624. return 'Error: Request error';
  625. }
  626. return 'success';
  627. }
  628. /**
  629. * Opens a form to delete a domain from a siteBuilder account.
  630. *
  631. * @param array $params common module parameters
  632. *
  633. * @see https://developers.whmcs.com/provisioning-modules/supported-functions/
  634. *
  635. * @return array template information
  636. */
  637. function siteBuilder_delSiteConfirm($params) {
  638. return array(
  639. 'templatefile' => 'siteBuilder_del_site_confirm',
  640. 'vars' => array(
  641. 'delsite' => $_POST['s'],
  642. ),
  643. );
  644. }
  645. /**
  646. * Removes a domain from a siteBuilder account.
  647. *
  648. * @param array $params common module parameters
  649. *
  650. * @see https://developers.whmcs.com/provisioning-modules/supported-functions/
  651. *
  652. * @return string "success" or an error message
  653. */
  654. function siteBuilder_delSite($params) {
  655. if(!filter_var($_POST['s'], FILTER_VALIDATE_DOMAIN, FILTER_FLAG_HOSTNAME)){
  656. return 'Error: invalid domain name';
  657. }
  658. $site = $_POST['s'];
  659. $siteBuilder = new ApiClient(getSiteBuilderApiURL($params), $params['serveraccesshash']);
  660. // undeploy
  661. $response = $siteBuilder->undeploy($params['username'], $site, $params['serverusername'], $params['serverpassword']);
  662. if($response['status'] != '200') {
  663. return 'Error: ' . $response['response']['error'];
  664. }
  665. // remove builder session
  666. $api = new SiteProApiClient('https://builder.thurdata.ch/api/', 'apikey0', '993yVHwC05TLsx2JI2XFlAhkkPUxR6JbQUYbI.a5HiRtmNV9');
  667. // use this for enterprise licenses and change 'your-bulder-domain.com' to your builder domain
  668. //$api = new SiteProApiClient('http://your-bulder-domain.com/api/', 'your_api_username', 'your_api_password');
  669. try {
  670. // this call is used to open builder, so you need to set correct parameters to represent users website you want to open
  671. // this data usually comes from your user/hosting manager system
  672. $res = $api->remoteCall('requestLogin', array(
  673. 'type' => 'internal', // (required) 'internal'
  674. 'domain' => $site, // (required) domain of the user website you want to edit
  675. 'lang' => 'de', // (optional) 2-letter language code, set language code you whant builder to open in
  676. 'apiUrl' => getSiteBuilderApiURL($params) . 'deploy/' . $params['username'] . '/' . $site, // (required) API endpoint URL
  677. 'resellerClientAccountId' => $params['serviceid'], // (required) ID of website/user in your system
  678. 'username' => $params['serverusername'], // (optional) authorization username to be used with API endpoint
  679. 'password' => 'your-secure-password', // (optional) authorization password to be used with API endpoint
  680. ));
  681. if (!$res || !is_object($res)) {
  682. logModuleCall(
  683. 'siteBuilder',
  684. __FUNCTION__,
  685. $params,
  686. 'Error: Response format error',
  687. $res
  688. );
  689. return 'Error: Response format error';
  690. } else if (isset($res->url) && $res->url) {
  691. $result = $api->remoteCall('delete-site', array(
  692. 'domain' => $site
  693. ));
  694. if (!$result || !is_object($result)) {
  695. logModuleCall(
  696. 'siteBuilder',
  697. __FUNCTION__,
  698. $params,
  699. 'Error: Response format error',
  700. $result
  701. );
  702. return 'Error: Response format error';
  703. } else if (isset($result->ok) && $res->ok) {
  704. return 'success';
  705. }
  706. } else {
  707. logModuleCall(
  708. 'siteBuilder',
  709. __FUNCTION__,
  710. $params,
  711. 'Error: Unknown error',
  712. $res
  713. );
  714. return 'Error: Unknown error';
  715. }
  716. } catch (\Exception $e) {
  717. logModuleCall(
  718. 'siteBuilder',
  719. __FUNCTION__,
  720. $params,
  721. 'Error: Request error',
  722. $e->getMessage()
  723. );
  724. return 'Error: Request error';
  725. }
  726. // update DB
  727. try {
  728. Capsule::table('sitePro_site')
  729. ->where('name', $site)
  730. ->delete();
  731. } catch (\Exception $e) {
  732. logModuleCall(
  733. 'siteBuilder',
  734. __FUNCTION__,
  735. $params,
  736. 'Error: could remove site from database',
  737. $e->getMessage()
  738. );
  739. return 'Error: could remove site from database';
  740. }
  741. // unset DNS
  742. $response = siteBuilderunsetDNS($params, $site);
  743. if($response != 'success') {
  744. return $response;
  745. }
  746. return 'success';
  747. }
  748. /**
  749. * Opens a form to delete a domain from a siteBuilder account.
  750. *
  751. * @param array $params common module parameters
  752. *
  753. * @see https://developers.whmcs.com/provisioning-modules/supported-functions/
  754. *
  755. * @return array template information
  756. */
  757. function siteBuilder_revSiteConfirm($params) {
  758. return array(
  759. 'templatefile' => 'siteBuilder_rev_site_confirm',
  760. 'vars' => array(
  761. 'revSite' => $_POST['s'],
  762. ),
  763. );
  764. }
  765. /**
  766. * Revert all Changes of the development Site.
  767. *
  768. * @param array $params common module parameters
  769. *
  770. * @see https://developers.whmcs.com/provisioning-modules/supported-functions/
  771. *
  772. * @return string "success" or an error message
  773. */
  774. function siteBuilder_revSite($params) {
  775. if(!filter_var($_POST['s'], FILTER_VALIDATE_DOMAIN, FILTER_FLAG_HOSTNAME)){
  776. return 'Error: invalid site name';
  777. }
  778. $site = $_POST['s'];
  779. $siteBuilder = new ApiClient(getSiteBuilderApiURL($params), $params['serveraccesshash']);
  780. $response = $siteBuilder->revert($params['username'], $site, $params['serverusername'], $params['serverpassword']);
  781. if($response['status'] != '200') {
  782. return 'Error: ' . $response['response']['error'];
  783. }
  784. // remove builder session
  785. $api = new SiteProApiClient('https://builder.thurdata.ch/api/', 'apikey0', '993yVHwC05TLsx2JI2XFlAhkkPUxR6JbQUYbI.a5HiRtmNV9');
  786. // use this for enterprise licenses and change 'your-bulder-domain.com' to your builder domain
  787. //$api = new SiteProApiClient('http://your-bulder-domain.com/api/', 'your_api_username', 'your_api_password');
  788. try {
  789. // this call is used to open builder, so you need to set correct parameters to represent users website you want to open
  790. // this data usually comes from your user/hosting manager system
  791. $res = $api->remoteCall('requestLogin', array(
  792. 'type' => 'internal', // (required) 'internal'
  793. 'domain' => $site, // (required) domain of the user website you want to edit
  794. 'lang' => 'de', // (optional) 2-letter language code, set language code you whant builder to open in
  795. 'apiUrl' => getSiteBuilderApiURL($params) . 'deploy/' . $params['username'] . '/' . $site, // (required) API endpoint URL
  796. 'resellerClientAccountId' => $params['serviceid'], // (required) ID of website/user in your system
  797. 'username' => $params['serverusername'], // (optional) authorization username to be used with API endpoint
  798. 'password' => 'your-secure-password', // (optional) authorization password to be used with API endpoint
  799. ));
  800. if (!$res || !is_object($res)) {
  801. logModuleCall(
  802. 'siteBuilder',
  803. __FUNCTION__,
  804. $params,
  805. 'Error: Response format error',
  806. $res
  807. );
  808. return 'Error: Response format error';
  809. } else if (isset($res->url) && $res->url) {
  810. $result = $api->remoteCall('delete-site', array(
  811. 'domain' => $site
  812. ));
  813. if (!$result || !is_object($result)) {
  814. logModuleCall(
  815. 'siteBuilder',
  816. __FUNCTION__,
  817. $params,
  818. 'Error: Response format error',
  819. $result
  820. );
  821. return 'Error: Response format error';
  822. } else if (isset($result->ok) && $res->ok) {
  823. return 'success';
  824. }
  825. } else {
  826. logModuleCall(
  827. 'siteBuilder',
  828. __FUNCTION__,
  829. $params,
  830. 'Error: Unknown error',
  831. $res
  832. );
  833. return 'Error: Unknown error';
  834. }
  835. } catch (\Exception $e) {
  836. logModuleCall(
  837. 'siteBuilder',
  838. __FUNCTION__,
  839. $params,
  840. 'Error: Request error',
  841. $e->getMessage()
  842. );
  843. return 'Error: Request error';
  844. }
  845. return 'success';
  846. }
  847. function siteBuilder_enableSite($params) {
  848. if(!filter_var($_POST['s'], FILTER_VALIDATE_DOMAIN, FILTER_FLAG_HOSTNAME)){
  849. return 'Error: invalid site name';
  850. }
  851. $site = $_POST['s'];
  852. $siteBuilder = new ApiClient(getSiteBuilderApiURL($params), $params['serveraccesshash']);
  853. // enable
  854. $response = $siteBuilder->enable($params['username'], $site, $params['serverusername'], $params['serverpassword']);
  855. if($response['status'] != '200') {
  856. return 'Error: ' . $response['response']['error'];
  857. }
  858. // update DB
  859. try {
  860. Capsule::table('sitePro_site')
  861. ->where('relid',$params['serviceid'])
  862. ->where('name',$site)
  863. ->update(array(
  864. 'enabled' => true,
  865. ));
  866. } catch (\Exception $e) {
  867. logModuleCall(
  868. 'siteBuilder',
  869. __FUNCTION__,
  870. $params,
  871. 'Error: could save site status in database',
  872. $e->getMessage()
  873. );
  874. return 'Error: could save site status in database';
  875. }
  876. return 'success';
  877. }
  878. function siteBuilder_disableSite($params) {
  879. if(!filter_var($_POST['s'], FILTER_VALIDATE_DOMAIN, FILTER_FLAG_HOSTNAME)){
  880. return 'Error: invalid site name';
  881. }
  882. $site = $_POST['s'];
  883. $siteBuilder = new ApiClient(getSiteBuilderApiURL($params), $params['serveraccesshash']);
  884. // disable
  885. $response = $siteBuilder->disable($params['username'], $site, $params['serverusername'], $params['serverpassword']);
  886. logModuleCall(
  887. 'siteBuilder',
  888. __FUNCTION__,
  889. $params,
  890. 'Debug',
  891. $response
  892. );
  893. if($response['status'] != '200') {
  894. return 'Error: ' . $response['response']['error'];
  895. }
  896. // update DB
  897. try {
  898. Capsule::table('sitePro_site')
  899. ->where('relid',$params['serviceid'])
  900. ->where('name',$site)
  901. ->update(array(
  902. 'enabled' => false,
  903. ));
  904. } catch (\Exception $e) {
  905. logModuleCall(
  906. 'siteBuilder',
  907. __FUNCTION__,
  908. $params,
  909. 'Error: could save site status in database',
  910. $e->getMessage()
  911. );
  912. return 'Error: could save site status in database';
  913. }
  914. return 'success';
  915. }
  916. // Helpers
  917. /**
  918. * Update a DNS zone for a domain setting a new record for a domain or subdomain of a CWP7 account.
  919. *
  920. * @param array $params common module parameters
  921. *
  922. * @see https://developers.whmcs.com/provisioning-modules/supported-functions/
  923. *
  924. * @return string "success" or an error message
  925. */
  926. function siteBuildersetDNS($params, $site) {
  927. $siteName = $site . '.';
  928. $zoneRecords = array();
  929. $domainRecord = array(
  930. 'line' => $siteName.'|A|0',
  931. 'name' => $siteName,
  932. 'type' => 'A',
  933. 'class' => 'IN',
  934. 'data' => array(
  935. 'address' => $params['serverip'],
  936. ),
  937. );
  938. array_push($zoneRecords, $domainRecord);
  939. $zoneIDcollection = Capsule::table('dns_manager2_zone')
  940. ->select('id')
  941. ->where('name', '=', $params['domain'])
  942. ->where('clientid', '=', $params['userid'])
  943. ->get();
  944. $zoneIDobj = $zoneIDcollection[0];
  945. $zoneID = $zoneIDobj->{'id'};
  946. if(!isset($zoneID)) {
  947. return 'Error: Zone for domain ' . $params['domain'] . ' or not owned by client';
  948. }
  949. $dnsZone = localAPI('dnsmanager', array( 'dnsaction' => 'getZone', 'zone_id' => $zoneID));
  950. foreach($dnsZone['data']->records as $record) {
  951. if(($record->name != $siteName) || ($record->type != 'A' && $record->type != 'CNAME')) {
  952. array_push($zoneRecords, $record);
  953. };
  954. }
  955. $result = localAPI('dnsmanager' ,
  956. array(
  957. 'dnsaction' => 'updateZone',
  958. 'zone_id' => $zoneID,
  959. 'records' => $zoneRecords,
  960. )
  961. );
  962. if($result['result'] != 'success') {
  963. return 'Error: ' . $result['message'];
  964. }
  965. return 'success';
  966. }
  967. /**
  968. * Removing a DNS record for a site of a siteBuilder account.
  969. *
  970. * @param array $params common module parameters
  971. *
  972. * @see https://developers.whmcs.com/provisioning-modules/supported-functions/
  973. *
  974. * @return string "success" or an error message
  975. */
  976. function siteBuilderunsetDNS($params, $site) {
  977. $siteName = $site . '.';
  978. $zoneRecords = array();
  979. $zoneIDcollection = Capsule::table('dns_manager2_zone')
  980. ->select('id')
  981. ->where('name', '=', $params['domain'])
  982. ->where('clientid', '=', $params['userid'])
  983. ->get();
  984. $zoneIDobj = $zoneIDcollection[0];
  985. $zoneID = $zoneIDobj->{'id'};
  986. if(!isset($zoneID)) {
  987. return 'Error: Zone for domain ' . $params['domain'] . ' or not owned by client';
  988. }
  989. $dnsZone = localAPI('dnsmanager', array( 'dnsaction' => 'getZone', 'zone_id' => $zoneID));
  990. foreach($dnsZone['data']->records as $record) {
  991. if(($record->name != $siteName) || ($record->type != 'A' && $record->type != 'CNAME')) {
  992. array_push($zoneRecords, $record);
  993. };
  994. }
  995. $result = localAPI('dnsmanager' ,
  996. array(
  997. 'dnsaction' => 'updateZone',
  998. 'zone_id' => $zoneID,
  999. 'records' => $zoneRecords,
  1000. )
  1001. );
  1002. if($result['result'] != 'success') {
  1003. return 'Error: ' . $result['message'];
  1004. }
  1005. return 'success';
  1006. }
  1007. /**
  1008. * Returns API Url .
  1009. *
  1010. * @param string $params common module parameters
  1011. * @param string $user
  1012. * @param string $params common module parameters
  1013. *
  1014. * @return string $apiUrl
  1015. */
  1016. function getSiteBuilderApiURL($params) {
  1017. $httpPrefix = $params['serversecure'] ? 'https://' : 'http://';
  1018. $serverPort = $params['serverport'] ? ':' . $params['serverport'] . '/' : '/';
  1019. return $httpPrefix . $params['serverhostname'] . $serverPort;
  1020. }
  1021. function getSites($serviceID) {
  1022. try {
  1023. $sites = Capsule::table('sitePro_site')
  1024. ->where('relid',$serviceID)
  1025. ->value('name');
  1026. } catch (\Exception $e) {
  1027. logModuleCall(
  1028. 'siteBuilder',
  1029. __FUNCTION__,
  1030. $params,
  1031. 'Error: could fetch sites from database',
  1032. $e->getMessage()
  1033. );
  1034. return 'Error: could fetch sites from database';
  1035. }
  1036. return $sites;
  1037. }
  1038. function getSitesEnabled($serviceID) {
  1039. try {
  1040. $sites = Capsule::table('sitePro_site')
  1041. ->where('relid',$serviceID)
  1042. ->where('enabled', 1)
  1043. ->value('name');
  1044. } catch (\Exception $e) {
  1045. logModuleCall(
  1046. 'siteBuilder',
  1047. __FUNCTION__,
  1048. $params,
  1049. 'Error: could fetch sites from database',
  1050. $e->getMessage()
  1051. );
  1052. return 'Error: could fetch sites from database';
  1053. }
  1054. return $sites;
  1055. }
  1056. function siteBuilderCreateTables() {
  1057. // Create a new table.
  1058. if (!Capsule::schema()->hasTable('sitePro_acc')) {
  1059. try {
  1060. Capsule::schema()->create(
  1061. 'sitePro_acc',
  1062. function ($table) { logModuleCall(
  1063. 'siteBuilder',
  1064. __FUNCTION__,
  1065. $params,
  1066. 'Debug',
  1067. $site
  1068. );
  1069. /** @var \Illuminate\Database\Schema\Blueprint $table */
  1070. $table->increments('id');
  1071. $table->string('account');
  1072. $table->integer('pid');
  1073. $table->boolean('enabled');
  1074. }
  1075. );
  1076. } catch (\Exception $e) {
  1077. echo "Unable to create sitePro_acc: {$e->getMessage()}";
  1078. }
  1079. }
  1080. if (!Capsule::schema()->hasTable('sitePro_site')) {
  1081. try {
  1082. Capsule::schema()->create(
  1083. 'sitePro_site',
  1084. function ($table) {
  1085. /** @var \Illuminate\Database\Schema\Blueprint $table */
  1086. $table->increments('id');
  1087. $table->integer('relid');
  1088. $table->string('name');
  1089. $table->boolean('enabled');
  1090. }
  1091. );
  1092. } catch (\Exception $e) {
  1093. echo "Unable to create sitePro_site: {$e->getMessage()}";
  1094. }
  1095. }
  1096. }