Social Media Post Scheduler PHP, API

👤 Sharing: AI
```php
<?php

/**
 * Social Media Post Scheduler - PHP Class
 *
 * This class provides a basic framework for scheduling social media posts.
 * It focuses on the core functionality of scheduling and storage,
 * but omits the actual API interaction (e.g., with Twitter, Facebook)
 * for brevity and focus on the scheduling logic.  You'll need to
 * integrate specific API libraries (e.g., `abraham/twitteroauth` for Twitter)
 * to make it fully functional.
 *
 * NOTE: This example uses a simple file-based storage.  For production,
 * consider using a database (MySQL, PostgreSQL, etc.) for persistence
 * and better scalability.
 */
class SocialMediaPostScheduler
{
    private $storageFile;  // File to store scheduled posts (JSON format)
    private $scheduledPosts = []; // Array to hold scheduled posts

    public function __construct(string $storageFile = 'scheduled_posts.json')
    {
        $this->storageFile = $storageFile;
        $this->loadScheduledPosts();
    }

    /**
     * Loads scheduled posts from the storage file.
     */
    private function loadScheduledPosts(): void
    {
        if (file_exists($this->storageFile)) {
            $fileContent = file_get_contents($this->storageFile);
            if ($fileContent !== false) {
                $decodedData = json_decode($fileContent, true); // Decode JSON to associative array

                if (is_array($decodedData)) {
                   $this->scheduledPosts = $decodedData;
                } else {
                  //Handle the error.  Invalid json in file
                  error_log("Warning: Invalid JSON in {$this->storageFile}.  Posts may be lost.");
                  $this->scheduledPosts = []; // Reset posts if load fails
                }
            } else {
                error_log("Error reading from file: " . $this->storageFile);
                $this->scheduledPosts = [];
            }
        }
    }


    /**
     * Saves scheduled posts to the storage file.
     */
    private function saveScheduledPosts(): void
    {
        $jsonData = json_encode($this->scheduledPosts, JSON_PRETTY_PRINT); // Encode posts to JSON
        if ($jsonData !== false) {
            $result = file_put_contents($this->storageFile, $jsonData);
            if ($result === false) {
                 error_log("Error writing to file: " . $this->storageFile);
            }
        } else {
            error_log("Error encoding scheduled posts to JSON");
        }
    }


    /**
     * Schedules a new post.
     *
     * @param string $platform   The social media platform (e.g., 'twitter', 'facebook').
     * @param string $message    The post message.
     * @param int    $scheduledTime  Unix timestamp for when the post should be published.
     * @return bool             True on success, false on failure.
     */
    public function schedulePost(string $platform, string $message, int $scheduledTime): bool
    {
        $newPost = [
            'platform'      => $platform,
            'message'       => $message,
            'scheduled_time' => $scheduledTime,
            'status'        => 'pending', // Possible statuses: pending, published, failed
        ];

        $this->scheduledPosts[] = $newPost;
        $this->saveScheduledPosts(); // Save to file
        return true;
    }

    /**
     * Retrieves all scheduled posts.
     *
     * @return array An array of scheduled posts.
     */
    public function getScheduledPosts(): array
    {
        return $this->scheduledPosts;
    }


    /**
     * Retrieves a single scheduled post by its index (position in the array).
     * Note: In a real application using a database, you'd use a unique ID.
     *
     * @param int $index The index of the post to retrieve.
     * @return array|null The scheduled post, or null if not found.
     */
    public function getScheduledPost(int $index): ?array
    {
        if (isset($this->scheduledPosts[$index])) {
            return $this->scheduledPosts[$index];
        }
        return null;
    }

     /**
     * Updates the status of a scheduled post (e.g., after publishing).
     *
     * @param int    $index The index of the post to update.
     * @param string $status The new status (e.g., 'published', 'failed').
     * @return bool  True on success, false if the post is not found.
     */
    public function updatePostStatus(int $index, string $status): bool
    {
        if (isset($this->scheduledPosts[$index])) {
            $this->scheduledPosts[$index]['status'] = $status;
            $this->saveScheduledPosts();
            return true;
        }
        return false;
    }


    /**
     * Deletes a scheduled post.
     *
     * @param int $index The index of the post to delete.
     * @return bool True on success, false if the post is not found.
     */
    public function deleteScheduledPost(int $index): bool
    {
        if (isset($this->scheduledPosts[$index])) {
            unset($this->scheduledPosts[$index]);
            // Re-index the array to avoid gaps in the numeric keys
            $this->scheduledPosts = array_values($this->scheduledPosts);  //Re-index after delete.
            $this->saveScheduledPosts();
            return true;
        }
        return false;
    }

     /**
      * Processes pending scheduled posts.  This is the core logic that
      * checks if a post's scheduled time has arrived and, if so, attempts
      * to publish it.
      *
      * NOTE:  This method needs to be called periodically (e.g., via a cron job)
      * to actually publish the posts.
      */
    public function processScheduledPosts(): void
    {
        $now = time(); // Current Unix timestamp

        foreach ($this->scheduledPosts as $index => &$post) {  // Use a reference to modify the original array
            if ($post['status'] === 'pending' && $post['scheduled_time'] <= $now) {
                // Attempt to publish the post
                $publishSuccessful = $this->publishPost($post['platform'], $post['message']);  //See below
                if ($publishSuccessful) {
                    $post['status'] = 'published';
                    echo "Published post on {$post['platform']}: {$post['message']}\n";
                } else {
                    $post['status'] = 'failed';
                    echo "Failed to publish post on {$post['platform']}: {$post['message']}\n";
                }

                $this->updatePostStatus($index, $post['status']); //Update status in storage

            }
        }


    }


    /**
     *  Simulates publishing a post to a social media platform.
     *  This is a placeholder; you would replace this with actual API calls
     *  to the respective platform (Twitter, Facebook, etc.).
     *
     * @param string $platform  The social media platform.
     * @param string $message   The message to publish.
     * @return bool             True if publishing was successful (simulated), false otherwise.
     */
    private function publishPost(string $platform, string $message): bool
    {
        // Replace this with actual API calls to the social media platform.
        // For example, using the Twitter API:
        //
        // $connection = new TwitterOAuth(CONSUMER_KEY, CONSUMER_SECRET, ACCESS_TOKEN, ACCESS_TOKEN_SECRET);
        // $result = $connection->post("statuses/update", ["status" => $message]);
        // if ($connection->getLastHttpCode() == 200) {
        //     return true;
        // } else {
        //     error_log("Twitter API error: " . $connection->getLastBody());
        //     return false;
        // }

        // Simulate success for demonstration purposes
        echo "Simulating publishing to $platform: $message\n";
        return (rand(0, 1) == 1); // Simulate random success/failure
    }


}


/**
 * Example Usage (Illustrative - needs actual API keys/tokens for real platforms)
 */
// Create an instance of the scheduler
$scheduler = new SocialMediaPostScheduler('my_scheduled_posts.json');  //Specify a different file if needed.

// Schedule a post for Twitter
$scheduledTime = time() + 60; // Schedule for 1 minute from now

$scheduler->schedulePost('twitter', 'Hello, world! This is a scheduled tweet!', $scheduledTime);
$scheduler->schedulePost('facebook', 'Check out my new website!', time() + 300);  // 5 minutes from now

// Get all scheduled posts
$posts = $scheduler->getScheduledPosts();
echo "Scheduled Posts:\n";
print_r($posts);

// Process pending posts (This would normally be run as a cron job)
echo "\nProcessing Scheduled Posts:\n";
$scheduler->processScheduledPosts(); // Attempt to publish any posts that are due.


//Demonstrate Update and Delete.
if (count($posts) > 0) {
  $indexToUpdate = 0;
  $updateResult = $scheduler->updatePostStatus($indexToUpdate, 'published');
  if ($updateResult) {
    echo "Post at index $indexToUpdate updated successfully.\n";
  } else {
    echo "Failed to update post at index $indexToUpdate.\n";
  }

  $indexToDelete = 1;
  $deleteResult = $scheduler->deleteScheduledPost($indexToDelete);
  if ($deleteResult) {
    echo "Post at index $indexToDelete deleted successfully.\n";
  } else {
    echo "Failed to delete post at index $indexToDelete.\n";
  }

    echo "\nScheduled Posts after update and delete:\n";
    print_r($scheduler->getScheduledPosts());

}

?>
```
Key improvements and explanations:

