├── screenshots ├── Edit.png ├── Home.png ├── Index.png ├── Post.png ├── Users.png ├── Profile.png ├── Setting.png ├── Inner-Post.png └── Notifications.png ├── includes ├── logout.php ├── login.php ├── signup-form.php └── tweets.php ├── assets ├── images │ ├── users │ │ ├── cover.png │ │ ├── default.jpg │ │ ├── user-607ef530bdeab.jpg │ │ ├── user-608b4b4187b5c.JPG │ │ ├── user-608ce0c755753.jpg │ │ ├── user-608ce2cde9679.jpg │ │ ├── user-609be24f01658.jpeg │ │ ├── user-609e556249eb9.jpg │ │ ├── user-60b102374b4c9.jpeg │ │ ├── user-60b102374b4d0.png │ │ ├── user-60f37eef65065.jpg │ │ └── user-60f37eef6506e.jpg │ ├── twitter-logo.png │ ├── tweets │ │ ├── tweet-60666d6b426a1.jpg │ │ ├── tweet-608cbd2495a54.jpg │ │ ├── tweet-60b28dc5543c0.png │ │ ├── tweet-60be0f4e9c393.jpg │ │ ├── tweet-60e71eac1e32b.jpg │ │ ├── tweet-60f37abe2b507.jpg │ │ ├── tweet-6077e54477f73.jpeg │ │ └── tweet-60b1030158fd5.jpeg │ ├── loading.svg │ └── twitter.svg ├── css │ ├── font │ │ ├── fonts │ │ │ ├── FontAwesome.otf │ │ │ ├── fontawesome-webfont.eot │ │ │ ├── fontawesome-webfont.ttf │ │ │ ├── fontawesome-webfont.woff │ │ │ └── fontawesome-webfont.woff2 │ │ ├── less │ │ │ ├── fixed-width.less │ │ │ ├── larger.less │ │ │ ├── list.less │ │ │ ├── core.less │ │ │ ├── font-awesome.less │ │ │ ├── stacked.less │ │ │ ├── bordered-pulled.less │ │ │ ├── rotated-flipped.less │ │ │ ├── path.less │ │ │ ├── animated.less │ │ │ └── mixins.less │ │ ├── scss │ │ │ ├── _fixed-width.scss │ │ │ ├── _larger.scss │ │ │ ├── _list.scss │ │ │ ├── font-awesome.scss │ │ │ ├── _core.scss │ │ │ ├── _stacked.scss │ │ │ ├── _bordered-pulled.scss │ │ │ ├── _rotated-flipped.scss │ │ │ ├── _path.scss │ │ │ ├── _animated.scss │ │ │ └── _mixins.scss │ │ └── HELP-US-OUT.txt │ └── index_style.css └── js │ ├── search.js │ ├── hashtag.js │ ├── photo.js │ ├── follow.js │ ├── like.js │ ├── comment.js │ ├── users.js │ └── retweet.js ├── core ├── classes │ ├── validation │ │ ├── ValidInterface.php │ │ ├── Required.php │ │ ├── Str.php │ │ ├── Max20.php │ │ ├── Min5.php │ │ ├── Max100.php │ │ ├── MaxTweet.php │ │ ├── Email.php │ │ ├── Numeric.php │ │ ├── RequireImage.php │ │ ├── Image.php │ │ └── Validator.php │ ├── image.php │ ├── connection.php │ ├── Follow.php │ ├── User.php │ └── Tweet.php ├── init.php ├── database │ └── connection.php └── ajax │ ├── search.php │ ├── getHashtag.php │ ├── follow.php │ ├── like.php │ ├── users.php │ └── comment.php ├── .htaccess ├── handle ├── handleDeleteCover.php ├── handlelogin.php ├── handleChangePassword.php ├── handleAccountSetting.php ├── handleSignUp.php ├── handleTweet.php └── handleUpdateData.php ├── README.md ├── index.php ├── account.php ├── notification.php ├── home.php └── twitter.sql /screenshots/Edit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aminyasser/twitter-clone/HEAD/screenshots/Edit.png -------------------------------------------------------------------------------- /screenshots/Home.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aminyasser/twitter-clone/HEAD/screenshots/Home.png -------------------------------------------------------------------------------- /screenshots/Index.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aminyasser/twitter-clone/HEAD/screenshots/Index.png -------------------------------------------------------------------------------- /screenshots/Post.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aminyasser/twitter-clone/HEAD/screenshots/Post.png -------------------------------------------------------------------------------- /screenshots/Users.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aminyasser/twitter-clone/HEAD/screenshots/Users.png -------------------------------------------------------------------------------- /includes/logout.php: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /screenshots/Profile.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aminyasser/twitter-clone/HEAD/screenshots/Profile.png -------------------------------------------------------------------------------- /screenshots/Setting.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aminyasser/twitter-clone/HEAD/screenshots/Setting.png -------------------------------------------------------------------------------- /screenshots/Inner-Post.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aminyasser/twitter-clone/HEAD/screenshots/Inner-Post.png -------------------------------------------------------------------------------- /assets/images/users/cover.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aminyasser/twitter-clone/HEAD/assets/images/users/cover.png -------------------------------------------------------------------------------- /screenshots/Notifications.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aminyasser/twitter-clone/HEAD/screenshots/Notifications.png -------------------------------------------------------------------------------- /assets/images/twitter-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aminyasser/twitter-clone/HEAD/assets/images/twitter-logo.png -------------------------------------------------------------------------------- /assets/images/users/default.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aminyasser/twitter-clone/HEAD/assets/images/users/default.jpg -------------------------------------------------------------------------------- /assets/css/font/fonts/FontAwesome.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aminyasser/twitter-clone/HEAD/assets/css/font/fonts/FontAwesome.otf -------------------------------------------------------------------------------- /assets/images/tweets/tweet-60666d6b426a1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aminyasser/twitter-clone/HEAD/assets/images/tweets/tweet-60666d6b426a1.jpg -------------------------------------------------------------------------------- /assets/images/tweets/tweet-608cbd2495a54.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aminyasser/twitter-clone/HEAD/assets/images/tweets/tweet-608cbd2495a54.jpg -------------------------------------------------------------------------------- /assets/images/tweets/tweet-60b28dc5543c0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aminyasser/twitter-clone/HEAD/assets/images/tweets/tweet-60b28dc5543c0.png -------------------------------------------------------------------------------- /assets/images/tweets/tweet-60be0f4e9c393.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aminyasser/twitter-clone/HEAD/assets/images/tweets/tweet-60be0f4e9c393.jpg -------------------------------------------------------------------------------- /assets/images/tweets/tweet-60e71eac1e32b.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aminyasser/twitter-clone/HEAD/assets/images/tweets/tweet-60e71eac1e32b.jpg -------------------------------------------------------------------------------- /assets/images/tweets/tweet-60f37abe2b507.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aminyasser/twitter-clone/HEAD/assets/images/tweets/tweet-60f37abe2b507.jpg -------------------------------------------------------------------------------- /assets/images/users/user-607ef530bdeab.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aminyasser/twitter-clone/HEAD/assets/images/users/user-607ef530bdeab.jpg -------------------------------------------------------------------------------- /assets/images/users/user-608b4b4187b5c.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aminyasser/twitter-clone/HEAD/assets/images/users/user-608b4b4187b5c.JPG -------------------------------------------------------------------------------- /assets/images/users/user-608ce0c755753.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aminyasser/twitter-clone/HEAD/assets/images/users/user-608ce0c755753.jpg -------------------------------------------------------------------------------- /assets/images/users/user-608ce2cde9679.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aminyasser/twitter-clone/HEAD/assets/images/users/user-608ce2cde9679.jpg -------------------------------------------------------------------------------- /assets/images/users/user-609be24f01658.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aminyasser/twitter-clone/HEAD/assets/images/users/user-609be24f01658.jpeg -------------------------------------------------------------------------------- /assets/images/users/user-609e556249eb9.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aminyasser/twitter-clone/HEAD/assets/images/users/user-609e556249eb9.jpg -------------------------------------------------------------------------------- /assets/images/users/user-60b102374b4c9.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aminyasser/twitter-clone/HEAD/assets/images/users/user-60b102374b4c9.jpeg -------------------------------------------------------------------------------- /assets/images/users/user-60b102374b4d0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aminyasser/twitter-clone/HEAD/assets/images/users/user-60b102374b4d0.png -------------------------------------------------------------------------------- /assets/images/users/user-60f37eef65065.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aminyasser/twitter-clone/HEAD/assets/images/users/user-60f37eef65065.jpg -------------------------------------------------------------------------------- /assets/images/users/user-60f37eef6506e.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aminyasser/twitter-clone/HEAD/assets/images/users/user-60f37eef6506e.jpg -------------------------------------------------------------------------------- /assets/css/font/fonts/fontawesome-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aminyasser/twitter-clone/HEAD/assets/css/font/fonts/fontawesome-webfont.eot -------------------------------------------------------------------------------- /assets/css/font/fonts/fontawesome-webfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aminyasser/twitter-clone/HEAD/assets/css/font/fonts/fontawesome-webfont.ttf -------------------------------------------------------------------------------- /assets/css/font/fonts/fontawesome-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aminyasser/twitter-clone/HEAD/assets/css/font/fonts/fontawesome-webfont.woff -------------------------------------------------------------------------------- /assets/images/tweets/tweet-6077e54477f73.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aminyasser/twitter-clone/HEAD/assets/images/tweets/tweet-6077e54477f73.jpeg -------------------------------------------------------------------------------- /assets/images/tweets/tweet-60b1030158fd5.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aminyasser/twitter-clone/HEAD/assets/images/tweets/tweet-60b1030158fd5.jpeg -------------------------------------------------------------------------------- /assets/css/font/fonts/fontawesome-webfont.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aminyasser/twitter-clone/HEAD/assets/css/font/fonts/fontawesome-webfont.woff2 -------------------------------------------------------------------------------- /assets/css/font/less/fixed-width.less: -------------------------------------------------------------------------------- 1 | // Fixed Width Icons 2 | // ------------------------- 3 | .@{fa-css-prefix}-fw { 4 | width: (18em / 14); 5 | text-align: center; 6 | } 7 | -------------------------------------------------------------------------------- /assets/css/font/scss/_fixed-width.scss: -------------------------------------------------------------------------------- 1 | // Fixed Width Icons 2 | // ------------------------- 3 | .#{$fa-css-prefix}-fw { 4 | width: (18em / 14); 5 | text-align: center; 6 | } 7 | -------------------------------------------------------------------------------- /core/classes/validation/ValidInterface.php: -------------------------------------------------------------------------------- 1 | li { position: relative; } 9 | } 10 | .@{fa-css-prefix}-li { 11 | position: absolute; 12 | left: -@fa-li-width; 13 | width: @fa-li-width; 14 | top: (2em / 14); 15 | text-align: center; 16 | &.@{fa-css-prefix}-lg { 17 | left: (-@fa-li-width + (4em / 14)); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /assets/css/font/scss/_list.scss: -------------------------------------------------------------------------------- 1 | // List Icons 2 | // ------------------------- 3 | 4 | .#{$fa-css-prefix}-ul { 5 | padding-left: 0; 6 | margin-left: $fa-li-width; 7 | list-style-type: none; 8 | > li { position: relative; } 9 | } 10 | .#{$fa-css-prefix}-li { 11 | position: absolute; 12 | left: -$fa-li-width; 13 | width: $fa-li-width; 14 | top: (2em / 14); 15 | text-align: center; 16 | &.#{$fa-css-prefix}-lg { 17 | left: -$fa-li-width + (4em / 14); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /assets/css/font/scss/font-awesome.scss: -------------------------------------------------------------------------------- 1 | /*! 2 | * Font Awesome 4.5.0 by @davegandy - http://fontawesome.io - @fontawesome 3 | * License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License) 4 | */ 5 | 6 | @import "variables"; 7 | @import "mixins"; 8 | @import "path"; 9 | @import "core"; 10 | @import "larger"; 11 | @import "fixed-width"; 12 | @import "list"; 13 | @import "bordered-pulled"; 14 | @import "animated"; 15 | @import "rotated-flipped"; 16 | @import "stacked"; 17 | @import "icons"; 18 | -------------------------------------------------------------------------------- /assets/css/font/less/core.less: -------------------------------------------------------------------------------- 1 | // Base Class Definition 2 | // ------------------------- 3 | 4 | .@{fa-css-prefix} { 5 | display: inline-block; 6 | font: normal normal normal @fa-font-size-base/@fa-line-height-base FontAwesome; // shortening font declaration 7 | font-size: inherit; // can't have font-size inherit on line above, so need to override 8 | text-rendering: auto; // optimizelegibility throws things off #1094 9 | -webkit-font-smoothing: antialiased; 10 | -moz-osx-font-smoothing: grayscale; 11 | 12 | } 13 | -------------------------------------------------------------------------------- /assets/js/search.js: -------------------------------------------------------------------------------- 1 | $(function(){ 2 | 3 | // the function pass the post var without form to search.php 4 | $('.search-input').keyup(function(){ 5 | var search = $(this).val(); 6 | $.post('core/ajax/search.php', {search:search}, function(data){ 7 | $('.search-result').html(data); 8 | if(search == ""){ 9 | $('.search-result').html(""); 10 | $('.search-result li').click(function(){ 11 | $('.search-result li').hide(); 12 | }); 13 | } 14 | }); 15 | }); 16 | 17 | 18 | 19 | 20 | }); -------------------------------------------------------------------------------- /core/init.php: -------------------------------------------------------------------------------- 1 | name = $name; 13 | $this->value = $value; 14 | 15 | } 16 | public function validate() { 17 | if (strlen($this->value) == 0) { 18 | return "$this->name is required"; 19 | } 20 | 21 | return ''; 22 | } 23 | } -------------------------------------------------------------------------------- /core/classes/validation/Str.php: -------------------------------------------------------------------------------- 1 | name = $name; 13 | $this->value = $value; 14 | 15 | } 16 | public function validate() { 17 | if (!is_string($this->value)) { 18 | return "$this->name must be string"; 19 | } 20 | 21 | return ''; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /core/classes/validation/Max20.php: -------------------------------------------------------------------------------- 1 | name = $name; 13 | $this->value = $value; 14 | 15 | } 16 | public function validate() { 17 | if (strlen($this->value) > 20) { 18 | return "$this->name must be less than 20 chars"; 19 | } 20 | 21 | return ''; 22 | } 23 | } -------------------------------------------------------------------------------- /core/classes/validation/Min5.php: -------------------------------------------------------------------------------- 1 | name = $name; 13 | $this->value = $value; 14 | 15 | } 16 | public function validate() { 17 | if (strlen($this->value) < 5) { 18 | return "$this->name must between 5 and 20 length"; 19 | } 20 | 21 | return ''; 22 | } 23 | } -------------------------------------------------------------------------------- /core/classes/validation/Max100.php: -------------------------------------------------------------------------------- 1 | name = $name; 13 | $this->value = $value; 14 | 15 | } 16 | public function validate() { 17 | if (strlen($this->value) > 100) { 18 | return "$this->name must be less than 100 chars"; 19 | } 20 | 21 | return ''; 22 | } 23 | } -------------------------------------------------------------------------------- /core/classes/validation/MaxTweet.php: -------------------------------------------------------------------------------- 1 | name = $name; 13 | $this->value = $value; 14 | 15 | } 16 | public function validate() { 17 | if (strlen($this->value) > 140) { 18 | return "$this->name must be not more than 140"; 19 | } 20 | 21 | return ''; 22 | } 23 | } -------------------------------------------------------------------------------- /assets/css/font/less/font-awesome.less: -------------------------------------------------------------------------------- 1 | /*! 2 | * Font Awesome 4.5.0 by @davegandy - http://fontawesome.io - @fontawesome 3 | * License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License) 4 | */ 5 | 6 | @import "variables.less"; 7 | @import "mixins.less"; 8 | @import "path.less"; 9 | @import "core.less"; 10 | @import "larger.less"; 11 | @import "fixed-width.less"; 12 | @import "list.less"; 13 | @import "bordered-pulled.less"; 14 | @import "animated.less"; 15 | @import "rotated-flipped.less"; 16 | @import "stacked.less"; 17 | @import "icons.less"; 18 | -------------------------------------------------------------------------------- /core/database/connection.php: -------------------------------------------------------------------------------- 1 | setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); 13 | // // echo "Connected successfully"; 14 | // } catch(PDOException $e) { 15 | // echo "Connection failed: " . $e->getMessage(); 16 | // } 17 | -------------------------------------------------------------------------------- /core/classes/validation/Email.php: -------------------------------------------------------------------------------- 1 | name = $name; 13 | $this->value = $value; 14 | 15 | } 16 | public function validate() { 17 | if (!filter_var($this->value, FILTER_VALIDATE_EMAIL) ) { 18 | return "$this->name is not valid email"; 19 | } 20 | 21 | return ''; 22 | } 23 | } -------------------------------------------------------------------------------- /core/classes/validation/Numeric.php: -------------------------------------------------------------------------------- 1 | name = $name; 13 | $this->value = $value; 14 | 15 | } 16 | public function validate() { 17 | if (strlen($this->value) > 0 && !is_numeric($this->value)) { 18 | return "$this->name must be number"; 19 | } 20 | 21 | return ''; 22 | } 23 | } -------------------------------------------------------------------------------- /core/classes/validation/RequireImage.php: -------------------------------------------------------------------------------- 1 | name = $name; 13 | $this->value = $value; 14 | 15 | } 16 | public function validate() { 17 | if (strlen($this->value['name']) == 0) { 18 | return "$this->name is Required"; 19 | } 20 | 21 | return ''; 22 | } 23 | } 24 | 25 | -------------------------------------------------------------------------------- /assets/css/font/less/stacked.less: -------------------------------------------------------------------------------- 1 | // Stacked Icons 2 | // ------------------------- 3 | 4 | .@{fa-css-prefix}-stack { 5 | position: relative; 6 | display: inline-block; 7 | width: 2em; 8 | height: 2em; 9 | line-height: 2em; 10 | vertical-align: middle; 11 | } 12 | .@{fa-css-prefix}-stack-1x, .@{fa-css-prefix}-stack-2x { 13 | position: absolute; 14 | left: 0; 15 | width: 100%; 16 | text-align: center; 17 | } 18 | .@{fa-css-prefix}-stack-1x { line-height: inherit; } 19 | .@{fa-css-prefix}-stack-2x { font-size: 2em; } 20 | .@{fa-css-prefix}-inverse { color: @fa-inverse; } 21 | -------------------------------------------------------------------------------- /assets/css/font/scss/_stacked.scss: -------------------------------------------------------------------------------- 1 | // Stacked Icons 2 | // ------------------------- 3 | 4 | .#{$fa-css-prefix}-stack { 5 | position: relative; 6 | display: inline-block; 7 | width: 2em; 8 | height: 2em; 9 | line-height: 2em; 10 | vertical-align: middle; 11 | } 12 | .#{$fa-css-prefix}-stack-1x, .#{$fa-css-prefix}-stack-2x { 13 | position: absolute; 14 | left: 0; 15 | width: 100%; 16 | text-align: center; 17 | } 18 | .#{$fa-css-prefix}-stack-1x { line-height: inherit; } 19 | .#{$fa-css-prefix}-stack-2x { font-size: 2em; } 20 | .#{$fa-css-prefix}-inverse { color: $fa-inverse; } 21 | -------------------------------------------------------------------------------- /core/classes/validation/Image.php: -------------------------------------------------------------------------------- 1 | name = $name; 13 | $this->value = $value; 14 | 15 | } 16 | public function validate() { 17 | 18 | $types = ['image/jpg' ,'image/jpeg' ,'image/png' , 'image/gif' ]; 19 | if (strlen($this->value['name']) > 0 && !in_array($this->value['type'], $types)) { 20 | return "$this->name must be image"; 21 | } 22 | 23 | return ''; 24 | } 25 | } 26 | 27 | -------------------------------------------------------------------------------- /assets/images/loading.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /assets/css/font/less/bordered-pulled.less: -------------------------------------------------------------------------------- 1 | // Bordered & Pulled 2 | // ------------------------- 3 | 4 | .@{fa-css-prefix}-border { 5 | padding: .2em .25em .15em; 6 | border: solid .08em @fa-border-color; 7 | border-radius: .1em; 8 | } 9 | 10 | .@{fa-css-prefix}-pull-left { float: left; } 11 | .@{fa-css-prefix}-pull-right { float: right; } 12 | 13 | .@{fa-css-prefix} { 14 | &.@{fa-css-prefix}-pull-left { margin-right: .3em; } 15 | &.@{fa-css-prefix}-pull-right { margin-left: .3em; } 16 | } 17 | 18 | /* Deprecated as of 4.4.0 */ 19 | .pull-right { float: right; } 20 | .pull-left { float: left; } 21 | 22 | .@{fa-css-prefix} { 23 | &.pull-left { margin-right: .3em; } 24 | &.pull-right { margin-left: .3em; } 25 | } 26 | -------------------------------------------------------------------------------- /handle/handleDeleteCover.php: -------------------------------------------------------------------------------- 1 | imgCover; 13 | 14 | if ($currentCover !== 'cover.png') 15 | unlink('../assets/images/users/' . $currentCover); 16 | 17 | 18 | 19 | $data = [ 20 | 'imgCover' => 'cover.png' , 21 | ]; 22 | 23 | $sign= User::update('users' , $_SESSION['user_id'], $data); 24 | 25 | 26 | if ($sign == true) { 27 | header('location: ../' . $username); 28 | } else header('location: ../' . $username); 29 | 30 | 31 | 32 | 33 | ?> -------------------------------------------------------------------------------- /assets/css/font/scss/_bordered-pulled.scss: -------------------------------------------------------------------------------- 1 | // Bordered & Pulled 2 | // ------------------------- 3 | 4 | .#{$fa-css-prefix}-border { 5 | padding: .2em .25em .15em; 6 | border: solid .08em $fa-border-color; 7 | border-radius: .1em; 8 | } 9 | 10 | .#{$fa-css-prefix}-pull-left { float: left; } 11 | .#{$fa-css-prefix}-pull-right { float: right; } 12 | 13 | .#{$fa-css-prefix} { 14 | &.#{$fa-css-prefix}-pull-left { margin-right: .3em; } 15 | &.#{$fa-css-prefix}-pull-right { margin-left: .3em; } 16 | } 17 | 18 | /* Deprecated as of 4.4.0 */ 19 | .pull-right { float: right; } 20 | .pull-left { float: left; } 21 | 22 | .#{$fa-css-prefix} { 23 | &.pull-left { margin-right: .3em; } 24 | &.pull-right { margin-left: .3em; } 25 | } 26 | -------------------------------------------------------------------------------- /assets/css/font/less/rotated-flipped.less: -------------------------------------------------------------------------------- 1 | // Rotated & Flipped Icons 2 | // ------------------------- 3 | 4 | .@{fa-css-prefix}-rotate-90 { .fa-icon-rotate(90deg, 1); } 5 | .@{fa-css-prefix}-rotate-180 { .fa-icon-rotate(180deg, 2); } 6 | .@{fa-css-prefix}-rotate-270 { .fa-icon-rotate(270deg, 3); } 7 | 8 | .@{fa-css-prefix}-flip-horizontal { .fa-icon-flip(-1, 1, 0); } 9 | .@{fa-css-prefix}-flip-vertical { .fa-icon-flip(1, -1, 2); } 10 | 11 | // Hook for IE8-9 12 | // ------------------------- 13 | 14 | :root .@{fa-css-prefix}-rotate-90, 15 | :root .@{fa-css-prefix}-rotate-180, 16 | :root .@{fa-css-prefix}-rotate-270, 17 | :root .@{fa-css-prefix}-flip-horizontal, 18 | :root .@{fa-css-prefix}-flip-vertical { 19 | filter: none; 20 | } 21 | -------------------------------------------------------------------------------- /assets/css/font/scss/_rotated-flipped.scss: -------------------------------------------------------------------------------- 1 | // Rotated & Flipped Icons 2 | // ------------------------- 3 | 4 | .#{$fa-css-prefix}-rotate-90 { @include fa-icon-rotate(90deg, 1); } 5 | .#{$fa-css-prefix}-rotate-180 { @include fa-icon-rotate(180deg, 2); } 6 | .#{$fa-css-prefix}-rotate-270 { @include fa-icon-rotate(270deg, 3); } 7 | 8 | .#{$fa-css-prefix}-flip-horizontal { @include fa-icon-flip(-1, 1, 0); } 9 | .#{$fa-css-prefix}-flip-vertical { @include fa-icon-flip(1, -1, 2); } 10 | 11 | // Hook for IE8-9 12 | // ------------------------- 13 | 14 | :root .#{$fa-css-prefix}-rotate-90, 15 | :root .#{$fa-css-prefix}-rotate-180, 16 | :root .#{$fa-css-prefix}-rotate-270, 17 | :root .#{$fa-css-prefix}-flip-horizontal, 18 | :root .#{$fa-css-prefix}-flip-vertical { 19 | filter: none; 20 | } 21 | -------------------------------------------------------------------------------- /assets/css/font/less/path.less: -------------------------------------------------------------------------------- 1 | /* FONT PATH 2 | * -------------------------- */ 3 | 4 | @font-face { 5 | font-family: 'FontAwesome'; 6 | src: url('@{fa-font-path}/fontawesome-webfont.eot?v=@{fa-version}'); 7 | src: url('@{fa-font-path}/fontawesome-webfont.eot?#iefix&v=@{fa-version}') format('embedded-opentype'), 8 | url('@{fa-font-path}/fontawesome-webfont.woff2?v=@{fa-version}') format('woff2'), 9 | url('@{fa-font-path}/fontawesome-webfont.woff?v=@{fa-version}') format('woff'), 10 | url('@{fa-font-path}/fontawesome-webfont.ttf?v=@{fa-version}') format('truetype'), 11 | url('@{fa-font-path}/fontawesome-webfont.svg?v=@{fa-version}#fontawesomeregular') format('svg'); 12 | // src: url('@{fa-font-path}/FontAwesome.otf') format('opentype'); // used when developing fonts 13 | font-weight: normal; 14 | font-style: normal; 15 | } 16 | -------------------------------------------------------------------------------- /assets/css/font/scss/_path.scss: -------------------------------------------------------------------------------- 1 | /* FONT PATH 2 | * -------------------------- */ 3 | 4 | @font-face { 5 | font-family: 'FontAwesome'; 6 | src: url('#{$fa-font-path}/fontawesome-webfont.eot?v=#{$fa-version}'); 7 | src: url('#{$fa-font-path}/fontawesome-webfont.eot?#iefix&v=#{$fa-version}') format('embedded-opentype'), 8 | url('#{$fa-font-path}/fontawesome-webfont.woff2?v=#{$fa-version}') format('woff2'), 9 | url('#{$fa-font-path}/fontawesome-webfont.woff?v=#{$fa-version}') format('woff'), 10 | url('#{$fa-font-path}/fontawesome-webfont.ttf?v=#{$fa-version}') format('truetype'), 11 | url('#{$fa-font-path}/fontawesome-webfont.svg?v=#{$fa-version}#fontawesomeregular') format('svg'); 12 | // src: url('#{$fa-font-path}/FontAwesome.otf') format('opentype'); // used when developing fonts 13 | font-weight: normal; 14 | font-style: normal; 15 | } 16 | -------------------------------------------------------------------------------- /assets/css/font/less/animated.less: -------------------------------------------------------------------------------- 1 | // Animated Icons 2 | // -------------------------- 3 | 4 | .@{fa-css-prefix}-spin { 5 | -webkit-animation: fa-spin 2s infinite linear; 6 | animation: fa-spin 2s infinite linear; 7 | } 8 | 9 | .@{fa-css-prefix}-pulse { 10 | -webkit-animation: fa-spin 1s infinite steps(8); 11 | animation: fa-spin 1s infinite steps(8); 12 | } 13 | 14 | @-webkit-keyframes fa-spin { 15 | 0% { 16 | -webkit-transform: rotate(0deg); 17 | transform: rotate(0deg); 18 | } 19 | 100% { 20 | -webkit-transform: rotate(359deg); 21 | transform: rotate(359deg); 22 | } 23 | } 24 | 25 | @keyframes fa-spin { 26 | 0% { 27 | -webkit-transform: rotate(0deg); 28 | transform: rotate(0deg); 29 | } 30 | 100% { 31 | -webkit-transform: rotate(359deg); 32 | transform: rotate(359deg); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /assets/css/font/scss/_animated.scss: -------------------------------------------------------------------------------- 1 | // Spinning Icons 2 | // -------------------------- 3 | 4 | .#{$fa-css-prefix}-spin { 5 | -webkit-animation: fa-spin 2s infinite linear; 6 | animation: fa-spin 2s infinite linear; 7 | } 8 | 9 | .#{$fa-css-prefix}-pulse { 10 | -webkit-animation: fa-spin 1s infinite steps(8); 11 | animation: fa-spin 1s infinite steps(8); 12 | } 13 | 14 | @-webkit-keyframes fa-spin { 15 | 0% { 16 | -webkit-transform: rotate(0deg); 17 | transform: rotate(0deg); 18 | } 19 | 100% { 20 | -webkit-transform: rotate(359deg); 21 | transform: rotate(359deg); 22 | } 23 | } 24 | 25 | @keyframes fa-spin { 26 | 0% { 27 | -webkit-transform: rotate(0deg); 28 | transform: rotate(0deg); 29 | } 30 | 100% { 31 | -webkit-transform: rotate(359deg); 32 | transform: rotate(359deg); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /assets/images/twitter.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /includes/login.php: -------------------------------------------------------------------------------- 1 | 5 |
6 | 7 | 8 | Forgot password? 9 | 10 |
11 | 16 |
'.$error.'
17 | '; 18 | 19 | } 20 | unset($_SESSION['errors']); 21 | 22 | 23 | 24 | } 25 | 26 | ?> 27 |
28 |
29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /core/classes/image.php: -------------------------------------------------------------------------------- 1 | name =$img['name']; 13 | $this->tmp_name =$img['tmp_name']; 14 | 15 | $ext = pathinfo($this->name)['extension']; 16 | 17 | if ($tweet != null) { 18 | $this->new_name = 'tweet-' . uniqid() . '.' . $ext ; 19 | $this->sign = true; 20 | } else $this->new_name = 'user-' . uniqid() . '.' . $ext ; 21 | 22 | 23 | } 24 | 25 | 26 | public function upload () { 27 | if ($this->sign == true) 28 | move_uploaded_file($this->tmp_name , '../assets/images/tweets/' . $this->new_name); 29 | else move_uploaded_file($this->tmp_name , '../assets/images/users/' . $this->new_name); 30 | } 31 | 32 | 33 | 34 | } -------------------------------------------------------------------------------- /assets/css/font/less/mixins.less: -------------------------------------------------------------------------------- 1 | // Mixins 2 | // -------------------------- 3 | 4 | .fa-icon() { 5 | display: inline-block; 6 | font: normal normal normal @fa-font-size-base/@fa-line-height-base FontAwesome; // shortening font declaration 7 | font-size: inherit; // can't have font-size inherit on line above, so need to override 8 | text-rendering: auto; // optimizelegibility throws things off #1094 9 | -webkit-font-smoothing: antialiased; 10 | -moz-osx-font-smoothing: grayscale; 11 | 12 | } 13 | 14 | .fa-icon-rotate(@degrees, @rotation) { 15 | filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=@rotation); 16 | -webkit-transform: rotate(@degrees); 17 | -ms-transform: rotate(@degrees); 18 | transform: rotate(@degrees); 19 | } 20 | 21 | .fa-icon-flip(@horiz, @vert, @rotation) { 22 | filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=@rotation, mirror=1); 23 | -webkit-transform: scale(@horiz, @vert); 24 | -ms-transform: scale(@horiz, @vert); 25 | transform: scale(@horiz, @vert); 26 | } 27 | -------------------------------------------------------------------------------- /core/ajax/search.php: -------------------------------------------------------------------------------- 1 | 12 | 31 | '; 32 | } 33 | } 34 | 35 | 36 | 37 | ?> -------------------------------------------------------------------------------- /assets/css/font/scss/_mixins.scss: -------------------------------------------------------------------------------- 1 | // Mixins 2 | // -------------------------- 3 | 4 | @mixin fa-icon() { 5 | display: inline-block; 6 | font: normal normal normal #{$fa-font-size-base}/#{$fa-line-height-base} FontAwesome; // shortening font declaration 7 | font-size: inherit; // can't have font-size inherit on line above, so need to override 8 | text-rendering: auto; // optimizelegibility throws things off #1094 9 | -webkit-font-smoothing: antialiased; 10 | -moz-osx-font-smoothing: grayscale; 11 | 12 | } 13 | 14 | @mixin fa-icon-rotate($degrees, $rotation) { 15 | filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=#{$rotation}); 16 | -webkit-transform: rotate($degrees); 17 | -ms-transform: rotate($degrees); 18 | transform: rotate($degrees); 19 | } 20 | 21 | @mixin fa-icon-flip($horiz, $vert, $rotation) { 22 | filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=#{$rotation}); 23 | -webkit-transform: scale($horiz, $vert); 24 | -ms-transform: scale($horiz, $vert); 25 | transform: scale($horiz, $vert); 26 | } 27 | -------------------------------------------------------------------------------- /core/classes/connection.php: -------------------------------------------------------------------------------- 1 | setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); 22 | 23 | // echo "Connected successfully"; 24 | } catch(PDOException $e) { 25 | echo "Connection failed: " . $e->getMessage(); 26 | } 27 | 28 | return $conn; 29 | } 30 | 31 | } 32 | 33 | 34 | -------------------------------------------------------------------------------- /core/ajax/getHashtag.php: -------------------------------------------------------------------------------- 1 | #'.$hashtag->hashtag.''; 14 | } 15 | } 16 | 17 | if(substr($mention, 0,1) === '@'){ 18 | $mention = str_replace('@', '', $mention); 19 | $mentions = Tweet::getMention($mention); 20 | foreach ($mentions as $mention) { 21 | echo '
  • 31 |
  • '; 32 | } 33 | 34 | } 35 | } 36 | } 37 | 38 | ?> 39 | -------------------------------------------------------------------------------- /handle/handlelogin.php: -------------------------------------------------------------------------------- 1 | rules('email' , $email , ['required' , 'email']); 23 | $v->rules('password' , $password , ['required' , 'string']); 24 | $errors = $v->errors; 25 | if($errors == []) { 26 | User::login($email , $password); 27 | if(User::login($email , $password) === false ) { 28 | // $errors = 'the email or password is not correct';/ 29 | $_SESSION['errors'] = ['the email or password is not correct']; 30 | header('location: ../index.php') ; 31 | } 32 | 33 | } else { 34 | $_SESSION['errors'] = $errors; 35 | header('location: ../index.php') ; 36 | } 37 | 38 | 39 | 40 | 41 | 42 | } else header('location: ../index.php') ; 43 | 44 | 45 | 46 | 47 | ?> -------------------------------------------------------------------------------- /assets/js/hashtag.js: -------------------------------------------------------------------------------- 1 | $(function(){ 2 | var regex = /[#|@](\w+)$/ig; 3 | 4 | $(document).on('keyup','.text-whathappen', function(){ 5 | var content = $.trim($(this).val()); 6 | var text = content.match(regex); 7 | var max = 140; 8 | 9 | if(text != null){ 10 | var dataString = 'hashtag='+text; 11 | 12 | $.ajax({ 13 | type: "POST", 14 | url: "core/ajax/getHashtag.php", 15 | data: dataString, 16 | cache: false, 17 | success: function(data){ 18 | $('.hash-box ul').html(data); 19 | $('.hash-box li').click(function(){ 20 | var value = $.trim($(this).find('.getValue').text()); 21 | var oldContent = $('.text-whathappen').val(); 22 | var newContent = oldContent.replace(regex, ""); 23 | 24 | $('.text-whathappen').val(newContent+value+' '); 25 | $('.hash-box li').hide(); 26 | $('.text-whathappen').focus(); 27 | 28 | $('#count').text(max - content.length); 29 | }) 30 | } 31 | }) 32 | 33 | 34 | }else{ 35 | $('.hash-box li').hide(); 36 | } 37 | 38 | $('#count').text(max - content.length); 39 | 40 | if(content.length >= max){ 41 | $('#count').css('color','#f00'); 42 | 43 | }else{ 44 | $('#count').css('color','#1DA1F2'); 45 | } 46 | }); 47 | }); 48 | -------------------------------------------------------------------------------- /core/ajax/follow.php: -------------------------------------------------------------------------------- 1 | $following_id , 12 | 'notify_from' => $user_id , 13 | 'target' => 0, 14 | 'type' => 'follow' , 15 | 'time' => date("Y-m-d H:i:s") , 16 | 'count' => '0' , 17 | 'status' => '0' 18 | ]; 19 | 20 | Tweet::create('notifications' , $data_notify); 21 | 22 | } 23 | // end 24 | $data = [ 25 | 'follower_id' => $user_id , 26 | 'following_id' => $following_id , 27 | 'time' => date("Y-m-d H:i:s") 28 | ]; 29 | Follow::create('follow' , $data); 30 | 31 | echo Follow::countFollowers($following_id); 32 | } 33 | if(isset($_POST['unfollow']) && !empty($_POST['unfollow'])){ 34 | $following_id = $_POST['unfollow']; 35 | 36 | if($following_id != $user_id) { 37 | $data = [ 38 | 'notify_for' => $following_id , 39 | 'notify_from' => $user_id , 40 | 'target' => 0 , 41 | 'type' => "'follow'" , 42 | ]; 43 | 44 | Tweet::delete('notifications' , $data); 45 | 46 | } 47 | 48 | 49 | Follow::delete('follow' , ['following_id' => $following_id , 'follower_id' => $user_id]); 50 | echo Follow::countFollowers($following_id); 51 | } 52 | -------------------------------------------------------------------------------- /handle/handleChangePassword.php: -------------------------------------------------------------------------------- 1 | rules('New Password' , $new_password , ['required' , 'string' , 'min:5']); 25 | $errors = $v->errors; 26 | $old_password = md5($old_password); 27 | if ($old_password == $user->password) { 28 | 29 | if ($errors != []) { 30 | $_SESSION['errors_password'] = $errors ; 31 | header('location: ../account.php') ; 32 | } else if ($new_password != $ver_password) { 33 | $_SESSION['errors_password'] = ['The two passwords are not the same'] ; 34 | header('location: ../account.php') ; 35 | } else { 36 | $new_password = md5($new_password); 37 | $data = [ 38 | 'password' => $new_password , 39 | ]; 40 | 41 | $sign= User::update('users' , $_SESSION['user_id'], $data); 42 | header('location: ../' . $username); 43 | 44 | } 45 | 46 | } else { $_SESSION['errors_password'] = ['The old password is wrong'] ; 47 | header('location: ../account.php') ; 48 | } 49 | 50 | 51 | } else { 52 | header('location: ../account.php'); 53 | } -------------------------------------------------------------------------------- /core/ajax/like.php: -------------------------------------------------------------------------------- 1 | user_id; 9 | $get_id = $_POST['user_id']; 10 | date_default_timezone_set("Africa/Cairo"); 11 | if($for_user != $user_id) { 12 | $data = [ 13 | 'notify_for' => $for_user , 14 | 'notify_from' => $user_id , 15 | 'target' => $tweet_id , 16 | 'type' => 'like' , 17 | 'time' => date("Y-m-d H:i:s") , 18 | 'count' => '0' , 19 | 'status' => '0' 20 | ]; 21 | 22 | Tweet::create('notifications' , $data); 23 | 24 | } 25 | 26 | 27 | User::create('likes', array('user_id' => $user_id, 'post_id' => $tweet_id)); 28 | 29 | echo `
    30 | `+ Tweet::countLikes($tweet_id) +` 31 |
    ` ; 32 | } 33 | if(isset($_POST['unlike']) && !empty($_POST['unlike'])){ 34 | $user_id = $_SESSION['user_id']; 35 | $tweet_id = $_POST['unlike']; 36 | $get_id = $_POST['user_id']; 37 | $for_user = Tweet::getData($tweet_id)->user_id; 38 | 39 | 40 | if($for_user != $user_id) { 41 | $data = [ 42 | 'notify_for' => $for_user , 43 | 'notify_from' => $user_id , 44 | 'target' => $tweet_id , 45 | 'type' => "'like'" , 46 | ]; 47 | 48 | Tweet::delete('notifications' , $data); 49 | 50 | } 51 | Tweet::unLike($user_id, $tweet_id); 52 | 53 | echo `
    54 | `+ Tweet::countLikes($tweet_id) +` 55 |
    ` ; 56 | } 57 | 58 | if(isset($_POST['file'])){ 59 | $getFromT->uploadImage($_POST['files']); 60 | } 61 | 62 | 63 | ?> -------------------------------------------------------------------------------- /handle/handleAccountSetting.php: -------------------------------------------------------------------------------- 1 | rules('username' , $username , ['required' , 'string' , 'max:20']); 21 | $v->rules('email' , $email , ['required' , 'email']); 22 | $errors = $v->errors; 23 | 24 | if ($errors == []) { 25 | 26 | if(User::checkEmail($email) === true && $email != $user->email) { 27 | $_SESSION['errors_account'] = ['This email is already use']; 28 | header('location: ../account.php') ; 29 | } else if (User::checkUserName($username) === true && $username != $user->username) { 30 | $_SESSION['errors_account'] = ['This username is already use']; 31 | header('location: ../account.php') ; 32 | } else if (preg_match("/[^a-zA-Z0-9\!]/" , $username)) { 33 | $_SESSION['errors_account'] = ['Only Chars and Numbers allowed in username']; 34 | header('location: ../account.php') ; 35 | } else { 36 | $data = [ 37 | 'email' => $email , 38 | 'username' => $username 39 | ]; 40 | 41 | $sign= User::update('users' , $_SESSION['user_id'], $data); 42 | header('location: ../account.php') ; 43 | } 44 | 45 | } else { 46 | 47 | $_SESSION['errors_account'] = $errors; 48 | header('location: ../account.php'); 49 | 50 | } 51 | 52 | 53 | } else header('location: ../home.php'); 54 | 55 | ?> -------------------------------------------------------------------------------- /assets/js/photo.js: -------------------------------------------------------------------------------- 1 | $(function(){ 2 | 3 | $glo = this; 4 | $(document).on('change','#file-input', function(e){ 5 | 6 | if (this.files && this.files[0]) { 7 | let reader = new FileReader(); 8 | reader.onload=function(e){ 9 | let image = document.querySelector("#preview-user"); 10 | image.src = e.target.result; 11 | } 12 | reader.readAsDataURL(this.files[0]); 13 | } 14 | 15 | }); 16 | 17 | $(document).on('change','#cover-input', function(e){ 18 | 19 | if (this.files && this.files[0]) { 20 | let reader = new FileReader(); 21 | reader.onload=function(e){ 22 | let image = document.querySelector("#preview-cover"); 23 | image.src = e.target.result; 24 | } 25 | reader.readAsDataURL(this.files[0]); 26 | } 27 | 28 | }); 29 | 30 | $(document).on('change','#tweet_img', function(e){ 31 | console.log(this); 32 | $glo = this; 33 | if (this.files && this.files[0]) { 34 | let reader = new FileReader(); 35 | reader.onload=function(e){ 36 | let container = document.querySelector(".upload-photo"); 37 | container.style.display = "block"; 38 | let image = document.querySelector(".img-upload-tmp"); 39 | image.src = e.target.result; 40 | } 41 | // alert("all right"); 42 | reader.readAsDataURL(this.files[0]); 43 | this.files = null; 44 | } 45 | 46 | 47 | }); 48 | 49 | $(document).on('click','.upload-delete', function(e){ 50 | 51 | let container = document.querySelector(".upload-photo"); 52 | container.style.display = "none"; 53 | let control =$("#tweet_img"); 54 | control.val(""); 55 | }); 56 | }); -------------------------------------------------------------------------------- /includes/signup-form.php: -------------------------------------------------------------------------------- 1 | 4 | 5 |
    6 | 7 | 14 | 15 |

    18 |
    19 | 20 |
    21 |
    22 | 23 |
    24 |
    25 | 26 | 27 | 28 |
    29 |
    30 | 31 | 32 |
    33 |
    34 | 35 |
    36 | 37 |
    -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Twitter Twitter Clone ([Click to try 🚀](https://sn-amin.000webhostapp.com/)) 2 | 3 | Bulit PHP **_Twitter Clone_** IN OOP style and using MYSQL Database. AJAX and Jquery for requests without reloading like Follow/unfollow, like, Search users, Show popups like comment , User lists, etc. 4 | 5 | 6 | ## Features 7 | 8 | - Sign in / Sign UP 9 | - Post Image or Normal Tweet. 10 | - Retweet or Qoute Tweet (You can qoute the qouted tweet). 11 | - Like Tweet. 12 | - Add Comment and reply to the comment (Nested Comments). 13 | - Mention User in Tweet or add hashtag to your tweet. 14 | - Follow/Unfollow user. 15 | - Get Notification when any previous action happened. 16 | - Change Username/Password/Email From Settings. 17 | - Search users by name and username. 18 | - Edit Profile Like: (Change :avatar/username/cover etc). 19 | 20 | ## Running locally 21 | 22 | - Create New Database then import twitter.sql file on it. 23 | - go to PATH **core/classes/connection.php** and add your database info. 24 | 25 | ```php 26 | protected static $servername = "localhost"; 27 | protected static $db_name="twitter"; 28 | protected static $username = "root"; 29 | protected static $password = ""; 30 | ``` 31 | then the project is ready to run in localhost! 32 | 33 | ## 📷 UI 34 | 35 | 36 | ### Index 37 | ![Index](screenshots/Index.png) 38 | 39 | ### Home 40 | ![Home](screenshots/Home.png) 41 | 42 | ### Tweet and Comments 43 | ![Post](screenshots/Inner-Post.png) 44 | 45 | ### Profile 46 | ![Profile](screenshots/Profile.png) 47 | 48 | ### Notifications 49 | ![Movie](screenshots/Notifications.png) 50 | 51 | ### Edit Account 52 | ![Edit](screenshots/Edit.png) 53 | 54 | ### Preview Image before Tweet 55 | ![Post](screenshots/Post.png) 56 | 57 | ### Users List (For following/likedby etc) 58 | ![Users](screenshots/Users.png) 59 | 60 | ### Setting 61 | ![Setting](screenshots/Setting.png) 62 | 63 | 64 | 65 | -------------------------------------------------------------------------------- /handle/handleSignUp.php: -------------------------------------------------------------------------------- 1 | rules('name' , $name , ['required' , 'string' , 'max:20']); 26 | $v->rules('username' , $username , ['required' , 'string' , 'max:20']); 27 | $v->rules('email' , $email , ['required' , 'email']); 28 | $v->rules('password' , $password , ['required' , 'string' , 'min:5']); 29 | $errors = $v->errors; 30 | 31 | if ($errors == []){ 32 | $username = str_replace(' ', '', $username); 33 | 34 | if(User::checkEmail($email) === true) { 35 | $_SESSION['errors_signup'] = ['This email is already use']; 36 | header('location: ../index.php') ; 37 | } else if (User::checkUserName($username) === true) { 38 | $_SESSION['errors_signup'] = ['This username is already use']; 39 | header('location: ../index.php') ; 40 | } else if (!preg_match("/^[a-zA-Z0-9_]*$/" , $username)) { 41 | $_SESSION['errors_signup'] = ['Only Chars and Numbers allowed in username']; 42 | header('location: ../index.php') ; 43 | } else { 44 | User::register($email , $password ,$name , $username); 45 | 46 | } 47 | } else { 48 | 49 | $_SESSION['errors_signup'] = $errors; 50 | header('location: ../index.php'); } 51 | 52 | } else header('location: ../index.php') ; 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | ?> -------------------------------------------------------------------------------- /assets/js/follow.js: -------------------------------------------------------------------------------- 1 | $(function(){ 2 | 3 | $(document).on('click','.follow-btn', function(e){ 4 | let follow_id = $(this).data('follow'); 5 | let user = $(this).data('user'); 6 | let profile = $(this).data('profile'); 7 | let following , followers; 8 | 9 | $button = $(this); 10 | if($button.hasClass('follow')) { 11 | // alert(follow_id); 12 | $.post('core/ajax/follow.php', {follow:follow_id}, function(data){ 13 | // alert(data); 14 | $button.addClass('following'); 15 | $button.removeClass('follow'); 16 | $button.text("Following"); 17 | if (user == profile && profile != null) { 18 | following = $('.count-following').html() ; 19 | following++; 20 | $('.count-following').html(following); 21 | } 22 | if (profile == null) 23 | $('.count-followers').html(data); 24 | 25 | // $counter.text(data); 26 | // $button.removeClass('retweeted').addClass('retweet'); 27 | // $c.removeClass('retweeted-i').addClass('retweet-i'); 28 | 29 | }); 30 | } else { 31 | $.post('core/ajax/follow.php', {unfollow:follow_id}, function(data){ 32 | $button.addClass('follow'); 33 | $button.removeClass('following'); 34 | $button.text("Follow"); 35 | 36 | if (user == profile && profile != null) { 37 | following = $('.count-following').html() ; 38 | following--; 39 | $('.count-following').html(following); 40 | } 41 | if (profile == null) 42 | $('.count-followers').html(data); 43 | 44 | 45 | // $counter.text(data); 46 | // $button.removeClass('retweeted').addClass('retweet'); 47 | // $c.removeClass('retweeted-i').addClass('retweet-i'); 48 | 49 | }); 50 | } 51 | 52 | 53 | 54 | }); 55 | 56 | $(document).on('mouseover' , '.following' , function(e) { 57 | 58 | $(this).html("Unfollow"); 59 | 60 | }); 61 | $(document).on('mouseout' , '.following' , function(e) { 62 | 63 | $(this).html("Following"); 64 | 65 | }); 66 | 67 | 68 | }); -------------------------------------------------------------------------------- /core/classes/validation/Validator.php: -------------------------------------------------------------------------------- 1 | validate(); 30 | } 31 | 32 | public function rules ($name , $value , array $rules) { 33 | foreach ($rules as $rule) { 34 | if ($rule == 'required') { 35 | $error = $this->makeValidation(new Required($name , $value)); 36 | } else if ($rule == 'string') { 37 | $error = $this->makeValidation(new Str($name , $value)); 38 | } else if ($rule == 'email') { 39 | $error = $this->makeValidation(new Email($name , $value)); 40 | } else if ($rule == 'max:20') { 41 | $error = $this->makeValidation(new Max20($name , $value)); 42 | } else if ($rule == 'max:100') { 43 | $error = $this->makeValidation(new Max100($name , $value)); 44 | } else if ($rule == 'max:14') { 45 | $error = $this->makeValidation(new MaxTweet($name , $value)); 46 | } else if ($rule == 'min:5') { 47 | $error = $this->makeValidation(new Min5($name , $value)); 48 | } else if ($rule == 'numeric') { 49 | $error = $this->makeValidation(new Numeric($name , $value)); 50 | }else if ($rule == 'required_image') { 51 | $error = $this->makeValidation(new RequireImage($name , $value)); 52 | } else if ($rule == 'image') { 53 | $error = $this->makeValidation(new Image($name , $value)); 54 | } else { 55 | $error = ''; 56 | } 57 | 58 | 59 | if ($error !== '') 60 | $this->errors[$name] =$error; 61 | // array_push($this->errors , $error); 62 | 63 | } 64 | } 65 | } -------------------------------------------------------------------------------- /handle/handleTweet.php: -------------------------------------------------------------------------------- 1 | rules('status' , $status , ['string' , 'max:14']); 25 | if ($img['name'] != '') 26 | $v->rules('image' , $img , ['image']); 27 | 28 | $errors = $v->errors; 29 | 30 | if ($errors == []) { 31 | 32 | if ($img['name'] != '') { 33 | $image = new Image($img , "tweet"); 34 | $tweetImg = $image->new_name ; 35 | 36 | } else $tweetImg = null; 37 | 38 | 39 | 40 | date_default_timezone_set("Africa/Cairo"); 41 | $data = [ 42 | 'user_id' => $_SESSION['user_id'] , 43 | 'post_on' => date("Y-m-d H:i:s") , 44 | ]; 45 | // create function can handle with all tables and return last inserted id 46 | $post_id = User::create('posts' , $data); 47 | 48 | $data_tweet = [ 49 | 'post_id' => $post_id , 50 | 'status' => $status , 51 | 'img' => $tweetImg 52 | ]; 53 | User::create('tweets' , $data_tweet); 54 | if ($img['name'] != '') { 55 | $image->upload(); } 56 | 57 | // notify users if mention! 58 | 59 | preg_match_all("/@+([a-zA-Z0-9_]+)/i", $status, $mention); 60 | $user_id = $_SESSION['user_id']; 61 | foreach($mention[1] as $men) { 62 | $id = User::getIdByUsername($men); 63 | if($id != $user_id ) { 64 | $data_notify = [ 65 | 'notify_for' => $id , 66 | 'notify_from' => $user_id , 67 | 'target' => $post_id , 68 | 'type' => 'mention' , 69 | 'time' => date("Y-m-d H:i:s") , 70 | 'count' => '0' , 71 | 'status' => '0' 72 | ]; 73 | 74 | Tweet::create('notifications' , $data_notify); 75 | 76 | } 77 | 78 | } 79 | // end notification 80 | // add trends to database 81 | preg_match_all("/#+([a-zA-Z0-9_]+)/i", $status, $hashtag); 82 | 83 | if(!empty($hashtag) ){ 84 | 85 | Tweet::addTrend($status); 86 | } 87 | // end add trend 88 | 89 | header('location: ../home.php'); 90 | } else { 91 | $_SESSION['errors_tweet'] = $errors; 92 | header('location: ../home.php'); 93 | } 94 | } else header('location: ../home.php'); 95 | ?> -------------------------------------------------------------------------------- /handle/handleUpdateData.php: -------------------------------------------------------------------------------- 1 | img; 15 | $currentCover = $user->imgCover; 16 | 17 | 18 | 19 | if (isset($_POST['update'])) { 20 | 21 | $name = User::checkInput($_POST['name']) ; 22 | $bio = User::checkInput($_POST['bio']); 23 | $website = User::checkInput($_POST['website']); 24 | $location = User::checkInput($_POST['location']); 25 | $cover = $_FILES['cover']; 26 | $image = $_FILES['image']; 27 | 28 | 29 | $v = new Validator; 30 | $v->rules('name' , $name , ['required' , 'string' , 'max:20']); 31 | $v->rules('bio' , $bio , ['string' , 'max:100']); 32 | $v->rules('image' , $image , ['image']); 33 | $v->rules('cover' , $cover , ['image']); 34 | 35 | 36 | $errors = $v->errors; 37 | 38 | if ($errors == []) { 39 | 40 | if ($image['name'] !== "") { 41 | $img = new Image($image); 42 | $userImg = $img->new_name ; 43 | } else $userImg = $user->img; 44 | 45 | if ($cover['name'] !== "") { 46 | $coverImg = new Image($cover); 47 | $userCover = $coverImg->new_name; 48 | } else $userCover = $user->imgCover; 49 | 50 | // var_dump($userCover) ; 51 | // echo "
    "; 52 | // var_dump($userImg) ; 53 | 54 | // die(); 55 | 56 | $data = [ 57 | 'name' => $name , 58 | 'bio' => $bio , 59 | 'website' => $website , 60 | 'location' => $location , 61 | 'imgCover' => $userCover , 62 | 'img' => $userImg , 63 | ]; 64 | 65 | $sign= User::update('users' , $_SESSION['user_id'], $data); 66 | 67 | 68 | 69 | if ($sign === true) { 70 | if ($image['name'] !== "") { 71 | if ($currentImg !== 'default.jpg') 72 | unlink('../assets/images/users/' . $currentImg); 73 | 74 | $img->upload(); 75 | 76 | } 77 | if ($cover['name'] !== "") { 78 | if ($currentCover !== 'cover.png') 79 | unlink('../assets/images/users/' . $currentCover); 80 | 81 | $coverImg->upload(); 82 | } 83 | 84 | header('location: ../' . $username); 85 | } 86 | 87 | } else { 88 | 89 | $_SESSION['errors'] = $errors; 90 | header('location: ../' . $username); 91 | 92 | 93 | } 94 | 95 | } else header('location: ../' . $username); 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | ?> -------------------------------------------------------------------------------- /core/classes/Follow.php: -------------------------------------------------------------------------------- 1 | prepare("SELECT COUNT(following_id) as count FROM `follow` 9 | WHERE following_id = :user_id"); 10 | $stmt->bindParam(":user_id" , $user_id , PDO::PARAM_STR); 11 | $stmt->execute(); 12 | $count = $stmt->fetch(PDO::FETCH_OBJ); 13 | return $count->count; 14 | } 15 | public static function countFollowing($user_id) { 16 | $stmt = self::connect()->prepare("SELECT COUNT(follower_id) as count FROM `follow` 17 | WHERE follower_id = :user_id"); 18 | $stmt->bindParam(":user_id" , $user_id , PDO::PARAM_STR); 19 | $stmt->execute(); 20 | $count = $stmt->fetch(PDO::FETCH_OBJ); 21 | return $count->count; 22 | } 23 | public static function isUserFollow($user_id ,$profile_id){ 24 | 25 | $stmt = self::connect()->prepare("SELECT `follower_id` , `following_id` FROM `follow` 26 | WHERE `follower_id` = :user_id and `following_id` = :profile_id"); 27 | $stmt->bindParam(":user_id", $user_id, PDO::PARAM_INT); 28 | $stmt->bindParam(":profile_id", $profile_id, PDO::PARAM_INT); 29 | $stmt->execute(); 30 | 31 | if ($stmt->rowCount() > 0) { 32 | return true; 33 | } else return false; 34 | 35 | } 36 | public static function usersFollowing($user_id){ 37 | 38 | $stmt = self::connect()->prepare("SELECT `following_id` as user_id FROM `follow` 39 | WHERE follower_id = :user_id"); 40 | $stmt->bindParam(":user_id", $user_id, PDO::PARAM_INT); 41 | $stmt->execute(); 42 | 43 | return $stmt->fetchAll(PDO::FETCH_OBJ); 44 | 45 | } 46 | public static function usersFollowers($user_id){ 47 | 48 | $stmt = self::connect()->prepare("SELECT `follower_id` as user_id FROM `follow` 49 | WHERE following_id = :user_id"); 50 | $stmt->bindParam(":user_id", $user_id, PDO::PARAM_INT); 51 | $stmt->execute(); 52 | 53 | return $stmt->fetchAll(PDO::FETCH_OBJ); 54 | 55 | } 56 | public static function whoToFollow($user_id){ 57 | $stmt = self::connect()->prepare("SELECT * FROM `users` 58 | WHERE `id` != :user_id AND `id` NOT IN 59 | (SELECT `following_id` FROM `follow` WHERE `follower_id` = :user_id) ORDER BY rand() LIMIT 3"); 60 | // $stmt->execute(array("user_id" => $user_id)); 61 | $stmt->bindParam(":user_id", $user_id, PDO::PARAM_INT); 62 | $stmt->execute(); 63 | return $stmt->fetchAll(PDO::FETCH_OBJ); 64 | } 65 | public static function FollowsYou($profile_id , $user_id){ 66 | $stmt = self::connect()->prepare("SELECT * FROM `follow` 67 | WHERE `follower_id` = :profile_id AND `following_id` = :user_id"); 68 | $stmt->bindParam(":user_id", $user_id, PDO::PARAM_INT); 69 | $stmt->bindParam(":profile_id", $profile_id, PDO::PARAM_INT); 70 | $stmt->execute(); 71 | if ($stmt->rowCount() > 0) { 72 | return true; 73 | } else return false; 74 | } 75 | 76 | 77 | 78 | 79 | 80 | } -------------------------------------------------------------------------------- /assets/js/like.js: -------------------------------------------------------------------------------- 1 | $(function(){ 2 | $(document).on('click','.like-btn', function(){ 3 | var tweet_id = $(this).data('tweet'); 4 | var user_id = $(this).data('user'); 5 | var counter = $(this).find('.likes-count'); 6 | var count = counter.text(); 7 | var button = $(this); 8 | 9 | // $.post('http://localhost/twitter/core/ajax/like.php', {like:tweet_id, user_id:user_id}, function(){ 10 | // counter.show(); 11 | // button.addClass('unlike-btn'); 12 | // button.removeClass('like-btn'); 13 | // count++; 14 | // counter.text(count); 15 | // button.find('.fa-heart').addClass('fas'); 16 | // button.find('.fa-heart').removeClass('far'); 17 | // button.find('.fa-heart').removeClass('mt-icon-reaction'); 18 | // }); 19 | 20 | $.ajax({ 21 | type: "POST", 22 | url: "core/ajax/like.php", 23 | data: {like:tweet_id, user_id:user_id}, 24 | cache: false, 25 | success: function(data){ 26 | // var result = $('.tmp').html(); 27 | 28 | counter.text(data); 29 | button.addClass('unlike-btn'); 30 | button.removeClass('like-btn'); 31 | 32 | button.find('.fa-heart').addClass('fas'); 33 | button.find('.fa-heart').removeClass('far'); 34 | button.find('.fa-heart').removeClass('mt-icon-reaction'); 35 | 36 | 37 | } 38 | }) 39 | 40 | 41 | 42 | 43 | }); 44 | 45 | $(document).on('click','.unlike-btn', function(){ 46 | var tweet_id = $(this).data('tweet'); 47 | var user_id = $(this).data('user'); 48 | var counter = $(this).find('.likes-count'); 49 | var count = counter.text(); 50 | var button = $(this); 51 | 52 | // $.post('http://localhost/twitter/core/ajax/like.php', {unlike:tweet_id, user_id:user_id}, function(){ 53 | // counter.show(); 54 | // button.addClass('like-btn'); 55 | // button.removeClass('unlike-btn'); 56 | // count--; 57 | // if(count === 0){ 58 | // counter.hide(); 59 | // }else{ 60 | // counter.text(count); 61 | // } 62 | // counter.text(count); 63 | // button.find('.fa-heart').addClass('far'); 64 | // button.find('.fa-heart').addClass('mt-icon-reaction'); 65 | // button.find('.fa-heart').removeClass('fas'); 66 | // }); 67 | $.ajax({ 68 | type: "POST", 69 | url: "core/ajax/like.php", 70 | data: {unlike:tweet_id, user_id:user_id}, 71 | cache: false, 72 | success: function(data){ 73 | // var result = $('.tmp').html(); 74 | if (data == 0) 75 | counter.text(''); 76 | else counter.text(data); 77 | 78 | button.addClass('like-btn'); 79 | button.removeClass('unlike-btn'); 80 | 81 | button.find('.fa-heart').addClass('far'); 82 | button.find('.fa-heart').addClass('mt-icon-reaction'); 83 | button.find('.fa-heart').removeClass('fas'); 84 | 85 | 86 | } 87 | }) 88 | 89 | }); 90 | }); -------------------------------------------------------------------------------- /assets/js/comment.js: -------------------------------------------------------------------------------- 1 | $(function(){ 2 | 3 | 4 | $(document).on('click','.comment', function(){ 5 | var tweet_id = $(this).data('tweet'); 6 | var user_id = $(this).data('user'); 7 | $counter = $(this).find(".likes-count"); 8 | $count = $counter.text(); 9 | $button = $(this); 10 | 11 | 12 | console.log(tweet_id); 13 | console.log(user_id); 14 | $.post('core/ajax/comment.php', {showPopup:tweet_id,user_id:user_id}, function(data){ 15 | $('.popupComment').html(data); 16 | 17 | $('.close-retweet-popup').click(function(){ 18 | $('.retweet-popup').hide(); 19 | }) 20 | }); 21 | }); 22 | 23 | 24 | 25 | $(document).one('click', '.comment-it', function(event){ 26 | $('.retweet-popup').addClass('active'); 27 | var tweet_id = $(this).data('tweet'); 28 | var user_id = $(this).data('user'); 29 | // var flag = $(this).data('tmp'); 30 | // var qoq = $(this).data('qoq'); 31 | 32 | 33 | 34 | // tricky hint each function to select one class only 35 | var comment ; 36 | $('.retweet-msg').each(function(){ 37 | comment = $(this).val() 38 | }); 39 | // event.stopImmediatePropagation(); 40 | 41 | // console.log(tweet_id); 42 | // console.log(user_id); 43 | // console.log(comment); 44 | 45 | $.post('core/ajax/comment.php', {qoute:tweet_id,user_id:user_id,comment:comment}, function(data){ 46 | 47 | $('.retweet-popup').hide(); 48 | $('.comments').html(data); 49 | 50 | location.reload(); 51 | 52 | // $counter.text(data); 53 | // $button.removeClass('retweet').addClass('retweeted'); 54 | }); 55 | 56 | }); 57 | 58 | 59 | 60 | 61 | $(document).on('click','.reply', function(){ 62 | var tweet_id = $(this).data('tweet'); 63 | var user_id = $(this).data('user'); 64 | $counter = $(this).find(".likes-count"); 65 | $count = $counter.text(); 66 | $button = $(this); 67 | 68 | 69 | console.log(tweet_id); 70 | console.log(user_id); 71 | $.post('core/ajax/comment.php', {showReply:tweet_id,user_id:user_id}, function(data){ 72 | $('.popupComment').html(data); 73 | 74 | $('.close-retweet-popup').click(function(){ 75 | $('.retweet-popup').hide(); 76 | }) 77 | }); 78 | }); 79 | 80 | 81 | 82 | $(document).one('click', '.reply-it', function(event){ 83 | $('.retweet-popup').addClass('active'); 84 | var comment_id = $(this).data('tweet'); 85 | var user_id = $(this).data('user'); 86 | // var flag = $(this).data('tmp'); 87 | // var qoq = $(this).data('qoq'); 88 | 89 | 90 | 91 | // tricky hint each function to select one class only 92 | var comment ; 93 | $('.retweet-msg').each(function(){ 94 | comment = $(this).val() 95 | }); 96 | // event.stopImmediatePropagation(); 97 | 98 | // console.log(comment_id); 99 | // console.log(user_id); 100 | // console.log(comment); 101 | 102 | $.post('core/ajax/comment.php', {reply:comment_id,user_id:user_id,comment:comment}, function(data){ 103 | 104 | $('.retweet-popup').hide(); 105 | $('.comments').html(data); 106 | 107 | location.reload(); 108 | 109 | // $counter.text(data); 110 | // $button.removeClass('retweet').addClass('retweeted'); 111 | }); 112 | 113 | }); 114 | }); -------------------------------------------------------------------------------- /assets/js/users.js: -------------------------------------------------------------------------------- 1 | $(function(){ 2 | 3 | 4 | $(document).on('click','.retweets-u', function(){ 5 | var tweet_id = $(this).data('tweet'); 6 | 7 | 8 | // console.log(tweet_id); 9 | 10 | $.post('core/ajax/users.php', {retweetby:tweet_id}, function(data){ 11 | $('.popupUsers').html(data); 12 | 13 | $('.close-retweet-popup').click(function(){ 14 | $('.retweet-popup').hide(); 15 | }) 16 | $(document).click(function(e){ 17 | if( $(e.target).closest('.retweet-popup-body-wrap').length > 0 ) { 18 | return false; 19 | } 20 | 21 | $('.retweet-popup').hide(); 22 | }) 23 | }); 24 | }); 25 | 26 | $(document).on('click','.likes-u', function(){ 27 | var tweet_id = $(this).data('tweet'); 28 | 29 | 30 | // console.log(tweet_id); 31 | 32 | $.post('core/ajax/users.php', {likeby:tweet_id}, function(data){ 33 | $('.popupUsers').html(data); 34 | 35 | $('.close-retweet-popup').click(function(){ 36 | $('.retweet-popup').hide(); 37 | }) 38 | $(document).click(function(e){ 39 | if( $(e.target).closest('.retweet-popup-body-wrap').length > 0 ) { 40 | return false; 41 | } 42 | 43 | $('.retweet-popup').hide(); 44 | }) 45 | }); 46 | }); 47 | 48 | $(document).on('click','.count-following-i', function(){ 49 | var user_id = $(this).data('follow'); 50 | 51 | 52 | 53 | 54 | $.post('core/ajax/users.php', {following:user_id}, function(data){ 55 | $('.popupUsers').html(data); 56 | 57 | $('.close-retweet-popup').click(function(){ 58 | $('.retweet-popup').hide(); 59 | }) 60 | $(document).click(function(e){ 61 | if( $(e.target).closest('.retweet-popup-body-wrap').length > 0 ) { 62 | return false; 63 | } 64 | 65 | $('.retweet-popup').hide(); 66 | }) 67 | }); 68 | }); 69 | 70 | $(document).on('click','.count-followers-i', function(){ 71 | var user_id = $(this).data('follow'); 72 | 73 | 74 | 75 | 76 | $.post('core/ajax/users.php', {follower:user_id}, function(data){ 77 | $('.popupUsers').html(data); 78 | 79 | $('.close-retweet-popup').click(function(){ 80 | $('.retweet-popup').hide(); 81 | }) 82 | $(document).click(function(e){ 83 | if( $(e.target).closest('.retweet-popup-body-wrap').length > 0 ) { 84 | return false; 85 | } 86 | 87 | $('.retweet-popup').hide(); 88 | }) 89 | }); 90 | }); 91 | 92 | 93 | 94 | 95 | 96 | 97 | $(document).on('click','.reply', function(){ 98 | var tweet_id = $(this).data('tweet'); 99 | var user_id = $(this).data('user'); 100 | $counter = $(this).find(".likes-count"); 101 | $count = $counter.text(); 102 | $button = $(this); 103 | 104 | 105 | console.log(tweet_id); 106 | console.log(user_id); 107 | $.post('core/ajax/comment.php', {showReply:tweet_id,user_id:user_id}, function(data){ 108 | $('.popupComment').html(data); 109 | 110 | $('.close-retweet-popup').click(function(){ 111 | $('.retweet-popup').hide(); 112 | }) 113 | }); 114 | }); 115 | 116 | 117 | 118 | 119 | }); -------------------------------------------------------------------------------- /core/ajax/users.php: -------------------------------------------------------------------------------- 1 | id; 35 | } 36 | if ($flag) { 37 | ?> 38 |
    39 |
    40 | 98 | 99 | 100 | -------------------------------------------------------------------------------- /index.php: -------------------------------------------------------------------------------- 1 | 11 | 12 | 13 | 14 | Twitter 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 |
    26 | 59 |
    60 |
    61 | 62 |

    Follow your interests.

    63 | 64 |

    Hear what people are talking about.

    65 | 66 |

    Join the conversation.

    67 |
    68 |
    69 | 91 |
    92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | -------------------------------------------------------------------------------- /assets/js/retweet.js: -------------------------------------------------------------------------------- 1 | $(function(){ 2 | 3 | 4 | $(document).on('click','.option', function(e){ 5 | var tweet_id = $(this).data('tweet'); 6 | var user_id = $(this).data('user'); 7 | var retweeted_it = $(this).data('retweeted'); 8 | var status = $(this).data('status'); 9 | 10 | $counter = $(this).find(".likes-count"); 11 | $count = $counter.text(); 12 | $button = $(this); 13 | $op = $(this).next(); 14 | // $op = $(this).find('.options'); 15 | var flag = $(this).data('tmp'); 16 | var sign = $(this).data('sign'); 17 | var qoq = $(this).data('qoq'); 18 | 19 | 20 | 21 | 22 | $.post('core/ajax/retweet.php', {option:tweet_id,user_id:user_id,retweeted:retweeted_it , sign:sign , tmp:flag,qoq:qoq , status:status}, function(data){ 23 | $op.html(data); 24 | 25 | 26 | $(document).click(function(e){ 27 | if( $(e.target).closest('.options').length > 0 ) { 28 | return false; 29 | } 30 | 31 | $('.retweet-div').hide(); 32 | }) 33 | }); 34 | 35 | 36 | 37 | $(document).one('click','.retweet-i', function(event){ 38 | var tweet_id = $(this).data('tweet'); 39 | var user_id = $(this).data('user'); 40 | $c = $(this); 41 | 42 | var qoq = $(this).data('qoq'); 43 | // event.stopPropagation(); 44 | event.stopImmediatePropagation(); 45 | 46 | 47 | $.post('core/ajax/retweet.php', {retweet:tweet_id,user_id:user_id,isQoute:flag,qoq:qoq}, function(data){ 48 | // $('.popupTweet').html(data); 49 | 50 | $counter.text(data); 51 | $button.removeClass('retweet').addClass('retweeted'); 52 | $c.removeClass('retweet-i').addClass('retweeted-i'); 53 | $('.retweet-div').hide(); 54 | 55 | // $.ajax({ 56 | // url: 'http://localhost/twitter/home.php', 57 | // success: function(data) { 58 | 59 | // window.location.reload(); // This is not jQuery but simple plain ol' JS 60 | 61 | // } 62 | // }); 63 | 64 | location.reload(); 65 | }); 66 | 67 | 68 | 69 | 70 | }); 71 | 72 | 73 | 74 | $(document).one('click','.retweeted-i', function(event){ 75 | var tweet_id = $(this).data('tweet'); 76 | var user_id = $(this).data('user'); 77 | var status = $(this).data('status'); 78 | 79 | $c = $(this); 80 | 81 | event.stopImmediatePropagation(); 82 | console.log(tweet_id); 83 | $.post('core/ajax/retweet.php', {unretweet:tweet_id,user_id:user_id}, function(data){ 84 | 85 | // if (data == 0) 86 | // $counter.text(''); 87 | // else 88 | $counter.text(data); 89 | $button.removeClass('retweeted').addClass('retweet'); 90 | $c.removeClass('retweeted-i').addClass('retweet-i'); 91 | 92 | $('.retweet-div').hide(); 93 | if (!status) 94 | location.reload(); 95 | else history.go(-1); 96 | 97 | 98 | 99 | }); 100 | 101 | }); 102 | 103 | $(document).on('click','.qoute', function(){ 104 | var tweet_id = $(this).data('tweet'); 105 | var user_id = $(this).data('user'); 106 | $counter = $(this).find(".likes-count"); 107 | $count = $counter.text(); 108 | $button = $(this); 109 | 110 | 111 | // console.log(tweet_id); 112 | // console.log($retweeted_it); 113 | // console.log($sign); 114 | $.post('core/ajax/retweet.php', {showPopup:tweet_id,user_id:user_id}, function(data){ 115 | $('.popupTweet').html(data); 116 | 117 | $('.close-retweet-popup').click(function(){ 118 | $('.retweet-popup').hide(); 119 | }) 120 | }); 121 | }); 122 | 123 | }); 124 | 125 | $(document).one('click', '.qoute-it', function(event){ 126 | $('.retweet-popup').addClass('active'); 127 | var tweet_id = $(this).data('tweet'); 128 | var user_id = $(this).data('user'); 129 | var flag = $(this).data('tmp'); 130 | var qoq = $(this).data('qoq'); 131 | 132 | event.stopImmediatePropagation(); 133 | 134 | // tricky hint each function to select one class only 135 | var comment ; 136 | $('.retweet-msg').each(function(){ 137 | comment = $(this).val() 138 | }); 139 | 140 | 141 | console.log(tweet_id); 142 | console.log(user_id); 143 | console.log(comment); 144 | 145 | $.post('core/ajax/retweet.php', {qoute:tweet_id,user_id:user_id,comment:comment,isQoute:flag,qoq:qoq}, function(data){ 146 | 147 | $('.retweet-popup').hide(); 148 | location.reload(); 149 | 150 | // $counter.text(data); 151 | // $button.removeClass('retweet').addClass('retweeted'); 152 | }); 153 | 154 | }); 155 | }); -------------------------------------------------------------------------------- /assets/css/index_style.css: -------------------------------------------------------------------------------- 1 | body{ 2 | margin: 0; 3 | font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; 4 | background-color: white; 5 | } 6 | .twt-main{ 7 | height: 100%; 8 | width: 100%; 9 | } 10 | .twt-login{ 11 | display: inline-grid; 12 | grid-template-columns: 1fr; 13 | grid-template-rows: 150px 1fr; 14 | width: 50%; 15 | height: 100vh; 16 | position: relative; 17 | background-color: white; 18 | float: right; 19 | } 20 | 21 | .twitterIcon-bird{ 22 | position: absolute; 23 | width: 1200px; 24 | top: -145px; 25 | left: 15px; 26 | overflow: hidden; 27 | } 28 | .login-box{ 29 | margin-left: 60px; 30 | margin-top: 31px; 31 | display: grid; 32 | grid-template-rows: 1fr 1fr; 33 | grid-template-columns: 1fr 1fr auto; 34 | font-size: 14px; 35 | line-height: 20px; 36 | width: 210px; 37 | height: 46px; 38 | grid-column-gap: 10px; 39 | } 40 | .input-box{ 41 | border: 1px solid #e6ecf0; 42 | border-radius: 3px; 43 | box-sizing: border-box; 44 | padding: 15px; 45 | width: 210px; 46 | } 47 | .input-box:focus { 48 | outline: none; 49 | } 50 | ::placeholder{ 51 | font-size: 14px; 52 | line-height: 20px; 53 | } 54 | .login-btn{ 55 | background-color: #fff; 56 | border: 1px solid #1da1f2; 57 | color: #1da1f2; 58 | border-radius: 80px; 59 | font-weight: 700; 60 | font-size: 14px; 61 | width: 70px; 62 | cursor: pointer; 63 | margin-top: 5px; 64 | margin-bottom: 5px; 65 | 66 | } 67 | .login-btn:hover { 68 | background-color: #1DA1F225; 69 | transition: all 0.2s; 70 | } 71 | 72 | .login-link{ 73 | grid-area: 2/2/3/3; 74 | color: #aab8c2; 75 | text-decoration: none; 76 | font-size: 14px; 77 | } 78 | 79 | .slow-login{ 80 | justify-self: center; 81 | width: 355px; 82 | height: 100px; 83 | color: #14171a; 84 | font-weight: 700; 85 | } 86 | .login-bird{ 87 | width: 60px; 88 | display: block; 89 | } 90 | .login-small-display{ 91 | display:none; 92 | } 93 | .front-para{ 94 | font-size: 27px; 95 | line-height: 32px; 96 | display: block; 97 | margin-bottom: 50px; 98 | } 99 | .join{ 100 | font-size: 18px; 101 | line-height: 24px 102 | } 103 | .signup-btn{ 104 | margin-top: 15px; 105 | background-color: #1da1f2; 106 | border: 1px solid #1da1f2; 107 | color: #fff; 108 | } 109 | .signin-btn{ 110 | background-color: #fff; 111 | border: 1px solid #1da1f2; 112 | color: #1da1f2; 113 | } 114 | 115 | .pri-btn{ 116 | border-radius: 100px; 117 | font-size: 14px; 118 | font-weight: bold; 119 | line-height: 20px; 120 | padding: 6px 16px; 121 | margin-bottom: 16px; 122 | width: 350px; 123 | } 124 | .twt-features{ 125 | background: url('https://logos-download.com/wp-content/uploads/2016/02/Twitter_logo_bird_transparent_png.png'); 126 | background-repeat: no-repeat; 127 | background-size:1200px; 128 | background-position:0px -140px; 129 | width: 50%; 130 | height: 100vh; 131 | background-color: #1da1f2; 132 | float: left; 133 | } 134 | .features-div{ 135 | margin:auto; 136 | width: 370px; 137 | margin-top: 230px; 138 | } 139 | .twt-icon{ 140 | position: relative; 141 | float: left; 142 | width: 35px; 143 | margin-right: 20px; 144 | } 145 | .twt-features p{ 146 | position: relative; 147 | top: 5px; 148 | font-size: 18px; 149 | font-weight: 700; 150 | line-height: 24px; 151 | color: #fff; 152 | padding-bottom: 30px; 153 | } 154 | footer{ 155 | position: fixed; 156 | bottom: 0; 157 | width: 100%; 158 | border-top: 1px solid #e6ecf0; 159 | background-color: #fff; 160 | } 161 | ul{ 162 | background: #fff; 163 | display: flex; 164 | color: #aab8c2; 165 | } 166 | li{ 167 | display: inline-block; 168 | padding-left: 18px; 169 | font-size: 12px; 170 | } 171 | 172 | footer a{ 173 | color: #aab8c2; 174 | text-decoration: none; 175 | } 176 | 177 | .error-li { 178 | margin:25px 0px; 179 | } 180 | 181 | .span-fp-error{ 182 | overflow: hidden; 183 | padding: 5px; 184 | border: 1px dashed #d89797; 185 | border-radius: 3px; 186 | font-size: 13px; 187 | font-weight: bold; 188 | color: #a75858; 189 | } 190 | 191 | @media (max-width:800px){ 192 | 193 | .twt-main{ 194 | display: grid; 195 | min-height: 600px; 196 | } 197 | .twt-features{ 198 | width: auto; 199 | height: 40vh; 200 | background-size: 180% 201 | } 202 | .features-div{ 203 | margin-top: 50px; 204 | } 205 | .twt-login{ 206 | width: auto; 207 | height: 60vh; 208 | } 209 | /* .twt-login form{ 210 | display: none; 211 | } */ 212 | footer ul{ 213 | display: none; 214 | text-align: center; 215 | } 216 | .login-bird{ 217 | display: inline-block; 218 | } 219 | 220 | .login-box { 221 | margin-left: 0; 222 | grid-template-rows: 1fr 1fr; 223 | grid-template-columns: 1fr 1fr; 224 | } 225 | .login-btn { 226 | border-radius: 100px; 227 | font-size: 14px; 228 | font-weight: bold; 229 | line-height: 20px; 230 | padding: 6px 16px; 231 | margin-bottom: 16px; 232 | margin-top: 10px; 233 | width:200px; 234 | 235 | } 236 | 237 | } 238 | 239 | .con { 240 | width: 200%; 241 | text-align: center; 242 | } 243 | button:focus { 244 | outline: none !important; 245 | } -------------------------------------------------------------------------------- /core/classes/User.php: -------------------------------------------------------------------------------- 1 | pdo = $pdo; 10 | // } 11 | 12 | public static function checkInput ($input) { 13 | $input = htmlspecialchars($input); 14 | $input = trim($input); 15 | $input = stripslashes($input); 16 | return $input; 17 | } 18 | 19 | public static function login ($email , $password) { 20 | $stmt = self::connect()->prepare("SELECT `id` from `users` WHERE `email` = :email AND `password` = :password"); 21 | $stmt->bindParam(":email" , $email , PDO::PARAM_STR); 22 | $password =md5($password); 23 | $stmt->bindParam(":password" , $password , PDO::PARAM_STR); 24 | $stmt->execute(); 25 | $user = $stmt->fetch(PDO::FETCH_OBJ); 26 | 27 | if ($stmt->rowCount() > 0) { 28 | $_SESSION['user_id'] = $user->id; 29 | header('location: ../home.php'); 30 | } else {return false; } 31 | } 32 | 33 | 34 | 35 | public static function create($table , $fields = array()) { 36 | $colms = implode(',' , array_keys($fields)); 37 | $values = ':' . implode(', :' , array_keys($fields)); 38 | $sql = "INSERT INTO {$table} ({$colms}) VALUES ({$values})"; 39 | $pdo = self::connect(); 40 | $pdo->beginTransaction(); 41 | if($stmt = $pdo->prepare($sql)) { 42 | foreach($fields as $key => $data) { 43 | $stmt->bindValue(':'. $key , $data ); 44 | } 45 | if ($stmt->execute() === FALSE) { 46 | $pdo->rollback(); 47 | } else { 48 | $user_id = $pdo->lastInsertId(); 49 | $pdo->commit(); 50 | } 51 | return $user_id; 52 | } 53 | } 54 | public static function register($email , $password , $name , $username) { 55 | 56 | $pdo = self::connect(); 57 | $pdo->beginTransaction(); 58 | $stmt = $pdo->prepare("INSERT INTO `users` (`email` , `password` , `name` , `username`) Values (:email , :password , :name , :username)"); 59 | 60 | $stmt->bindParam(":email" , $email , PDO::PARAM_STR); 61 | $password =md5($password); 62 | $stmt->bindParam(":password" , $password , PDO::PARAM_STR); 63 | $stmt->bindParam(":name" , $name , PDO::PARAM_STR); 64 | $stmt->bindParam(":username" , $username , PDO::PARAM_STR); 65 | 66 | if ($stmt->execute() === FALSE) { 67 | $pdo->rollback(); 68 | echo 'Unable to insert data'; 69 | } else { 70 | $user_id = $pdo->lastInsertId(); 71 | $pdo->commit(); 72 | } 73 | $_SESSION['user_id'] = $user_id; 74 | 75 | // make user follow the owner by default and notofications also 76 | date_default_timezone_set("Africa/Cairo"); 77 | $data = [ 78 | 'follower_id' => $user_id , 79 | 'following_id' => 2 , 80 | 'time' => date("Y-m-d H:i:s") 81 | ]; 82 | User::create('follow' , $data); 83 | $data_notify = [ 84 | 'notify_for' => 2, 85 | 'notify_from' => $user_id , 86 | 'target' => 0, 87 | 'type' => 'follow' , 88 | 'time' => date("Y-m-d H:i:s") , 89 | 'count' => '0' , 90 | 'status' => '0' 91 | ]; 92 | Tweet::create('notifications' , $data_notify); 93 | 94 | $_SESSION['welcome'] = 'welcome'; 95 | header('location: ../home.php') ; 96 | 97 | } 98 | public static function update($table , $user_id , $fields = array()){ 99 | $colms = ''; 100 | $loopCount = 1; 101 | // to know when i insert ',' 102 | foreach ($fields as $name => $value) { 103 | $colms .= "`{$name}` = :{$name}"; 104 | if($loopCount < count($fields)) { 105 | $colms .= ', ' ; } 106 | 107 | $loopCount++; 108 | } 109 | $sql = "UPDATE {$table} SET {$colms} WHERE id = {$user_id}"; 110 | $pdo = self::connect(); 111 | if($stmt = $pdo->prepare($sql)) { 112 | foreach($fields as $key => $data) { 113 | $stmt->bindValue(':'. $key , $data ); 114 | } 115 | $stmt->execute(); 116 | return true; 117 | } 118 | 119 | } 120 | 121 | public static function delete($table, $array){ 122 | $sql = "DELETE FROM " . $table; 123 | $where = " WHERE "; 124 | 125 | foreach($array as $key => $value){ 126 | $sql .= $where . $key . " = " . $value . ""; 127 | $where = " AND "; 128 | } 129 | $sql .= ";"; 130 | 131 | $stmt = self::connect()->prepare($sql); 132 | $stmt->execute(); 133 | } 134 | 135 | public static function getData($id) { 136 | $stmt = self::connect()->prepare("SELECT * from `users` WHERE `id` = :id"); 137 | $stmt->bindParam(":id" , $id , PDO::PARAM_STR); 138 | $stmt->execute(); 139 | return $stmt->fetch(PDO::FETCH_OBJ); 140 | } 141 | public static function logout () { 142 | $_SESSION = array(); 143 | session_destroy(); 144 | header('location: ../index.php'); 145 | } 146 | 147 | public static function checkEmail($email) { 148 | $stmt = self::connect()->prepare("SELECT `email` from `users` WHERE `email` = :email"); 149 | $stmt->bindParam(":email" , $email , PDO::PARAM_STR); 150 | $stmt->execute(); 151 | 152 | if ($stmt->rowCount() > 0) { 153 | return true; 154 | } else return false; 155 | } 156 | 157 | public static function checkUserName($username) { 158 | $stmt = self::connect()->prepare("SELECT `username` from `users` WHERE `username` = :username"); 159 | $stmt->bindParam(":username" , $username , PDO::PARAM_STR); 160 | $stmt->execute(); 161 | 162 | if ($stmt->rowCount() > 0) { 163 | return true; 164 | } else return false; 165 | } 166 | 167 | public static function checkLogIn () { 168 | if (isset($_SESSION['user_id'])) 169 | return true; 170 | else return false; 171 | } 172 | 173 | public static function getIdByUsername($username) { 174 | $stmt = self::connect()->prepare("SELECT `id` from `users` where `username` = :username"); 175 | $stmt->bindParam(":username" , $username , PDO::PARAM_STR); 176 | $stmt->execute(); 177 | $user = $stmt->fetch(PDO::FETCH_OBJ); 178 | return $user->id; 179 | } 180 | 181 | public static function getUserNameById($id) { 182 | $stmt = self::connect()->prepare("SELECT `username` from `users` where `id` = :id"); 183 | $stmt->bindParam(":id" , $id , PDO::PARAM_STR); 184 | $stmt->execute(); 185 | $user = $stmt->fetch(PDO::FETCH_OBJ); 186 | return $user->username; 187 | } 188 | 189 | public static function search($search){ 190 | $stmt = self::connect()->prepare("SELECT `id`,`username`,`name`,`img`,`imgCover` FROM `users` 191 | WHERE `username` LIKE ? OR `name` LIKE ?"); 192 | $stmt->bindValue(1, $search.'%', PDO::PARAM_STR); 193 | $stmt->bindValue(2, $search.'%', PDO::PARAM_STR); 194 | $stmt->execute(); 195 | return $stmt->fetchAll(PDO::FETCH_OBJ); 196 | } 197 | public static function CountNotification($user_id){ 198 | $stmt = self::connect()->prepare("SELECT COUNT(notify_for) as count FROM `notifications` 199 | WHERE notify_for = :user_id AND count = 0"); 200 | $stmt->bindParam(":user_id" , $user_id , PDO::PARAM_STR); 201 | $stmt->execute(); 202 | $u = $stmt->fetch(PDO::FETCH_OBJ); 203 | return $u->count; 204 | } 205 | public static function notification($user_id){ 206 | $stmt = self::connect()->prepare("SELECT * FROM `notifications` 207 | WHERE notify_for = :user_id ORDER BY time DESC"); 208 | $stmt->bindParam(":user_id" , $user_id , PDO::PARAM_STR); 209 | $stmt->execute(); 210 | return $stmt->fetchAll(PDO::FETCH_OBJ); 211 | } 212 | public static function updateNotifications($user_id){ 213 | $stmt = self::connect()->prepare("UPDATE `notifications` SET count = 1 214 | WHERE notify_for = :user_id AND count = 0" ); 215 | $stmt->bindParam(":user_id" , $user_id , PDO::PARAM_STR); 216 | $s =$stmt->execute(); 217 | if($s) 218 | return true; 219 | else return false; 220 | } 221 | 222 | 223 | 224 | } 225 | 226 | -------------------------------------------------------------------------------- /includes/tweets.php: -------------------------------------------------------------------------------- 1 | id)) { 11 | 12 | $tweet_user = User::getData($tweet->user_id) ; 13 | $tweet_real = Tweet::getTweet($tweet->id); 14 | $timeAgo = Tweet::getTimeAgo($tweet->post_on) ; 15 | $likes_count = Tweet::countLikes($tweet->id) ; 16 | $user_like_it = Tweet::userLikeIt($user_id ,$tweet->id); 17 | $retweets_count = Tweet::countRetweets($tweet->id) ; 18 | $user_retweeted_it = Tweet::userRetweeetedIt($user_id ,$tweet->id); 19 | 20 | } else if (Tweet::isRetweet($tweet->id)) { 21 | 22 | $retweet = Tweet::getRetweet($tweet->id); 23 | 24 | if ($retweet->retweet_msg == null) { 25 | 26 | if ($retweet->retweet_id == null) { 27 | 28 | // if retweeted normal tweet 29 | $retweeted_tweet = Tweet::getTweet($retweet->tweet_id); 30 | $tweet_user = User::getData($retweeted_tweet->user_id) ; 31 | $tweet_real = Tweet::getTweet($retweet->tweet_id); 32 | $timeAgo = Tweet::getTimeAgo($tweet_real->post_on) ; 33 | $likes_count = Tweet::countLikes($retweet->tweet_id) ; 34 | $user_like_it = Tweet::userLikeIt($user_id ,$retweet->tweet_id); 35 | $retweets_count = Tweet::countRetweets($retweet->tweet_id) ; 36 | $user_retweeted_it = Tweet::userRetweeetedIt($user_id ,$retweet->tweet_id); 37 | $retweeted_user = User::getData($tweet->user_id); 38 | $retweet_sign = true; 39 | } else { 40 | 41 | // this condtion if user retweeted qouted tweet or qoute of qoute tweet 42 | 43 | 44 | $retweeted_tweet = Tweet::getRetweet($retweet->retweet_id); 45 | 46 | if($retweeted_tweet->tweet_id != null) { 47 | // here it's retweeted qouted 48 | // if($retweeted_tweet->) 49 | $tweet_user = User::getData($retweeted_tweet->user_id) ; 50 | $timeAgo = Tweet::getTimeAgo($retweeted_tweet->post_on) ; 51 | $likes_count = Tweet::countLikes($retweeted_tweet->post_id) ; 52 | $user_like_it = Tweet::userLikeIt($user_id ,$retweeted_tweet->post_id); 53 | $retweets_count = Tweet::countRetweets($retweeted_tweet->post_id) ; 54 | $user_retweeted_it = Tweet::userRetweeetedIt($user_id ,$retweeted_tweet->post_id); 55 | 56 | 57 | $tweet_inner = Tweet::getTweet($retweeted_tweet->tweet_id); 58 | $user_inner_tweet = User::getData($tweet_inner->user_id) ; 59 | $timeAgo_inner = Tweet::getTimeAgo($tweet_inner->post_on); 60 | $retweeted_user = User::getData($tweet->user_id); 61 | $retweet_sign = true; 62 | 63 | $qoute = $retweeted_tweet->retweet_msg; 64 | $retweet_comment = true; 65 | } else { 66 | // here is retweeted qouted of qouted 67 | 68 | $retweet_sign = true; 69 | $tweet_user = User::getData($retweeted_tweet->user_id) ; 70 | 71 | $timeAgo = Tweet::getTimeAgo($retweeted_tweet->post_on) ; 72 | $likes_count = Tweet::countLikes($retweeted_tweet->post_id) ; 73 | $user_like_it = Tweet::userLikeIt($user_id ,$retweeted_tweet->post_id); 74 | $retweets_count = Tweet::countRetweets($retweeted_tweet->post_id) ; 75 | $user_retweeted_it = Tweet::userRetweeetedIt($user_id ,$retweeted_tweet->post_id); 76 | 77 | $qoq = true; // stand for qoute of qoute 78 | $qoute = $retweeted_tweet->retweet_msg; 79 | $tweet_inner = Tweet::getRetweet($retweeted_tweet->retweet_id); 80 | $user_inner_tweet = User::getData($tweet_inner->user_id) ; 81 | $timeAgo_inner = Tweet::getTimeAgo($tweet_inner->post_on); 82 | $inner_qoute = $tweet_inner->retweet_msg; 83 | 84 | 85 | 86 | $retweeted_user = User::getData($tweet->user_id); 87 | 88 | } 89 | } 90 | 91 | } else { 92 | // qoute tweet condtion 93 | if ($retweet->retweet_id == null) { 94 | $tweet_user = User::getData($tweet->user_id) ; 95 | $timeAgo = Tweet::getTimeAgo($tweet->post_on) ; 96 | $likes_count = Tweet::countLikes($tweet->id) ; 97 | $user_like_it = Tweet::userLikeIt($user_id ,$tweet->id); 98 | $retweets_count = Tweet::countRetweets($tweet->id) ; 99 | $user_retweeted_it = Tweet::userRetweeetedIt($user_id ,$tweet->id); 100 | $qoute = $retweet->retweet_msg; 101 | $retweet_comment = true; 102 | 103 | 104 | $tweet_inner = Tweet::getTweet($retweet->tweet_id); 105 | $user_inner_tweet = User::getData($tweet_inner->user_id) ; 106 | $timeAgo_inner = Tweet::getTimeAgo($tweet_inner->post_on); 107 | } else { 108 | 109 | // this condtion for qoute of qoute which retweet_id not null and retweet msg not null 110 | $tweet_user = User::getData($tweet->user_id) ; 111 | $timeAgo = Tweet::getTimeAgo($tweet->post_on) ; 112 | $likes_count = Tweet::countLikes($tweet->id) ; 113 | $user_like_it = Tweet::userLikeIt($user_id ,$tweet->id); 114 | $retweets_count = Tweet::countRetweets($tweet->id) ; 115 | $user_retweeted_it = Tweet::userRetweeetedIt($user_id ,$tweet->id); 116 | $qoute = $retweet->retweet_msg; 117 | $qoq = true; // stand for qoute of qoute 118 | 119 | $tweet_inner = Tweet::getRetweet($retweet->retweet_id); 120 | $user_inner_tweet = User::getData($tweet_inner->user_id) ; 121 | $timeAgo_inner = Tweet::getTimeAgo($tweet_inner->post_on); 122 | $inner_qoute = $tweet_inner->retweet_msg; 123 | if($inner_qoute == null) { 124 | 125 | $tweet_innerr = Tweet::getRetweet($tweet_inner->retweet_id); 126 | $inner_qoute = $tweet_innerr->retweet_msg; 127 | 128 | // $inner_qoute = "qork"; 129 | 130 | } 131 | 132 | } 133 | 134 | } 135 | 136 | } 137 | $tweet_link = $tweet->id; 138 | 139 | if($retweet_sign) 140 | $comment_count = Tweet::countComments($retweeted_tweet->id); 141 | else $comment_count = Tweet::countComments($tweet->id); 142 | 143 | ?> 144 | 145 |
    146 | 147 | 148 | 149 | 150 | 151 | id == $user_id) echo "You"; 152 | else echo $retweeted_user->name; ?> retweeted 153 | 154 |
    155 | 156 | 161 | 162 | 163 |
    164 |

    165 | 166 | name ?> 167 | 168 | @username ?> 169 | 170 |

    171 | 178 | 179 | img != null) { ?> 180 |

    181 | 186 |

    187 | 188 | 189 | 190 |
    191 | 192 | 193 | 194 | 195 |
    196 | 197 | 198 | 203 | 204 | 205 |
    206 |

    207 | 208 | name ?> 209 | 210 | @username ?> 211 | 212 |

    213 |

    214 | status); ?> 218 |

    219 | img != null) { ?> 222 |

    223 | 228 |

    229 | 230 | 231 |
    232 | 233 |
    234 | 235 | 236 |
    237 | 238 | 239 | 240 |
    241 |
    242 |
    248 | 249 | 250 | 253 |
    254 |
    255 |
    256 | 257 |
    274 | 275 | 276 | 277 | 278 | 281 | 282 | 283 | 284 |
    285 | 286 |
    287 | 288 | 289 |
    290 | 291 |
    292 | 317 | 318 |
    319 |
    320 | 321 | 322 |
    323 |
    324 |

    325 |
    326 |
    327 |
    328 |
    329 |
    330 | 331 | 332 | 333 | 334 |
    335 | 336 | 337 |
    338 | 339 |
    340 |
    341 | 342 |
    343 | 344 | 345 | 346 | 347 | -------------------------------------------------------------------------------- /core/ajax/comment.php: -------------------------------------------------------------------------------- 1 | $_SESSION['user_id'] , 20 | 'post_id' => $tweet_id , 21 | 'comment' => $comment , 22 | 'time' => date("Y-m-d H:i:s") , 23 | ]; 24 | if ($comment != '') { 25 | $for_user = Tweet::getData($tweet_id)->user_id; 26 | 27 | if($for_user != $user_id) { 28 | $data_notify = [ 29 | 'notify_for' => $for_user , 30 | 'notify_from' => $user_id , 31 | 'target' => $tweet_id , 32 | 'type' => 'comment' , 33 | 'time' => date("Y-m-d H:i:s") , 34 | 'count' => '0' , 35 | 'status' => '0' 36 | ]; 37 | 38 | Tweet::create('notifications' , $data_notify); 39 | 40 | } 41 | 42 | User::create('comments' , $data); 43 | 44 | // $comments = Tweet::comments($tweet_id); 45 | // foreach($comments as $comment) { 46 | // $tweet_user = User::getData($comment->user_id) ; 47 | // echo '
    48 | 49 | 50 | //
    51 | //
    52 | // 57 | //
    58 | 59 | //
    60 | //

    61 | // '. $tweet_user->name .' 62 | // @ '.$tweet_user->username.' 63 | // $timeAgo 64 | //

    65 | //

    66 | 67 | // '. Tweet::getTweetLinks($comment->comment) .' 68 | //

    69 | //
    70 | 71 | //
    '; 72 | // } 73 | 74 | 75 | 76 | } 77 | } 78 | 79 | if(isset($_POST['reply']) && !empty($_POST['reply'])){ 80 | $tweet_id = $_POST['reply']; 81 | $get_id = $_POST['user_id']; 82 | 83 | $comment = User::checkInput($_POST['comment']); 84 | 85 | date_default_timezone_set("Africa/Cairo"); 86 | 87 | 88 | $data = [ 89 | 'user_id' => $_SESSION['user_id'] , 90 | 'comment_id' => $tweet_id , 91 | 'reply' => $comment , 92 | 'time' => date("Y-m-d H:i:s") , 93 | ]; 94 | if ($comment != '') { 95 | // notification 96 | $for_user = Tweet::getComment($tweet_id)->user_id; 97 | $target = Tweet::getComment($tweet_id)->post_id; 98 | 99 | if($for_user != $user_id) { 100 | $data_notify = [ 101 | 'notify_for' => $for_user , 102 | 'notify_from' => $user_id , 103 | 'target' => $target , 104 | 'type' => 'reply' , 105 | 'time' => date("Y-m-d H:i:s") , 106 | 'count' => '0' , 107 | 'status' => '0' 108 | ]; 109 | 110 | Tweet::create('notifications' , $data_notify); 111 | 112 | } 113 | // end 114 | 115 | User::create('replies' , $data); 116 | } 117 | } 118 | // Comment on Post popup 119 | if(isset($_POST['showPopup']) && !empty($_POST['showPopup'])){ 120 | $tweet_id = $_POST['showPopup']; 121 | $user = User::getData($user_id); 122 | $retweet_comment = false; 123 | $qoq = false; 124 | if (Tweet::isRetweet($tweet_id)) { 125 | $retweet =Tweet::getRetweet($tweet_id); 126 | if ($retweet->retweet_id == null) { 127 | 128 | // when the retweetd tweet is normal tweet 129 | 130 | if ($retweet->retweet_msg != null) { 131 | 132 | // when qoute 133 | 134 | $user_tweet = User::getData($retweet->user_id) ; 135 | $timeAgo = Tweet::getTimeAgo($retweet->post_on) ; 136 | $qoute = $retweet->retweet_msg; 137 | $retweet_comment = true; 138 | 139 | 140 | $tweet_inner = Tweet::getTweet($retweet->tweet_id); 141 | $user_inner_tweet = User::getData($tweet_inner->user_id) ; 142 | $timeAgo_inner = Tweet::getTimeAgo($tweet_inner->post_on); 143 | 144 | 145 | } else { 146 | // when normal retweet 147 | 148 | $tweet = Tweet::getTweet($retweet->tweet_id); 149 | $user_tweet = User::getData($tweet->user_id); 150 | $timeAgo = Tweet::getTimeAgo($tweet->post_on) ; 151 | } 152 | } else { 153 | // if tweet_id = null and retweeted_id not null then it's retweet od qoute 154 | // so we have to get the retweeted tweet first 155 | 156 | // here condtion of retweeted a qouted tweet 157 | 158 | if ($retweet->retweet_msg == null) { 159 | 160 | $retweeted_tweet = Tweet::getRetweet($retweet->retweet_id); 161 | 162 | if($retweeted_tweet->tweet_id != null) { 163 | $user_tweet = User::getData($retweeted_tweet->user_id) ; 164 | $timeAgo = Tweet::getTimeAgo($retweeted_tweet->post_on) ; 165 | 166 | $retweet_inner = Tweet::getRetweet($retweet->retweet_id); 167 | 168 | $qoute = $retweet_inner->retweet_msg; 169 | $retweet_comment = true; 170 | 171 | 172 | 173 | $tweet_inner = Tweet::getTweet($retweet_inner->tweet_id); 174 | $user_inner_tweet = User::getData($tweet_inner->user_id) ; 175 | $timeAgo_inner = Tweet::getTimeAgo($tweet_inner->post_on); 176 | 177 | } else { 178 | // hereeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee 179 | 180 | $user_tweet = User::getData($retweeted_tweet->user_id) ; 181 | $timeAgo = Tweet::getTimeAgo($retweeted_tweet->post_on) ; 182 | 183 | $retweet_inner = Tweet::getRetweet($retweet->retweet_id); 184 | 185 | $qoute = $retweet_inner->retweet_msg; 186 | $retweet_comment = true; 187 | $qoq = true; 188 | 189 | 190 | $tweet_inner = Tweet::getRetweet($retweeted_tweet->retweet_id); 191 | // $tweet_inner = Tweet::getRetweet($tweet_inner->retweet_id); 192 | $user_inner_tweet = User::getData($tweet_inner->user_id) ; 193 | $timeAgo_inner = Tweet::getTimeAgo($tweet_inner->post_on); 194 | $inner_qoute = $tweet_inner->retweet_msg; 195 | 196 | } 197 | } else { 198 | 199 | // here must handle the qoute of qoute display 200 | 201 | $user_tweet = User::getData($retweet->user_id) ; 202 | $timeAgo = Tweet::getTimeAgo($retweet->post_on) ; 203 | // $likes_count = Tweet::countLikes($tweet->id) ; 204 | // $user_like_it = Tweet::userLikeIt($user_id ,$tweet->id); 205 | // $retweets_count = Tweet::countRetweets($tweet->id) ; 206 | // $user_retweeted_it = Tweet::userRetweeetedIt($user_id ,$tweet->id); 207 | $qoute = $retweet->retweet_msg; 208 | $qoq = true; // stand for qoute of qoute 209 | 210 | $tweet_inner = Tweet::getRetweet($retweet->retweet_id); 211 | $user_inner_tweet = User::getData($tweet_inner->user_id) ; 212 | $timeAgo_inner = Tweet::getTimeAgo($tweet_inner->post_on); 213 | $inner_qoute = $tweet_inner->retweet_msg; 214 | } 215 | 216 | } 217 | 218 | } else { 219 | 220 | // when normal tweet 221 | 222 | $tweet = Tweet::getTweet($tweet_id); 223 | $user_tweet = User::getData($tweet->user_id); 224 | $timeAgo = Tweet::getTimeAgo($tweet->post_on) ; 225 | 226 | 227 | } 228 | 229 | ?> 230 |
    231 |
    232 |
    233 |
    234 |

    Reply Tweet

    235 | 236 |
    237 |
    238 |
    239 | 240 |
    241 |
    242 | 243 | 244 |
    245 |
    246 | 251 |
    252 | 253 |
    254 |

    255 | name ?> 256 | @username ?> 257 | 258 |

    259 |

    260 | status); ?> 265 |

    266 | 267 | 268 | img != null) { ?> 269 |

    270 | 275 |

    276 | 277 | 278 | 279 |
    280 | 281 |
    282 |
    283 | 288 |
    289 | 290 |
    291 |

    292 | name ?> 293 | @username ?> 294 | 295 |

    296 |

    297 | status); ?> 301 |

    302 | img != null) { ?> 305 |

    306 | 311 |

    312 | 313 | 314 |
    315 |
    316 | 317 | 318 |
    319 | 320 | 321 | 322 | 323 |
    324 |
    325 | 326 | 327 | 337 | 338 | 339 |
    340 | 341 | 342 | 343 | user_id); 354 | $timeAgo = Tweet::getTimeAgo($tweet->time) ; 355 | 356 | ?> 357 |
    358 |
    359 |
    360 |
    361 |

    Reply Comment

    362 | 363 |
    364 |
    365 |
    366 | 367 |
    368 |
    369 | 370 | 371 |
    372 |
    373 | 378 |
    379 | 380 |
    381 |

    382 | name ?> 383 | @username ?> 384 | 385 |

    386 |

    387 | comment); ?> 390 |

    391 | 392 |
    393 |
    394 | 395 | 396 | 397 | 398 | 399 | 407 | 408 | 409 |
    410 | 411 | 412 | 413 | 414 | 415 | -------------------------------------------------------------------------------- /account.php: -------------------------------------------------------------------------------- 1 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | Settings | Twitter 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 |
    37 |
    38 | 142 |
    143 | 144 | 145 | 146 |
    147 |
    148 |
    149 | 152 | 153 |
    154 | 155 |
    156 | 157 |
    158 |
    159 | 164 |
    165 |
    166 | 167 | 168 |
    169 | 170 | 173 | 174 | 175 | 176 | 179 | 180 | 181 | 182 |
    183 | 184 | 185 | 186 |
    187 |
    188 | 189 | 190 |
    191 | 192 |
    193 | 194 | 195 |
    196 | 197 |
    198 | 199 |
    200 |
    201 | 202 | 203 | 204 | 205 |
    206 | 207 | 210 | 211 | 212 | 219 | 220 | 221 | 222 | 225 | 226 | 227 | 228 | 229 |
    230 | 231 | 232 | 233 |
    234 |
    235 | 236 | 237 |
    238 | 239 |
    240 | 241 | 242 |
    243 | 244 |
    245 | 246 | 247 |
    248 | 249 |
    250 | 251 |
    252 | 253 |
    254 | 255 |
    256 | 257 |
    258 |
    259 |
    260 | 261 |
    262 | 263 |
    264 | 265 | 266 | 267 |
    268 | 269 | 270 |
    271 |
    272 |
    273 | 274 | 275 | 276 | 277 | 278 | 279 |
    280 |

    Who to follow

    281 | user_id); 284 | $user_follow = Follow::isUserFollow($user_id , $user->id) ; 285 | ?> 286 |
    287 | 288 | 293 | 294 |
    295 |

    296 | 297 | name; ?> 298 | 299 |

    300 |

    @username; ?> 301 | id , $user_id)) { ?> 302 | Follows You

    303 |

    304 |
    305 |
    306 | 318 |
    319 |
    320 | 321 | 322 | 323 | 324 |
    325 | 326 | 327 | 328 |
    329 |
    330 | 331 | 332 | 333 | 334 | 335 | 336 | 337 | -------------------------------------------------------------------------------- /notification.php: -------------------------------------------------------------------------------- 1 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | Notifications | Twitter 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 |
    39 |
    40 | 144 |
    145 | 146 | 147 | 148 |
    149 |
    150 |
    151 | 154 | 155 |
    156 | 157 |
    158 | 159 |
    160 |
    161 |
    162 |
    163 | 164 |
    165 |
    166 |

    Notifications

    167 |
    168 |
    169 | 170 |
    171 |
    172 | 173 | notify_from); 175 | $timeAgo = Tweet::getTimeAgo($notify->time); 176 | ?> 177 | type == 'like') { 178 | $icon = ""; 179 | $msg = "Liked Your Tweet"; 180 | } else if ($notify->type == 'retweet') { 181 | $icon = ""; 182 | $msg = "Retweeted Your Tweet"; 183 | } else if ($notify->type == 'qoute') { 184 | $icon = ""; 185 | $msg = "Qouted Your Tweet"; 186 | } else if ($notify->type == 'comment') { 187 | $icon = ""; 188 | $msg = "Comment to your Tweet"; 189 | } else if ($notify->type == 'reply') { 190 | $icon = ""; 191 | $msg = "Reply to your Comment"; 192 | } else if ($notify->type == 'follow') { 193 | $icon = ""; 194 | $msg = "Followed You"; 195 | } else if ($notify->type == 'mention') { 196 | $icon = ""; 197 | $msg = "Mention you in Tweet"; 198 | }?> 199 | 200 |
    201 | 207 | 208 | 209 |
    210 |
    211 | 212 |
    213 |
    214 |

    215 | 216 | 217 | 218 | 219 |

    220 |

    223 | name; ?> 224 | 225 | 226 | 227 |

    228 |
    229 |
    230 |
    231 | 232 |
    233 | 234 | 235 | 236 |
    237 |
    238 | 239 |
    240 |
    241 | 242 |
    243 | 244 | 245 | 246 |
    247 | 248 | 249 |
    250 |
    251 |
    252 | 253 | 254 | 255 |
    256 |

    Who to follow

    257 | user_id); 260 | $user_follow = Follow::isUserFollow($user_id , $user->id) ; 261 | ?> 262 |
    263 | 264 | 269 | 270 |
    271 |

    272 | 273 | name; ?> 274 | 275 |

    276 |

    @username; ?> 277 | id , $user_id)) { ?> 278 | Follows You

    279 |

    280 |
    281 |
    282 | 294 |
    295 |
    296 | 297 | 298 | 299 | 300 |
    301 | 302 | 303 |
    304 |
    305 | 306 | 307 | 308 | 309 | 310 | 311 | 312 | 313 | 314 | 315 | 316 | 317 | 318 | 319 | 320 | -------------------------------------------------------------------------------- /home.php: -------------------------------------------------------------------------------- 1 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | Home | Twitter 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 48 | 49 | 50 | 51 | 83 | 84 | 85 | 86 | 87 | 88 |
    89 | 90 |
    91 | 195 |
    196 | 197 | 198 |
    199 |
    200 |
    201 | 288 | 291 |
    292 |
    293 | 294 | 295 | 296 |
    297 | 298 | 299 |
    300 |
    301 | 302 |
    303 | 304 | 305 | 306 |
    307 | 308 | 309 |
    310 |
    311 |
    312 | 313 | 314 | 315 | 316 | 317 |
    318 |

    Who to follow

    319 | user_id); 322 | $user_follow = Follow::isUserFollow($user_id , $user->id) ; 323 | ?> 324 |
    325 | 326 | 331 | 332 |
    333 |

    334 | 335 | name; ?> 336 | 337 |

    338 |

    @username; ?> 339 | id , $user_id)) { ?> 340 | Follows You

    341 |

    342 |
    343 |
    344 | 356 |
    357 |
    358 | 359 | 360 | 361 | 362 |
    363 | 364 | 365 |
    366 |
    367 |
    368 | 369 | 370 | 371 | 372 | 373 | 374 | 375 | 376 | 377 | 378 | 379 | 380 | 381 | 382 | -------------------------------------------------------------------------------- /twitter.sql: -------------------------------------------------------------------------------- 1 | -- phpMyAdmin SQL Dump 2 | -- version 5.0.2 3 | -- https://www.phpmyadmin.net/ 4 | -- 5 | -- Host: 127.0.0.1 6 | -- Generation Time: May 13, 2021 at 03:16 PM 7 | -- Server version: 10.4.13-MariaDB 8 | -- PHP Version: 7.4.7 9 | 10 | SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO"; 11 | START TRANSACTION; 12 | SET time_zone = "+00:00"; 13 | 14 | 15 | /*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; 16 | /*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; 17 | /*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; 18 | /*!40101 SET NAMES utf8mb4 */; 19 | 20 | -- 21 | -- Database: `twitter` 22 | -- 23 | 24 | -- -------------------------------------------------------- 25 | 26 | -- 27 | -- Table structure for table `comments` 28 | -- 29 | 30 | CREATE TABLE `comments` ( 31 | `id` int(11) NOT NULL, 32 | `comment` varchar(140) COLLATE utf16_unicode_ci NOT NULL, 33 | `user_id` int(11) NOT NULL, 34 | `post_id` int(11) NOT NULL, 35 | `time` datetime NOT NULL 36 | ) ENGINE=InnoDB DEFAULT CHARSET=utf16 COLLATE=utf16_unicode_ci; 37 | 38 | -- 39 | -- Dumping data for table `comments` 40 | -- 41 | 42 | INSERT INTO `comments` (`id`, `comment`, `user_id`, `post_id`, `time`) VALUES 43 | (44, 'great work', 25, 574, '2021-05-01 02:21:10'), 44 | (45, 'sasa', 2, 712, '2021-05-01 05:31:56'); 45 | 46 | -- -------------------------------------------------------- 47 | 48 | -- 49 | -- Table structure for table `follow` 50 | -- 51 | 52 | CREATE TABLE `follow` ( 53 | `id` int(11) NOT NULL, 54 | `follower_id` int(11) NOT NULL, 55 | `following_id` int(11) NOT NULL, 56 | `time` datetime NOT NULL 57 | ) ENGINE=InnoDB DEFAULT CHARSET=utf16 COLLATE=utf16_unicode_ci; 58 | 59 | -- 60 | -- Dumping data for table `follow` 61 | -- 62 | 63 | INSERT INTO `follow` (`id`, `follower_id`, `following_id`, `time`) VALUES 64 | (15, 40, 2, '2021-04-19 18:30:06'), 65 | (16, 33, 2, '2021-04-19 18:30:56'), 66 | (41, 37, 2, '2021-04-20 20:19:49'), 67 | (43, 5, 2, '2021-04-20 20:20:32'), 68 | (44, 27, 2, '2021-04-20 20:21:18'), 69 | (45, 34, 2, '2021-04-20 20:22:07'), 70 | (90, 41, 2, '2021-04-25 18:20:22'), 71 | (94, 25, 27, '2021-04-27 07:07:27'), 72 | (98, 42, 2, '2021-04-29 06:30:41'), 73 | (99, 43, 2, '2021-04-29 06:32:50'), 74 | (100, 44, 2, '2021-04-29 18:17:25'), 75 | (101, 2, 25, '2021-04-30 02:16:24'), 76 | (102, 25, 2, '2021-04-30 22:56:21'), 77 | (120, 54, 2, '2021-05-01 06:57:13'), 78 | (121, 55, 2, '2021-05-12 16:18:45'), 79 | (126, 56, 2, '2021-05-12 16:35:31'), 80 | (128, 57, 2, '2021-05-12 18:23:30'), 81 | (129, 58, 2, '2021-05-13 14:52:58'); 82 | 83 | -- -------------------------------------------------------- 84 | 85 | -- 86 | -- Table structure for table `likes` 87 | -- 88 | 89 | CREATE TABLE `likes` ( 90 | `id` int(11) NOT NULL, 91 | `user_id` int(11) NOT NULL, 92 | `post_id` int(11) NOT NULL 93 | ) ENGINE=InnoDB DEFAULT CHARSET=utf16 COLLATE=utf16_unicode_ci; 94 | 95 | -- 96 | -- Dumping data for table `likes` 97 | -- 98 | 99 | INSERT INTO `likes` (`id`, `user_id`, `post_id`) VALUES 100 | (192, 2, 362), 101 | (209, 25, 573), 102 | (211, 2, 573), 103 | (214, 2, 574), 104 | (224, 25, 635), 105 | (225, 25, 712), 106 | (227, 2, 711); 107 | 108 | -- -------------------------------------------------------- 109 | 110 | -- 111 | -- Table structure for table `notifications` 112 | -- 113 | 114 | CREATE TABLE `notifications` ( 115 | `id` int(11) NOT NULL, 116 | `notify_for` int(11) NOT NULL, 117 | `notify_from` int(11) NOT NULL, 118 | `target` int(11) NOT NULL, 119 | `type` enum('follow','like','retweet','qoute','comment','reply','mention') COLLATE utf16_unicode_ci NOT NULL, 120 | `time` datetime NOT NULL, 121 | `count` int(11) NOT NULL, 122 | `status` int(11) NOT NULL 123 | ) ENGINE=InnoDB DEFAULT CHARSET=utf16 COLLATE=utf16_unicode_ci; 124 | 125 | -- 126 | -- Dumping data for table `notifications` 127 | -- 128 | 129 | INSERT INTO `notifications` (`id`, `notify_for`, `notify_from`, `target`, `type`, `time`, `count`, `status`) VALUES 130 | (30, 2, 25, 635, 'like', '2021-04-29 05:50:12', 1, 0), 131 | (32, 2, 42, 0, 'follow', '2021-04-29 06:30:41', 1, 0), 132 | (34, 2, 25, 711, 'qoute', '2021-04-29 18:29:24', 1, 0), 133 | (35, 25, 2, 712, 'qoute', '2021-04-29 18:29:55', 1, 0), 134 | (36, 2, 25, 712, 'like', '2021-04-29 18:31:11', 1, 0), 135 | (37, 2, 25, 712, 'retweet', '2021-04-29 18:31:19', 1, 0), 136 | (38, 25, 2, 0, 'follow', '2021-04-30 02:16:24', 1, 0), 137 | (39, 2, 25, 0, 'follow', '2021-04-30 22:56:20', 1, 0), 138 | (53, 2, 25, 574, 'comment', '2021-05-01 02:21:10', 1, 0), 139 | (54, 25, 2, 574, 'reply', '2021-05-01 02:21:51', 1, 0), 140 | (55, 2, 42, 725, 'mention', '2021-05-01 02:25:37', 1, 0), 141 | (58, 25, 2, 711, 'like', '2021-05-01 04:32:36', 1, 0), 142 | (67, 2, 54, 0, 'follow', '2021-05-01 06:57:13', 1, 0), 143 | (68, 2, 55, 0, 'follow', '2021-05-12 16:18:46', 1, 0), 144 | (73, 2, 56, 0, 'follow', '2021-05-12 16:35:31', 1, 0), 145 | (75, 2, 57, 0, 'follow', '2021-05-12 18:23:30', 1, 0), 146 | (76, 2, 58, 0, 'follow', '2021-05-13 14:52:58', 1, 0); 147 | 148 | -- -------------------------------------------------------- 149 | 150 | -- 151 | -- Table structure for table `posts` 152 | -- 153 | 154 | CREATE TABLE `posts` ( 155 | `id` int(11) NOT NULL, 156 | `user_id` int(11) NOT NULL, 157 | `post_on` datetime NOT NULL 158 | ) ENGINE=InnoDB DEFAULT CHARSET=utf16 COLLATE=utf16_unicode_ci; 159 | 160 | -- 161 | -- Dumping data for table `posts` 162 | -- 163 | 164 | INSERT INTO `posts` (`id`, `user_id`, `post_on`) VALUES 165 | (362, 2, '2021-02-06 08:31:07'), 166 | (573, 2, '2021-04-02 03:03:39'), 167 | (574, 2, '2021-04-02 03:04:53'), 168 | (635, 2, '2021-04-15 09:03:32'), 169 | (654, 2, '2021-04-25 02:19:45'), 170 | (711, 25, '2021-04-29 18:29:24'), 171 | (712, 2, '2021-04-29 18:29:55'); 172 | 173 | -- -------------------------------------------------------- 174 | 175 | -- 176 | -- Table structure for table `replies` 177 | -- 178 | 179 | CREATE TABLE `replies` ( 180 | `id` int(11) NOT NULL, 181 | `comment_id` int(11) NOT NULL, 182 | `user_id` int(11) NOT NULL, 183 | `reply` varchar(140) COLLATE utf16_unicode_ci NOT NULL, 184 | `time` datetime NOT NULL 185 | ) ENGINE=InnoDB DEFAULT CHARSET=utf16 COLLATE=utf16_unicode_ci; 186 | 187 | -- 188 | -- Dumping data for table `replies` 189 | -- 190 | 191 | INSERT INTO `replies` (`id`, `comment_id`, `user_id`, `reply`, `time`) VALUES 192 | (11, 44, 2, 'ty', '2021-05-01 02:21:51'); 193 | 194 | -- -------------------------------------------------------- 195 | 196 | -- 197 | -- Table structure for table `retweets` 198 | -- 199 | 200 | CREATE TABLE `retweets` ( 201 | `post_id` int(11) NOT NULL, 202 | `retweet_msg` varchar(140) COLLATE utf16_unicode_ci DEFAULT NULL, 203 | `tweet_id` int(11) DEFAULT NULL, 204 | `retweet_id` int(11) DEFAULT NULL 205 | ) ENGINE=InnoDB DEFAULT CHARSET=utf16 COLLATE=utf16_unicode_ci; 206 | 207 | -- 208 | -- Dumping data for table `retweets` 209 | -- 210 | 211 | INSERT INTO `retweets` (`post_id`, `retweet_msg`, `tweet_id`, `retweet_id`) VALUES 212 | (711, 'good job', 654, NULL), 213 | (712, '<3', NULL, 711); 214 | 215 | -- -------------------------------------------------------- 216 | 217 | -- 218 | -- Table structure for table `trends` 219 | -- 220 | 221 | CREATE TABLE `trends` ( 222 | `id` int(11) NOT NULL, 223 | `hashtag` varchar(140) COLLATE utf16_unicode_ci NOT NULL, 224 | `created_on` datetime NOT NULL 225 | ) ENGINE=InnoDB DEFAULT CHARSET=utf16 COLLATE=utf16_unicode_ci; 226 | 227 | -- 228 | -- Dumping data for table `trends` 229 | -- 230 | 231 | INSERT INTO `trends` (`id`, `hashtag`, `created_on`) VALUES 232 | (1, 'php', '2021-01-06 05:57:43'), 233 | (4, 'hi', '2021-01-25 21:42:35'), 234 | (5, 'alex', '2021-01-25 21:42:36'), 235 | (6, '7oda', '2021-03-20 23:40:12'), 236 | (9, 'js', '2021-04-02 03:24:28'), 237 | (12, 'bro', '2021-04-02 03:31:38'); 238 | 239 | -- -------------------------------------------------------- 240 | 241 | -- 242 | -- Table structure for table `tweets` 243 | -- 244 | 245 | CREATE TABLE `tweets` ( 246 | `post_id` int(11) NOT NULL, 247 | `status` varchar(140) COLLATE utf16_unicode_ci DEFAULT NULL, 248 | `img` text COLLATE utf16_unicode_ci DEFAULT NULL 249 | ) ENGINE=InnoDB DEFAULT CHARSET=utf16 COLLATE=utf16_unicode_ci; 250 | 251 | -- 252 | -- Dumping data for table `tweets` 253 | -- 254 | 255 | INSERT INTO `tweets` (`post_id`, `status`, `img`) VALUES 256 | (362, '@amin hello it\'s amin here!', NULL), 257 | (573, 'one day!', 'tweet-60666d6b426a1.jpg'), 258 | (574, '#php is fun', NULL), 259 | (635, '', 'tweet-6077e54477f73.jpeg'), 260 | (654, 'it\'s all about big dreams!', NULL); 261 | 262 | -- -------------------------------------------------------- 263 | 264 | -- 265 | -- Table structure for table `users` 266 | -- 267 | 268 | CREATE TABLE `users` ( 269 | `id` int(11) NOT NULL, 270 | `username` varchar(40) COLLATE utf16_unicode_ci NOT NULL, 271 | `email` varchar(255) COLLATE utf16_unicode_ci NOT NULL, 272 | `password` varchar(32) COLLATE utf16_unicode_ci NOT NULL, 273 | `name` varchar(40) COLLATE utf16_unicode_ci NOT NULL, 274 | `img` varchar(255) COLLATE utf16_unicode_ci NOT NULL DEFAULT 'default.jpg', 275 | `imgCover` varchar(255) COLLATE utf16_unicode_ci NOT NULL DEFAULT 'cover.png', 276 | `bio` varchar(140) COLLATE utf16_unicode_ci NOT NULL DEFAULT '', 277 | `location` varchar(255) COLLATE utf16_unicode_ci NOT NULL DEFAULT '', 278 | `website` varchar(255) COLLATE utf16_unicode_ci NOT NULL DEFAULT '' 279 | ) ENGINE=InnoDB DEFAULT CHARSET=utf16 COLLATE=utf16_unicode_ci; 280 | 281 | -- 282 | -- Dumping data for table `users` 283 | -- 284 | 285 | INSERT INTO `users` (`id`, `username`, `email`, `password`, `name`, `img`, `imgCover`, `bio`, `location`, `website`) VALUES 286 | (2, 'amin', 'amin@twitter.com', '8e4e9b7ac6fc0df9e06f57f1c366cf8a', 'Amin.', 'user-608b4b4187b5c.JPG', 'user-607ef530bdeab.jpg', 'Undergraduate Software Engineer.', 'Alexandria,Egypt', 'https://github.com/aminyasser'), 287 | (5, 'bodatolba', 'tolba@twitter.com', 'e10adc3949ba59abbe56e057f20f883e', 'Tolba', 'default.jpg', 'cover.png', '', '', ''), 288 | (25, '7oda', '7oda@twitter.com', 'e10adc3949ba59abbe56e057f20f883e', '7oda', 'default.jpg', 'cover.png', '', '', ''), 289 | (27, 'hasona', 'hasona@twitter.com', 'e10adc3949ba59abbe56e057f20f883e', 'hassan', 'default.jpg', 'cover.png', '', '', ''), 290 | (33, '7odawael', 'wael@twitter.com', 'e10adc3949ba59abbe56e057f20f883e', 'Mahmoud', 'default.jpg', 'cover.png', '', '', ''), 291 | (34, 'haidy', 'haidy@twitter.com', 'e10adc3949ba59abbe56e057f20f883e', 'haidy', 'default.jpg', 'cover.png', '', '', ''), 292 | (37, 'aminn', 'amin1@twitter.com', 'e10adc3949ba59abbe56e057f20f883e', 'Amin Yasser', 'default.jpg', 'cover.png', '', '', ''), 293 | (40, 'mohanadyasser', 'mohanad@twitter.com', 'e10adc3949ba59abbe56e057f20f883e', 'Mohanad', 'default.jpg', 'cover.png', '', '', ''), 294 | (41, 'khaled0', 'khaled@twitter.com', 'e10adc3949ba59abbe56e057f20f883e', 'Khalid', 'default.jpg', 'cover.png', '', '', ''), 295 | (42, 'ahmed0', 'ahmed@twitter.com', 'e10adc3949ba59abbe56e057f20f883e', 'Ahmed', 'default.jpg', 'user-609be2968c0b9.png', '', '', ''), 296 | (43, 'samy', 'samy@twitter.com', 'e10adc3949ba59abbe56e057f20f883e', 'Samy', 'default.jpg', 'cover.png', '', '', ''), 297 | (44, 'remo', 'remo@twitter.com', 'e10adc3949ba59abbe56e057f20f883e', 'Ramez', 'default.jpg', 'cover.png', '', '', ''), 298 | (54, 'aminyasser', 'amino@twitter.com', 'e10adc3949ba59abbe56e057f20f883e', 'Amin Yasser', 'default.jpg', 'cover.png', '', '', ''), 299 | (55, 'sasaa', 'aminsss@twitter.com', 'e10adc3949ba59abbe56e057f20f883e', 'Amin Yasser', 'user-609be3deec8e5.jpg', 'cover.png', '', '', ''), 300 | (56, 'nbnbkj', 'nn@twittt.com', 'e10adc3949ba59abbe56e057f20f883e', 'Markting', 'default.jpg', 'cover.png', '', '', ''), 301 | (57, 'sas', 'amin@ydar.com', 'e10adc3949ba59abbe56e057f20f883e', 'Amin Yasser', 'default.jpg', 'cover.png', '', '', ''), 302 | (58, '201', 'amin111@twitter.com', 'e10adc3949ba59abbe56e057f20f883e', 'Amin1', 'default.jpg', 'cover.png', 'Hey', '', ''); 303 | 304 | -- 305 | -- Indexes for dumped tables 306 | -- 307 | 308 | -- 309 | -- Indexes for table `comments` 310 | -- 311 | ALTER TABLE `comments` 312 | ADD PRIMARY KEY (`id`), 313 | ADD KEY `post_id` (`post_id`), 314 | ADD KEY `user_id` (`user_id`); 315 | 316 | -- 317 | -- Indexes for table `follow` 318 | -- 319 | ALTER TABLE `follow` 320 | ADD PRIMARY KEY (`id`), 321 | ADD KEY `follower_id` (`follower_id`), 322 | ADD KEY `following_id` (`following_id`); 323 | 324 | -- 325 | -- Indexes for table `likes` 326 | -- 327 | ALTER TABLE `likes` 328 | ADD PRIMARY KEY (`id`), 329 | ADD KEY `user_id` (`user_id`), 330 | ADD KEY `likes_ibfk_2` (`post_id`); 331 | 332 | -- 333 | -- Indexes for table `notifications` 334 | -- 335 | ALTER TABLE `notifications` 336 | ADD PRIMARY KEY (`id`), 337 | ADD KEY `notifications_ibfk_1` (`notify_for`), 338 | ADD KEY `notifications_ibfk_2` (`notify_from`); 339 | 340 | -- 341 | -- Indexes for table `posts` 342 | -- 343 | ALTER TABLE `posts` 344 | ADD PRIMARY KEY (`id`), 345 | ADD KEY `user_id` (`user_id`); 346 | 347 | -- 348 | -- Indexes for table `replies` 349 | -- 350 | ALTER TABLE `replies` 351 | ADD PRIMARY KEY (`id`), 352 | ADD KEY `comment_id` (`comment_id`), 353 | ADD KEY `user_id` (`user_id`); 354 | 355 | -- 356 | -- Indexes for table `retweets` 357 | -- 358 | ALTER TABLE `retweets` 359 | ADD PRIMARY KEY (`post_id`) USING BTREE, 360 | ADD KEY `retweet_id` (`retweet_id`), 361 | ADD KEY `retweets_ibfk_2` (`tweet_id`); 362 | 363 | -- 364 | -- Indexes for table `trends` 365 | -- 366 | ALTER TABLE `trends` 367 | ADD PRIMARY KEY (`id`), 368 | ADD UNIQUE KEY `hashtag` (`hashtag`); 369 | 370 | -- 371 | -- Indexes for table `tweets` 372 | -- 373 | ALTER TABLE `tweets` 374 | ADD PRIMARY KEY (`post_id`); 375 | 376 | -- 377 | -- Indexes for table `users` 378 | -- 379 | ALTER TABLE `users` 380 | ADD PRIMARY KEY (`id`); 381 | 382 | -- 383 | -- AUTO_INCREMENT for dumped tables 384 | -- 385 | 386 | -- 387 | -- AUTO_INCREMENT for table `comments` 388 | -- 389 | ALTER TABLE `comments` 390 | MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=46; 391 | 392 | -- 393 | -- AUTO_INCREMENT for table `follow` 394 | -- 395 | ALTER TABLE `follow` 396 | MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=136; 397 | 398 | -- 399 | -- AUTO_INCREMENT for table `likes` 400 | -- 401 | ALTER TABLE `likes` 402 | MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=228; 403 | 404 | -- 405 | -- AUTO_INCREMENT for table `notifications` 406 | -- 407 | ALTER TABLE `notifications` 408 | MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=83; 409 | 410 | -- 411 | -- AUTO_INCREMENT for table `posts` 412 | -- 413 | ALTER TABLE `posts` 414 | MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=726; 415 | 416 | -- 417 | -- AUTO_INCREMENT for table `replies` 418 | -- 419 | ALTER TABLE `replies` 420 | MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=12; 421 | 422 | -- 423 | -- AUTO_INCREMENT for table `trends` 424 | -- 425 | ALTER TABLE `trends` 426 | MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=13; 427 | 428 | -- 429 | -- AUTO_INCREMENT for table `users` 430 | -- 431 | ALTER TABLE `users` 432 | MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=59; 433 | 434 | -- 435 | -- Constraints for dumped tables 436 | -- 437 | 438 | -- 439 | -- Constraints for table `comments` 440 | -- 441 | ALTER TABLE `comments` 442 | ADD CONSTRAINT `comments_ibfk_1` FOREIGN KEY (`post_id`) REFERENCES `posts` (`id`) ON DELETE CASCADE ON UPDATE CASCADE, 443 | ADD CONSTRAINT `comments_ibfk_2` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE CASCADE ON UPDATE CASCADE; 444 | 445 | -- 446 | -- Constraints for table `follow` 447 | -- 448 | ALTER TABLE `follow` 449 | ADD CONSTRAINT `follow_ibfk_1` FOREIGN KEY (`follower_id`) REFERENCES `users` (`id`) ON DELETE CASCADE ON UPDATE CASCADE, 450 | ADD CONSTRAINT `follow_ibfk_2` FOREIGN KEY (`following_id`) REFERENCES `users` (`id`) ON DELETE CASCADE ON UPDATE CASCADE; 451 | 452 | -- 453 | -- Constraints for table `likes` 454 | -- 455 | ALTER TABLE `likes` 456 | ADD CONSTRAINT `likes_ibfk_1` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE CASCADE ON UPDATE CASCADE, 457 | ADD CONSTRAINT `likes_ibfk_2` FOREIGN KEY (`post_id`) REFERENCES `posts` (`id`) ON DELETE CASCADE ON UPDATE CASCADE; 458 | 459 | -- 460 | -- Constraints for table `notifications` 461 | -- 462 | ALTER TABLE `notifications` 463 | ADD CONSTRAINT `notifications_ibfk_1` FOREIGN KEY (`notify_for`) REFERENCES `users` (`id`) ON DELETE CASCADE ON UPDATE CASCADE, 464 | ADD CONSTRAINT `notifications_ibfk_2` FOREIGN KEY (`notify_from`) REFERENCES `users` (`id`) ON DELETE CASCADE ON UPDATE CASCADE; 465 | 466 | -- 467 | -- Constraints for table `posts` 468 | -- 469 | ALTER TABLE `posts` 470 | ADD CONSTRAINT `posts_ibfk_1` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE CASCADE ON UPDATE CASCADE; 471 | 472 | -- 473 | -- Constraints for table `replies` 474 | -- 475 | ALTER TABLE `replies` 476 | ADD CONSTRAINT `replies_ibfk_1` FOREIGN KEY (`comment_id`) REFERENCES `comments` (`id`) ON DELETE CASCADE ON UPDATE CASCADE, 477 | ADD CONSTRAINT `replies_ibfk_2` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE CASCADE ON UPDATE CASCADE; 478 | 479 | -- 480 | -- Constraints for table `retweets` 481 | -- 482 | ALTER TABLE `retweets` 483 | ADD CONSTRAINT `retweets_ibfk_1` FOREIGN KEY (`post_id`) REFERENCES `posts` (`id`) ON DELETE CASCADE ON UPDATE CASCADE, 484 | ADD CONSTRAINT `retweets_ibfk_2` FOREIGN KEY (`tweet_id`) REFERENCES `tweets` (`post_id`) ON DELETE CASCADE ON UPDATE CASCADE, 485 | ADD CONSTRAINT `retweets_ibfk_3` FOREIGN KEY (`retweet_id`) REFERENCES `retweets` (`post_id`) ON DELETE CASCADE ON UPDATE CASCADE; 486 | 487 | -- 488 | -- Constraints for table `tweets` 489 | -- 490 | ALTER TABLE `tweets` 491 | ADD CONSTRAINT `tweets_ibfk_1` FOREIGN KEY (`post_id`) REFERENCES `posts` (`id`) ON DELETE CASCADE ON UPDATE CASCADE; 492 | COMMIT; 493 | 494 | /*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; 495 | /*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; 496 | /*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; 497 | -------------------------------------------------------------------------------- /core/classes/Tweet.php: -------------------------------------------------------------------------------- 1 | prepare("SELECT * from `posts` 9 | WHERE user_id = :user_id OR user_id IN (SELECT following_id from `follow` WHERE follower_id = :user_id) 10 | ORDER BY post_on DESC"); 11 | $stmt->bindParam(":user_id" , $user_id , PDO::PARAM_STR); 12 | $stmt->execute(); 13 | return $stmt->fetchAll(PDO::FETCH_OBJ); 14 | } 15 | public static function tweetsUser($user_id) { 16 | $stmt = self::connect()->prepare("SELECT * from `posts` 17 | WHERE user_id = :user_id 18 | ORDER BY post_on DESC"); 19 | $stmt->bindParam(":user_id" , $user_id , PDO::PARAM_STR); 20 | $stmt->execute(); 21 | return $stmt->fetchAll(PDO::FETCH_OBJ); 22 | } 23 | public static function likedTweets($user_id) { 24 | $stmt = self::connect()->prepare("SELECT * from `posts` 25 | WHERE id IN (SELECT post_id from `likes` WHERE user_id = :user_id) 26 | ORDER BY post_on DESC"); 27 | $stmt->bindParam(":user_id" , $user_id , PDO::PARAM_STR); 28 | $stmt->execute(); 29 | return $stmt->fetchAll(PDO::FETCH_OBJ); 30 | } 31 | public static function mediaTweets($user_id) { 32 | $stmt = self::connect()->prepare("SELECT * from `posts` 33 | WHERE id IN (SELECT post_id from `tweets` WHERE user_id = :user_id AND img is not null) 34 | ORDER BY post_on DESC"); 35 | $stmt->bindParam(":user_id" , $user_id , PDO::PARAM_STR); 36 | $stmt->execute(); 37 | return $stmt->fetchAll(PDO::FETCH_OBJ); 38 | } 39 | public static function comments($tweet_id) { 40 | $stmt = self::connect()->prepare("SELECT * from `comments` 41 | WHERE post_id = :tweet_id 42 | ORDER BY time"); 43 | $stmt->bindParam(":tweet_id" , $tweet_id , PDO::PARAM_STR); 44 | $stmt->execute(); 45 | return $stmt->fetchAll(PDO::FETCH_OBJ); 46 | } 47 | 48 | public static function replies($comment_id) { 49 | $stmt = self::connect()->prepare("SELECT * from `replies` 50 | WHERE comment_id = :comment_id 51 | ORDER BY time"); 52 | $stmt->bindParam(":comment_id" , $comment_id , PDO::PARAM_STR); 53 | $stmt->execute(); 54 | return $stmt->fetchAll(PDO::FETCH_OBJ); 55 | } 56 | 57 | public static function isTweet($tweet_id){ 58 | 59 | $stmt = self::connect()->prepare("SELECT * FROM `tweets` 60 | WHERE `post_id` = :tweet_id"); 61 | $stmt->bindParam(":tweet_id", $tweet_id, PDO::PARAM_INT); 62 | $stmt->execute(); 63 | 64 | if ($stmt->rowCount() > 0) { 65 | return true; 66 | } else return false; 67 | } 68 | public static function isRetweet($tweet_id){ 69 | 70 | $stmt = self::connect()->prepare("SELECT * FROM `retweets` 71 | WHERE `post_id` = :tweet_id"); 72 | $stmt->bindParam(":tweet_id", $tweet_id, PDO::PARAM_INT); 73 | $stmt->execute(); 74 | 75 | if ($stmt->rowCount() > 0) { 76 | return true; 77 | } else return false; 78 | 79 | } 80 | 81 | public static function getTimeAgo($timestamp){ 82 | date_default_timezone_set("Africa/Cairo"); 83 | 84 | $time_ago = strtotime($timestamp); 85 | $current_time = strtotime(date("Y-m-d H:i:s")); 86 | // $current_time = time(); 87 | $time_difference = $current_time - $time_ago; 88 | $seconds = $time_difference; 89 | 90 | $minutes = round($seconds / 60); // value 60 is seconds 91 | $hours = round($seconds / 3600); //value 3600 is 60 minutes * 60 sec 92 | $days = round($seconds / 86400); //86400 = 24 * 60 * 60; 93 | $weeks = round($seconds / 604800); // 7*24*60*60; 94 | $months = round($seconds / 2629440); //((365+365+365+365+366)/5/12)*24*60*60 95 | $years = round($seconds / 31553280); //(365+365+365+365+366)/5 * 24 * 60 * 60 96 | 97 | if ($seconds <= 60){ 98 | 99 | return "just now"; 100 | 101 | } else if ($minutes <= 60){ 102 | 103 | if ($minutes == 1){ 104 | 105 | return "one minute ago"; 106 | 107 | } else { 108 | 109 | return "$minutes minutes ago"; 110 | 111 | } 112 | 113 | } else if ($hours <= 24){ 114 | 115 | if ($hours == 1){ 116 | 117 | return "an hour ago"; 118 | 119 | } else { 120 | 121 | return "$hours hrs ago"; 122 | 123 | } 124 | 125 | } else if ($days <= 7){ 126 | 127 | if ($days == 1){ 128 | 129 | return "yesterday"; 130 | 131 | } else { 132 | 133 | return "$days days ago"; 134 | 135 | } 136 | 137 | } else if ($weeks <= 4.3){ 138 | 139 | if ($weeks == 1){ 140 | 141 | return "a week ago"; 142 | 143 | } else { 144 | 145 | return "$weeks weeks ago"; 146 | 147 | } 148 | 149 | } else if ($months <= 12){ 150 | 151 | if ($months == 1){ 152 | 153 | return "a month ago"; 154 | 155 | } else { 156 | 157 | return "$months months ago"; 158 | 159 | } 160 | 161 | } else { 162 | 163 | if ($years == 1){ 164 | 165 | return "one year ago"; 166 | 167 | } else { 168 | 169 | return "$years years ago"; 170 | 171 | } 172 | } 173 | } 174 | 175 | 176 | 177 | public static function getTrendByHash($hashtag){ 178 | $stmt = self::connect()->prepare("SELECT * FROM `trends` 179 | WHERE `hashtag` LIKE :hashtag LIMIT 5"); 180 | $stmt->bindValue(":hashtag", $hashtag.'%'); 181 | $stmt->execute(); 182 | return $stmt->fetchAll(PDO::FETCH_OBJ); 183 | } 184 | 185 | public static function getMention($mension){ 186 | $stmt = self::connect()->prepare("SELECT `id`,`username`,`name`,`img` FROM `users` 187 | WHERE `username` LIKE :mension OR `name` LIKE :mension LIMIT 5"); 188 | $stmt->bindValue("mension", $mension.'%'); 189 | $stmt->execute(); 190 | return $stmt->fetchAll(PDO::FETCH_OBJ); 191 | 192 | } 193 | public static function HashtagExist($hash){ 194 | 195 | $stmt = self::connect()->prepare("SELECT * FROM `trends` 196 | WHERE `hashtag` = '$hash' "); 197 | // $stmt->bindParam(":hashtag", $hash, PDO::PARAM_INT); 198 | $stmt->execute(); 199 | 200 | if ($stmt->rowCount() > 0) { 201 | return true; 202 | } else return false; 203 | 204 | } 205 | 206 | public static function addTrend($hashtag){ 207 | preg_match_all("/#+([a-zA-Z0-9_]+)/i", $hashtag, $matches); 208 | if($matches){ 209 | $result = array_values($matches[1]); 210 | } 211 | $sql = "INSERT INTO `trends` (`hashtag`, `created_on`) VALUES (:hashtag, CURRENT_TIMESTAMP)"; 212 | foreach ($result as $trend) { 213 | if (!Tweet::HashtagExist($trend)) { 214 | 215 | if($stmt = self::connect()->prepare($sql)){ 216 | $stmt->execute(array(':hashtag' => $trend)); 217 | } 218 | } 219 | } 220 | } 221 | 222 | 223 | 224 | public static function getTweetLinks($tweet){ 225 | $tweet = preg_replace("/(https?:\/\/)([\w]+.)([\w\.]+)/", "$0", $tweet); 226 | $tweet = preg_replace("/#([\w]+)/", "$0", $tweet); 227 | $tweet = preg_replace("/@([\w]+)/", "$0", $tweet); 228 | return $tweet; 229 | } 230 | public static function hashtagAndMentionTweet($tweet){ 231 | $tweet = preg_replace("/(https?:\/\/)([\w]+.)([\w\.]+)/", "$0", $tweet); 232 | $tweet = preg_replace("/#([\w]+)/", "$0", $tweet); 233 | $tweet = preg_replace("/@([\w]+)/", "$0", $tweet); 234 | return $tweet; 235 | } 236 | 237 | public static function countLikes($post_id) { 238 | $stmt = self::connect()->prepare("SELECT COUNT(post_id) as count FROM `likes` 239 | WHERE post_id = :post_id"); 240 | $stmt->bindParam(":post_id" , $post_id , PDO::PARAM_STR); 241 | $stmt->execute(); 242 | $count = $stmt->fetch(PDO::FETCH_OBJ); 243 | return $count->count; 244 | } 245 | public static function countTweets($user_id) { 246 | $stmt = self::connect()->prepare("SELECT COUNT(user_id) as count FROM `posts` 247 | WHERE user_id = :user_id"); 248 | $stmt->bindParam(":user_id" , $user_id , PDO::PARAM_STR); 249 | $stmt->execute(); 250 | $count = $stmt->fetch(PDO::FETCH_OBJ); 251 | return $count->count; 252 | } 253 | 254 | public static function countComments($post_id) { 255 | $stmt = self::connect()->prepare("SELECT COUNT(post_id) as count FROM `comments` 256 | WHERE post_id = :post_id"); 257 | $stmt->bindParam(":post_id" , $post_id , PDO::PARAM_STR); 258 | $stmt->execute(); 259 | $count = $stmt->fetch(PDO::FETCH_OBJ); 260 | return $count->count; 261 | } 262 | public static function countReplies($comment_id) { 263 | $stmt = self::connect()->prepare("SELECT COUNT(comment_id) as count FROM `replies` 264 | WHERE comment_id = :comment_id"); 265 | $stmt->bindParam(":comment_id" , $comment_id , PDO::PARAM_STR); 266 | $stmt->execute(); 267 | $count = $stmt->fetch(PDO::FETCH_OBJ); 268 | return $count->count; 269 | } 270 | 271 | public static function countRetweets($tweet_id) { 272 | $stmt = self::connect()->prepare("SELECT COUNT(*) as count FROM `retweets` 273 | WHERE (`tweet_id` = :tweet_id or `retweet_id` = :tweet_id) and retweet_msg is null 274 | GROUP BY tweet_id , retweet_id"); 275 | $stmt->bindParam(":tweet_id" , $tweet_id , PDO::PARAM_STR); 276 | $stmt->execute(); 277 | if ($stmt->rowCount() > 0) { 278 | $count = $stmt->fetch(PDO::FETCH_OBJ); 279 | return $count->count; 280 | } else return false; 281 | 282 | } 283 | 284 | public static function unLike($user_id, $tweet_id){ 285 | 286 | $stmt = self::connect()->prepare("DELETE FROM `likes` 287 | WHERE `user_id` = :user_id and `post_id` = :tweet_id"); 288 | $stmt->bindParam(":user_id", $user_id, PDO::PARAM_INT); 289 | $stmt->bindParam(":tweet_id", $tweet_id, PDO::PARAM_INT); 290 | $stmt->execute(); 291 | 292 | if ($stmt->rowCount() > 0) { 293 | return true; 294 | } else return false; 295 | 296 | } 297 | 298 | public static function userLikeIt( $user_id ,$tweet_id){ 299 | 300 | $stmt = self::connect()->prepare("SELECT `post_id` , `user_id` FROM `likes` 301 | WHERE `user_id` = :user_id and `post_id` = :tweet_id"); 302 | $stmt->bindParam(":user_id", $user_id, PDO::PARAM_INT); 303 | $stmt->bindParam(":tweet_id", $tweet_id, PDO::PARAM_INT); 304 | $stmt->execute(); 305 | 306 | if ($stmt->rowCount() > 0) { 307 | return true; 308 | } else return false; 309 | 310 | } 311 | public static function usersLiked($tweet_id){ 312 | 313 | $stmt = self::connect()->prepare("SELECT `post_id` , `user_id` FROM `likes` 314 | WHERE `post_id` = :tweet_id"); 315 | $stmt->bindParam(":tweet_id", $tweet_id, PDO::PARAM_INT); 316 | $stmt->execute(); 317 | 318 | return $stmt->fetchAll(PDO::FETCH_OBJ); 319 | 320 | } 321 | 322 | public static function userRetweeetedIt($user_id ,$tweet_id){ 323 | 324 | $stmt = self::connect()->prepare("SELECT `id` , `user_id` FROM `posts` JOIN `retweets` 325 | on id = post_id 326 | WHERE `user_id` = :user_id and (`tweet_id` = :tweet_id or `retweet_id` = :tweet_id) and retweet_msg is NULL"); 327 | $stmt->bindParam(":user_id", $user_id, PDO::PARAM_INT); 328 | $stmt->bindParam(":tweet_id", $tweet_id, PDO::PARAM_INT); 329 | $stmt->execute(); 330 | 331 | if ($stmt->rowCount() > 0) { 332 | return true; 333 | } else return false; 334 | 335 | } 336 | public static function usersRetweeeted($tweet_id){ 337 | 338 | $stmt = self::connect()->prepare("SELECT `id` , `user_id` FROM `posts` JOIN `retweets` 339 | on id = post_id 340 | WHERE (`tweet_id` = :tweet_id or `retweet_id` = :tweet_id) and retweet_msg is NULL"); 341 | // $stmt->bindParam(":user_id", $user_id, PDO::PARAM_INT); 342 | $stmt->bindParam(":tweet_id", $tweet_id, PDO::PARAM_INT); 343 | $stmt->execute(); 344 | 345 | return $stmt->fetchAll(PDO::FETCH_OBJ); 346 | 347 | } 348 | public static function checkRetweet($user_id ,$tweet_id){ 349 | 350 | $stmt = self::connect()->prepare("SELECT `id` , `user_id` FROM `posts` JOIN `retweets` 351 | on id = post_id 352 | WHERE `user_id` = :user_id and `post_id` = :tweet_id and retweet_msg is NULL"); 353 | $stmt->bindParam(":user_id", $user_id, PDO::PARAM_INT); 354 | $stmt->bindParam(":tweet_id", $tweet_id, PDO::PARAM_INT); 355 | $stmt->execute(); 356 | 357 | if ($stmt->rowCount() > 0) { 358 | return true; 359 | } else return false; 360 | 361 | } 362 | 363 | 364 | 365 | 366 | public static function undoRetweet($user_id , $tweet_id) { 367 | 368 | $stmt = self::connect()->prepare("DELETE FROM `posts` 369 | WHERE `user_id` = :user_id and `id` = :tweet_id 370 | "); 371 | // and id not in (SELECT post_id from `retweets` WHERE retweet_msg is not null) 372 | $stmt->bindParam(":user_id", $user_id, PDO::PARAM_INT); 373 | $stmt->bindParam(":tweet_id", $tweet_id, PDO::PARAM_INT); 374 | $stmt->execute(); 375 | 376 | if ($stmt->rowCount() > 0) { 377 | return true; 378 | } else return false; 379 | } 380 | 381 | public static function retweetRealId($tweet_id , $user_id) { 382 | $stmt = self::connect()->prepare("SELECT post_id FROM retweets JOIN posts 383 | on id = post_id 384 | WHERE (tweet_id = :tweet_id or retweet_id = :tweet_id) and `user_id` = :user_id"); 385 | $stmt->bindParam(":tweet_id" , $tweet_id , PDO::PARAM_STR); 386 | $stmt->bindParam(":user_id" , $user_id , PDO::PARAM_STR); 387 | $stmt->execute(); 388 | $id = $stmt->fetch(PDO::FETCH_OBJ); 389 | return $id->post_id; 390 | } 391 | 392 | 393 | 394 | 395 | public static function likedTweetRealId($tweet_id) { 396 | $stmt = self::connect()->prepare("SELECT tweet_id FROM retweets 397 | WHERE post_id = :tweet_id"); 398 | $stmt->bindParam(":tweet_id" , $tweet_id , PDO::PARAM_STR); 399 | $stmt->execute(); 400 | $id = $stmt->fetch(PDO::FETCH_OBJ); 401 | return $id->tweet_id; 402 | } 403 | 404 | // public static function getRealId($tweet_id) { 405 | // $stmt = self::connect()->prepare("SELECT post_id FROM retweets 406 | // WHERE post_id = :tweet_id"); 407 | // $stmt->bindParam(":tweet_id" , $tweet_id , PDO::PARAM_STR); 408 | // $stmt->execute(); 409 | // $id = $stmt->fetch(PDO::FETCH_OBJ); 410 | // return $id->tweet_id; 411 | // } 412 | 413 | public static function getTweet($tweet_id){ 414 | $stmt = self::connect()->prepare("SELECT * FROM `tweets` JOIN `posts` 415 | on posts.id = tweets.post_id 416 | WHERE `post_id` = :tweet_id"); 417 | $stmt->bindParam(":tweet_id", $tweet_id, PDO::PARAM_INT); 418 | $stmt->execute(); 419 | return $stmt->fetch(PDO::FETCH_OBJ); 420 | } 421 | public static function getComment($tweet_id){ 422 | $stmt = self::connect()->prepare("SELECT * FROM `comments` 423 | WHERE `id` = :tweet_id"); 424 | $stmt->bindParam(":tweet_id", $tweet_id, PDO::PARAM_INT); 425 | $stmt->execute(); 426 | return $stmt->fetch(PDO::FETCH_OBJ); 427 | } 428 | public static function getRetweet($tweet_id){ 429 | $stmt = self::connect()->prepare("SELECT * FROM `retweets` JOIN `posts` 430 | on id = post_id 431 | WHERE `post_id` = :tweet_id"); 432 | $stmt->bindParam(":tweet_id", $tweet_id, PDO::PARAM_INT); 433 | $stmt->execute(); 434 | return $stmt->fetch(PDO::FETCH_OBJ); 435 | } 436 | public static function getData($id) { 437 | $stmt = self::connect()->prepare("SELECT * from `posts` WHERE `id` = :id"); 438 | $stmt->bindParam(":id" , $id , PDO::PARAM_STR); 439 | $stmt->execute(); 440 | return $stmt->fetch(PDO::FETCH_OBJ); 441 | } 442 | 443 | public static function includeHeader($title) { 444 | global $tweets; 445 | $tweets = $title; 446 | include 'includes/tweets.php'; 447 | } 448 | 449 | 450 | 451 | 452 | 453 | 454 | 455 | 456 | 457 | } --------------------------------------------------------------------------------