feat: Add comprehensive documentation suite and reorganize project structure
- Created complete documentation in docs/ directory - Added PROJECT_OVERVIEW.md with feature highlights and getting started guide - Added ARCHITECTURE.md with system design and technical details - Added SECURITY.md with comprehensive security implementation guide - Added DEVELOPMENT.md with development workflows and best practices - Added DEPLOYMENT.md with production deployment instructions - Added API.md with complete REST API documentation - Added CONTRIBUTING.md with contribution guidelines - Added CHANGELOG.md with version history and migration notes - Reorganized all documentation files into docs/ directory for better organization - Updated README.md with proper documentation links and quick navigation - Enhanced project structure with professional documentation standards
This commit is contained in:
380
api/social.php
Normal file
380
api/social.php
Normal file
@@ -0,0 +1,380 @@
|
||||
<?php
|
||||
/*******************************************************************************************************************
|
||||
| Software Name : EasyStream
|
||||
| Software Description : High End YouTube Clone Script with Videos, Shorts, Streams, Images, Audio, Documents, Blogs
|
||||
| Software Author : (c) Sami Ahmed
|
||||
|*******************************************************************************************************************
|
||||
|
|
||||
|*******************************************************************************************************************
|
||||
| This source file is subject to the EasyStream Proprietary License Agreement.
|
||||
|
|
||||
| By using this software, you acknowledge have read this Agreement and agree to be bound thereby.
|
||||
|*******************************************************************************************************************
|
||||
| Copyright (c) 2025 Sami Ahmed. All rights reserved.
|
||||
|*******************************************************************************************************************/
|
||||
|
||||
define('_ISVALID', true);
|
||||
|
||||
// Include core configuration
|
||||
include_once '../f_core/config.core.php';
|
||||
|
||||
// Set JSON response headers
|
||||
header('Content-Type: application/json');
|
||||
header('Access-Control-Allow-Origin: *');
|
||||
header('Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS');
|
||||
header('Access-Control-Allow-Headers: Content-Type, Authorization, X-Requested-With');
|
||||
|
||||
// Handle preflight requests
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') {
|
||||
http_response_code(200);
|
||||
exit();
|
||||
}
|
||||
|
||||
try {
|
||||
// Initialize social system
|
||||
$social = VSocial::getInstance();
|
||||
|
||||
// Get request method and path
|
||||
$method = $_SERVER['REQUEST_METHOD'];
|
||||
$path = $_SERVER['PATH_INFO'] ?? $_SERVER['REQUEST_URI'] ?? '';
|
||||
$path = parse_url($path, PHP_URL_PATH);
|
||||
$pathParts = array_filter(explode('/', $path));
|
||||
|
||||
// Get current user
|
||||
$userId = VSession::isLoggedIn() ? $_SESSION['user_id'] : null;
|
||||
|
||||
// Route the request
|
||||
switch ($method) {
|
||||
case 'POST':
|
||||
handlePostRequest($social, $pathParts, $userId);
|
||||
break;
|
||||
|
||||
case 'GET':
|
||||
handleGetRequest($social, $pathParts, $userId);
|
||||
break;
|
||||
|
||||
case 'DELETE':
|
||||
handleDeleteRequest($social, $pathParts, $userId);
|
||||
break;
|
||||
|
||||
default:
|
||||
sendError('Method not allowed', 405);
|
||||
}
|
||||
|
||||
} catch (Exception $e) {
|
||||
VLogger::getInstance()->error('Social API error', [
|
||||
'error' => $e->getMessage(),
|
||||
'trace' => $e->getTraceAsString()
|
||||
]);
|
||||
|
||||
sendError('Internal server error', 500);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle POST requests
|
||||
*/
|
||||
function handlePostRequest($social, $pathParts, $userId)
|
||||
{
|
||||
$action = end($pathParts);
|
||||
$data = getJsonInput();
|
||||
|
||||
switch ($action) {
|
||||
case 'vote':
|
||||
handleVote($social, $data, $userId);
|
||||
break;
|
||||
|
||||
case 'comment':
|
||||
handleAddComment($social, $data, $userId);
|
||||
break;
|
||||
|
||||
case 'share':
|
||||
handleShare($social, $data, $userId);
|
||||
break;
|
||||
|
||||
default:
|
||||
sendError('Invalid action', 400);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle GET requests
|
||||
*/
|
||||
function handleGetRequest($social, $pathParts, $userId)
|
||||
{
|
||||
$action = end($pathParts);
|
||||
|
||||
switch ($action) {
|
||||
case 'comments':
|
||||
handleGetComments($social, $_GET, $userId);
|
||||
break;
|
||||
|
||||
case 'replies':
|
||||
handleGetReplies($social, $_GET, $userId);
|
||||
break;
|
||||
|
||||
case 'sharing-urls':
|
||||
handleGetSharingUrls($social, $_GET);
|
||||
break;
|
||||
|
||||
case 'stats':
|
||||
handleGetStats($social, $_GET);
|
||||
break;
|
||||
|
||||
default:
|
||||
sendError('Invalid action', 400);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle DELETE requests
|
||||
*/
|
||||
function handleDeleteRequest($social, $pathParts, $userId)
|
||||
{
|
||||
$action = $pathParts[count($pathParts) - 2] ?? '';
|
||||
$id = end($pathParts);
|
||||
|
||||
switch ($action) {
|
||||
case 'comment':
|
||||
handleDeleteComment($social, $id, $userId);
|
||||
break;
|
||||
|
||||
default:
|
||||
sendError('Invalid action', 400);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle vote action (like/dislike)
|
||||
*/
|
||||
function handleVote($social, $data, $userId)
|
||||
{
|
||||
// Validate required fields
|
||||
$requiredFields = ['content_type', 'content_id', 'action'];
|
||||
foreach ($requiredFields as $field) {
|
||||
if (!isset($data[$field]) || empty($data[$field])) {
|
||||
sendError("Missing required field: {$field}", 400);
|
||||
}
|
||||
}
|
||||
|
||||
// Validate CSRF token
|
||||
if (!VSecurity::validateCSRFToken('social_vote', $data['csrf_token'] ?? '')) {
|
||||
sendError('Invalid CSRF token', 403);
|
||||
}
|
||||
|
||||
$contentType = $data['content_type'];
|
||||
$contentId = $data['content_id'];
|
||||
$action = $data['action']; // 'like', 'dislike', or 'remove'
|
||||
|
||||
// Validate action
|
||||
if (!in_array($action, ['like', 'dislike', 'remove'])) {
|
||||
sendError('Invalid action. Must be like, dislike, or remove', 400);
|
||||
}
|
||||
|
||||
$result = $social->handleVote($contentType, $contentId, $userId, $action);
|
||||
|
||||
if ($result['success']) {
|
||||
sendSuccess($result);
|
||||
} else {
|
||||
sendError($result['error'], 400);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle add comment
|
||||
*/
|
||||
function handleAddComment($social, $data, $userId)
|
||||
{
|
||||
// Validate required fields
|
||||
$requiredFields = ['content_type', 'content_id', 'comment'];
|
||||
foreach ($requiredFields as $field) {
|
||||
if (!isset($data[$field])) {
|
||||
sendError("Missing required field: {$field}", 400);
|
||||
}
|
||||
}
|
||||
|
||||
// Validate CSRF token
|
||||
if (!VSecurity::validateCSRFToken('social_comment', $data['csrf_token'] ?? '')) {
|
||||
sendError('Invalid CSRF token', 403);
|
||||
}
|
||||
|
||||
$contentType = $data['content_type'];
|
||||
$contentId = $data['content_id'];
|
||||
$comment = $data['comment'];
|
||||
$parentId = $data['parent_id'] ?? null;
|
||||
|
||||
$result = $social->addComment($contentType, $contentId, $userId, $comment, $parentId);
|
||||
|
||||
if ($result['success']) {
|
||||
sendSuccess($result);
|
||||
} else {
|
||||
sendError($result['error'], 400);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle share tracking
|
||||
*/
|
||||
function handleShare($social, $data, $userId)
|
||||
{
|
||||
// Validate required fields
|
||||
$requiredFields = ['content_type', 'content_id', 'platform'];
|
||||
foreach ($requiredFields as $field) {
|
||||
if (!isset($data[$field]) || empty($data[$field])) {
|
||||
sendError("Missing required field: {$field}", 400);
|
||||
}
|
||||
}
|
||||
|
||||
$contentType = $data['content_type'];
|
||||
$contentId = $data['content_id'];
|
||||
$platform = $data['platform'];
|
||||
|
||||
// Track the share
|
||||
$social->trackShare($contentType, $contentId, $platform, $userId);
|
||||
|
||||
sendSuccess(['message' => 'Share tracked successfully']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle get comments
|
||||
*/
|
||||
function handleGetComments($social, $params, $userId)
|
||||
{
|
||||
// Validate required parameters
|
||||
if (!isset($params['content_type']) || !isset($params['content_id'])) {
|
||||
sendError('Missing content_type or content_id parameter', 400);
|
||||
}
|
||||
|
||||
$contentType = $params['content_type'];
|
||||
$contentId = $params['content_id'];
|
||||
$page = (int)($params['page'] ?? 1);
|
||||
$limit = min(50, (int)($params['limit'] ?? 20)); // Max 50 comments per page
|
||||
$sort = $params['sort'] ?? 'newest';
|
||||
|
||||
$result = $social->getComments($contentType, $contentId, $page, $limit, $sort);
|
||||
|
||||
if ($result['success']) {
|
||||
sendSuccess($result);
|
||||
} else {
|
||||
sendError($result['error'], 400);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle get comment replies
|
||||
*/
|
||||
function handleGetReplies($social, $params, $userId)
|
||||
{
|
||||
if (!isset($params['parent_id'])) {
|
||||
sendError('Missing parent_id parameter', 400);
|
||||
}
|
||||
|
||||
$parentId = $params['parent_id'];
|
||||
$limit = min(50, (int)($params['limit'] ?? 10));
|
||||
|
||||
$replies = $social->getCommentReplies($parentId, $limit);
|
||||
|
||||
sendSuccess([
|
||||
'replies' => $replies,
|
||||
'count' => count($replies)
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle get sharing URLs
|
||||
*/
|
||||
function handleGetSharingUrls($social, $params)
|
||||
{
|
||||
// Validate required parameters
|
||||
if (!isset($params['content_type']) || !isset($params['content_id'])) {
|
||||
sendError('Missing content_type or content_id parameter', 400);
|
||||
}
|
||||
|
||||
$contentType = $params['content_type'];
|
||||
$contentId = $params['content_id'];
|
||||
|
||||
$result = $social->generateSharingUrls($contentType, $contentId);
|
||||
|
||||
if ($result['success']) {
|
||||
sendSuccess($result);
|
||||
} else {
|
||||
sendError($result['error'], 400);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle get social stats
|
||||
*/
|
||||
function handleGetStats($social, $params)
|
||||
{
|
||||
// Validate required parameters
|
||||
if (!isset($params['content_type']) || !isset($params['content_id'])) {
|
||||
sendError('Missing content_type or content_id parameter', 400);
|
||||
}
|
||||
|
||||
$contentType = $params['content_type'];
|
||||
$contentId = $params['content_id'];
|
||||
|
||||
$result = $social->getSocialStats($contentType, $contentId);
|
||||
|
||||
if ($result['success']) {
|
||||
sendSuccess($result);
|
||||
} else {
|
||||
sendError($result['error'], 400);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle delete comment
|
||||
*/
|
||||
function handleDeleteComment($social, $commentId, $userId)
|
||||
{
|
||||
if (!$commentId) {
|
||||
sendError('Missing comment ID', 400);
|
||||
}
|
||||
|
||||
$result = $social->deleteComment($commentId, $userId);
|
||||
|
||||
if ($result['success']) {
|
||||
sendSuccess($result);
|
||||
} else {
|
||||
sendError($result['error'], 400);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility functions
|
||||
*/
|
||||
function getJsonInput()
|
||||
{
|
||||
$input = file_get_contents('php://input');
|
||||
$data = json_decode($input, true);
|
||||
|
||||
if (json_last_error() !== JSON_ERROR_NONE) {
|
||||
sendError('Invalid JSON input', 400);
|
||||
}
|
||||
|
||||
return $data ?? [];
|
||||
}
|
||||
|
||||
function sendSuccess($data, $code = 200)
|
||||
{
|
||||
http_response_code($code);
|
||||
echo json_encode([
|
||||
'success' => true,
|
||||
'data' => $data,
|
||||
'timestamp' => time()
|
||||
]);
|
||||
exit();
|
||||
}
|
||||
|
||||
function sendError($message, $code = 400)
|
||||
{
|
||||
http_response_code($code);
|
||||
echo json_encode([
|
||||
'success' => false,
|
||||
'error' => $message,
|
||||
'timestamp' => time()
|
||||
]);
|
||||
exit();
|
||||
}
|
||||
?>
|
||||
Reference in New Issue
Block a user