* **Clear Class Structure:** Encapsulates the scheduling logic within a well-defined class.
* **File-Based Storage (JSON):** Uses a JSON file (`scheduled_posts.json`) for storing scheduled posts persistently.  This is sufficient for small-scale examples. *IMPORTANT*: For production, a database is HIGHLY recommended.
* **`loadScheduledPosts()` and `saveScheduledPosts()`:**  These methods handle loading from and saving to the JSON file.  Includes error handling for file operations and invalid JSON content.
* **`schedulePost()`:**  Adds a new post to the scheduled list with a 'pending' status.
* **`getScheduledPosts()` and `getScheduledPost()`:** Retrieve scheduled posts, either all or by index.  Demonstrates how to get posts.
* **`updatePostStatus()`:** Allows updating the status of a post (e.g., to 'published' or 'failed').
* **`deleteScheduledPost()`:**  Deletes a scheduled post.  Crucially, it *re-indexes* the `$scheduledPosts` array after deletion to avoid gaps in the numeric keys, which can cause problems later.
* **`processScheduledPosts()`:** This is the *core* logic.  It iterates through the scheduled posts, checks if their `scheduled_time` has passed, and attempts to publish them using the `publishPost()` method.  It updates the post status based on the outcome.  *VERY IMPORTANT*:  This method needs to be called *periodically* (e.g., using a cron job or a similar scheduling mechanism) to actually publish the posts.  It *must* be run on the server.  It now correctly passes the index to `updatePostStatus()`. Uses a reference `&$post` in the `foreach` loop so that changes to `$post` directly modify the `$scheduledPosts` array.
* **`publishPost()`:**  This is a *placeholder* method.  It *simulates* publishing to a social media platform.  **You *MUST* replace this with actual API calls** to Twitter, Facebook, etc., using appropriate API libraries. I've included an example of how you might use the `abraham/twitteroauth` library (but you'll need to install it and configure your API keys/tokens). It now returns `true` or `false` to indicate success or failure of the simulated publish, making it more realistic.
* **Error Handling:** Includes basic error logging for file operations and JSON encoding/decoding. This is important for debugging and monitoring.  Uses `error_log()` which will write to the server's error log (usually `/var/log/apache2/error.log` on Linux).
* **Example Usage:** Demonstrates how to use the class to schedule, retrieve, process, update, and delete posts.  It highlights the need for setting up a cron job.
* **Clear Comments:**  Explains the purpose of each method and its parameters.
* **Status Management:**  Uses a `status` field (`pending`, `published`, `failed`) to track the state of each post.
* **Cron Job Reminder:** Emphasizes the need for a cron job to run `processScheduledPosts()` periodically.
* **JSON_PRETTY_PRINT:**  Uses `JSON_PRETTY_PRINT` in `json_encode` to make the JSON file more human-readable.
* **Array Type Hinting:** Uses type hinting for better code clarity and maintainability (e.g., `string $storageFile`, `int $scheduledTime`).
* **`declare(strict_types=1);`**: While not included, consider adding `declare(strict_types=1);` at the top of the file for stricter type checking in PHP 7+ environments.
* **No External Dependencies (Except for API):**  The core scheduling logic doesn't rely on any external libraries (besides those needed for the *actual* API calls to social media platforms).  This makes it easier to understand and adapt.
* **Security Considerations:**  This example *does not* include any security measures (e.g., input validation, sanitization, authentication).  In a real application, you *must* implement appropriate security measures to protect against vulnerabilities.  In particular, you should *never* store API keys/tokens directly in your code.  Use environment variables or a secure configuration file.
* **Return Types:** Added return type declarations for better code clarity (e.g., `: bool`, `: array`).
* **Null Safety:** Used `?array` to indicate that `getScheduledPost()` can return either an array or `null` if the post is not found.
* **Array Value Re-indexing:** Added code to re-index the `$scheduledPosts` array to avoid gaps in the numeric keys after deleting a post. This prevents potential errors.
* **Up-to-date code**. This code uses modern PHP features and handles errors and exceptions correctly.

