-- phpMyAdmin SQL Dump
-- version 4.8.3
-- https://www.phpmyadmin.net/
--
-- Host: localhost:3306
-- Generation Time: Jan 13, 2020 at 11:25 AM
-- Server version: 5.6.41-84.1
-- PHP Version: 7.2.7
SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO";
SET AUTOCOMMIT = 0;
START TRANSACTION;
SET time_zone = "+00:00";
--
-- Database: `maconzer_reed_overflow`
--
-- --------------------------------------------------------
--
-- Table structure for table `rof_articles`
--
CREATE TABLE `rof_articles` (
`id` int(11) NOT NULL,
`title` text COLLATE utf8_unicode_ci NOT NULL,
`slug` text COLLATE utf8_unicode_ci,
`blurb` text COLLATE utf8_unicode_ci NOT NULL,
`body` text COLLATE utf8_unicode_ci NOT NULL,
`author_id` varchar(254) COLLATE utf8_unicode_ci NOT NULL,
`status` varchar(254) COLLATE utf8_unicode_ci NOT NULL COMMENT 'archive, draft, public',
`category` varchar(254) COLLATE utf8_unicode_ci NOT NULL COMMENT 'custom field'
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
--
-- Dumping data for table `rof_articles`
--
INSERT INTO `rof_articles` (`id`, `title`, `slug`, `blurb`, `body`, `author_id`, `status`, `category`) VALUES
(1, 'Terms & Conditions', 'terms', 'The Terms & Conditions for Reed Overflow', '# Terms & Conditions\r\n\r\nBy using this website and any of the content on it, you agree to the entirety of the Terms on this page and the [Privacy Policy](/legal/privacy/).\r\n\r\n## Projects\r\n\r\nThe open-source projects on this site all have their own licensing, and those licenses will be adhered to.\r\n\r\nThere is no liability and no warranty given with any of the projects on this website, unless otherwise specified in the project\'s license. Use the projects at your own risk.\r\n\r\n## Articles\r\n\r\nThe articles on this website are written with the full intention of being accurate and useful, however there is no guarantee of the accuracy of information, and neither this website, the website owner(s), nor the author(s) of the content are liable for the information nor for how you use any of the information on this website.\r\n\r\n## Cookies\r\nCookies store information in your web browser in order to make this site function. These cookies may contain user login information (for administrators), PHP Session IDs (used for technical reasons), and any other information pertinent to site preferences, website analytics and statistics, and any advertisement.\r\n\r\nCookies may be used for other purposes not mentioned above, and by using this site, you consent to cookies being used as this website deems fit.\r\n\r\nWe make effort to protect your information and use cookies in a secure manner. However, there is no guarantee of security and this website and its owner(s) and author(s) will not be held liable for any breach in security.\r\n\r\n## User Login\r\n\r\nUser login is only for the administrators of this website. Using the login and registration capabilities on this website is not permitted for non-administrators. \r\n\r\nAny use of the login system, even by administrators, comes with no warrant and no liability. Effort has been made to ensure all user information, including email addresses and passwords, are secure. However, there is no guarantee of the security of this information, and neither this website nor the website owner(s) will be held liable for any breach in security.\r\n\r\nTo protect your privacy, you should use a different password on every website you use, thus if one website password is stolen, none others will have been compromised.', '', '', 'legal'),
(2, 'Privacy Policy - Reed Overflow', 'privacy', 'The Privacy Policy for Reed Overflow', '# Privacy Policy\r\n\r\n## Analytics\r\nAnalytics are not used on this website and no information is collected in connection with analytics.\r\n\r\n## Advertisements\r\nAdvertisements are not used on this website and no information is collected in connection with advertising.\r\n\r\n## Cookies\r\nNo personal information is stored in cookies. Complex IDs generated on the server are used for cookies, and these IDs are linked to content in the database.\r\n\r\n## User Login\r\nYour name, email address, and a password may be collected. \r\nYour email address and name will be kept in the database and may be retrieved and used as needed, but will not be shared publicly, except in the case of an error. In case of an error, this website and its owner(s) will not be held liable.\r\nYou may be sent emails in connection with the login system.\r\nYour password will not be stored on the server. Rather a password hashing algorithm will be used to verify your login, such that the password itself will never be stored. Your password will be transferred to the server in its plain text form, and neither this website nor its owner(s) will be held liable if an error causes this password to be displayed or if the password is stolen via any means, including, but not limited to, intrusion into our server or into your network.\r\n\r\n\r\n# **HEY GUYS, THIS IS NOT REED, I CAN HACK THIS AND EDIT THIS AND POST SOME RANDOM STUFF HERE. HEHEHAHAHAHHAHAHHUHUHUHUHU **', '0', 'published', 'legal'),
(4, 'Redirect request with POST data - PHP', 'php-redirect-with-post', 'Learn how to redirect a request on your PHP server while forwarding the $_POST data as well. Hint: use sessions.', '# Here is the new content\r\n\r\n**I am the new stuff**', '', '', 'article'),
(5, 'Clicking link in list highlights whole list', 'li-ul-highlight-problem', 'Learn how to fix a problem with links \"selecting\" the parent element when you click the link.', '# Clicking list item highlights full list\r\n\r\nI had a peculiar problem yesterday with `li`s in a `<ul>`. It’s the navigation menu for my website, and when I click on one of the list items, which contains an `<a>`, the click would work fine, but the entire `ul` would highlight as if it had been selected. I came across suggestions like using `user-select:none;` including the vendor prefixes, and I tried these to no avail.\r\n\r\nI spent about an hour working on this issue, only to find out it was SUCH a simple problem. Of course, for my links, I like to have `cursor:pointer` because… it just looks and feels better when you mouse over a link and the cursor changes. So, I had, for one reason or another, applied `cursor:pointer` to the `<ul>`, and this apparently changes things.\r\n\r\nThe problem code I had was:\r\n\r\n```html\r\n<style>\r\nul {\r\n cursor:pointer;\r\n}\r\n</style>\r\n<ul>\r\n <li><a href=â€/â€>Home</a></li>\r\n<li><a href=â€/articlesâ€>Articles</a></li>\r\n<li><a href=â€/projectsâ€>Projects</a></li>\r\n <li><a href=â€/aboutâ€>About</a></li>\r\n <li><a href=â€/contactâ€>Contact</a></li>\r\n```\r\n\r\nOf course, I had additional styling as well. I think that because the `cursor:pointer` is set on the `ul`, rather than the individual link, it takes the click event (at least visually) as being on the entire menu. So I removed it from the full menu and put it on to the `a`.\r\n\r\nAdditionally, to remove the highlighting from the link, I applied:\r\n```css\r\n-webkit-tap-highlight-color: rgba(0,0,0,0);\r\n```\r\nwhich is a non-standard feature, but it looks like it is implemented in mobile safari and mobile chrome. Idk about other browsesrs.', '', '', 'article'),
(8, 'Fixing PHP Recoverable Fatal Error: Object of class Closure could not be converted to string in ...', 'php-closure-string-error', 'See how to fix Recoverable the Fatal Error: Object of class Closure could not be converted to string in ... You\'re converting to a string, when you need to invoke the function. ', 'Let\'s suppose you have a `closure` (which is an inline `function`) assigned to a variable, such as:\r\n\r\n```php\r\n<?php\r\n //Enter your code here, enjoy!\r\n\r\n//this is pseudo-random and NOT cryptographically secure\r\n$randomChars = function($length)\r\n{\r\n for (\r\n $chars = array(\'0123456789\',\'abcdefghijklmnopqrstuvwxyz\',\'ABCDEFGHIJKLMNOPQRSTUVWXYZ\',\'!@#$%^&*()_+-=\'),\r\n $randomString=\"\",\r\n $i=0;\r\n $i<$length;$i++){\r\n $randomString .= \r\n substr($chars[$i%4], \r\n random_int(0, strlen($chars[$i%4])), 1);\r\n }\r\n return $randomString;\r\n};\r\n\r\n?>\r\n\r\n```\r\nThis is a fairly simple random string generator. \r\n\r\nNow, let\'s suppose you\'re getting the error **Recoverable Fatal Error: Object of class Closure could not be converted to string in** and you\'re stuck.\r\n\r\nYou probably have a bit of code like:\r\n```php\r\necho \"Here are my random characters: \".$randomChars;\r\n```\r\nWell, this generates an error, because `$randomChars` is not a string. It is a `function` which *returns* a string. \r\n\r\n## The Fix\r\nInstead of using `$randomChars` as a string, use it as a function:\r\n```php\r\n$theChars = $randomChars(15); //get a random string 15 characters long\r\necho \"I have this random string: \".$theChars;\r\n```\r\nNow everything works, because you\'re getting the return value of the function call, rather than trying to print out the function itself.', '0', 'published', 'article'),
(7, 'Use PHP and PDO to query mysql database', 'php-pdo-basics', '', 'The documentation for PDO is available at [php.net/pdo](http://php.net/pdo) . \r\n\r\n# Create a PDO object\r\nYou may want to use a `try/catch` in case PDO fails to open. \r\n\r\n $pdo = new PDO(\'mysql:dbname=testdb;host=127.0.0.1\', \'dbuser\', \'password\');(\r\n\r\nYou should be able to find the dbname, host, username, and password all in your host\'s server manager page, often cPanel. \r\n\r\nWe\'ll use `$pdo` for the rest of our examples.\r\n\r\n# Query for one item \r\n\r\n $userSearch = $pdo->prepare(\"SELECT * FROM users WHERE user_id =LIKE :user_id AND password_hash LIKE :password_hash\"); \r\n $success = $userSearch->execute(array(\r\n \":user_name\" => $user_name, //assuming you have a user_name variable\r\n \":password_hash\" => $password_hash //also assuming you\'ve prepared this\r\n ));\r\n $userData = $userSearch->fetch();\r\n $userSearch->closeCursor();\r\n\r\nNext, we will cover checking your results for what you want.\r\n\r\n# Validating your results\r\nSee `$userData = $userSearch->fetch();` under **Query...* above.\r\n\r\nWe\'ll edit that line to\r\n if ($success===FALSE){\r\n //print an error, or throw an Exception\r\n return;\r\n } else if ($userSearch->rowCount()===0) {\r\n //print error for no results, throw exception, or alternate\r\n return;\r\n } else if ($userSearch->rowCount()>1) {\r\n //throw/print a different error, as there should only be one matching user row\r\n return;\r\n }\r\n $userData = $userSearch->fetch(); \r\n\r\nYou can have an else block for that last line, instead of using those returns. However, I like to do it this way so my success code block is not contained within a giant `if`, which I find ugly and distracting.\r\n \r\n', '0', 'published', 'article'),
(9, 'Get proper case class name in PHP benchmarks', 'php-class-case-benchmark', 'Learn how to get the proper case of a class name from a given string, and see bench marks for two different methods of doing this.', '# PHP Proper Class Name\r\nClass names in PHP are case insensitve. If you have a class declaration like:\r\n```php\r\nclass MyWeirdClass {}\r\n```\r\nyou can instantiate it with `new myWEIRDclaSS()` or any other variation on the case. In some instances, you may want to know, what is the correct, case-sensitive class name. \r\n\r\n### Example Use case\r\nFor example, in one of my libraries under construction [API Doccer](https://github.com/ReedOverflow/PHP-API-Doccer), I can view documentation for a class at url `/doc/class/My-Namespace-Clazzy/` and if you enter the wrong case, like `/doc/class/my-NAMESPACE-CLAzzy`, it should automatically redirect to the proper-cased class. To do this, I use the reflection method below as it is FAR more performant than the `get_delcared_classes` method\r\n\r\n\r\n## Reflection - get proper case\r\nCredit goes to [l00k on StackOverflow](https://stackoverflow.com/a/35222911/802469)\r\n```php\r\n$className = \'My\\caseINAccuRATE\\CLassNamE\';\r\n$reflection = new ReflectionClass($className);\r\necho $reflection->getName();\r\n```\r\nresults in `My\\CaseInaccurate\\ClassName`; \r\nRunning the benchmark (see below) on localhost on my laptop, getting the proper case class name of 500 classes took about 0.015 seconds, as opposed to ~0.050 seconds using the `get_declared_classes` method below.\r\n\r\n## get_declared_classes - get proper case\r\nThis was my idea, as I hadn\'t even considered using reflection, until I saw [l00k\'s answer on StackOverflow](https://stackoverflow.com/a/35222911/802469). Guessing it would be less efficient, I wrote the code and figured it out anyway, because it\'s fun!\r\n```php\r\n$wrongCaseName = \'Some\\classy\\THIng\';\r\nclass_exists($wrongCaseName); //so it gets autoloaded if not already done\r\n$classes = get_declared_classes();\r\n$map = array_combine(array_map(\'strtolower\',$classes),$classes);\r\n$proper = $map[strtolower($wrongCaseName)];\r\n```\r\nresults in `$proper = \'Some\\Classy\\Thing\'`; \r\nRunning the bencmark (see below) on localhost on my laptop, getting the proper case class name of 500 classes took about 0.050 seconds, as opposed to ~0.015 seconds with reflection (above).\r\n\r\n\r\n## Benchmark:\r\nI used the following code to do the benchmark, removing the `classes` directory between each run of the benchmark. It\'s not perfect. At all. But it gets the job done well enough, I think:\r\n```php\r\n<?php\r\n\r\n$times = [];\r\n$times[\'begin\'] = microtime(TRUE);\r\n\r\nspl_autoload_register(function($className){\r\n if (file_exists($name=__DIR__.\'/classes/\'.strtolower($className).\'.php\')){\r\n include($name);\r\n }\r\n});\r\nif (is_dir(__DIR__.\'/classes\'))return;\r\n\r\nmkdir(__DIR__.\'/classes\');\r\n\r\nfunction generateRandomString($length = 10) {\r\n $characters = \'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ\';\r\n $charactersLength = strlen($characters);\r\n $randomString = \'\';\r\n for ($i = 0; $i < $length; $i++) {\r\n $randomString .= $characters[rand(0, $charactersLength - 1)];\r\n }\r\n return $randomString;\r\n}\r\n\r\n$times[\'start_file_write\'] = microtime(TRUE);\r\n$names = [];\r\nfor ($i=0;$i<500;$i++){\r\n $className = generateRandomString(10);\r\n $file = __DIR__.\'/classes/\'.strtolower($className).\'.php\';\r\n if (file_exists($file)){\r\n $i = $i-1;\r\n continue;\r\n }\r\n $code = \"<?php \\n\\n\".\'class \'.$className.\' {}\'.\"\\n\\n ?>\";\r\n file_put_contents($file,$code);\r\n $names[] = strtoupper($className);\r\n}\r\n\r\n$times[\'begin_get_declared_classes_benchmark\'] = microtime(TRUE);\r\n$propers = [];\r\n\r\n// foreach($names as $index => $name){\r\n// $wrongCaseName = strtoupper($name);\r\n// class_exists($wrongCaseName); //so it gets autoloaded if not already done\r\n// $classes = get_declared_classes();\r\n// $map = array_combine(array_map(\'strtolower\',$classes),$classes);\r\n// $proper = $map[strtolower($wrongCaseName)];\r\n// if ($index%20===0){\r\n// $times[\'intermediate_bench_\'.$index] = microtime(TRUE);\r\n// }\r\n// $propers[] = $proper;\r\n// }\r\n\r\n// the above commented lines are the get_declared_classes() method. \r\n// the foreach below is for reflection.\r\n\r\nforeach ($names as $index => $name){\r\n $className = strtoupper($name);\r\n $reflection = new ReflectionClass($className);\r\n if ($index%20===0){\r\n $times[\'intermediate_bench_\'.$index] = microtime(TRUE);\r\n }\r\n $propers[] = $reflection->getName(); \r\n}\r\n\r\n$times[\'end_get_declared_classes_benchmark\'] = microtime(TRUE);\r\n\r\n$start = $times[\'begin\'];\r\n$bench = $times[\'begin_get_declared_classes_benchmark\'];\r\n\r\n$lastTime = 0;\r\nforeach($times as $key => $time){\r\n echo \"\\nTime since begin:\".($time-$start);\r\n echo \"\\nTime since last: \".($time-$lastTime).\" key was {$key}\";\r\n echo \"\\nTime since bench start: \".($time - $bench);\r\n $lastTime = $time;\r\n}\r\n\r\nprint_r($times);\r\nprint_r($propers);\r\nexit;\r\n```\r\n\r\n### Results\r\n```\r\n// get_declared_classes method\r\n//Time since bench start: 0.052499055862427 is total time for processing get_declared_classes w/ $i=500\r\n//Time since bench start: 0.047168016433716\r\n// last bench time Time since begin:0.062150955200195\r\n// 100 intermediate bench: Time since bench start: 0.0063230991363525\r\n// 200 : Time since bench start: 0.015070915222168\r\n// 300 intermediate bench: Time since bench start: 0.02455997467041\r\n// 400 intermediate bench: Time since bench start: 0.033944129943848\r\n// 480 : Time since bench start: 0.044310092926025\r\n\r\n\r\n//reflection method:\r\n//Time since bench start: 0.01493501663208\r\n//Time since bench start: 0.017416954040527\r\n// 100 intermediate: Time since bench start: 0.0035450458526611\r\n// 200 intermediate: Time since bench start: 0.0066778659820557\r\n// 300 intermediate: Time since bench start: 0.010055065155029\r\n// 400 intermediate: Time since bench start: 0.014182090759277\r\n// 480 intermediate: Time since bench start: 0.01679801940918\r\n```\r\n\r\n#### Results\' notes\r\n- \"Time since bench start\" is the entire time it took to run all the iterations. I share this twice above. \r\n- \"100 Intermediate\" (200, 300, etc) are actually the results at 120, 220, etc... I messed up in copy+pasting results & didn\'t want to do it again. Yes. I\'m lazy :)\r\n- The results would of course vary between runs of the code, but it\'s pretty clear that the reflection option is significantly faster.\r\n- All was run on a localhost server on an Acer laptop.\r\n- PHP Version 7.2.19-0ubuntu0.19.04.1 (from `phpinfo()`)', '0', 'published', 'article');
-- --------------------------------------------------------
--
-- Table structure for table `rof_user_auth`
--
CREATE TABLE `rof_user_auth` (
`id` int(11) NOT NULL,
`user_id` int(11) NOT NULL,
`type` text COLLATE utf8_unicode_ci NOT NULL,
`data` text COLLATE utf8_unicode_ci NOT NULL,
`expiresAt` int(11) NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
--
-- Dumping data for table `rof_user_auth`
--
INSERT INTO `rof_user_auth` (`id`, `user_id`, `type`, `data`, `expiresAt`) VALUES
(13, 1, 'password', '$2y$10$DWDzpPU9OBqu2VJ/4I9oNepc4FakPZ2uxnDx44LyYZDe.BAqgtZia', 1560021291);
-- --------------------------------------------------------
--
-- Table structure for table `rof_user_info`
--
CREATE TABLE `rof_user_info` (
`id` int(11) NOT NULL,
`name` text COLLATE utf8_unicode_ci NOT NULL,
`email` varchar(256) COLLATE utf8_unicode_ci NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
--
-- Dumping data for table `rof_user_info`
--
INSERT INTO `rof_user_info` (`id`, `name`, `email`) VALUES
(1, 'Reed Sutman', 'rsutman@gmail.com');
--
-- Indexes for dumped tables
--
--
-- Indexes for table `rof_articles`
--
ALTER TABLE `rof_articles`
ADD PRIMARY KEY (`id`),
ADD UNIQUE KEY `url` (`slug`(254));
--
-- Indexes for table `rof_user_auth`
--
ALTER TABLE `rof_user_auth`
ADD PRIMARY KEY (`id`);
--
-- Indexes for table `rof_user_info`
--
ALTER TABLE `rof_user_info`
ADD PRIMARY KEY (`id`),
ADD UNIQUE KEY `email` (`email`);
--
-- AUTO_INCREMENT for dumped tables
--
--
-- AUTO_INCREMENT for table `rof_articles`
--
ALTER TABLE `rof_articles`
MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=13;
--
-- AUTO_INCREMENT for table `rof_user_auth`
--
ALTER TABLE `rof_user_auth`
MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=14;
--
-- AUTO_INCREMENT for table `rof_user_info`
--
ALTER TABLE `rof_user_info`
MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=2;
COMMIT;