Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 25
0.00% covered (danger)
0.00%
0 / 3
CRAP
0.00% covered (danger)
0.00%
0 / 1
Bitcoin_Address_Factory
0.00% covered (danger)
0.00%
0 / 25
0.00% covered (danger)
0.00%
0 / 3
42
0.00% covered (danger)
0.00%
0 / 1
 get_post_id_for_address
0.00% covered (danger)
0.00%
0 / 9
0.00% covered (danger)
0.00%
0 / 1
12
 save_new
0.00% covered (danger)
0.00%
0 / 15
0.00% covered (danger)
0.00%
0 / 1
6
 get_by_post_id
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
1<?php
2/**
3 * Save new Bitcoin addresses in WordPress, and fetch them via xpub or post id.
4 *
5 * @package    brianhenryie/bh-wp-bitcoin-gateway
6 */
7
8namespace BrianHenryIE\WP_Bitcoin_Gateway\API\Addresses;
9
10use Exception;
11use wpdb;
12
13/**
14 * Interface for creating/getting Bitcoin_Address objects stored in wp_posts table.
15 */
16class Bitcoin_Address_Factory {
17
18    /**
19     * Given a bitcoin master public key, get the WordPress post_id it is saved under.
20     *
21     * @param string $address Xpub|ypub|zpub.
22     *
23     * @return int|null The post id if it exists, null if it is not found.
24     */
25    public function get_post_id_for_address( string $address ): ?int {
26
27        $post_id = wp_cache_get( $address, Bitcoin_Address::POST_TYPE );
28
29        if ( is_numeric( $post_id ) ) {
30            return (int) $post_id;
31        }
32
33        /**
34         * WordPress database object.
35         *
36         * TODO: Can this be replaced with a `get_posts()` call?
37         *
38         * @var wpdb $wpdb
39         */
40        global $wpdb;
41        // phpcs:disable WordPress.DB.DirectDatabaseQuery.DirectQuery
42        // @phpstan-ignore-next-line
43        $post_id = $wpdb->get_var( $wpdb->prepare( "SELECT ID FROM $wpdb->posts WHERE post_name=%s", sanitize_title( $address ) ) );
44
45        if ( ! is_null( $post_id ) ) {
46            $post_id = intval( $post_id );
47            wp_cache_add( $address, $post_id, Bitcoin_Address::POST_TYPE );
48        }
49
50        return $post_id;
51    }
52
53    /**
54     * Wrapper on wp_insert_post(), sets the address as the post_title, post_excerpt and post_name.
55     *
56     * @param string         $address The Bitcoin address.
57     * @param int            $address_index The derivation sequence number.
58     * @param Bitcoin_Wallet $wallet The wallet whose xpub this address was derived from.
59     *
60     * @return int The new post_id.
61     *
62     * @throws Exception When WordPress fails to create the wp_post.
63     */
64    public function save_new( string $address, int $address_index, Bitcoin_Wallet $wallet ): int {
65
66        // TODO: Validate address, throw exception.
67
68        $args = array(
69            'post_type'    => Bitcoin_Address::POST_TYPE,
70            'post_name'    => sanitize_title( $address ), // An indexed column.
71            'post_excerpt' => $address,
72            'post_title'   => $address,
73            'post_status'  => 'unknown',
74            'post_parent'  => $wallet->get_post_id(),
75            'meta_input'   => array(
76                Bitcoin_Address::DERIVATION_PATH_SEQUENCE_NUMBER_META_KEY => $address_index,
77            ),
78        );
79
80        $post_id = wp_insert_post( $args, true );
81
82        if ( is_wp_error( $post_id ) ) {
83            // TODO Log.
84            throw new Exception( 'WordPress failed to create a post for the wallet.' );
85        }
86
87        // TODO: Maybe start a background job to check for transactions. Where is best to do that?
88
89        return $post_id;
90    }
91
92    /**
93     * Given the id of the wp_posts row storing the bitcoin address, return the typed Bitcoin_Address object.
94     *
95     * @param int $post_id WordPress wp_posts ID.
96     *
97     * @return Bitcoin_Address
98     * @throws Exception When the post_type of the post returned for the given post_id is not a Bitcoin_Address.
99     */
100    public function get_by_post_id( int $post_id ): Bitcoin_Address {
101        return new Bitcoin_Address( $post_id );
102    }
103}