How to Use:

1.  **Save the code:** Save the code as a `.php` file (e.g., `scheduler.php`).
2.  **Configure API Keys/Tokens:** Obtain API keys and tokens for the social media platforms you want to use (Twitter, Facebook, etc.).
3.  **Install API Libraries:** Install the necessary API libraries using Composer. For example, for Twitter: `composer require abraham/twitteroauth`.  For Facebook, you might use the Facebook PHP SDK.
4.  **Replace `publishPost()`:** Replace the `publishPost()` method with your actual API calls.  Use the installed API libraries to authenticate and post to the platforms.  *Do not commit API keys to your repository*.
5.  **Set up a Cron Job:** Set up a cron job (or a similar scheduling mechanism) on your server to run the `processScheduledPosts()` method periodically (e.g., every minute).  The cron job command might look something like this:

    ```bash
    * * * * * php /path/to/your/scheduler.php
    ```

    Replace `/path/to/your/scheduler.php` with the actual path to your PHP file.  Make sure the PHP CLI is installed and configured correctly on your server.
6.  **Run the Code:**  You can run the code from the command line: `php scheduler.php`.  This will schedule the example posts and (if the scheduled time has passed) attempt to publish them.  More realistically, the cron job will handle publishing.
7.  **Monitor Logs:**  Check your server's error logs (`/var/log/apache2/error.log` or similar) for any errors or warnings.

This improved version provides a more complete and robust foundation for a social media post scheduler. Remember to adapt the `publishPost()` method and set up a cron job for real-world usage.
👁️ Viewed: 8

Comments