Advertisement
am_dot_com

cn20210409

Apr 9th, 2021 (edited)
114
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
PHP 16.61 KB | None | 0 0
  1. <?php
  2. //require __DIR__."/vendor/autoload.php";
  3. require "./vendor/autoload.php";
  4. use am\internet\GoogleSearch;
  5.  
  6. //complementar leitura de erros com a utilização de: gcloud app logs tail -s default
  7. mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
  8.  
  9. define("CLOUD", true);
  10.  
  11. class SimplestGoogleCloudSQL
  12. {
  13.     const CREATE_SCHEMA_MYSQL_STATEMENT = "create schema if not exists `%s` default character set %s collate %s;";
  14.  
  15.     const CREATE_TABLE_TEST_STATEMENT = "
  16.        create table if not exists `%s`.`%s` (
  17.        id int not null auto_increment,
  18.        url varchar(512),
  19.        context text,
  20.        whenFound datetime not null,
  21.        primary key (id)
  22.    )";
  23.  
  24.     const MYSQL_DEFAULT_CHARSET = "utf8mb4"; //2019-02-14
  25.     const MYSQL_DEFAULT_COLLATE = "utf8mb4_unicode_ci"; //2019-02-14
  26.  
  27.     const DEFAULT_SCHEMA_NAME = "schema21four06";
  28.     const TABLE_TEST_NAME = "urls";
  29.  
  30.     const ACCEPTABLE_DB_ERRORS = [
  31.         0, //no error
  32.         1007, //database exists
  33.         1050 //table exists
  34.     ];
  35.  
  36.     //----------------------------------------------------------------------------
  37.     private $mDB;
  38.  
  39.     private $mDBSchema;
  40.     private $mDBUserName;
  41.     private $mDBUserPassword;
  42.     private $mDBHost;
  43.     private $mDBPort;
  44.     private $mSocketOrNamedPipe;
  45.  
  46.     private $mDBErr;
  47.     private $mDBMsg;
  48.  
  49.     private $mEchoDbErrors; //20190318
  50.  
  51.     //----------------------------------------------------------------------------
  52.     public function __construct(
  53.         $pHost,
  54.         $pUser,
  55.         $pPass,
  56.         $pSchema,
  57.         $pPort,
  58.         $pSocketOrNamedPipe
  59.     )
  60.     {
  61.         $db =
  62.             mysqli_connect(
  63.                 $pHost,
  64.                 $pUser,
  65.                 $pPass,
  66.                 null,//so it can connect to any schema/database in the instance
  67.                 //$pSchema, //received for other purposes, not for the connection purpose
  68.                 $pPort,
  69.                 $pSocketOrNamedPipe //specifies the socket or named pipe that should be used
  70.             );
  71.  
  72.         $e = mysqli_connect_errno();
  73.         $eM = mysqli_connect_error();
  74.  
  75.         if ($e !== 0) {
  76.             $strMsg =
  77.                 sprintf(
  78.                     "mysqli_connect error\nError code: %d\nError msg: %s\n",
  79.                     $e,
  80.                     $eM
  81.                 );
  82.             self::fb($strMsg);
  83.         } else {
  84.             $this->mDBHost = $pHost;
  85.             $this->mDBUserName = $pUser;
  86.             $this->mDBUserPassword = $pPass;
  87.             $this->mDBPort = $pPort;
  88.             $this->mDBSchema = $pSchema;
  89.             $this->mSocketOrNamedPipe = $pSocketOrNamedPipe;
  90.  
  91.             $this->mEchoDbErrors = true;
  92.  
  93.             $strMsg = "SUCCESS in connecting to database!" . PHP_EOL;
  94.             self::fb($strMsg);
  95.             //$this->mDB->close();
  96.         }
  97.  
  98.         $this->mDB = $e === 0 ? $db : false;
  99.     }//__construct
  100.  
  101.     //----------------------------------------------------------------------------
  102.     public function dbGetInstallProcedure(
  103.         $pbCreateSchema = true
  104.     )
  105.     {
  106.         $ret = [];
  107.  
  108.         if ($pbCreateSchema) {
  109.             $ret[] = trim(sprintf(
  110.                 self::CREATE_SCHEMA_MYSQL_STATEMENT,
  111.                 $this->mDBSchema,
  112.                 self::MYSQL_DEFAULT_CHARSET, //2019-02-14
  113.                 self::MYSQL_DEFAULT_COLLATE //2019-02-14
  114.             ));
  115.         }//if
  116.  
  117.         $ret[] = trim(sprintf(
  118.             self::CREATE_TABLE_TEST_STATEMENT,
  119.             $this->mDBSchema,
  120.             self::TABLE_TEST_NAME
  121.         ));
  122.         return $ret;
  123.     }//dbGetInstallProcedure
  124.  
  125.     //----------------------------------------------------------------------------
  126.     const ERRORS_DISPLAY_ONLY_THE_SINGLE_MOST_RECENT_ONE = -1;
  127.  
  128.     public function dbErrorsEcho(
  129.         $piHowManyErrorsToShow = self::ERRORS_DISPLAY_ONLY_THE_SINGLE_MOST_RECENT_ONE
  130.     )
  131.     {
  132.         $strMsg = "@" . __FUNCTION__ . ", " . date("Y-m-d H:i:s") . PHP_EOL;
  133.         self::fb($strMsg);
  134.  
  135.         $piHowManyErrorsToShow =
  136.             $piHowManyErrorsToShow === -1 || $piHowManyErrorsToShow > count($this->mDBMsg) ?
  137.                 count($this->mDBMsg)
  138.                 :
  139.                 $piHowManyErrorsToShow;
  140.  
  141.         $iHowManyMsgs = count($this->mDBMsg);
  142.         for ($i = $iHowManyMsgs - 1, $iErrorsShown = 0; $iErrorsShown < $piHowManyErrorsToShow; $i--, $iErrorsShown++) {
  143.             $strMsg =
  144.                 sprintf(
  145.                     "error code: %d | %s",
  146.                     $this->mDBErr[$i],
  147.                     $this->mDBMsg[$i]
  148.                 );
  149.  
  150.             $strMsg .= PHP_EOL;
  151.             self::fb($strMsg);
  152.         }//for
  153.     }//dbErrorsEcho
  154.  
  155.     //----------------------------------------------------------------------------
  156.     public function dbInstall(
  157.         $pbTryToExecuteInstallProcedure = true
  158.     )
  159.     {
  160.         $bReturn = true;
  161.  
  162.         $installProcedure = $this->dbGetInstallProcedure(
  163.             $pbTryToExecuteInstallProcedure
  164.         );
  165.  
  166.         foreach ($installProcedure as $installStatement) {
  167.             self::fb($installStatement . "\n");
  168.  
  169.             /*
  170.              * For successful SELECT, SHOW, DESCRIBE or EXPLAIN queries mysqli_query will return a mysqli_result
  171.              * For other successful queries mysqli_query will return true and false on failure.
  172.              */
  173.             $queryResult = $this->mDB->query($installStatement);
  174.             $e = mysqli_errno($this->mDB);
  175.             $eM = mysqli_error($this->mDB);
  176.  
  177.             $bAcceptableError = array_search($e, self::ACCEPTABLE_DB_ERRORS) !== false;
  178.             $bReturn = $bReturn && $bAcceptableError;
  179.  
  180.             $this->mDBErr[] = $e;
  181.             $this->mDBMsg[] = $eM;
  182.  
  183.             if ($this->mEchoDbErrors) {
  184.                 $this->dbErrorsEcho(1);
  185.             }
  186.         }//foreach
  187.  
  188.         return $bReturn;
  189.     }//dbInstall
  190.  
  191.     //_.-^-._.-^-._.-^-._.-^-._.-^-._.-^-._.-^-._.-^-._.-^-._.-^-._.-^-._.-^-._.-^-._.-^-._.-^-._.-^-.
  192.     public static function fb(
  193.         string $pMessage, //2019-03-20, refactored $m to $pMessage
  194.         bool $pbInjectTimeStamp = true
  195.     )
  196.     {
  197.         $sapiName = php_sapi_name();
  198.         //echo "sapiName = $sapiName  ";
  199.  
  200.         $CONSOLE = ($sapiName === 'cli');
  201.  
  202.         if (!$CONSOLE) {
  203.             $pMessage = str_replace("\n", "<br>", $pMessage);
  204.         } else {
  205.             //$m=str_replace("<mark>", "** ", $m);
  206.             //$m=str_replace("</mark>", " **", $m);
  207.             $pMessage = str_replace("<br>", PHP_EOL, $pMessage);
  208.             $pMessage = str_replace("<hr>", "----------------------------------------------------\n", $pMessage); //20140902
  209.             $pMessage = str_replace("\n", PHP_EOL, $pMessage);
  210.         }
  211.  
  212.         //http://stackoverflow.com/questions/3133209/how-to-flush-output-after-each-echo-call
  213.         try {
  214.             @ob_end_flush();
  215.  
  216.             //while (@ob_end_flush()); //flush all output buffers
  217.         } catch (\Exception $e) {
  218.             $mError = $e->getMessage();
  219.             $strMsg = "Exception $mError while exec'ing \"ob_end_flush();\"" . PHP_EOL;
  220.             echo $strMsg;
  221.         }
  222.  
  223.         # CODE THAT NEEDS IMMEDIATE FLUSHING
  224.        $now = date("Y-m-d H:i:s");
  225.         if ($pbInjectTimeStamp) { //2019-03-20 , timestamp made optional via new param
  226.             $strMsg = "$now: $pMessage";
  227.             echo $strMsg;
  228.         } else {
  229.             echo $pMessage;
  230.         }
  231.  
  232.         try {
  233.             ob_start();
  234.         } catch (\Exception $e) {
  235.             $mError = $e->getMessage();
  236.             $strMsg = "Exception $mError while exec'ing \"ob_start();\"" . PHP_EOL;
  237.             echo $strMsg;
  238.         }
  239.  
  240.         return $pMessage;
  241.     }//fb - feedback
  242.  
  243.     //_.-^-._.-^-._.-^-._.-^-._.-^-._.-^-._.-^-._.-^-._.-^-._.-^-._.-^-._.-^-._.-^-._.-^-._.-^-._.-^-.
  244.     public function dbSelectWhereUrlExistsInDownloadsTable(
  245.         $pUrl
  246.     )
  247.     {
  248.         if ($this->mDB) {
  249.             $strPrePreparedStatement = sprintf(
  250.             //"select id, url, context, whenFound from `%s` where `url` = ?",
  251.                 "select id, url, context, whenFound from `%s`.`%s` where `url` = ?",
  252.                 //"select id from %s.%s where url = ?",
  253.                 $this->mDBSchema,
  254.                 self::TABLE_TEST_NAME
  255.             );
  256.  
  257.             //mysqli_stmt data type
  258.             $mysqli_stmt_SelectUrl =
  259.                 $this->mDB->prepare(
  260.                     $strPrePreparedStatement
  261.                 );
  262.  
  263.             $strMsg = "PREPARED @dbSelectWhereUrlExistsInDownloadsTable = $strPrePreparedStatement" . PHP_EOL;
  264.             self::fb($strMsg);
  265.  
  266.             /*
  267.             Binds variables to prepared statement ? zones
  268.             i    corresponding variable has type integer
  269.             d    corresponding variable has type double
  270.             s    corresponding variable has type string
  271.             b    corresponding variable is a blob and will be sent in packets
  272.             */
  273.             $pStr2 = date("Y-m-d");
  274.             $mysqli_stmt_SelectUrl->bind_param(
  275.                 "s",
  276.                 $pUrl
  277.             );
  278.  
  279.             $bExecPreparedStatementResult = $mysqli_stmt_SelectUrl->execute();
  280.  
  281.             $strMsg = "EXECUTED prepared statement@dbSelectWhereUrlExistsInDownloadsTable" . PHP_EOL;
  282.             self::fb($strMsg);
  283.  
  284.             if ($bExecPreparedStatementResult) {
  285.                 /*
  286.                  * about the query result
  287.                  * For successful SELECT, SHOW, DESCRIBE or EXPLAIN queries mysqli_query will return a mysqli_result
  288.                  * For other successful queries mysqli_query will return true and false on failure.
  289.                  */
  290.                 //Gets a result set from a prepared statement
  291.                 $queryResult = $mysqli_stmt_SelectUrl->get_result();
  292.  
  293.                 //Uncaught Error: Object of class mysqli_result could not be converted to string
  294.                 //echo "QUERY RESULT = $queryResult".PHP_EOL;
  295.  
  296.                 $iHowManyResults = mysqli_num_rows($queryResult); //Gets the number of rows in a result but depends on $queryResult being of type mysqli_result
  297.                 //affected_rows : An integer greater than zero indicates the number of rows affected or retrieved
  298.                 $iHowManyResults = $mysqli_stmt_SelectUrl->affected_rows; //does NOT depend on the $query_result data type
  299.  
  300.                 if ($iHowManyResults > 0) {
  301.                     $mysqli_stmt_SelectUrl->close(); //only close after doing all necessary ops, including bind_result
  302.                     //end of PREPARED STATEMENT pattern
  303.  
  304.                     //Returns an array of associative or numeric arrays holding result rows.
  305.                     //MYSQLI_ASSOC, MYSQLI_NUM, or MYSQLI_BOTH.
  306.                     $rows = mysqli_fetch_all(
  307.                         $queryResult,
  308.                         MYSQLI_ASSOC
  309.                     );
  310.                     /*
  311.                     $idOfFirstProbablyOnlyRecordMatchingSelect = intval($rows[0]["id"]);
  312.  
  313.                     return $idOfFirstProbablyOnlyRecordMatchingSelect;
  314.                     */
  315.                     return $rows;
  316.                 }//if there were row results
  317.             }//if prepared statement executed ok
  318.             $e = mysqli_errno($this->mDB);
  319.             $eM = mysqli_error($this->mDB);
  320.             $this->mDBErr[] = $e;
  321.             $this->mDBMsg[] = $eM;
  322.  
  323.             if ($this->mEchoDbErrors) {
  324.                 $this->dbErrorsEcho(1);
  325.             }
  326.         }//if
  327.         return false;
  328.     }//dbSelectWhereUrlExistsInDownloadsTable
  329.  
  330.     //_.-^-._.-^-._.-^-._.-^-._.-^-._.-^-._.-^-._.-^-._.-^-._.-^-._.-^-._.-^-._.-^-._.-^-._.-^-._.-^-.
  331.     public function dbInsert(
  332.         $pUrl,
  333.         $pContext = "",
  334.         $pbAcceptRepeats = true
  335.     )
  336.     {
  337.         $aRowsWhereUrlExistsOrFalse = $this->dbSelectWhereUrlExistsInDownloadsTable($pUrl);
  338.  
  339.         $bCanProceed = $pbAcceptRepeats || (!$pbAcceptRepeats && $aRowsWhereUrlExistsOrFalse === false);
  340.  
  341.         $iInsertedAtThisId = false;
  342.         if ($bCanProceed) //does not exist yet
  343.         {
  344.             $strMsg = "Url ($pUrl) found to be NOT existing" . PHP_EOL;
  345.             self::fb($strMsg);
  346.  
  347.             $strNow = date("Y-m-d H:i:s");
  348.  
  349.             $strPrePreparedStatement = sprintf(
  350.                 "insert into `%s`.`%s` values (null, ?, ?, ?)",
  351.                 $this->mDBSchema,
  352.                 self::TABLE_TEST_NAME
  353.             );
  354.             $mysqli_stmt_insertUrl = $this->mDB->prepare(
  355.             //"insert into `%s`.`%s` values (null, ?, ?, ?)"
  356.                 $strPrePreparedStatement
  357.             );
  358.  
  359.             /*
  360.             Binds variables to prepared statement ? zones
  361.             i    corresponding variable has type integer
  362.             d    corresponding variable has type double
  363.             s    corresponding variable has type string
  364.             b    corresponding variable is a blob and will be sent in packets
  365.             */
  366.             $mysqli_stmt_insertUrl->bind_param(
  367.                 "sss",
  368.                 $pUrl, //url
  369.                 $pContext, //context (was whereFound until 2021-03-23)
  370.                 $strNow //whenFound (DATETIME in SQL, string in PHP)
  371.             );
  372.  
  373.             $strMsg = "BEFORE mysqli_stmt_insertUrl->execute();" . PHP_EOL;
  374.             self::fb($strMsg);
  375.  
  376.             $bExecResult = $mysqli_stmt_insertUrl->execute();
  377.             $e = mysqli_errno($this->mDB);
  378.             $eM = mysqli_error($this->mDB);
  379.  
  380.             $strMsg = "AFTER mysqli_stmt_insertUrl->execute(); with error=$e msg=$eM" . PHP_EOL;
  381.             self::fb($strMsg);
  382.  
  383.             if ($bExecResult) {
  384.                 $strMsg = "IN bExecResultSuccess" . PHP_EOL;
  385.                 self::fb($strMsg);
  386.                 /*
  387.                  * for inserts, mysqli_link->query() should true on success, false on failure
  388.                  * with mysqli_stmt->getResult, on 2018-12-02, I was getting a false bool return on a successful insert
  389.                  */
  390.  
  391.                 /*
  392.                  * get_result should return a
  393.                  * mysqli_result
  394.                  *
  395.                  * the $mysqli_stmt_insertUrl provides 10 attributes:
  396.                  * affected_rows, num_rows, inserted_id, param_count, field_count, errno, error, error_list, sqlstate and id
  397.                  * accessible like e.g.
  398.                  * $mysqli_stmt_insertUrl->inserted_id
  399.                  */
  400.  
  401.                 $queryResult = $mysqli_stmt_insertUrl->get_result();
  402.  
  403.                 $mysqli_stmt_insertUrl->close();
  404.                 //end of PREPARED STATEMENT pattern
  405.  
  406.                 $iInsertedAtThisId = mysqli_insert_id($this->mDB);
  407.             }//if correct execution
  408.  
  409.             $e = mysqli_errno($this->mDB);
  410.             $eM = mysqli_error($this->mDB);
  411.             $this->mDBErr[] = $e;
  412.             $this->mDBMsg[] = $eM;
  413.  
  414.             if ($this->mEchoDbErrors) {
  415.                 $this->dbErrorsEcho(100);
  416.             }
  417.  
  418.             return $iInsertedAtThisId;
  419.         }//if URL was not yet in database
  420.  
  421.         return false; //did not insert
  422.     }//dbInsertUrlIntoDownloadsTable
  423. }//SimplestGoogleCloudSQL
  424.  
  425. define("CLOUD", true);
  426.  
  427. if (CLOUD) {
  428.     $db = new SimplestGoogleCloudSQL(
  429.         null,
  430.         "root",
  431.         "1234!",
  432.         SimplestGoogleCloudSQL::DEFAULT_SCHEMA_NAME, //will be created if it does not exist
  433.         3306,
  434.         //"/cloudsql/<project id>:<region>:<sql instance name>
  435.         "/cloudsql/cloud-search-307909:europe-west1:am-210407"
  436.     );
  437. } else {
  438.     $db = new SimplestGoogleCloudSQL(
  439.         "localhost",
  440.         "test",
  441.         "1234",
  442.         //"schema210323",
  443.         SimplestGoogleCloudSQL::DEFAULT_SCHEMA_NAME, //will be created if it does not exist
  444.         3306,
  445.         null
  446.     );
  447. }
  448.  
  449. echo $db->dbInstall(
  450.     true //unnecesssary, but makes it clear that one can switch off the install procedure
  451. );
  452.  
  453. SimplestGoogleCloudSQL::fb("Will now test an insert" . PHP_EOL);
  454.  
  455. $strNow = date("Y-m-d H:i:s");
  456.  
  457. $exp = $_POST['nameTextSearch'];
  458. $strTestUrl = "https://www.google.com/search?q=".$exp;
  459.  
  460. echo "<h1>Will search for $exp</h1>";
  461. $o = new GoogleSearch($exp); //havendo use am\internet\GoogleSearch, pode usar-se esta instanciação abreviada
  462. //$o = new \am\internet\GoogleSearch($exp); //se não houvesse use am\internet\GoogleSearch
  463.  
  464. $html = $o->getSearchResults();
  465. echo $html;
  466.  
  467. $result = $db->dbInsert(
  468.     $strTestUrl, //in production it will the exact URL used for the search request, here it can be any string for testing purposes
  469.     $html, //the "context"
  470.     true //do NOT accept repeats
  471. );
  472.  
  473. $strResult = $result === false ? "NOTHING INSERTED" : $result;
  474. SimplestGoogleCloudSQL::fb("The result of the insert was $strResult" . PHP_EOL);
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement